diff --git a/.github/workflows/build_cmake_tarball.yml b/.github/workflows/build_cmake_tarball.yml new file mode 100644 index 0000000000..2f50850e86 --- /dev/null +++ b/.github/workflows/build_cmake_tarball.yml @@ -0,0 +1,165 @@ +name: CMake Tarball + +# This file is part of t8code. +# t8code is a C library to manage a collection (a forest) of multiple +# connected adaptive space-trees of general element types in parallel. +# +# Copyright (C) 2024 the developers +# +# t8code is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# t8code 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with t8code; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +# +# This github CI script constructs a tarball and checks if it is build correctly. +# + +env: + MAKEFLAGS: "-j2 V=0" + + +on: + push: + branches: + - main + - develop + - CI-*tarball* # for testing this script, all feature branches with "tarball" in their name + pull_request: + branches: + - main + - develop + workflow_dispatch: + +jobs: + build: + + if: (github.event_name == 'schedule' && github.repository == 'DLR-AMR/t8code') || (github.event_name != 'schedule') + runs-on: ubuntu-20.04 + container: dlramr/t8code-ubuntu:t8-dependencies + timeout-minutes: 90 + steps: +# +# Setup and bootstrap +# + - uses: actions/checkout@v4 + with: + fetch-tags: true # required to get version tags + fetch-depth: 0 # required to get all history, especially the version tags + - name: install sudo + run: apt update && apt install sudo + # On the github Ubuntu 20.04, sudo is not available by default + # we need it, however, to update/upgrade our packages. + - name: Update packages + run: sudo apt-get update && sudo apt-get upgrade -y + # This step is necessary to get the newest package data + - name: disable ownership checks + run: git config --global --add safe.directory '*' + - name: init submodules + run: git submodule init + - name: update submodules + run: git submodule update + - name: bootstrap + run: ./bootstrap +# +# T8CODE +# with p4est and sc as internal dependencies which is needed for make dist +# +# + - name: less-test option + if: ${{ inputs.LESS_TESTS }} + run: export LESS_TEST_OPTION="-DT8CODE_ENABLE_LESS_TESTS=ON" + && echo LESS_TEST_OPTION="$LESS_TEST_OPTION" >> $GITHUB_ENV + - name: build config variables + run: export CONFIG_OPTIONS="${LESS_TEST_OPTION} -GNinja -DT8CODE_USE_SYSTEM_SC=OFF -DT8CODE_USE_SYSTEM_P4EST=OFF -DT8CODE_BUILD_PEDANTIC=ON -DT8CODE_ENABLE_MPI=$MPI -DCMAKE_BUILD_TYPE=$BUILD_TYPE" + && echo CONFIG_OPTIONS="$CONFIG_OPTIONS" >> $GITHUB_ENV + - name: cmake + run: mkdir build && cd build && cmake ../ $CONFIG_OPTIONS + - name: OnFailUploadLog + if: failure() + uses: actions/upload-artifact@v4 + with: + name: config.log + path: build/config.log +# Start building tarball + - name: Install pandoc + uses: nikeee/setup-pandoc@v1 + - name: Test pandoc + run: pandoc --version +# Build the tarball + - name: Make tarball + run: cd build && ninja GenerateVersionFile && ninja package_source && mkdir tarballs && mv package/*Source.tar.gz tarballs +# Upload the tarball + - name: upload tarball + uses: actions/upload-artifact@v4 + with: + name: tarballs + path: build/tarballs + + test-tarball: + needs: build + runs-on: ubuntu-20.04 + container: dlramr/t8code-ubuntu:t8-dependencies + timeout-minutes: 90 + steps: + - name: install sudo + run: apt update && apt install sudo + # On the github Ubuntu 20.04, sudo is not available by default + # we need it, however, to update/upgrade our packages. + - name: Update packages + run: sudo apt-get update && sudo apt-get upgrade -y + # This step is necessary to get the newest package data + - name: Download tarball + uses: actions/download-artifact@v4 + with: + name: tarballs + path: tarballs + - name: Extract tarball + run: tar xzf tarballs/*.tar.gz -C $RUNNER_TEMP + - name: update Github_env + run: export TAR_DIR="$RUNNER_TEMP/`basename tarballs/*.tar.gz .tar.gz`" && + echo TAR_DIR="$TAR_DIR" >>$GITHUB_ENV + +# build config vars + - name: less-test-option + if: github.event_name == 'pull_request' + run: export LESS_TEST_OPTION="-DT8CODE_ENABLE_LESS_TESTS=ON" + && echo LESS_TEST_OPTION="$LESS_TEST_OPTION" >> $GITHUB_ENV + - name: build config variables + run: export CONFIG_OPTIONS="${LESS_TEST_OPTION} -GNinja -DT8CODE_USE_SYSTEM_SC=OFF -DT8CODE_USE_SYSTEM_P4EST=OFF -DT8CODE_BUILD_PEDANTIC=ON -DT8CODE_ENABLE_MPI=$MPI -DCMAKE_BUILD_TYPE=$BUILD_TYPE" + && echo CONFIG_OPTIONS="$CONFIG_OPTIONS" >> $GITHUB_ENV + - name: Check vars + run: echo "[$CONFIG_DEBUG]" + - name: configure from Tarball + run: mkdir build_tar && cd build_tar && cmake $TAR_DIR $CONFIG_OPTIONS + - name: OnFailUploadLog + if: failure() + uses: actions/upload-artifact@v4 + with: + name: build_tar.log + path: build_tar/config.log + - name: build + run: cd build_tar && ninja + - name: install + run: cd build_tar && ninja install + - name: check serial + run: cd build_tar && ctest -R _serial + - name: check parallel + run: cd build_tar && ctest -R _parallel + - name: OnFailUploadLog + if: failure() + uses: actions/upload-artifact@v4 + with: + name: build_tar.log + path: build_tar/test-suite.log + + diff --git a/.github/workflows/ci_playground.yml b/.github/workflows/ci_playground.yml deleted file mode 100644 index 73039d43db..0000000000 --- a/.github/workflows/ci_playground.yml +++ /dev/null @@ -1,121 +0,0 @@ -name: CI-playground - -# This file is part of t8code. -# t8code is a C library to manage a collection (a forest) of multiple -# connected adaptive space-trees of general element types in parallel. -# -# Copyright (C) 2015 the developers -# -# t8code is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# t8code 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 General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with t8code; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - - -# The purpose of this script is for debugging and testing -# the github CI without the need to trigger the whole workflow. -# Its contents may change arbitrarily. - -on: - push: - branches: - - feature-*CI* # for testing this script, all feature branches with "CI" in their name - - workflow_dispatch: # Be able to trigger this manually on github.com - -jobs: - test_vars: - runs-on: ubuntu-20.04 - container: dlramr/t8code-ubuntu:t8-dependencies - env: - SC_DEBUG: ../sc/build_debug - P4EST_DEBUG: ../p4est/build_debug - steps: - - name: Test vars - run: echo "[$SC_DEBUG] [$P4EST_DEBUG]" - - name: New envs - run: echo NEW_VAR=blub >> $GITHUB_ENV - - name: Test var - run: echo $NEW_VAR ${{ env.NEW_VAR }} - - name: Test var for if not set - run: echo IF_VAR= >> $GITHUB_ENV - - name: print if 0 or var set - if: ${{ 0 || env.IF_VAR }} - run: echo $IF_VAR - - name: print if var set - if: ${{ env.IF_VAR }} - run: echo $IF_VAR - - name: print if 0 - if: 0 - run: echo 0 is true - - name: print var - run: echo $IF_VAR - - name: Test var for if set - run: echo IF_VAR2=1 >> $GITHUB_ENV - - name: print if var set - if: ${{ env.IF_VAR2 }} - run: echo $IF_VAR2 - - name: print if 0 or var set - if: ${{ 0 || env.IF_VAR2 }} - run: echo $IF_VAR2 - - name: print if 0 - if: 0 - run: echo 0 is true - - name: print var - run: echo $IF_VAR2 - - test_cache: - runs-on: ubuntu-20.04 - steps: - - uses: actions/checkout@v4 - with: - fetch-tags: true # required to get version tags - fetch-depth: 0 # required to get all history, especially the version tags - - name: install sudo - run: apt update && apt install sudo - # On the github Ubuntu 20.04, sudo is not available by default - # we need it, however, to update/upgrade our packages. - - name: Update packages - run: sudo apt-get update && sudo apt-get upgrade -y - # This step is necessary to get the newest package data - - name: define sc var - run: hash=`git rev-parse HEAD:sc` && echo sc_commit=$hash >> $GITHUB_ENV - - name: define p4est var - run: hash=`git rev-parse HEAD:sc` && echo sc_commit=$hash >> $GITHUB_ENV - - name: Test var - run: echo $sc_commit $p4est_commit - # Cache sc - - name: create folder var - run: echo test_path=$PWD/test_path >> $GITHUB_ENV - - name: Cache SC - id: sc_cache - uses: actions/cache@v4 - with: - path: | - sc/build_test - sc/build_test_ci/install - ${{ env.test_path }} - # increase this number to trigger new caching - key: sc-3 - - name: create build and write commit - if: steps.sc_cache.outputs.cache-hit != 'true' - run: mkdir sc/build_test - && date >> sc/build_test/commit.log - && echo $sc_commit >> sc/build_test/commit.log - && mkdir sc/build_test_ci && mkdir sc/build_test_ci/install - && date >> sc/build_test_ci/install/commit.log - && mkdir test_path - && date >> test_path/test.log - - name: print files - run: cat sc/build_test/commit.log - && cat sc/build_test_ci/install/commit.log - && cat test_path/test.log diff --git a/.github/workflows/tests_cmake_t8code_api.yml b/.github/workflows/tests_cmake_t8code_api.yml new file mode 100644 index 0000000000..d96b5d0b33 --- /dev/null +++ b/.github/workflows/tests_cmake_t8code_api.yml @@ -0,0 +1,111 @@ +name: CMake tests t8code api + + +# This file is part of t8code. +# t8code is a C library to manage a collection (a forest) of multiple +# connected adaptive space-trees of general element types in parallel. +# +# Copyright (C) 2024 the developers +# +# t8code is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# t8code 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with t8code; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +on: + workflow_call: + inputs: + MAKEFLAGS: + required: true + type: string + description: 'Make flags to use for compilation (like -j4)' + MPI: + required: true + type: string + description: 'Use MPI for compilation (ON/OFF)' + BUILD_TYPE: + required: true + type: string + description: 'Build type (Release/Debug)' + LESS_TESTS: + required: true + type: boolean + description: 'Enable less tests option for configuring' + +jobs: + t8code_cmake_tests: + timeout-minutes: 30 + runs-on: ubuntu-latest + container: dlramr/t8code-ubuntu:t8-dependencies + steps: +# +# Setup +# + - name: Download artifacts + uses: actions/download-artifact@v4 + with: + name: SC_P4EST_MPI_${{ inputs.MPI }} + - name: untar artifact + run: tar -xf artifact.tar && rm artifact.tar + - name: Update packages + run: apt-get update && apt-get upgrade -y + # This seems to be necessary because of the docker container + - name: disable ownership checks + run: git config --global --add safe.directory '*' + - name: Get input vars + run: export MAKEFLAGS="${{ inputs.MAKEFLAGS }}" + && export MPI="${{ inputs.MPI }}" + && export BUILD_TYPE="${{ inputs.BUILD_TYPE }}" + && export SC_PATH=$PWD/sc/build/$BUILD_TYPE + && export P4EST_PATH=$PWD/p4est/build/$BUILD_TYPE + && echo MAKEFLAGS="$MAKEFLAGS" >> $GITHUB_ENV + && echo MPI="$MPI" >> $GITHUB_ENV + && echo BUILD_TYPE="$BUILD_TYPE" >> $GITHUB_ENV + && echo SC_PATH="$SC_PATH" >> $GITHUB_ENV + && echo P4EST_PATH="$P4EST_PATH" >> $GITHUB_ENV +# +# T8CODE +# +# + # build config vars + - name: less-test option + if: ${{ inputs.LESS_TESTS }} + run: export LESS_TEST_OPTION="-DT8CODE_ENABLE_LESS_TESTS=ON" + && echo LESS_TEST_OPTION="$LESS_TEST_OPTION" >> $GITHUB_ENV + - name: build config variables + run: export CONFIG_OPTIONS="${LESS_TEST_OPTION} -GNinja -DT8CODE_USE_SYSTEM_SC=ON -DT8CODE_USE_SYSTEM_P4EST=ON -DT8CODE_BUILD_PEDANTIC=ON -DT8CODE_ENABLE_MPI=$MPI -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DSC_DIR=$SC_PATH/install/cmake -DP4EST_DIR=$P4EST_PATH/install/cmake" + && echo CONFIG_OPTIONS="$CONFIG_OPTIONS" >> $GITHUB_ENV + # cmake and test with fortran + - name: check fortran + run: echo "Checking fortran" + - name: echo cmake line + run: echo cmake ../ $CONFIG_OPTIONS -DT8CODE_BUILD_FORTRAN_INTERFACE=ON + - name: cmake MPI fortran debug + run: mkdir build_fortran && cd build_fortran && cmake ../ $CONFIG_OPTIONS -DT8CODE_ENABLE_FORTRAN=ON + - name: OnFailUploadLog + if: failure() + uses: actions/upload-artifact@v4 + with: + name: cmake_${{ inputs.BUILD_TYPE }}_MPI_${{ inputs.MPI }}_fortran.log + path: build_fortran/CMakeFiles/CMakeOutput.log + - name: make + run: cd build_fortran && ninja $MAKEFLAGS + - name: ninja install + run: cd build_fortran && ninja install $MAKEFLAGS + - name: ninja test + run: cd build_fortran && ninja test + - name: OnFailUploadLog + if: failure() + uses: actions/upload-artifact@v4 + with: + name: test-suite_${{ inputs.BUILD_TYPE }}_MPI_${{ inputs.MPI }}_fortran.log + path: build_fortran/Testing/Temporary/LastTest.log diff --git a/.github/workflows/tests_cmake_t8code_w_shipped_submodules.yml b/.github/workflows/tests_cmake_t8code_w_shipped_submodules.yml new file mode 100644 index 0000000000..01f83aac5b --- /dev/null +++ b/.github/workflows/tests_cmake_t8code_w_shipped_submodules.yml @@ -0,0 +1,116 @@ +name: CMake tests t8code with shipped submodules + + +# This file is part of t8code. +# t8code is a C library to manage a collection (a forest) of multiple +# connected adaptive space-trees of general element types in parallel. +# +# Copyright (C) 2024 the developers +# +# t8code is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# t8code 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with t8code; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +on: + workflow_call: + inputs: + MAKEFLAGS: + required: true + type: string + description: 'Make flags to use for compilation (like -j4)' + MPI: + required: true + type: string + description: 'Use MPI for compilation (ON/OFF)' + BUILD_TYPE: + required: true + type: string + description: 'Build type (Release/Debug)' + LESS_TESTS: + required: true + type: boolean + description: 'Enable less tests option for configuring' + +jobs: + t8code_cmake_tests: + timeout-minutes: 30 + runs-on: ubuntu-latest + container: dlramr/t8code-ubuntu:t8-dependencies + steps: +# +# Setup +# + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Update packages + run: apt-get update && apt-get upgrade -y + # This seems to be necessary because of the docker container + - name: disable ownership checks + run: git config --global --add safe.directory '*' + - name: init submodules + run: git submodule init + - name: update submodules + run: git submodule update + - name: Get input vars + run: export MAKEFLAGS="${{ inputs.MAKEFLAGS }}" + && export MPI="${{ inputs.MPI }}" + && export BUILD_TYPE="${{ inputs.BUILD_TYPE }}" + && echo MAKEFLAGS="$MAKEFLAGS" >> $GITHUB_ENV + && echo MPI="$MPI" >> $GITHUB_ENV + && echo BUILD_TYPE="$BUILD_TYPE" >> $GITHUB_ENV +# +# T8CODE +# + # build config vars + - name: less-test option + if: ${{ inputs.LESS_TESTS }} + run: export LESS_TEST_OPTION="-DT8CODE_ENABLE_LESS_TESTS=ON" + && echo LESS_TEST_OPTION="$LESS_TEST_OPTION" >> $GITHUB_ENV + - name: build config variables + run: export CONFIG_OPTIONS="${LESS_TEST_OPTION} -GNinja -DT8CODE_BUILD_PEDANTIC=ON -DT8CODE_ENABLE_MPI=$MPI -DCMAKE_BUILD_TYPE=$BUILD_TYPE" + && echo CONFIG_OPTIONS="$CONFIG_OPTIONS" >> $GITHUB_ENV + # cmake and test + - name: Printing MPI compiler info + run: mpicc --version && mpirun --version + - name: Printing GCC compiler info + run: gcc --version && g++ --version + - name: echo cmake line + run: echo cmake ../ $CONFIG_OPTIONS + - name: cmake + run: mkdir build && cd build && cmake ../ $CONFIG_OPTIONS + - name: OnFailUploadLog + if: failure() + uses: actions/upload-artifact@v4 + with: + name: cmake_w_submodules_${{ inputs.BUILD_TYPE }}_MPI_${{ inputs.MPI }}.log + path: build/CMakeFiles/CMakeOutput.log + - name: ninja + run: cd build && ninja $MAKEFLAGS + - name: ninja install + run: cd build && ninja install $MAKEFLAGS + - name: serial tests (if MPI is enabled) + run: cd build && ctest $MAKEFLAGS -R _serial + if: ${{ inputs.MPI == 'ON' }} + - name: parallel tests (if MPI is enabled) + run: cd build && ctest -R _parallel + if: ${{ inputs.MPI == 'ON' }} + - name: tests (if MPI is disabled) + run: cd build && ctest $MAKEFLAGS + if: ${{ inputs.MPI == 'OFF' }} + - name: OnFailUploadLog + if: failure() + uses: actions/upload-artifact@v4 + with: + name: test-suite_w_submodules_${{ inputs.BUILD_TYPE }}_MPI_${{ inputs.MPI }}.log + path: build/Testing/Temporary/LastTest.log diff --git a/.github/workflows/tests_cmake_testsuite.yml b/.github/workflows/tests_cmake_testsuite.yml index ba3616153c..ac20231bc5 100644 --- a/.github/workflows/tests_cmake_testsuite.yml +++ b/.github/workflows/tests_cmake_testsuite.yml @@ -114,3 +114,30 @@ jobs: BUILD_TYPE: ${{ matrix.BUILD_TYPE }} LESS_TESTS: ${{ github.event_name == 'pull_request' }} + # Run t8code linkage tests with and without MPI and in serial and debug mode + t8code_api_tests: + if: (github.event_name == 'schedule' && github.repository == 'DLR-AMR/t8code') || (github.event_name != 'schedule') + uses: ./.github/workflows/tests_cmake_t8code_api.yml + strategy: + fail-fast: false + matrix: + MPI: [ON] # For now the fortran API only supports building with MPI + BUILD_TYPE: [Debug, Release] + include: + - MAKEFLAGS: -j4 + needs: preparation + with: + MAKEFLAGS: ${{ matrix.MAKEFLAGS }} + MPI: ${{ matrix.MPI }} + BUILD_TYPE: ${{ matrix.BUILD_TYPE }} + LESS_TESTS: ${{ github.event_name == 'pull_request' }} + + # Run t8code tests with shipped submodules. This test is only for the build system, so only one config is tested. + t8code_w_shipped_submodules_tests: + if: (github.event_name == 'schedule' && github.repository == 'DLR-AMR/t8code') || (github.event_name != 'schedule') + uses: ./.github/workflows/tests_cmake_t8code_w_shipped_submodules.yml + with: + MAKEFLAGS: -j4 + MPI: ON + BUILD_TYPE: Debug + LESS_TESTS: ${{ github.event_name == 'pull_request' }} diff --git a/.gitignore b/.gitignore index 03984a386e..da972a4f2d 100644 --- a/.gitignore +++ b/.gitignore @@ -22,6 +22,9 @@ config.status Doxyfile doxygen/ +CMakeCache.txt +CMakeFiles/ + src/stamp-h1 src/t8_config.h src/pre_config.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 90dd8cdcb2..d04c785c09 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,7 +4,7 @@ include(cmake/GitProjectVersion.cmake) project( T8CODE DESCRIPTION "Parallel algorithms and data structures for tree-based AMR with arbitrary element shapes." - LANGUAGES C CXX + LANGUAGES C CXX Fortran VERSION "${T8CODE_VERSION_MAJOR}.${T8CODE_VERSION_MINOR}.${T8CODE_VERSION_PATCH}" ) include( CTest ) @@ -15,6 +15,7 @@ option( T8CODE_BUILD_TESTS "Build t8code's automated tests" ON ) option( T8CODE_BUILD_TUTORIALS "Build t8code's tutorials" ON ) option( T8CODE_BUILD_EXAMPLES "Build t8code's examples" ON ) option( T8CODE_BUILD_BENCHMARKS "Build t8code's benchmarks" ON ) +option( T8CODE_BUILD_FORTRAN_INTERFACE "Build t8code's Fortran interface" OFF ) option( T8CODE_ENABLE_LESS_TESTS "Tests not as thoroughly to speed up the test suite. Tests the same functionality. (WARNING: Use with care.)" OFF ) option( T8CODE_ENABLE_MPI "Enable t8code's features which rely on MPI" ON ) @@ -56,7 +57,12 @@ set( CMAKE_CXX_EXTENSIONS OFF ) set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH}) if( T8CODE_ENABLE_MPI ) - find_package( MPI COMPONENTS C REQUIRED ) + if( T8CODE_BUILD_FORTRAN_INTERFACE ) + find_package( MPI COMPONENTS C Fortran REQUIRED ) + else() + find_package( MPI COMPONENTS C REQUIRED ) + endif() + if( NOT MPIEXEC_EXECUTABLE ) message( FATAL_ERROR "MPIEXEC was not found" ) endif() @@ -136,3 +142,14 @@ endif() if ( T8CODE_BUILD_DOCUMENTATION ) add_subdirectory( ${CMAKE_CURRENT_LIST_DIR}/doc ) endif() + +if( T8CODE_BUILD_FORTRAN_INTERFACE ) + enable_language( Fortran ) + add_subdirectory( ${CMAKE_CURRENT_LIST_DIR}/api/t8_fortran_interface ) + + if( NOT T8CODE_ENABLE_MPI ) + message( FATAL_ERROR "Fortran API only available when MPI is enabled." ) + endif() +endif() + +include (cmake/CPackConfig.cmake) diff --git a/Makefile.am b/Makefile.am index f0872791e7..e4c53198bb 100644 --- a/Makefile.am +++ b/Makefile.am @@ -47,6 +47,7 @@ dist_t8aclocal_DATA = config/t8_include.m4 \ config/t8_netcdf.m4 \ config/t8_vtk.m4 \ config/t8_occ.m4 \ + config/t8_fortran.m4 \ config/t8_mpi.m4 diff --git a/README.md b/README.md index 3e5b00e21e..b71e4ba413 100644 --- a/README.md +++ b/README.md @@ -68,7 +68,7 @@ We provide a short guide to install t8code in our Wiki [Installation guide](http ### Getting started To get familiar with t8code and its algorithms and data structures we recommend executing the tutorial examples in `tutorials` - and read the corresponding Wiki pages starting with [Step 0 - Helloworld](https://github.com/holke/t8code/wiki/Step-0---Hello-World). + and read the corresponding Wiki pages starting with [Step 0 - Helloworld](https://github.com/DLR-AMR/t8code/wiki/Step-0---Hello-World). A sophisticated example of a complete numerical simulation is our finite volume solver of the advection equation in `example/advection`. diff --git a/api/Makefile.am b/api/Makefile.am index 974f210370..b27d462ba9 100644 --- a/api/Makefile.am +++ b/api/Makefile.am @@ -10,8 +10,24 @@ libt8_installed_headers_fortran_interface = \ dist_fortraninterfaceinclude_HEADERS = $(libt8_installed_headers_fortran_interface) +# Save the module sources in a different variable for later use +t8_fortran_module_sources = api/t8_fortran_interface/t8_fortran_interface_mod.f90 + +# Add the Fortran sources to the lib +libt8_compiled_sources += $(t8_fortran_module_sources) + +AM_FCFLAGS = libt8_compiled_sources += \ api/t8_fortran_interface/t8_fortran_interface.c -AM_CPPFLAGS += -I@top_srcdir@/api +AM_CPPFLAGS += -I@top_srcdir@/api/t8_fortran_interface +MODSOURCES = $(t8_fortran_module_sources) + +src_libt8_la_FCFLAGS = $(AM_FCFLAGS) +src_libt8_la_FFLAGS = $(FFLAGS) + +# Include the Fortran specific variables and rules +include api/t8_fortran_interface/t8_fortran_specific.mk + +# T8_ENABLE_FORTRAN endif diff --git a/api/t8_fortran_interface/CMakeLists.txt b/api/t8_fortran_interface/CMakeLists.txt new file mode 100644 index 0000000000..3072277cd3 --- /dev/null +++ b/api/t8_fortran_interface/CMakeLists.txt @@ -0,0 +1,18 @@ +# Link in C-Fortran interface file into libt8. +target_sources( T8 PRIVATE t8_fortran_interface.c ) +target_sources( T8 PRIVATE t8_fortran_interface_mod.f90 ) + +# Add this directory to header search path. +target_include_directories( T8 PRIVATE ${CMAKE_CURRENT_LIST_DIR} ) + +# Install header files. +install( + FILES ${CMAKE_CURRENT_LIST_DIR}/t8_fortran_interface.h + DESTINATION ${CMAKE_INSTALL_PREFIX}/include/t8_fortran_interface +) + +# Install module files. +install( + FILES ${CMAKE_BINARY_DIR}/src/t8_fortran_interface_mod.mod + DESTINATION ${CMAKE_INSTALL_PREFIX}/include/t8_fortran_interface +) diff --git a/api/t8_fortran_interface/t8_fortran_interface.c b/api/t8_fortran_interface/t8_fortran_interface.c index 92d0ab5a8e..487ca829fe 100644 --- a/api/t8_fortran_interface/t8_fortran_interface.c +++ b/api/t8_fortran_interface/t8_fortran_interface.c @@ -20,7 +20,7 @@ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#include +#include #include #include #include diff --git a/api/t8_fortran_interface/t8_fortran_interface.h b/api/t8_fortran_interface/t8_fortran_interface.h index 3424a34d61..195205f280 100644 --- a/api/t8_fortran_interface/t8_fortran_interface.h +++ b/api/t8_fortran_interface/t8_fortran_interface.h @@ -35,6 +35,7 @@ #include #include #include +#include typedef int (*t8_fortran_adapt_coordinate_callback) (double x, double y, double z, int is_family); diff --git a/api/t8_fortran_interface/t8_fortran_interface_mod.f90 b/api/t8_fortran_interface/t8_fortran_interface_mod.f90 new file mode 100644 index 0000000000..5001bc70cf --- /dev/null +++ b/api/t8_fortran_interface/t8_fortran_interface_mod.f90 @@ -0,0 +1,327 @@ +!! This file is part of t8code. +!! t8code is a C library to manage a collection (a forest) of multiple +!! connected adaptive space-trees of general element classes in parallel. +!! +!! Copyright (C) 2024 the developers +!! +!! t8code is free software; you can redistribute it and/or modify +!! it under the terms of the GNU General Public License as published by +!! the Free Software Foundation; either version 2 of the License, or +!! (at your option) any later version. +!! +!! t8code 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 General Public License for more details. +!! +!! You should have received a copy of the GNU General Public License +!! along with t8code; if not, write to the Free Software Foundation, Inc., +!! 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +module t8_fortran_interface_mod + + use, intrinsic :: ISO_C_BINDING + + + !!! Interface for t8_fortran_MPI_Comm_new + !!! Given a fortran MPI Communicator, converts it into C and + !!! returns a pointer to the C MPI communicator. + !!! This function allocates memory that needs to be freed with + !!! t8_fortran_mpi_comm_delete_f + !!! + !!! Code modified from: https://stackoverflow.com/questions/42530620/how-to-pass-mpi-communicator-handle-from-fortran-to-c-using-iso-c-binding + INTERFACE + type (C_PTR) FUNCTION t8_fortran_mpi_comm_new_f (FCOMM) & + BIND(C, NAME='t8_fortran_MPI_Comm_new') + use, intrinsic :: ISO_C_BINDING, only: c_int, c_ptr + IMPLICIT NONE + INTEGER (C_INT), VALUE :: Fcomm + END FUNCTION t8_fortran_mpi_comm_new_f + END INTERFACE + + !!! Free memory of a C MPI communicator pointer that was + !!! allocated using t8_fortran_mpi_comm_new_f + INTERFACE + subroutine t8_fortran_mpi_comm_delete_f (Ccomm) & + BIND(C, NAME='t8_fortran_MPI_Comm_delete') + use, intrinsic :: ISO_C_BINDING, only: c_ptr + IMPLICIT NONE + type (c_ptr), value :: Ccomm + END subroutine t8_fortran_mpi_comm_delete_f + END INTERFACE + + !!! Initialize sc and t8code with a given C MPI Communicator + Interface + subroutine t8_fortran_init_all_f (Ccomm) & + BIND(C, NAME='t8_fortran_init_all') + use, intrinsic :: ISO_C_BINDING, only: c_ptr + IMPLICIT NONE + type (c_ptr), value :: Ccomm + END subroutine t8_fortran_init_all_f + end Interface + + !!! Initialize sc and t8code with a given C MPI Communicator + Interface + subroutine t8_fortran_init_all_noMPI_f () & + BIND(C, NAME='t8_fortran_init_all_noMPI') + END subroutine t8_fortran_init_all_noMPI_f + end Interface + + Interface + type (c_ptr) function t8_cmesh_new_periodic_tri_f (Ccomm) & + bind (c, name = 't8_cmesh_new_periodic_tri_wrap') + use, intrinsic :: ISO_C_BINDING, only: c_ptr + IMPLICIT NONE + type (c_ptr), value :: Ccomm + end function t8_cmesh_new_periodic_tri_f + end Interface + + Interface + integer (c_int) function t8_cmesh_vtk_write_file_f (cmesh, fileprefix, scale) & + bind (c, name = 't8_cmesh_vtk_write_file') + use, intrinsic :: ISO_C_BINDING, only: c_ptr, c_int, c_char, c_double + IMPLICIT NONE + type (c_ptr), value :: cmesh + character (c_char) :: fileprefix + real (c_double), value :: scale + end function t8_cmesh_vtk_write_file_f + end Interface + + Interface + subroutine t8_cmesh_destroy_f (cmesh) & + bind (c, name = 't8_cmesh_destroy') + use, intrinsic :: ISO_C_BINDING, only: c_ptr + IMPLICIT NONE + type (c_ptr) :: cmesh + end subroutine t8_cmesh_destroy_f + end Interface + + Interface + subroutine t8_fortran_cmesh_init_f (cmesh) & + bind (c, name = 't8_cmesh_init') + use, intrinsic :: ISO_C_BINDING, only: c_ptr + IMPLICIT NONE + type (c_ptr) :: cmesh + end subroutine t8_fortran_cmesh_init_f + end Interface + + Interface + type (c_ptr) function t8_fortran_geometry_linear_new_f (dimension) & + bind (c, name = 't8_geometry_linear_new') + use, intrinsic :: ISO_C_BINDING, only: c_int, c_ptr + IMPLICIT NONE + integer (c_int), value :: dimension + end function t8_fortran_geometry_linear_new_f + end Interface + + Interface + subroutine t8_fortran_cmesh_register_geometry_f (cmesh, geometry) & + bind (c, name = 't8_cmesh_register_geometry') + use, intrinsic :: ISO_C_BINDING, only: c_ptr + IMPLICIT NONE + type (c_ptr), value :: cmesh + type (c_ptr), value :: geometry + end subroutine t8_fortran_cmesh_register_geometry_f + end Interface + + Interface + subroutine t8_fortran_cmesh_set_tree_class_f (cmesh, gtree_id, tree_class) & + bind (c, name = 't8_cmesh_set_tree_class') + use, intrinsic :: ISO_C_BINDING, only: c_ptr, c_int64_t, c_int + IMPLICIT NONE + type (c_ptr), value :: cmesh + integer (c_int64_t), value :: gtree_id + integer (c_int), value :: tree_class + end subroutine t8_fortran_cmesh_set_tree_class_f + end Interface + + Interface + subroutine t8_fortran_cmesh_set_tree_vertices_f (cmesh, ltree_id, vertices, num_vertices) & + bind (c, name = 't8_cmesh_set_tree_vertices') + use, intrinsic :: ISO_C_BINDING, only: c_ptr, c_int, c_int64_t + IMPLICIT NONE + type (c_ptr), value :: cmesh + integer (c_int64_t), value :: ltree_id + type(c_ptr),value :: vertices + integer (c_int), value :: num_vertices + end subroutine t8_fortran_cmesh_set_tree_vertices_f + end Interface + + Interface + subroutine t8_fortran_cmesh_set_join_f (cmesh, gtree1, gtree2, face1, face2, orientation) & + bind (c, name = 't8_cmesh_set_join') + use, intrinsic :: ISO_C_BINDING, only: c_ptr, c_int, c_int64_t + IMPLICIT NONE + type (c_ptr), value :: cmesh + integer (c_int64_t), value :: gtree1 + integer (c_int64_t), value :: gtree2 + integer (c_int), value :: face1 + integer (c_int), value :: face2 + integer (c_int), value :: orientation + end subroutine t8_fortran_cmesh_set_join_f + end Interface + + Interface + subroutine t8_fortran_cmesh_set_join_by_vertices_noConn_f (cmesh, ntrees, eclasses, vertices, do_both_directions) & + bind (c, name = 't8_fortran_cmesh_set_join_by_vertices_noConn') + use, intrinsic :: ISO_C_BINDING, only: c_ptr, c_int + IMPLICIT NONE + type (c_ptr), value :: cmesh + integer (c_int), value :: ntrees + type (c_ptr), value :: eclasses + type (c_ptr), value :: vertices + integer (c_int), value :: do_both_directions + end subroutine t8_fortran_cmesh_set_join_by_vertices_noConn_f + end Interface + + Interface + subroutine t8_fortran_cmesh_commit_f (cmesh, Ccom) & + bind (c, name = 't8_fortran_cmesh_commit') + use, intrinsic :: ISO_C_BINDING, only: c_ptr + IMPLICIT NONE + type (c_ptr), value :: cmesh + type (c_ptr), value :: Ccom + end subroutine t8_fortran_cmesh_commit_f + end Interface + + Interface + type (c_ptr) function t8_forest_new_uniform_default_f (cmesh, level, do_face_ghost, Ccomm) & + bind (c, name = 't8_forest_new_uniform_default') + use, intrinsic :: ISO_C_BINDING, only: c_ptr, c_int + IMPLICIT NONE + type (c_ptr), value :: cmesh + integer (c_int), value :: level + integer (c_int), value :: do_face_ghost + type (c_ptr), value :: Ccomm + end function t8_forest_new_uniform_default_f + end Interface + + + Interface + subroutine t8_forest_unref_f (forest) & + bind (c, name = 't8_forest_unref') + use, intrinsic :: ISO_C_BINDING, only: c_ptr + IMPLICIT NONE + type (c_ptr) :: forest + end subroutine t8_forest_unref_f + end Interface + + + Interface + integer (c_int) function t8_forest_write_vtk_f (forest, fileprefix) & + bind (c, name = 't8_forest_write_vtk') + use, intrinsic :: ISO_C_BINDING, only: c_ptr, c_int, c_char, c_double + IMPLICIT NONE + type (c_ptr), value :: forest + character (c_char) :: fileprefix + end function t8_forest_write_vtk_f + end Interface + + Interface + subroutine t8_forest_iterate_replace_f (forest_new, forest_old, replace_fn) & + bind (c, name = 't8_forest_iterate_replace') + use, intrinsic :: ISO_C_BINDING, only: c_ptr + IMPLICIT NONE + type (c_ptr), value :: forest_new + type (c_ptr), value :: forest_old + type (c_ptr), value :: replace_fn + end subroutine t8_forest_iterate_replace_f + end Interface + + Interface + integer (c_int) function t8_forest_get_local_num_elements (forest) & + bind (c, name = 't8_forest_get_local_num_elements') + use, intrinsic :: ISO_C_BINDING, only: c_ptr, c_int + IMPLICIT NONE + type (c_ptr), value :: forest + end function t8_forest_get_local_num_elements + end Interface + + Interface + integer (c_int) function t8_forest_get_global_num_elements (forest) & + bind (c, name = 't8_forest_get_global_num_elements') + use, intrinsic :: ISO_C_BINDING, only: c_ptr, c_int + IMPLICIT NONE + type (c_ptr), value :: forest + end function t8_forest_get_global_num_elements + end Interface + + Interface + integer (c_int) function t8_forest_get_num_local_trees (forest) & + bind (c, name = 't8_forest_get_num_local_trees') + use, intrinsic :: ISO_C_BINDING, only: c_ptr, c_int + IMPLICIT NONE + type (c_ptr), value :: forest + end function t8_forest_get_num_local_trees + end Interface + + Interface + integer (c_int) function t8_forest_get_tree_num_elements (forest, ltreeid) & + bind (c, name = 't8_forest_get_tree_num_elements') + use, intrinsic :: ISO_C_BINDING, only: c_ptr, c_int + IMPLICIT NONE + type (c_ptr), value :: forest + integer (c_int), value :: ltreeid + end function t8_forest_get_tree_num_elements + end Interface + + Interface + type (c_ptr) function t8_forest_get_element_in_tree (forest, ltreeid, leid_in_tree) & + bind (c, name = 't8_forest_get_element_in_tree') + use, intrinsic :: ISO_C_BINDING, only: c_ptr, c_int + IMPLICIT NONE + type (c_ptr), value :: forest + integer (c_int), value :: ltreeid, leid_in_tree + end function t8_forest_get_element_in_tree + end Interface + + Interface + subroutine t8_forest_element_from_ref_coords (forest, ltreeid, element, ref_coords, num_coords, coords_out) & + bind (c, name = 't8_forest_element_from_ref_coords') + use, intrinsic :: ISO_C_BINDING, only: c_ptr, c_int, c_double + IMPLICIT NONE + type (c_ptr), value :: forest, element + integer (c_int), value :: ltreeid, num_coords + real (c_double), dimension(3) :: ref_coords, coords_out + end subroutine t8_forest_element_from_ref_coords + end Interface + + Interface + subroutine t8_global_productionf_noargs_f (string) & + bind (c, name = 't8_global_productionf_noargs') + use, intrinsic :: ISO_C_BINDING, only: c_char + IMPLICIT NONE + character (c_char) :: string + end subroutine t8_global_productionf_noargs_f + end Interface + + Interface + subroutine t8_fortran_finalize_f () & + bind (c, name = 't8_fortran_finalize') + IMPLICIT NONE + end subroutine t8_fortran_finalize_f + end Interface + + Interface + type (c_ptr) function t8_fortran_adapt_by_coordinates_f (forest, recursive, callback) & + bind (c, name = 't8_fortran_adapt_by_coordinates') + use, intrinsic :: ISO_C_BINDING, only : c_ptr, c_int + IMPLICIT NONE + type (c_ptr), value :: forest + integer (c_int), value :: recursive + type (c_ptr), value :: callback + end function t8_fortran_adapt_by_coordinates_f + end Interface + + Interface + subroutine t8_fortran_element_volume_f (forest, ltreeid, element) & + bind (c, name = 't8_forest_element_volume') + use, intrinsic :: ISO_C_BINDING, only: c_ptr, c_int + IMPLICIT NONE + type (c_ptr), value :: forest + integer (c_int), value :: ltreeid + type (c_ptr), value :: element + end subroutine t8_fortran_element_volume_f + end Interface + +End module t8_fortran_interface_mod diff --git a/api/t8_fortran_interface/t8_fortran_specific.mk b/api/t8_fortran_interface/t8_fortran_specific.mk new file mode 100644 index 0000000000..3bde84337f --- /dev/null +++ b/api/t8_fortran_interface/t8_fortran_specific.mk @@ -0,0 +1,47 @@ +if T8_ENABLE_FORTRAN +# Clean up modules files in the root directory (if no module directory has been specified) +CLEANFILES += *.$(FC_MODEXT) + +# Get the supplied FCFLAGS +AM_FCFLAGS += @FCFLAGS@ + +# Define a variable holding the module directory (for a rule below) +t8_current_moddir = + +if T8_WITH_MODDIR +# Updates for the module output and include path (if a separate module directory has been specified) +AM_FCFLAGS += $(FC_MODOUT)@T8_FORTRAN_MODULE_DIR@ $(FC_MODINC)@T8_FORTRAN_MODULE_DIR@ +AM_CPPFLAGS += -I@T8_FORTRAN_MODULE_DIR@ + +# Clean the module files in this directory +CLEANFILES += @T8_FORTRAN_MODULE_DIR@/*.$(FC_MODEXT) + +# Add the creation of the module directory as an order only prerequisite to the Fortran module files +$(MODSOURCES): %.f90 : | create-moddir + +# Rule to create the module directory +create-moddir: + @$(MKDIR_P) @T8_FORTRAN_MODULE_DIR@ + +# Save the module directory +t8_current_moddir += @T8_FORTRAN_MODULE_DIR@/ + +# End if T8_WITH_MODDIR +endif + +# If the install target is made, we will copy the module files into the include directory (after the installation of the header files) +install-data-hook: + @cp -fp $(t8_current_moddir)*.$(FC_MODEXT) $(includedir)/t8_fortran_interface + +# Define dependencies of the Fortran modules (in case they depend on other modules) +# This needs to be done in order to ensure the correct build process in any case + +# Define dependencies for all Fortran programs of the Fortran modules +# This needs to be done in order to ensure the correct build process in any case +# ... + +# TODO: Implement t8_fortran_test depends on the modules: t8_fortran_interface +#example/Fortran/t8_fortran_test.o : api/t8_fortran_interface/t8_fortran_interface.o + +# end if T8_ENABLE_FORTRAN +endif diff --git a/cmake/CPackConfig.cmake b/cmake/CPackConfig.cmake new file mode 100644 index 0000000000..0d87a38539 --- /dev/null +++ b/cmake/CPackConfig.cmake @@ -0,0 +1,51 @@ +set(CPACK_PACKAGE_VENDOR "DLR-SC AMR") +set(CPACK_PACKAGE_NAME "T8CODE") +set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Parallel algorithms and data structures for tree-based AMR with arbitrary element shapes.") +set(CPACK_PACKAGE_VERSION_MAJOR ${T8CODE_VERSION_MAJOR}) +set(CPACK_PACKAGE_VERSION_MINOR ${T8CODE_VERSION_MINOR}) +set(CPACK_PACKAGE_VERSION_PATCH ${T8CODE_VERSION_PATCH}) +set(CPACK_RESOURCE_FILE_README "${CMAKE_CURRENT_SOURCE_DIR}/README.md") +set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/COPYING") +set(CPACK_PACKAGE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/package) +set(CPACK_PACKAGE_ICON ${CMAKE_CURRENT_SOURCE_DIR}/t8code_logo.png) + +# Define a variable for the version file +set(VERSION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/version.txt") + + +# Custom command to generate the version file +add_custom_command( + OUTPUT ${VERSION_FILE} + COMMAND ${CMAKE_COMMAND} -E echo "Version ${T8CODE_VERSION_MAJOR}.${T8CODE_VERSION_MINOR}.${T8CODE_VERSION_PATCH}" > ${VERSION_FILE} + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt # Change as needed + ) + +# Create a custom target to ensure the version file is generated +add_custom_target(GenerateVersionFile ALL DEPENDS ${VERSION_FILE}) + +set(CPACK_SOURCE_GENERATOR "TGZ;ZIP") +set(CPACK_SOURCE_INCLUDE_FILES ${VERSION_FILE}) +set(CPACK_SOURCE_IGNORE_FILES .git/ .github/ .vscode/ _CPack_Packages/ +.gitmodules .gitignore +${PROJECT_BINARY_DIR}/ +Makefile.in +aclocal.m4 +autom4te.cache/ +build/ +bin/ +configure +DartConfiguration.tcl +CMakeCache.txt +build/ +build-aux/ +configure +config.log +compile_commands.json +) + +set(CPACK_PACKAGE_NAME "T8CODE") +set(CPACK_VERBATIM_VARIABLES TRUE) + + +include(CPack) + diff --git a/cmake/FindOpenCASCADE.cmake b/cmake/FindOpenCASCADE.cmake index 0e21bc0b7e..6eb5c10c22 100644 --- a/cmake/FindOpenCASCADE.cmake +++ b/cmake/FindOpenCASCADE.cmake @@ -1,4 +1,4 @@ -# taken and adapted from the heekscad project: https://github.com/Heeks +# Taken and adapted from the heekscad project: https://github.com/Heeks # HeeksCAD is covered by the new BSD license @@ -34,25 +34,25 @@ IF( NOT OpenCASCADE_FOUND ) ENDIF( CMAKE_SIZEOF_VOID_P EQUAL 4 ) IF(UNIX) - set( _incsearchpath /usr/include/opencascade /usr/include/ /opt/occ/inc ${CASROOT}/inc ${CASROOT}/include/) - set( _libsearchpath /usr/lib64 /usr/lib /opt/occ/lib ${CASROOT}/lib64 ${CASROOT}/lib ) + set( _incsearchpath /usr/include/opencascade;/usr/include/;/opt/occ/inc;${CASROOT}/inc;${CASROOT}/include/ ) + set( _libsearchpath /usr/lib64;/usr/lib;/opt/occ/lib;${CASROOT}/lib64;${CASROOT}/lib ) ELSE(UNIX) IF (WIN32) - set( _incsearchpath ${CASROOT}\\inc ${CASROOT}\\include) + set( _incsearchpath ${CASROOT}\\inc;${CASROOT}\\include) set( _testdllname TKernel.dll ) - set( _libsearchpath ${CASROOT}\\win32\\lib ${CASROOT}\\win${BITS}\\lib ${CASROOT}\\win${BITS}\\vc9\\lib ${CASROOT}\\win${BITS}\\vc10\\lib ${CASROOT}\\win${BITS}\\vc14\\lib) - set( _dllsearchpath ${CASROOT}\\win32\\bin ${CASROOT}\\win${BITS}\\bin ${CASROOT}\\win${BITS}\\vc9\\bin ${CASROOT}\\win${BITS}\\vc10\\bin ${CASROOT}\\win${BITS}\\vc14\\bin) + set( _libsearchpath ${CASROOT}\\win32\\lib;${CASROOT}\\win${BITS}\\lib;${CASROOT}\\win${BITS}\\vc9\\lib;${CASROOT}\\win${BITS}\\vc10\\lib;${CASROOT}\\win${BITS}\\vc14\\lib) + set( _dllsearchpath ${CASROOT}\\win32\\bin;${CASROOT}\\win${BITS}\\bin;${CASROOT}\\win${BITS}\\vc9\\bin;${CASROOT}\\win${BITS}\\vc10\\bin;${CASROOT}\\win${BITS}\\vc14\\bin) ELSE(WIN32) message( FATAL_ERROR "Unknown system! Exiting." ) ENDIF (WIN32) ENDIF (UNIX) #find the include dir by looking for Standard_Real.hxx - FIND_PATH( OpenCASCADE_INCLUDE_DIR Standard_Real.hxx PATH_SUFFIXES oce PATHS ${_incsearchpath} DOC "Path to OCC includes" ) - IF( OpenCASCADE_INCLUDE_DIR STREQUAL Standard_Real.hxx-NOTFOUND ) + FIND_PATH( OpenCASCADE_INCLUDE_DIR Standard_Real.hxx PATH_SUFFIXES oce PATHS ${_incsearchpath} DOC "Path to OCC includes" ) + IF( OpenCASCADE_INCLUDE_DIR MATCHES "NOTFOUND" ) SET( OpenCASCADE_FOUND FALSE CACHE BOOL FORCE ) - MESSAGE( FATAL_ERROR "Cannot find OCC include dir. Install opencascade or set CASROOT or create a symlink /opt/occ/inc pointing to the correct directory." ) - ENDIF( OpenCASCADE_INCLUDE_DIR STREQUAL Standard_Real.hxx-NOTFOUND ) + MESSAGE( FATAL_ERROR "Cannot find OCC include dir. Install opencascade or add the include directory to INCLUDE or set CASROOT or create a symlink /opt/occ/inc pointing to the correct directory." ) + ENDIF( OpenCASCADE_INCLUDE_DIR MATCHES "NOTFOUND" ) # Find one lib and save its directory to OpenCASCADE_LINK_DIRECTORY. Because # OCC has so many libs, there is increased risk of a name collision. @@ -60,21 +60,21 @@ IF( NOT OpenCASCADE_FOUND ) SET( OpenCASCADE_LINK_DIRECTORY "OpenCASCADE_LINK_DIRECTORY-NOTFOUND" CACHE PATH "Path to OCC libs" ) FIND_LIBRARY(TKernel_OCCLIB NAMES TKernel PATHS ${_libsearchpath} ${OpenCASCADE_LINK_DIRECTORY}) MARK_AS_ADVANCED( TKernel_OCCLIB ) - IF(TKernel_OCCLIB STREQUAL TKernel_OCCLIB-NOTFOUND) + IF(TKernel_OCCLIB MATCHES "NOTFOUND") SET( OpenCASCADE_FOUND FALSE CACHE BOOL FORCE ) - MESSAGE( FATAL_ERROR "Cannot find OCC lib dir. Install opencascade or set CASROOT or create a symlink /opt/occ/lib pointing to the dir where the OCC libs are." ) - ELSE(TKernel_OCCLIB STREQUAL TKernel_OCCLIB-NOTFOUND) + MESSAGE( FATAL_ERROR "Cannot find OCC lib dir. Install opencascade or add the lib directory to LIB or set CASROOT or create a symlink /opt/occ/lib pointing to the dir where the OCC libs are." ) + ELSE(TKernel_OCCLIB MATCHES "NOTFOUND") GET_FILENAME_COMPONENT(TMPDIR ${TKernel_OCCLIB} PATH) SET( OpenCASCADE_LINK_DIRECTORY ${TMPDIR} CACHE PATH "Path to OCC libs" FORCE) - ENDIF(TKernel_OCCLIB STREQUAL TKernel_OCCLIB-NOTFOUND) + ENDIF(TKernel_OCCLIB MATCHES "NOTFOUND") # check dll path if(WIN32) FIND_PATH( OpenCASCADE_DLL_DIRECTORY ${_testdllname} PATH ${_dllsearchpath} DOC "Path to OCC dlls" NO_SYSTEM_ENVIRONMENT_PATH) - IF( OpenCASCADE_DLL_DIRECTORY STREQUAL OpenCASCADE_DLL_DIRECTORY-NOTFOUND ) + IF( OpenCASCADE_DLL_DIRECTORY MATCHES "NOTFOUND" ) SET( OpenCASCADE_FOUND FALSE CACHE BOOL FORCE ) MESSAGE( FATAL_ERROR "Cannot find OCC DLL dir. Install opencascade or set CASROOT to the correct directory." ) - ENDIF( OpenCASCADE_DLL_DIRECTORY STREQUAL OpenCASCADE_DLL_DIRECTORY-NOTFOUND ) + ENDIF( OpenCASCADE_DLL_DIRECTORY MATCHES "NOTFOUND" ) endif(WIN32) # everything was found diff --git a/cmake/GitProjectVersion.cmake b/cmake/GitProjectVersion.cmake index c92ce991da..1e6f227d28 100644 --- a/cmake/GitProjectVersion.cmake +++ b/cmake/GitProjectVersion.cmake @@ -1,32 +1,54 @@ find_package( Git REQUIRED ) -# See `scr/t8_version.h` for the documentation of following definitions. +if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/.git") + # See `scr/t8_version.h` for the documentation of following definitions. + + execute_process( COMMAND ${GIT_EXECUTABLE} describe --tags --dirty + COMMAND cut -c 2- + WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} + OUTPUT_VARIABLE T8CODE_VERSION_RAW + OUTPUT_STRIP_TRAILING_WHITESPACE ) + execute_process( COMMAND echo ${T8CODE_VERSION_RAW} + COMMAND cut -d- -f1 + OUTPUT_VARIABLE T8CODE_VERSION_NUMBERS + OUTPUT_STRIP_TRAILING_WHITESPACE ) + execute_process( COMMAND echo ${T8CODE_VERSION_RAW} + COMMAND cut -d- -f2- + OUTPUT_VARIABLE T8CODE_VERSION_POINT + OUTPUT_STRIP_TRAILING_WHITESPACE ) + + # To reuse the version in other CMakeLists. + else() + if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/version.txt") + file(READ "${CMAKE_CURRENT_SOURCE_DIR}/version.txt" VERSION_CONTENT) + # Extract the version number + string(REGEX MATCH "Version ([0-9])\.([0-9]+)\.([0-9]+)" VERSION_MATCH "${VERSION_CONTENT}" ) + if (VERSION_MATCH) + # The version number will be in ${CMAKE_MATCH_1} + set(T8CODE_VERSION_NUMBERS "${CMAKE_MATCH_1}.${CMAKE_MATCH_2}.${CMAKE_MATCH_3}") + set(T8CODE_VERSION_RAW "${CMAKE_MATCH_1}.${CMAKE_MATCH_2}.${CMAKE_MATCH_3}") + message(STATUS "Extracted Version: ${T8CODE_VERSION_NUMBERS}") + else() + message(WARNING "Version number not found in version.txt") + endif() + else() + message(WARNING "Version information not found") + endif() +endif() + -execute_process( COMMAND ${GIT_EXECUTABLE} describe --tags --dirty - COMMAND cut -c 2- - WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} - OUTPUT_VARIABLE T8CODE_VERSION_RAW - OUTPUT_STRIP_TRAILING_WHITESPACE ) -execute_process( COMMAND echo ${T8CODE_VERSION_RAW} - COMMAND cut -d- -f1 - OUTPUT_VARIABLE T8CODE_VERSION_NUMBERS - OUTPUT_STRIP_TRAILING_WHITESPACE ) -execute_process( COMMAND echo ${T8CODE_VERSION_RAW} - COMMAND cut -d- -f2- - OUTPUT_VARIABLE T8CODE_VERSION_POINT - OUTPUT_STRIP_TRAILING_WHITESPACE ) execute_process( COMMAND echo ${T8CODE_VERSION_NUMBERS} - COMMAND cut -d. -f1 - OUTPUT_VARIABLE T8CODE_VERSION_MAJOR - OUTPUT_STRIP_TRAILING_WHITESPACE ) + COMMAND cut -d. -f1 + OUTPUT_VARIABLE T8CODE_VERSION_MAJOR + OUTPUT_STRIP_TRAILING_WHITESPACE ) execute_process( COMMAND echo ${T8CODE_VERSION_NUMBERS} - COMMAND cut -d. -f2 - OUTPUT_VARIABLE T8CODE_VERSION_MINOR - OUTPUT_STRIP_TRAILING_WHITESPACE ) + COMMAND cut -d. -f2 + OUTPUT_VARIABLE T8CODE_VERSION_MINOR + OUTPUT_STRIP_TRAILING_WHITESPACE ) execute_process( COMMAND echo ${T8CODE_VERSION_NUMBERS} - COMMAND cut -d. -f3 - OUTPUT_VARIABLE T8CODE_VERSION_PATCH - OUTPUT_STRIP_TRAILING_WHITESPACE ) - -# To reuse the version in other CMakeLists. + COMMAND cut -d. -f3 + OUTPUT_VARIABLE T8CODE_VERSION_PATCH + OUTPUT_STRIP_TRAILING_WHITESPACE ) set(T8_VERSION ${T8CODE_VERSION_NUMBERS} CACHE INTERNAL "") + + diff --git a/config/t8_fortran.m4 b/config/t8_fortran.m4 new file mode 100644 index 0000000000..b1e452376e --- /dev/null +++ b/config/t8_fortran.m4 @@ -0,0 +1,34 @@ +dnl T8_CHECK_FORTRAN +dnl This functions checks some properties of Fortran modules and +dnl whether specific directory for the Fortran module files has been specified or not. +dnl +dnl A directory may be specified by the option --with-moddir= +dnl This option is only of relevance if the option --enable-fortran has been chosen, +dnl since only in this case Fortran codes will be compiled +dnl +AC_DEFUN([T8_CHECK_FORTRAN], [ + +dnl Check if a directory has been specified which will hold the module files +T8_ARG_WITH([moddir], + [if Fortran modules will be built, this option specifies an explicit directory which should hold the module files (use --with-moddir=)], + [MODDIR]) + +dnl If Fortran is enabled +if test "x$T8_ENABLE_FORTRAN" != xno ; then + +dnl Check the properties of Fortran modules (after the Fortran Compiler has been found by MPI_ENGAGE) +AC_FC_MODULE_EXTENSION +AC_FC_MODULE_FLAG +AC_FC_MODULE_OUTPUT_FLAG + +if test "x$T8_WITH_MODDIR" = xyes ; then + dnl The option is given without a directory + AC_MSG_ERROR([missing directory path for the module directory]) +elif test "x$T8_WITH_MODDIR" != xno ; then + AC_MSG_NOTICE([we have set a module dir var]) + dnl Substitute the variable in the makefile + AC_SUBST(T8_FORTRAN_MODULE_DIR, $T8_WITH_MODDIR) +fi + +fi +]) diff --git a/example/IO/forest/netcdf/t8_write_forest_netcdf.cxx b/example/IO/forest/netcdf/t8_write_forest_netcdf.cxx index bf7462bb74..079ab4c042 100644 --- a/example/IO/forest/netcdf/t8_write_forest_netcdf.cxx +++ b/example/IO/forest/netcdf/t8_write_forest_netcdf.cxx @@ -42,15 +42,9 @@ #include #include #include -<<<<<<< HEAD -#include +#include #include #include -======= -#include -#include -#include ->>>>>>> t8origin/main /* In this example is the use of the netcdf feature exemplary displayed. * We show how to write out a forest in the netCDF format and how to create additional (integer/double) netCDF variables which hold element data. diff --git a/pull_request_template.md b/pull_request_template.md index e6c1982284..de9763105b 100644 --- a/pull_request_template.md +++ b/pull_request_template.md @@ -10,7 +10,7 @@ As a reviewer please read through all the code lines and make sure that the code #### General - [ ] The reviewer executed the new code features at least once and checked the results manually -- [ ] The code follows the [t8code coding guidelines](https://github.com/holke/t8code/wiki/Coding-Guideline) +- [ ] The code follows the [t8code coding guidelines](https://github.com/DLR-AMR/t8code/wiki/Coding-Guideline) - [ ] New source/header files are properly added to the Makefiles - [ ] The code is well documented - [ ] All function declarations, structs/classes and their members have a proper doxygen documentation diff --git a/scripts/README.md b/scripts/README.md index f488ff64b6..110dd9d6d3 100644 --- a/scripts/README.md +++ b/scripts/README.md @@ -4,7 +4,7 @@ This folder contains several scripts that are useful for t8code users and develo ## Indentation -The purpose of the indentation scripts is to help t8code developers to indent their code according to the t8code [indentation guidelines](https://github.com/holke/t8code/wiki/Coding-Guideline#indentation). Please read these guidelines before using these scripts. +The purpose of the indentation scripts is to help t8code developers to indent their code according to the t8code [indentation guidelines](https://github.com/DLR-AMR/t8code/wiki/Coding-Guideline#indentation). Please read these guidelines before using these scripts. #### t8indent @@ -16,7 +16,7 @@ Sometimes `t8indent` does produce undesired results. Therefore, after indenting #### pre-commit -This script should be copied to your `.git/hooks` folder. `git` then automatically checks the indentation of committed files and prevents you from committing wrongly indented files. See [Git indentation workflow](https://github.com/holke/t8code/wiki/Coding-Guideline#git-indentation-workflow). +This script should be copied to your `.git/hooks` folder. `git` then automatically checks the indentation of committed files and prevents you from committing wrongly indented files. See [Git indentation workflow](https://github.com/DLR-AMR/t8code/wiki/Coding-Guideline#git-indentation-workflow). #### check_if_file_indented.scp diff --git a/scripts/t8indent b/scripts/t8indent index 8c1567acb7..bf5aff81a3 100755 --- a/scripts/t8indent +++ b/scripts/t8indent @@ -31,8 +31,7 @@ FORMAT_OPTIONS="-i --style=file" # Required version of the clang format program. REQUIRED_VERSION_MAJOR="17" REQUIRED_VERSION_MINOR="0" -REQUIRED_VERSION_PATCH="1" -REQUIRED_VERSION_STRING="${REQUIRED_VERSION_MAJOR}.${REQUIRED_VERSION_MINOR}.${REQUIRED_VERSION_PATCH}" +REQUIRED_VERSION_STRING="${REQUIRED_VERSION_MAJOR}.${REQUIRED_VERSION_MINOR}" FORMAT=`which clang-format 2> /dev/null` @@ -52,7 +51,7 @@ MAJOR=`echo $VERSION | cut -d. -f1` MINOR=`echo $VERSION | cut -d. -f2` PATCH=`echo $VERSION | cut -d. -f3` -if [[ "$MAJOR" != "$REQUIRED_VERSION_MAJOR" || $MINOR != "$REQUIRED_VERSION_MINOR" || $PATCH != "$REQUIRED_VERSION_PATCH" ]]; then +if [[ "$MAJOR" != "$REQUIRED_VERSION_MAJOR" || $MINOR != "$REQUIRED_VERSION_MINOR" ]]; then echo "Please install clang-format version $REQUIRED_VERSION_STRING" exit 1 fi diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d80de92643..899c014f74 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -94,7 +94,7 @@ target_sources( T8 PRIVATE t8_cmesh/t8_cmesh_vtk_reader.cxx t8_cmesh/t8_cmesh_save.cxx t8_cmesh/t8_cmesh_netcdf.c - t8_cmesh/t8_cmesh_trees.c + t8_cmesh/t8_cmesh_trees.cxx t8_cmesh/t8_cmesh_commit.cxx t8_cmesh/t8_cmesh_partition.cxx t8_cmesh/t8_cmesh_copy.c diff --git a/src/Makefile.am b/src/Makefile.am index cda468ea23..a390b91bf2 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -76,10 +76,10 @@ libt8_installed_headers_geometry_impl = \ src/t8_geometry/t8_geometry_implementations/t8_geometry_zero.h libt8_installed_headers_vtk = \ src/t8_vtk/t8_vtk_reader.hxx \ + src/t8_vtk/t8_vtk_types.h \ src/t8_vtk/t8_vtk_writer.hxx \ src/t8_vtk/t8_vtk_types.h \ - src/t8_vtk/t8_vtk_writer.h \ - src/t8_vtk/t8_vtk_types.h + src/t8_vtk/t8_vtk_writer.h libt8_installed_headers_netcdf = \ src/t8_netcdf/t8_nc.hxx \ src/t8_netcdf/t8_nc_mesh.hxx \ @@ -91,7 +91,6 @@ libt8_installed_headers_netcdf = \ src/t8_netcdf/t8_nc_geo_domain.hxx \ src/t8_netcdf/t8_nc_geo_utilities.hxx \ src/t8_netcdf/t8_nc_input_variable.hxx - libt8_installed_headers_schemes_default = libt8_installed_headers_default_common = libt8_installed_headers_default_vertex = @@ -125,7 +124,7 @@ libt8_compiled_sources = \ src/t8_cmesh/t8_cmesh_stash.c \ src/t8_cmesh/t8_cmesh_vtk_reader.cxx \ src/t8_cmesh/t8_cmesh_save.cxx \ - src/t8_cmesh/t8_cmesh_trees.c src/t8_cmesh/t8_cmesh_commit.cxx \ + src/t8_cmesh/t8_cmesh_trees.cxx src/t8_cmesh/t8_cmesh_commit.cxx \ src/t8_cmesh/t8_cmesh_partition.cxx\ src/t8_cmesh/t8_cmesh_copy.c src/t8_data/t8_shmem.c \ src/t8_cmesh/t8_cmesh_geometry.cxx \ @@ -169,7 +168,6 @@ libt8_compiled_sources = \ src/t8_netcdf/t8_nc_geo_utilities.cxx - # this variable is used for headers that are not publicly installed T8_CPPFLAGS = diff --git a/src/t8_cmesh/t8_cmesh_commit.cxx b/src/t8_cmesh/t8_cmesh_commit.cxx index 65dc12751c..1e2abb2089 100644 --- a/src/t8_cmesh/t8_cmesh_commit.cxx +++ b/src/t8_cmesh/t8_cmesh_commit.cxx @@ -84,7 +84,7 @@ t8_cmesh_set_shmem_type (sc_MPI_Comm comm) } static void -t8_cmesh_add_attributes (const t8_cmesh_t cmesh, sc_hash_t *ghost_ids, size_t *attribute_data_offset) +t8_cmesh_add_attributes (const t8_cmesh_t cmesh, sc_hash_t *ghost_ids) { t8_stash_attribute_struct_t *attribute; const t8_stash_t stash = cmesh->stash; @@ -94,6 +94,7 @@ t8_cmesh_add_attributes (const t8_cmesh_t cmesh, sc_hash_t *ghost_ids, size_t *a temp_facejoin = T8_ALLOC_ZERO (t8_ghost_facejoin_t, 1); + t8_locidx_t ghosts_inserted = 0; ltree = -1; for (si = 0, sj = 0; si < stash->attributes.elem_count; si++, sj++) { attribute = (t8_stash_attribute_struct_t *) sc_array_index (&stash->attributes, si); @@ -112,9 +113,13 @@ t8_cmesh_add_attributes (const t8_cmesh_t cmesh, sc_hash_t *ghost_ids, size_t *a T8_ASSERT (ghost_ids != NULL); temp_facejoin->ghost_id = attribute->id; if (sc_hash_lookup (ghost_ids, temp_facejoin, (void ***) &facejoin_pp)) { + T8_ASSERT ((t8_locidx_t) sj == (t8_locidx_t) (*facejoin_pp)->attr_id); + if (sj == 0) { + ghosts_inserted++; + } /* attribute is on a ghost tree */ - t8_cmesh_trees_add_ghost_attribute (cmesh->trees, 0, attribute, (*facejoin_pp)->local_id, - (*facejoin_pp)->attr_id, attribute_data_offset); + t8_cmesh_trees_add_ghost_attribute (cmesh->trees, attribute, (*facejoin_pp)->local_id, ghosts_inserted, + (*facejoin_pp)->attr_id); (*facejoin_pp)->attr_id++; } } @@ -167,7 +172,7 @@ t8_cmesh_commit_replicated_new (t8_cmesh_t cmesh) t8_stash_attribute_sort (cmesh->stash); cmesh->num_trees = cmesh->num_local_trees = num_trees; cmesh->first_tree = 0; - t8_cmesh_add_attributes (cmesh, NULL, NULL); + t8_cmesh_add_attributes (cmesh, NULL); /* Set all face connections */ t8_cmesh_trees_set_all_boundary (cmesh, cmesh->trees); @@ -198,7 +203,6 @@ t8_cmesh_commit_partitioned_new (t8_cmesh_t cmesh, sc_MPI_Comm comm) t8_cghost_t ghost1; int F; size_t si; - size_t attribute_data_offset; #if T8_ENABLE_DEBUG sc_flopinfo_t fi, snapshot; @@ -375,7 +379,7 @@ t8_cmesh_commit_partitioned_new (t8_cmesh_t cmesh, sc_MPI_Comm comm) ghost1->att_offset += attribute->attr_size; } } - attribute_data_offset = t8_cmesh_trees_finish_part (cmesh->trees, 0); + t8_cmesh_trees_finish_part (cmesh->trees, 0); t8_cmesh_trees_set_all_boundary (cmesh, cmesh->trees); /* Go through all face_neighbour entries and parse every @@ -473,7 +477,7 @@ t8_cmesh_commit_partitioned_new (t8_cmesh_t cmesh, sc_MPI_Comm comm) * counting the attributes per tree. */ t8_stash_attribute_sort (cmesh->stash); - t8_cmesh_add_attributes (cmesh, ghost_ids, &attribute_data_offset); + t8_cmesh_add_attributes (cmesh, ghost_ids); /* compute global number of trees. id1 serves as buffer since * global number and local number have different datatypes */ diff --git a/src/t8_cmesh/t8_cmesh_examples.cxx b/src/t8_cmesh/t8_cmesh_examples.cxx index 0a8da3d897..975477cc2b 100644 --- a/src/t8_cmesh/t8_cmesh_examples.cxx +++ b/src/t8_cmesh/t8_cmesh_examples.cxx @@ -371,7 +371,7 @@ t8_cmesh_new_pyramid (sc_MPI_Comm comm) /* Use linear geometry */ t8_cmesh_register_geometry (cmesh, 3); t8_cmesh_set_tree_class (cmesh, 0, T8_ECLASS_PYRAMID); - t8_cmesh_set_tree_vertices (cmesh, 0, vertices, 15); + t8_cmesh_set_tree_vertices (cmesh, 0, vertices, 5); t8_cmesh_commit (cmesh, comm); return cmesh; } @@ -684,7 +684,7 @@ t8_cmesh_new_hypercube (t8_eclass_t eclass, sc_MPI_Comm comm, int do_bcast, int if (do_partition) { t8_global_errorf ( "WARNING: Partitioning the hypercube cmesh is currently not supported.\n" - "Using this cmesh will crash when vertices are used. See also https://github.com/holke/t8code/issues/79\n"); + "Using this cmesh will crash when vertices are used. See also https://github.com/DLR-AMR/t8code/issues/79\n"); } mpiret = sc_MPI_Comm_rank (comm, &mpirank); @@ -2150,7 +2150,6 @@ t8_cmesh_new_prism_geometry (sc_MPI_Comm comm) return cmesh; } -<<<<<<< HEAD /* On each process, create a num_x by num_y (by num_z) brick connectivity and * make a cmesh connectivity from the disjoint union of those. * Example: 2 processors, @@ -2278,8 +2277,6 @@ t8_cmesh_new_brick_wall (t8_gloidx_t num_x, t8_gloidx_t num_y, t8_gloidx_t num_z return t8_cmesh_new_hypercube_pad (elem_type, comm, boundary_vertices, num_x, num_y, num_z, use_axis_aligned); } -======= ->>>>>>> t8origin/main /* Construct a tetrahedral cmesh that has all possible face to face * connections and orientations. */ t8_cmesh_t diff --git a/src/t8_cmesh/t8_cmesh_trees.c b/src/t8_cmesh/t8_cmesh_trees.cxx similarity index 85% rename from src/t8_cmesh/t8_cmesh_trees.c rename to src/t8_cmesh/t8_cmesh_trees.cxx index 8e9f06ef23..9c136c554f 100644 --- a/src/t8_cmesh/t8_cmesh_trees.c +++ b/src/t8_cmesh/t8_cmesh_trees.cxx @@ -25,6 +25,9 @@ * TODO: document this file */ +#include +#include +#include #include "t8_cmesh_stash.h" #include "t8_cmesh_trees.h" @@ -210,6 +213,46 @@ t8_cmesh_trees_start_part (const t8_cmesh_trees_t trees, const int proc, const t part->first_ghost_id = lfirst_ghost; } +/* Helper struct for sorting the number of ghost attributes by global id. + * In order to sort them, we need the part ghost id to access the global id. + * Thus, we store both the part id and the number of attributes. */ +typedef struct +{ + t8_locidx_t part_ghost_id; + t8_gloidx_t global_id; + int num_attributes; + int attribute_offset; +} t8_part_ghost_id_and_num_atts; + +/* Compare function for t8_part_ghost_id_and_num_atts to compare by global id. +* +* Return True if global_id of if_A < global_id of id_B +* Return False otherwise +* */ +bool +t8_compare_id_and_att_by_global_id (t8_part_ghost_id_and_num_atts &id_A, t8_part_ghost_id_and_num_atts &id_B) +{ + return id_A.global_id < id_B.global_id; +} + +/* Compare function for t8_part_ghost_id_and_num_atts to compare by local id. +* +* Return True if local id of if_A < local id of id_B +* Return False otherwise +* */ +bool +t8_compare_id_and_att_by_part_id (t8_part_ghost_id_and_num_atts &id_A, t8_part_ghost_id_and_num_atts &id_B) +{ + return id_A.part_ghost_id < id_B.part_ghost_id; +} + +static std::vector +t8_cmesh_allocate_ghost_num_atts_array (t8_locidx_t part_num_ghosts) +{ + std::vector num_attributes_of_ghosts (part_num_ghosts); + return num_attributes_of_ghosts; +} + /* After all classes of trees and ghosts have been set and after the * number of tree attributes was set and their total size (per tree) * stored temporarily in the att_offset variable @@ -218,21 +261,17 @@ t8_cmesh_trees_start_part (const t8_cmesh_trees_t trees, const int proc, const t /* The workflow can be: call start_part, set tree and ghost classes maually, call * init_attributes, call finish_part, successively call add_attributes * and also set all face neighbors (TODO: write function)*/ -size_t +void t8_cmesh_trees_finish_part (const t8_cmesh_trees_t trees, const int proc) { t8_part_tree_t part; t8_ctree_t tree; t8_cghost_t ghost; - size_t tree_attr_bytes; - size_t ghost_attr_bytes; - size_t face_neigh_bytes; /* count the total number of bytes needed for face_neighbor information */ - size_t first_face; /* offset of the first face neighbor information */ - size_t first_tree; /* offset of the first tree */ - size_t first_ghost; /* offset of the first ghost */ - size_t temp_offset; /* offset of the currently looked at tree/ghost */ - size_t num_tree_attributes; /* total number of tree attributes */ - size_t num_ghost_attributes; /* total number of ghost attributes */ + size_t tree_attr_data_bytes; + size_t ghost_attr_data_bytes; + size_t face_neigh_bytes; /* count the total number of bytes needed for face_neighbor information */ + size_t temp_offset; /* offset of the currently looked at tree/ghost */ + size_t num_tree_attributes; /* total number of tree attributes */ t8_attribute_info_struct_t *attr; t8_locidx_t it; #ifndef SC_ENABLE_REALLOC @@ -243,16 +282,22 @@ t8_cmesh_trees_finish_part (const t8_cmesh_trees_t trees, const int proc) part = t8_cmesh_trees_get_part (trees, proc); T8_ASSERT (part != NULL); - num_tree_attributes = num_ghost_attributes = 0; - tree_attr_bytes = ghost_attr_bytes = face_neigh_bytes = 0; + num_tree_attributes = 0; + tree_attr_data_bytes = ghost_attr_data_bytes = face_neigh_bytes = 0; /* The offset of the first tree */ - first_tree = 0; + const size_t first_tree = 0; /* The offset of the first ghost */ - first_ghost = first_tree + part->num_trees * sizeof (t8_ctree_struct_t); + const size_t first_ghost = first_tree + part->num_trees * sizeof (t8_ctree_struct_t); /* The offset of the first ghost face */ - first_face = first_ghost + part->num_ghosts * sizeof (t8_cghost_struct_t); + const size_t first_face = first_ghost + part->num_ghosts * sizeof (t8_cghost_struct_t); + + /* First pass through ghosts to set the face neighbor offsets. */ + /* Additionally, we need to sort the number of attributes according to the global id in order + * to properly compute the attribute info offsets later. */ + + std::vector num_attributes_of_ghosts + = t8_cmesh_allocate_ghost_num_atts_array (part->num_ghosts); - /* First pass through ghosts to set the face neighbor offsets */ temp_offset = first_ghost; for (it = 0; it < part->num_ghosts; it++) { ghost = t8_part_tree_get_ghost (part, it + part->first_ghost_id); @@ -264,7 +309,27 @@ t8_cmesh_trees_finish_part (const t8_cmesh_trees_t trees, const int proc) face_neigh_bytes += T8_ADD_PADDING (face_neigh_bytes); T8_ASSERT (face_neigh_bytes % T8_PADDING_SIZE == 0); temp_offset += sizeof (t8_cghost_struct_t); + + /* Add the number of attributes of this ghost to the array. */ + t8_part_ghost_id_and_num_atts &lid_and_num_atts_entry = num_attributes_of_ghosts[it]; + lid_and_num_atts_entry.part_ghost_id = it; + lid_and_num_atts_entry.num_attributes = ghost->num_attributes; + lid_and_num_atts_entry.global_id = ghost->treeid; + lid_and_num_atts_entry.attribute_offset = 0; + } + /* We now sort the array of num attributes by global id */ + std::sort (num_attributes_of_ghosts.begin (), num_attributes_of_ghosts.end (), t8_compare_id_and_att_by_global_id); + + if (part->num_ghosts > 0) { + num_attributes_of_ghosts[0].attribute_offset = 0; } + for (t8_locidx_t ighost = 1; ighost < part->num_ghosts; ++ighost) { + // Build the sum: 0 a a+b a+b+c a+b+c+d + num_attributes_of_ghosts[ighost].attribute_offset + = num_attributes_of_ghosts[ighost - 1].attribute_offset + num_attributes_of_ghosts[ighost - 1].num_attributes; + } + /* We now need to sort the offset sum by local id again. */ + std::sort (num_attributes_of_ghosts.begin (), num_attributes_of_ghosts.end (), t8_compare_id_and_att_by_part_id); /* First pass through trees to set the face neighbor offsets */ temp_offset = 0; @@ -280,41 +345,51 @@ t8_cmesh_trees_finish_part (const t8_cmesh_trees_t trees, const int proc) /* Second pass through trees to set attribute offsets */ temp_offset = 0; + size_t next_tree_offset = 0; // Compute the offset of the next tree for (it = 0; it < part->num_trees; it++) { tree = t8_part_tree_get_tree (part, it + part->first_tree_id); - tree_attr_bytes += tree->att_offset; /* att_offset temporarily stored the total size of the attributes */ + tree_attr_data_bytes += tree->att_offset; /* att_offset temporarily stored the total size of the attributes */ /* The att_offset of the tree is the first_face plus the number of attribute * bytes used by previous trees minus the temp_offset */ tree->att_offset = first_face - temp_offset + face_neigh_bytes + num_tree_attributes * sizeof (t8_attribute_info_struct_t); + T8_ASSERT (it == 0 || tree->att_offset == next_tree_offset); num_tree_attributes += tree->num_attributes; temp_offset += sizeof (t8_ctree_struct_t); + next_tree_offset + = tree->att_offset + tree->num_attributes * sizeof (t8_attribute_info_struct_t) - sizeof (t8_ctree_struct_t); } - tree_attr_bytes += num_tree_attributes * sizeof (t8_attribute_info_struct_t); + const size_t tree_attr_total_bytes = tree_attr_data_bytes + num_tree_attributes * sizeof (t8_attribute_info_struct_t); /* Second pass through ghosts to set attribute offsets */ - temp_offset = first_ghost; + temp_offset = 0; + size_t num_ghost_attributes = 0; /* total number of ghost attributes */ + /* To get the offset of the first ghost attribute info, we have to add the bytes + * of all tree attributes. */ + size_t first_ghost_offset = next_tree_offset + tree_attr_data_bytes; for (it = 0; it < part->num_ghosts; it++) { ghost = t8_part_tree_get_ghost (part, it + part->first_ghost_id); - ghost_attr_bytes += ghost->att_offset; /* att_offset temporarily stored the total size of the attributes */ - /* The att_offset of the tree is the first_face plus the number of attribute - * bytes used by previous trees minus the temp_offset */ - ghost->att_offset = first_face - temp_offset + face_neigh_bytes + tree_attr_bytes - + num_ghost_attributes * sizeof (t8_attribute_info_struct_t); - num_ghost_attributes += ghost->num_attributes; + ghost_attr_data_bytes += ghost->att_offset; /* att_offset temporarily stored the total size of the attributes */ + /* The att_offset of the ghost is the offset of the first ghost + the attribute + * offset of this ghost minus the size of all previous ghosts. */ + ghost->att_offset = first_ghost_offset + + num_attributes_of_ghosts[it].attribute_offset * sizeof (t8_attribute_info_struct_t) + - temp_offset; temp_offset += sizeof (t8_cghost_struct_t); + num_ghost_attributes += ghost->num_attributes; } - ghost_attr_bytes += num_ghost_attributes * sizeof (t8_attribute_info_struct_t); - size_t attr_bytes = tree_attr_bytes + ghost_attr_bytes; + const size_t ghost_attr_total_bytes + = ghost_attr_data_bytes + num_ghost_attributes * sizeof (t8_attribute_info_struct_t); + const size_t attr_total_bytes = tree_attr_total_bytes + ghost_attr_total_bytes; /* Done setting all tree and ghost offsets */ - /* Allocate memory, first_face + attr_bytes + face_neigh_bytes gives the new total byte count */ + /* Allocate memory, first_face + attr_total_bytes + face_neigh_bytes gives the new total byte count */ #ifdef SC_ENABLE_REALLOC /* Since we use realloc and padding, memcmp will not work if we don't set everything to zero, solved with memset */ - SC_REALLOC (part->first_tree, char, first_face + attr_bytes + +face_neigh_bytes); - memset (part->first_tree + first_face, 0, attr_bytes + face_neigh_bytes) + SC_REALLOC (part->first_tree, char, first_face + attr_total_bytes + face_neigh_bytes); + memset (part->first_tree + first_face, 0, attr_total_bytes + face_neigh_bytes) #else - temp = T8_ALLOC_ZERO (char, first_face + attr_bytes + face_neigh_bytes); + temp = T8_ALLOC_ZERO (char, first_face + attr_total_bytes + face_neigh_bytes); memcpy (temp, part->first_tree, first_face); T8_FREE (part->first_tree); part->first_tree = temp; @@ -324,7 +399,11 @@ t8_cmesh_trees_finish_part (const t8_cmesh_trees_t trees, const int proc) attr = (t8_attribute_info_struct_t *) (part->first_tree + first_face + face_neigh_bytes); attr->attribute_offset = num_tree_attributes * sizeof (t8_attribute_info_struct_t); } - return num_ghost_attributes * sizeof (t8_attribute_info_struct_t); + if (num_ghost_attributes > 0) { + ghost = t8_part_tree_get_ghost (part, 0); + attr = (t8_attribute_info_struct_t *) (part->first_tree + first_face + face_neigh_bytes + tree_attr_total_bytes); + attr->attribute_offset = num_ghost_attributes * sizeof (t8_attribute_info_struct_t); + } } void @@ -608,7 +687,7 @@ t8_cmesh_trees_copy_toproc (t8_cmesh_trees_t trees_dest, const t8_cmesh_trees_t void t8_cmesh_trees_init_attributes (const t8_cmesh_trees_t trees, const t8_locidx_t ltree_id, const size_t num_attributes, - const size_t attr_bytes) + const size_t attr_info_bytes) { int proc; t8_ctree_t tree; @@ -619,7 +698,7 @@ t8_cmesh_trees_init_attributes (const t8_cmesh_trees_t trees, const t8_locidx_t T8_ASSERT (proc >= 0 && proc < t8_cmesh_trees_get_num_procs (trees)); tree = t8_part_tree_get_tree (t8_cmesh_trees_get_part (trees, proc), ltree_id); - tree->att_offset = attr_bytes; /* This is only temporary until t8_cmesh_trees_finish_part + tree->att_offset = attr_info_bytes; /* This is only temporary until t8_cmesh_trees_finish_part is called */ tree->num_attributes = num_attributes; } @@ -676,9 +755,9 @@ t8_cmesh_trees_add_attribute (const t8_cmesh_trees_t trees, const int proc, cons } void -t8_cmesh_trees_add_ghost_attribute (const t8_cmesh_trees_t trees, const int proc, - const t8_stash_attribute_struct_t *attr, const t8_locidx_t local_ghost_id, - const size_t index, size_t *attribute_data_offset) +t8_cmesh_trees_add_ghost_attribute (const t8_cmesh_trees_t trees, const t8_stash_attribute_struct_t *attr, + const t8_locidx_t local_ghost_id, const t8_locidx_t ghosts_inserted, + const size_t index) { t8_part_tree_t part; t8_cghost_t ghost; @@ -690,11 +769,10 @@ t8_cmesh_trees_add_ghost_attribute (const t8_cmesh_trees_t trees, const int proc T8_ASSERT (attr->attr_data != NULL || attr->attr_size == 0); T8_ASSERT (attr->id >= 0); - part = t8_cmesh_trees_get_part (trees, proc); + part = t8_cmesh_trees_get_part (trees, 0); ghost = t8_part_tree_get_ghost (part, local_ghost_id); attr_info = T8_GHOST_ATTR_INFO (ghost, index); - attr_info->attribute_offset = *attribute_data_offset; new_attr_data = T8_GHOST_ATTR (ghost, attr_info); memcpy (new_attr_data, attr->attr_data, attr->attr_size); @@ -704,9 +782,19 @@ t8_cmesh_trees_add_ghost_attribute (const t8_cmesh_trees_t trees, const int proc attr_info->package_id = attr->package_id; attr_info->attribute_size = attr->attr_size; - *attribute_data_offset += attr->attr_size; - if (index == (size_t) ghost->num_attributes - 1) { - *attribute_data_offset -= ghost->num_attributes * sizeof (t8_attribute_info_struct_t); + /* If we are not yet at the last attribute of the part, + * get next attribute and set its offset*/ + if (!(index == (size_t) ghost->num_attributes - 1 && part->num_ghosts == ghosts_inserted)) { + /* Store offset of current attribute */ + const size_t offset = attr_info->attribute_offset; + attr_info = attr_info + 1; + attr_info->attribute_offset = offset + attr->attr_size; + /* if the current attribute was the last attribute of the tree + * the next attribute offset must be corrected by the size of + * the attribute infos of the current tree */ + if (index == (size_t) ghost->num_attributes - 1) { + attr_info->attribute_offset -= ghost->num_attributes * sizeof (t8_attribute_info_struct_t); + } } } diff --git a/src/t8_cmesh/t8_cmesh_trees.h b/src/t8_cmesh/t8_cmesh_trees.h index 919a576bfd..60bbc74ac7 100644 --- a/src/t8_cmesh/t8_cmesh_trees.h +++ b/src/t8_cmesh/t8_cmesh_trees.h @@ -220,7 +220,7 @@ t8_cmesh_trees_start_part (t8_cmesh_trees_t trees, int proc, t8_locidx_t lfirst_ * \param [in,out] trees The trees structure to be updated. * \param [in] proc The number of the part to be finished. */ -size_t +void t8_cmesh_trees_finish_part (t8_cmesh_trees_t trees, int proc); /** Copy the tree_to_proc and ghost_to_proc arrays of one tree structure to @@ -433,9 +433,19 @@ void t8_cmesh_trees_add_attribute (const t8_cmesh_trees_t trees, int proc, const t8_stash_attribute_struct_t *attr, t8_locidx_t tree_id, size_t index); +/** Add the next ghost attribute from stash to the correct position in the char pointer structure + * Since it is created from stash, all attributes are added to part 0. + * The following attribute offset gets updated already. + * \param [in,out] trees The trees structure, whose char array is updated. + * \param [in] attr The stash attribute that is added. + * \param [in] local_ghost_id The local ghost id. + * \param [in] ghosts_inserted The number of ghost that were already inserted, so that we do not write over the end. + * \param [in] index The attribute index of the attribute to be added. +*/ + void -t8_cmesh_trees_add_ghost_attribute (const t8_cmesh_trees_t trees, int proc, const t8_stash_attribute_struct_t *attr, - t8_locidx_t local_ghost_id, size_t index, size_t *attribute_data_offset); +t8_cmesh_trees_add_ghost_attribute (const t8_cmesh_trees_t trees, const t8_stash_attribute_struct_t *attr, + t8_locidx_t local_ghost_id, t8_locidx_t ghosts_inserted, size_t index); /** Return the number of parts of a trees structure. * \param [in] trees The trees structure. diff --git a/src/t8_forest/t8_forest.cxx b/src/t8_forest/t8_forest.cxx index 41fb758b67..0a8fb6b29e 100644 --- a/src/t8_forest/t8_forest.cxx +++ b/src/t8_forest/t8_forest.cxx @@ -4158,6 +4158,17 @@ t8_forest_new_uniform (t8_cmesh_t cmesh, t8_scheme_cxx_t *scheme, const int leve /* Initialize the forest */ t8_forest_init (&forest); + + if (cmesh->set_partition) { + t8_cmesh_t cmesh_uniform_partition; + t8_cmesh_init (&cmesh_uniform_partition); + t8_cmesh_set_derive (cmesh_uniform_partition, cmesh); + t8_scheme_cxx_ref (scheme); + t8_cmesh_set_partition_uniform (cmesh_uniform_partition, level, scheme); + t8_cmesh_commit (cmesh_uniform_partition, comm); + cmesh = cmesh_uniform_partition; + } + /* Set the cmesh, scheme and level */ t8_forest_set_cmesh (forest, cmesh, comm); t8_forest_set_scheme (forest, scheme); diff --git a/src/t8_geometry/t8_geometry_with_vertices.cxx b/src/t8_geometry/t8_geometry_with_vertices.cxx index 33f591d478..b2f4590e01 100644 --- a/src/t8_geometry/t8_geometry_with_vertices.cxx +++ b/src/t8_geometry/t8_geometry_with_vertices.cxx @@ -48,6 +48,8 @@ t8_geometry_with_vertices::t8_geom_tree_negative_volume () const /* Only three dimensional eclass do have a volume */ return false; } + T8_ASSERT (t8_eclass_to_dimension[active_tree_class] + == 3); // Should we include 4 dimensional classes, we need to catch that here and implement it. T8_ASSERT (active_tree_class == T8_ECLASS_TET || active_tree_class == T8_ECLASS_HEX || active_tree_class == T8_ECLASS_PRISM || active_tree_class == T8_ECLASS_PYRAMID); diff --git a/src/t8_vtk/t8_vtk_writer.hxx b/src/t8_vtk/t8_vtk_writer.hxx index 6bb94bfe4e..8b992effc5 100644 --- a/src/t8_vtk/t8_vtk_writer.hxx +++ b/src/t8_vtk/t8_vtk_writer.hxx @@ -93,8 +93,8 @@ class vtk_writer { const bool write_ghosts, const bool curved_flag, std::string fileprefix, const int num_data, t8_vtk_data_field_t *data, sc_MPI_Comm comm) : write_treeid (write_treeid), write_mpirank (write_mpirank), write_level (write_level), - write_ghosts (write_ghosts), curved_flag (curved_flag), fileprefix (fileprefix), num_data (num_data), data (data), - comm (comm) + write_element_id (write_element_id), write_ghosts (write_ghosts), curved_flag (curved_flag), + fileprefix (fileprefix), num_data (num_data), data (data), comm (comm) { } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index a035c6278f..076d1599d1 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -20,7 +20,15 @@ function( add_t8_test ) set(TEST_BUILD_DIR "${CMAKE_BINARY_DIR}/${TEST_RELATIVE_DIR}") add_executable( ${ADD_T8_TEST_NAME} ${ADD_T8_TEST_SOURCES} ) - target_link_libraries( ${ADD_T8_TEST_NAME} PRIVATE T8 gtest pthread) + + # Check if test is a Fortran file and if MPI is enabled. + string ( FIND ${ADD_T8_TEST_NAME} "fortran" is_fortran_file ) + if ( (${is_fortran_file} GREATER_EQUAL 0) AND T8CODE_ENABLE_MPI ) + target_include_directories( ${ADD_T8_TEST_NAME} PRIVATE ${CMAKE_BINARY_DIR}/src ) + target_link_libraries( ${ADD_T8_TEST_NAME} PRIVATE T8 gtest pthread MPI::MPI_Fortran ) + else() + target_link_libraries( ${ADD_T8_TEST_NAME} PRIVATE T8 gtest pthread ) + endif () set_target_properties(${ADD_T8_TEST_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${TEST_BUILD_DIR}" @@ -192,6 +200,10 @@ add_t8_test( NAME t8_gtest_pack_unpack_serial SOURCES t8_gtest_main.cx add_t8_test( NAME t8_gtest_root_serial SOURCES t8_gtest_main.cxx t8_schemes/t8_gtest_root.cxx ) add_t8_test( NAME t8_gtest_scheme_consistency_serial SOURCES t8_gtest_main.cxx t8_schemes/t8_gtest_scheme_consistency.cxx ) +if( T8CODE_BUILD_FORTRAN_INTERFACE AND T8CODE_ENABLE_MPI ) + add_t8_test( NAME t8_test_fortran_mpi_interface_init_parallel SOURCES api/t8_fortran_interface/t8_test_mpi_init.f90 ) +endif() + copy_test_file( test_cube_unstructured_1.inp ) copy_test_file( test_cube_unstructured_2.inp ) copy_test_file( test_vtk_tri.vtu ) diff --git a/test/api/t8_fortran_interface/t8_test_mpi_init.f90 b/test/api/t8_fortran_interface/t8_test_mpi_init.f90 new file mode 100644 index 0000000000..665a6d0ec7 --- /dev/null +++ b/test/api/t8_fortran_interface/t8_test_mpi_init.f90 @@ -0,0 +1,51 @@ +!! This file is part of t8code. +!! t8code is a C library to manage a collection (a forest) of multiple +!! connected adaptive space-trees of general element classes in parallel. +!! +!! Copyright (C) 2024 the developers +!! +!! t8code is free software; you can redistribute it and/or modify +!! it under the terms of the GNU General Public License as published by +!! the Free Software Foundation; either version 2 of the License, or +!! (at your option) any later version. +!! +!! t8code 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 General Public License for more details. +!! +!! You should have received a copy of the GNU General Public License +!! along with t8code; if not, write to the Free Software Foundation, Inc., +!! 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +!! Description: +!! +!! This program tests if t8code can be initialized from Fortran +!! with given MPI communicator. Works only when MPI is enabled. + +program t8_test_mpi_init + use mpi + use iso_c_binding, only: c_ptr, c_int + use t8_fortran_interface_mod + + implicit none + + integer :: ierror, fcomm + type(c_ptr) :: ccomm + + call MPI_Init (ierror) + + if (ierror /= 0) then + print *, 'MPI initialization failed.' + stop 1 + endif + + fcomm = MPI_COMM_WORLD + ccomm = t8_fortran_mpi_comm_new_f (fcomm) + + call t8_fortran_init_all_f (ccomm) + call t8_fortran_finalize_f () + + print *, 'All good!' + stop 0 +end program diff --git a/test/t8_cmesh/t8_gtest_cmesh_partition.cxx b/test/t8_cmesh/t8_gtest_cmesh_partition.cxx index d5b41e8555..019f374ac4 100644 --- a/test/t8_cmesh/t8_gtest_cmesh_partition.cxx +++ b/test/t8_cmesh/t8_gtest_cmesh_partition.cxx @@ -39,15 +39,7 @@ class t8_cmesh_partition_class: public testing::TestWithParamparam_to_string (name); - - size_t found = name.find (std::string ("t8_cmesh_new_from_class__Pyramid_sc_MPI_COMM_WORLD")); - if (found != std::string::npos) { - /* Test not working for pyramids */ - GTEST_SKIP (); - } - found = GetParam ()->name.find (std::string ("empty")); + size_t found = GetParam ()->name.find (std::string ("empty")); if (found != std::string::npos) { /* Tests not working for empty cmeshes */ GTEST_SKIP (); diff --git a/test/t8_cmesh/t8_gtest_cmesh_set_join_by_vertices.cxx b/test/t8_cmesh/t8_gtest_cmesh_set_join_by_vertices.cxx index d6fbd6d773..190d51dc43 100644 --- a/test/t8_cmesh/t8_gtest_cmesh_set_join_by_vertices.cxx +++ b/test/t8_cmesh/t8_gtest_cmesh_set_join_by_vertices.cxx @@ -445,11 +445,15 @@ class t8_cmesh_set_join_by_vertices_class: public testing::TestWithParamname.find (std::string ("bigmesh")); if (found != std::string::npos) { - /* skip bigmeshes as they get to large */ + /* skip bigmeshes as they do not have vertices from which to build the connectivity */ GTEST_SKIP (); } cmesh = GetParam ()->cmesh_create (); + if (cmesh->set_partition) { + /* skip partitioned cmeshes, as they do not have all necessary vertex information for the neighbors */ + GTEST_SKIP (); + } } void diff --git a/test/t8_cmesh/t8_gtest_multiple_attributes.cxx b/test/t8_cmesh/t8_gtest_multiple_attributes.cxx index 7e3fad23df..39462ebfb8 100644 --- a/test/t8_cmesh/t8_gtest_multiple_attributes.cxx +++ b/test/t8_cmesh/t8_gtest_multiple_attributes.cxx @@ -124,8 +124,7 @@ TEST_P (cmesh_multiple_attributes, multiple_attributes) t8_locidx_t num_ghosts = t8_cmesh_get_num_ghosts (cmesh_mult_at_from_stash); for (t8_locidx_t ltree_id = 0; ltree_id < num_local_trees + num_ghosts; ltree_id++) { const t8_gloidx_t gtree_id = t8_cmesh_get_global_id (cmesh_mult_at_from_stash, ltree_id); - const double *vertices_partition = (double *) t8_cmesh_get_attribute ( - cmesh_mult_at_from_stash, t8_get_package_id (), T8_CMESH_VERTICES_ATTRIBUTE_KEY, ltree_id); + const double *vertices_partition = t8_cmesh_get_tree_vertices (cmesh_mult_at_from_stash, ltree_id); const t8_eclass_t eclass = (ltree_id < num_local_trees) ? t8_cmesh_get_tree_class (cmesh_one_at, ltree_id) : t8_cmesh_get_ghost_class (cmesh_one_at, ltree_id - num_local_trees); @@ -133,9 +132,12 @@ TEST_P (cmesh_multiple_attributes, multiple_attributes) /* Compare vertices with reference vertices. */ for (int v_id = 0; v_id < 8; v_id++) { - EXPECT_EQ (vertices_partition[v_id * 3], vertices_ref[v_id * 3] + gtree_id); - EXPECT_EQ (vertices_partition[v_id * 3 + 1], vertices_ref[v_id * 3 + 1]); - EXPECT_EQ (vertices_partition[v_id * 3 + 2], vertices_ref[v_id * 3 + 2]); + EXPECT_EQ (vertices_partition[v_id * 3], vertices_ref[v_id * 3] + gtree_id) + << " at tree id " << ltree_id << " and vertex " << v_id; + EXPECT_EQ (vertices_partition[v_id * 3 + 1], vertices_ref[v_id * 3 + 1]) + << " at tree id " << ltree_id << " and rtex " << v_id; + EXPECT_EQ (vertices_partition[v_id * 3 + 2], vertices_ref[v_id * 3 + 2]) + << " at tree id " << ltree_id << " and vertex " << v_id; } /* Compare second attribute with global tree id. */ t8_locidx_t att; @@ -150,4 +152,4 @@ TEST_P (cmesh_multiple_attributes, multiple_attributes) } /* Test for different number of trees. */ -INSTANTIATE_TEST_SUITE_P (t8_gtest_multiple_attributes, cmesh_multiple_attributes, testing::Range (1, 4)); +INSTANTIATE_TEST_SUITE_P (t8_gtest_multiple_attributes, cmesh_multiple_attributes, testing::Range (1, 10)); diff --git a/test/t8_cmesh_generator/t8_cmesh_parametrized_examples/t8_cmesh_new_hypercube_param.hxx b/test/t8_cmesh_generator/t8_cmesh_parametrized_examples/t8_cmesh_new_hypercube_param.hxx index e0639fe49d..f43445b0a8 100644 --- a/test/t8_cmesh_generator/t8_cmesh_parametrized_examples/t8_cmesh_new_hypercube_param.hxx +++ b/test/t8_cmesh_generator/t8_cmesh_parametrized_examples/t8_cmesh_new_hypercube_param.hxx @@ -61,7 +61,7 @@ example_set *cmesh_example = (example_set *) new cmesh_cartesian_product_params< std::make_pair (periodic_eclasses.begin (), periodic_eclasses.end ()), std::make_pair (cmesh_params::my_comms.begin (), cmesh_params::my_comms.end ()), std::make_pair (cmesh_params::do_bcast.begin (), cmesh_params::do_bcast.end ()), - std::make_pair (cmesh_params::no_partition.begin (), cmesh_params::no_partition.end ()), + std::make_pair (cmesh_params::partition.begin (), cmesh_params::partition.end ()), std::make_pair (cmesh_params::periodic.begin (), cmesh_params::periodic.end ()), cmesh_wrapper, param_to_string, "t8_cmesh_new_hypercube_"); @@ -72,7 +72,7 @@ example_set *cmesh_example_pyra = (example_set *) new cmesh_cartesian_product_pa std::make_pair (nonperiodic_eclasses.begin (), nonperiodic_eclasses.end ()), std::make_pair (cmesh_params::my_comms.begin (), cmesh_params::my_comms.end ()), std::make_pair (cmesh_params::do_bcast.begin (), cmesh_params::do_bcast.end ()), - std::make_pair (cmesh_params::no_partition.begin (), cmesh_params::no_partition.end ()), + std::make_pair (cmesh_params::partition.begin (), cmesh_params::partition.end ()), std::make_pair (cmesh_params::no_periodic.begin (), cmesh_params::no_periodic.end ()), cmesh_wrapper, param_to_string, "t8_cmesh_new_hypercube_"); } // namespace new_hypercube_cmesh diff --git a/tutorials/CMakeLists.txt b/tutorials/CMakeLists.txt index 760dbbe65e..8e749f3854 100644 --- a/tutorials/CMakeLists.txt +++ b/tutorials/CMakeLists.txt @@ -28,6 +28,11 @@ function( add_t8_tutorial ) install( TARGETS ${ADD_T8_TUTORIAL_NAME} DESTINATION ${CMAKE_INSTALL_PREFIX}/bin ) endfunction() +#copy tutorial files to the exact same location in the builddir as they are in the source dir +function( copy_tutorial_file TUTORIAL_FILE_NAME_SUBPATH ) + configure_file(${CMAKE_CURRENT_LIST_DIR}/${TUTORIAL_FILE_NAME_SUBPATH} ${CMAKE_CURRENT_BINARY_DIR}/${TUTORIAL_FILE_NAME_SUBPATH} COPYONLY) +endfunction() + add_t8_tutorial( NAME t8_step0_helloworld SOURCES general/t8_step0_helloworld.cxx ) add_t8_tutorial( NAME t8_step1_coarsemesh SOURCES general/t8_step1_coarsemesh.cxx ) add_t8_tutorial( NAME t8_step2_uniform_forest SOURCES general/t8_step2_uniform_forest.cxx ) @@ -38,4 +43,9 @@ add_t8_tutorial( NAME t8_step6_stencil SOURCES general/t8_step6 add_t8_tutorial( NAME t8_step7_interpolation SOURCES general/t8_step7_main.cxx general/t8_step7_interpolation.cxx ) add_t8_tutorial( NAME t8_tutorial_build_cmesh SOURCES general/t8_tutorial_build_cmesh.cxx general/t8_tutorial_build_cmesh_main.cxx) add_t8_tutorial( NAME t8_tutorial_search SOURCES general/t8_tutorial_search.cxx general/t8_step3_adapt_forest.cxx ) -add_t8_tutorial( NAME t8_features_curved_meshes SOURCES features/t8_features_curved_meshes.cxx) \ No newline at end of file +add_t8_tutorial( NAME t8_features_curved_meshes SOURCES features/t8_features_curved_meshes.cxx) + +copy_tutorial_file (features/t8_features_curved_meshes_generate_cmesh_hex.geo) +copy_tutorial_file (features/t8_features_curved_meshes_generate_cmesh_quad.geo) +copy_tutorial_file (features/t8_features_curved_meshes_generate_cmesh_tet.geo) +copy_tutorial_file (features/t8_features_curved_meshes_generate_cmesh_tri.geo) diff --git a/tutorials/general/t8_step0_helloworld.cxx b/tutorials/general/t8_step0_helloworld.cxx index 8f3a533d25..db49959ec3 100644 --- a/tutorials/general/t8_step0_helloworld.cxx +++ b/tutorials/general/t8_step0_helloworld.cxx @@ -20,7 +20,7 @@ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -/* See also: https://github.com/holke/t8code/wiki/Step-0---Hello-World +/* See also: https://github.com/DLR-AMR/t8code/wiki/Step-0---Hello-World * * In this example we initialize t8code and print a small welcome message. * This is the t8code equivalent of HelloWorld. */ diff --git a/tutorials/general/t8_step1_coarsemesh.cxx b/tutorials/general/t8_step1_coarsemesh.cxx index 8723922c89..c21a7b26c9 100644 --- a/tutorials/general/t8_step1_coarsemesh.cxx +++ b/tutorials/general/t8_step1_coarsemesh.cxx @@ -20,7 +20,7 @@ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -/* See also: https://github.com/holke/t8code/wiki/Step-1---Creating-a-coarse-mesh +/* See also: https://github.com/DLR-AMR/t8code/wiki/Step-1---Creating-a-coarse-mesh * * In this example we build a coarse mesh with a cube geometry. * The cube is meshed with 6 coarse tetrahedra. diff --git a/tutorials/general/t8_step2_uniform_forest.cxx b/tutorials/general/t8_step2_uniform_forest.cxx index 40bc03e2ed..8f50c99f2f 100644 --- a/tutorials/general/t8_step2_uniform_forest.cxx +++ b/tutorials/general/t8_step2_uniform_forest.cxx @@ -20,7 +20,7 @@ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -/* See also: https://github.com/holke/t8code/wiki/Step-2---Creating-a-uniform-forest +/* See also: https://github.com/DLR-AMR/t8code/wiki/Step-2---Creating-a-uniform-forest * * After we learned how to create a cmesh in step1, we will * now build our first partitioned forest, get its local and global diff --git a/tutorials/general/t8_step4_partition_balance_ghost.cxx b/tutorials/general/t8_step4_partition_balance_ghost.cxx index 2c75649751..c844ff59d8 100644 --- a/tutorials/general/t8_step4_partition_balance_ghost.cxx +++ b/tutorials/general/t8_step4_partition_balance_ghost.cxx @@ -20,7 +20,7 @@ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -/* See also: https://github.com/holke/t8code/wiki/Step-4---Partition,-Balance,-Ghost +/* See also: https://github.com/DLR-AMR/t8code/wiki/Step-4---Partition,-Balance,-Ghost * * This is step4 of the t8code tutorials. * After generating a coarse mesh (step1), building a uniform forest diff --git a/tutorials/general/t8_step5_element_data.cxx b/tutorials/general/t8_step5_element_data.cxx index 25f3cda356..ad39d288de 100644 --- a/tutorials/general/t8_step5_element_data.cxx +++ b/tutorials/general/t8_step5_element_data.cxx @@ -20,7 +20,7 @@ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -/* See also: https://github.com/holke/t8code/wiki/Step-5---Store-element-data +/* See also: https://github.com/DLR-AMR/t8code/wiki/Step-5---Store-element-data * * This is step5 of the t8code tutorials. * In the following we will store data in the individual elements of our forest. diff --git a/tutorials/general/t8_step5_element_data_c_interface.c b/tutorials/general/t8_step5_element_data_c_interface.c index a32596f4ce..b10d637696 100644 --- a/tutorials/general/t8_step5_element_data_c_interface.c +++ b/tutorials/general/t8_step5_element_data_c_interface.c @@ -20,7 +20,7 @@ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -/* See also: https://github.com/holke/t8code/wiki/Step-5---Store-element-data +/* See also: https://github.com/DLR-AMR/t8code/wiki/Step-5---Store-element-data * * This is step5 of the t8code tutorials using the C interface of t8code. * In the following we will store data in the individual elements of our forest. diff --git a/tutorials/general/t8_tutorial_search.cxx b/tutorials/general/t8_tutorial_search.cxx index 8a056468e9..adf6164192 100644 --- a/tutorials/general/t8_tutorial_search.cxx +++ b/tutorials/general/t8_tutorial_search.cxx @@ -20,7 +20,7 @@ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -/* See also: https://github.com/holke/t8code/wiki/Tutorial:-Search +/* See also: https://github.com/DLR-AMR/t8code/wiki/Tutorial:-Search * In this tutorial we discuss t8code's search algorithm. * search is a powerful tool to identify leaf elements that match a given condition * and execute a function on them.