diff --git a/.github/workflows/code_coverage.yml b/.github/workflows/code_coverage.yml index 6ed2b7179f..a46c923465 100644 --- a/.github/workflows/code_coverage.yml +++ b/.github/workflows/code_coverage.yml @@ -91,7 +91,7 @@ jobs: run: export TEST_LEVEL_FLAG="-DT8CODE_TEST_LEVEL=${{ inputs.TEST_LEVEL }}" && echo TEST_LEVEL_FLAG="$TEST_LEVEL_FLAG" >> $GITHUB_ENV - name: build config variables - run: export CONFIG_OPTIONS="${TEST_LEVEL_FLAG} -DT8CODE_CODE_COVERAGE=ON -DT8CODE_USE_SYSTEM_SC=ON -DT8CODE_USE_SYSTEM_P4EST=ON -DT8CODE_BUILD_PEDANTIC=ON -DT8CODE_BUILD_WALL=ON -DT8CODE_BUILD_WERROR=ON -DT8CODE_ENABLE_MPI=$MPI -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DT8CODE_BUILD_FORTRAN_INTERFACE=ON -DSC_DIR=$SC_PATH/install/cmake -DP4EST_DIR=$P4EST_PATH/install/cmake -DT8CODE_BUILD_BENCHMARKS=OFF -DT8CODE_BUILD_DOCUMENTATION=OFF -DT8CODE_BUILD_EXAMPLES=OFF -DT8CODE_BUILD_TUTORIALS=OFF" + run: export CONFIG_OPTIONS="${TEST_LEVEL_FLAG} -DT8CODE_CODE_COVERAGE=ON -DT8CODE_USE_SYSTEM_SC=ON -DT8CODE_USE_SYSTEM_P4EST=ON -DT8CODE_BUILD_PEDANTIC=ON -DT8CODE_BUILD_WALL=ON -DT8CODE_BUILD_WERROR=ON -DT8CODE_ENABLE_MPI=$MPI -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DT8CODE_BUILD_FORTRAN_INTERFACE=ON -DT8CODE_BUILD_MESH_HANDLE=ON -DSC_DIR=$SC_PATH/install/cmake -DP4EST_DIR=$P4EST_PATH/install/cmake -DT8CODE_BUILD_BENCHMARKS=OFF -DT8CODE_BUILD_DOCUMENTATION=OFF -DT8CODE_BUILD_EXAMPLES=OFF -DT8CODE_BUILD_TUTORIALS=OFF" && echo CONFIG_OPTIONS="$CONFIG_OPTIONS" >> $GITHUB_ENV # cmake - name: echo cmake line diff --git a/.github/workflows/tests_cmake_t8code_api.yml b/.github/workflows/tests_cmake_t8code_api.yml index 3291090385..d9524c4867 100644 --- a/.github/workflows/tests_cmake_t8code_api.yml +++ b/.github/workflows/tests_cmake_t8code_api.yml @@ -85,37 +85,35 @@ jobs: run: export TEST_LEVEL_FLAG="-DT8CODE_TEST_LEVEL=${{ inputs.TEST_LEVEL }}" && echo TEST_LEVEL_FLAG="$TEST_LEVEL_FLAG" >> $GITHUB_ENV - name: build config variables - run: export CONFIG_OPTIONS="${TEST_LEVEL_FLAG} -GNinja -DCMAKE_C_FLAGS_DEBUG=${DEBUG_CONFIG} -DCMAKE_CXX_FLAGS_DEBUG=${DEBUG_CONFIG} -DT8CODE_BUILD_FORTRAN_INTERFACE=ON -DT8CODE_USE_SYSTEM_SC=ON -DT8CODE_USE_SYSTEM_P4EST=ON -DT8CODE_BUILD_PEDANTIC=ON -DT8CODE_BUILD_WALL=ON -DT8CODE_BUILD_WERROR=ON -DT8CODE_BUILD_WEXTRA=ON -DT8CODE_ENABLE_MPI=$MPI -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DSC_DIR=$SC_PATH/install/cmake -DP4EST_DIR=$P4EST_PATH/install/cmake" + run: export CONFIG_OPTIONS="${TEST_LEVEL_FLAG} -GNinja -DCMAKE_C_FLAGS_DEBUG=${DEBUG_CONFIG} -DCMAKE_CXX_FLAGS_DEBUG=${DEBUG_CONFIG} -DT8CODE_BUILD_FORTRAN_INTERFACE=ON -DT8CODE_BUILD_MESH_HANDLE=ON -DT8CODE_USE_SYSTEM_SC=ON -DT8CODE_USE_SYSTEM_P4EST=ON -DT8CODE_BUILD_PEDANTIC=ON -DT8CODE_BUILD_WALL=ON -DT8CODE_BUILD_WERROR=ON -DT8CODE_BUILD_WEXTRA=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" + # cmake and test with api options - name: echo cmake line run: echo cmake ../ $CONFIG_OPTIONS - - name: cmake MPI fortran debug - run: mkdir build_fortran && cd build_fortran && cmake ../ $CONFIG_OPTIONS + - name: cmake + run: mkdir build_api && cd build_api && cmake ../ $CONFIG_OPTIONS - name: OnFailUploadLog if: failure() uses: actions/upload-artifact@v5 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: cmake_${{ inputs.BUILD_TYPE }}_MPI_${{ inputs.MPI }}_api.log + path: build_api/CMakeFiles/CMakeOutput.log + - name: ninja + run: cd build_api && ninja $MAKEFLAGS - name: ninja install - run: cd build_fortran && ninja install $MAKEFLAGS + run: cd build_api && ninja install $MAKEFLAGS - name: serial tests (if MPI is enabled) - run: cd build_fortran && ctest $MAKEFLAGS -R _serial + run: cd build_api && ctest $MAKEFLAGS -R _serial if: ${{ inputs.MPI == 'ON' }} - name: parallel tests (if MPI is enabled) - run: cd build_fortran && ctest -R _parallel + run: cd build_api && ctest -R _parallel if: ${{ inputs.MPI == 'ON' }} - name: tests (if MPI is disabled) - run: cd build_fortran && ctest $MAKEFLAGS + run: cd build_api && ctest $MAKEFLAGS if: ${{ inputs.MPI == 'OFF' }} - name: OnFailUploadLog if: failure() uses: actions/upload-artifact@v5 with: - name: test-suite_${{ inputs.BUILD_TYPE }}_MPI_${{ inputs.MPI }}_fortran.log - path: build_fortran/Testing/Temporary/LastTest.log + name: test-suite_${{ inputs.BUILD_TYPE }}_MPI_${{ inputs.MPI }}_api.log + path: build_api/Testing/Temporary/LastTest.log diff --git a/.github/workflows/tests_cmake_valgrind.yml b/.github/workflows/tests_cmake_valgrind.yml index 0d85804095..f0174e6eb3 100644 --- a/.github/workflows/tests_cmake_valgrind.yml +++ b/.github/workflows/tests_cmake_valgrind.yml @@ -86,7 +86,7 @@ jobs: run: export TEST_LEVEL_FLAG="-DT8CODE_TEST_LEVEL=${{ inputs.TEST_LEVEL }}" && echo TEST_LEVEL_FLAG="$TEST_LEVEL_FLAG" >> $GITHUB_ENV - name: build config variables - run: export CONFIG_OPTIONS="${TEST_LEVEL_FLAG} -GNinja -DT8CODE_USE_SYSTEM_SC=ON -DT8CODE_USE_SYSTEM_P4EST=ON -DT8CODE_BUILD_PEDANTIC=ON -DT8CODE_BUILD_WALL=ON -DT8CODE_BUILD_WERROR=ON -DT8CODE_ENABLE_MPI=$MPI -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DSC_DIR=$SC_PATH/install/cmake -DP4EST_DIR=$P4EST_PATH/install/cmake -DT8CODE_BUILD_FORTRAN_INTERFACE=ON" + run: export CONFIG_OPTIONS="${TEST_LEVEL_FLAG} -GNinja -DT8CODE_USE_SYSTEM_SC=ON -DT8CODE_USE_SYSTEM_P4EST=ON -DT8CODE_BUILD_PEDANTIC=ON -DT8CODE_BUILD_WALL=ON -DT8CODE_BUILD_WERROR=ON -DT8CODE_ENABLE_MPI=$MPI -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DSC_DIR=$SC_PATH/install/cmake -DP4EST_DIR=$P4EST_PATH/install/cmake -DT8CODE_BUILD_FORTRAN_INTERFACE=ON -DT8CODE_BUILD_MESH_HANDLE=ON" && echo CONFIG_OPTIONS="$CONFIG_OPTIONS" >> $GITHUB_ENV # cmake - name: echo cmake line diff --git a/CMakeLists.txt b/CMakeLists.txt index 84bed9ad77..c3197a2932 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -48,6 +48,7 @@ cmake_dependent_option( T8CODE_BUILD_TPL_EXAMPLES "Build the examples from libsc option( T8CODE_BUILD_TUTORIALS "Build t8code's tutorials" ON ) option( T8CODE_BUILD_BENCHMARKS "Build t8code's benchmarks" ON ) +option( T8CODE_BUILD_MESH_HANDLE "Build t8code's mesh handle" OFF ) option( T8CODE_BUILD_FORTRAN_INTERFACE "Build t8code's Fortran interface" OFF ) option( T8CODE_ENABLE_MPI "Enable t8code's features which rely on MPI" ON ) @@ -247,6 +248,10 @@ endif() add_subdirectory( ${CMAKE_CURRENT_LIST_DIR}/src ) +if( T8CODE_BUILD_MESH_HANDLE ) + add_subdirectory( ${CMAKE_CURRENT_LIST_DIR}/mesh_handle ) +endif() + if ( T8CODE_BUILD_TESTS ) add_subdirectory( ${CMAKE_CURRENT_LIST_DIR}/test ) endif() diff --git a/doc/Doxyfile.in b/doc/Doxyfile.in index 46db9b0d99..61ae0865d7 100644 --- a/doc/Doxyfile.in +++ b/doc/Doxyfile.in @@ -982,6 +982,7 @@ WARN_LOGFILE = # Note: If this tag is empty the current directory is searched. INPUT = @top_srcdir@/src \ + @top_srcdir@/mesh_handle \ @top_srcdir@/doc/mainpage.dox # This tag can be used to specify the character encoding of the source files diff --git a/mesh_handle/CMakeLists.txt b/mesh_handle/CMakeLists.txt new file mode 100644 index 0000000000..c2d9e1815f --- /dev/null +++ b/mesh_handle/CMakeLists.txt @@ -0,0 +1,54 @@ +# 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) 2025 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. + +# Define own library for mesh handle. +if ( T8CODE_BUILD_AS_SHARED_LIBRARY ) + add_library( T8_MESH_HANDLE SHARED ) + set_target_properties( T8_MESH_HANDLE PROPERTIES POSITION_INDEPENDENT_CODE ON ) +else() + add_library( T8_MESH_HANDLE STATIC ) +endif() + +add_library( T8CODE::T8_MESH_HANDLE ALIAS T8_MESH_HANDLE ) +set_target_properties(T8_MESH_HANDLE PROPERTIES OUTPUT_NAME mesh_handle) + +target_include_directories( T8_MESH_HANDLE PUBLIC + $ + $ +) + +target_sources(T8_MESH_HANDLE PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/mesh.cxx) +install( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + DESTINATION include/ + FILES_MATCHING PATTERN "*.hxx" +) + +target_link_libraries(T8_MESH_HANDLE PUBLIC T8) + +install( TARGETS T8_MESH_HANDLE + EXPORT ${PROJECT_NAME}-targets + ARCHIVE DESTINATION lib + LIBRARY DESTINATION lib + RUNTIME DESTINATION bin +) + +if( T8CODE_EXPORT_COMPILE_COMMANDS ) + set_target_properties( T8_MESH_HANDLE PROPERTIES EXPORT_COMPILE_COMMANDS ON ) +endif( T8CODE_EXPORT_COMPILE_COMMANDS ) diff --git a/mesh_handle/README.md b/mesh_handle/README.md new file mode 100644 index 0000000000..5339218920 --- /dev/null +++ b/mesh_handle/README.md @@ -0,0 +1,11 @@ +# mesh_handle # +**REMARK: Please note that this feature is still work-in-progress, so a lot of functionality is still missing, but will be added step by step.** + +In this folder, we define a mesh handle. +Some application codes are designed for unstructured or uniform meshes and cannot use t8code's tree-based structures directly. For this purpose, an iterable mesh data structure is created as an intermediate level. This frees the users from having to work with the forest-of-trees based concept and increases the usability. Please note that it is not guaranteed that the mesh is conformal and does not contain hanging nodes. + +If you want to use the handle, note that is has its own library. Turn the option `T8CODE_BUILD_MESH_HANDLE` to `ON` and link against the target `T8_MESH_HANDLE` in addition to the usual t8code target please. + +The [mesh.hxx](mesh.hxx) defines the mesh class of the handle. +The [element.hxx](element.hxx) defines the elements used in the mesh class. +The [competences.hxx](competences.hxx) defines additional competences/functionality of an element to access additional data. diff --git a/mesh_handle/competences.hxx b/mesh_handle/competences.hxx new file mode 100644 index 0000000000..c452555fd4 --- /dev/null +++ b/mesh_handle/competences.hxx @@ -0,0 +1,99 @@ +/* +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) 2025 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. +*/ + +/** \file competences.hxx + * Definition of the additional competences/functionalities that can be used for the mesh class. + * Especially, competences to cache functionalities of elements instead of calculating them each time a function + * is called are provided. + * + * All competences have the same inheritance pattern: + * We use the CRTP pattern as we may need to access members of the derived class \ref t8_mesh_handle::element. + * The t8_crtp_operator is used for convenience/clear code (avoid to type a static cast explicitly each time + * we need functionality of TUnderlying). + * Especially for the competences to cache functionality, the access of members is not necessary, + * such that it is not obvious why we use the crtp. For competences that extend the functionality of the element, + * this is required. + * We use it for all competences for consistency and compatibility with the \ref t8_mesh_handle::element class. + */ + +#ifndef T8_COMPETENCES_HXX +#define T8_COMPETENCES_HXX + +#include +#include +#include +#include +#include +#include +#include + +namespace t8_mesh_handle +{ + +/** + * Competence to cache the vertex coordinates of an element at the first function call. + * \tparam TUnderlying Use the \ref element with specified competences as template parameter. + */ +template +struct cache_vertex_coordinates: public t8_crtp_operator +{ + public: + /** + * Function that checks if the cache for the vertex coordinates has been filled. + * \return true if the cache for the vertex coordinates has been filled, false otherwise. + */ + bool + vertex_cache_filled () const + { + return !m_vertex_coordinates.empty (); + } + + protected: + mutable std::vector + m_vertex_coordinates; /**< Cache for the vector of vertex coordinate arrays. Empty vector if not filled. */ +}; + +/** + * Competence to cache the centroid of an element at the first function call. + * \tparam TUnderlying Use the \ref element with specified competences as template parameter. + */ +template +struct cache_centroid: public t8_crtp_operator +{ + public: + /** + * Function that checks if the cache for the centroid has been filled. + * \return true if the cache for the centroid has been filled, false otherwise. + */ + bool + centroid_cache_filled () const + { + return m_centroid.has_value (); + } + + protected: + mutable std::optional + m_centroid; /**< Cache for the coordinates of the centroid. Use optional to allow no value if cache is not filled. */ +}; + +} // namespace t8_mesh_handle +#endif /* !T8_COMPETENCES_HXX */ diff --git a/mesh_handle/element.hxx b/mesh_handle/element.hxx new file mode 100644 index 0000000000..685792e9f7 --- /dev/null +++ b/mesh_handle/element.hxx @@ -0,0 +1,267 @@ +/* +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) 2025 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. +*/ + +/** \file element.hxx + * Definition of the elements used in the \ref t8_mesh_handle::mesh class. + */ + +#ifndef T8_ELEMENT_HXX +#define T8_ELEMENT_HXX + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace t8_mesh_handle +{ +/* Forward declaration of the \ref mesh class of the handle. + */ +template +class mesh; + +/** + * Class for the elements of the mesh handle. + * The element without specified template parameters provides default implementations for basic functionality + * as accessing the refinement level or the centroid. With this implementation, the functionality is calculated each time + * the function is called. + * Use the competences defined in \ref competences.hxx as template parameter to cache the functionality instead of + * recalculating in every function call. + * To add functionality to the element, you can also simply write your own competence class and give it as a template parameter. + * You can access the functions implemented in your competence via the element. + * + * The inheritance pattern is inspired by the \ref T8Type class (which also uses the CRTP). + * We decided to use this structure 1.) to be able to add new functionality easily and + * 2.) for the cached options to keep the number of class member variables of the default to a minimum to save memory. + * The choice between calculate and cache is a tradeoff between runtime and memory usage. + * + * \tparam TCompetence The competences you want to add to the default functionality of the element. + */ +template