From 4bf71635f9bf9c27cfb0c41ff49f2d84dec27905 Mon Sep 17 00:00:00 2001 From: David Knapp Date: Mon, 4 Aug 2025 16:27:44 +0200 Subject: [PATCH 01/20] Added cmesh fortran test --- test/CMakeLists.txt | 1 + .../t8_fortran_interface/t8_test_cmesh.f90 | 76 +++++++++++++++++++ 2 files changed, 77 insertions(+) create mode 100644 test/api/t8_fortran_interface/t8_test_cmesh.f90 diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 21b812aaab..d4e4b73308 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -194,6 +194,7 @@ add_t8_cpp_test( NAME t8_gtest_set_linear_id_serial SOURCES t8_schemes/t add_t8_cpp_test( NAME t8_gtest_elements_are_family_serial SOURCES t8_schemes/t8_gtest_elements_are_family.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 ) + add_t8_test( NAME t8_test_fortran_mpi_interface_cmesh_parallel SOURCES api/t8_fortran_interface/t8_test_cmesh.f90 ) endif() add_t8_cpp_test( NAME t8_gtest_vector_split_serial SOURCES t8_vector_helper/t8_gtest_vector_split.cxx ) diff --git a/test/api/t8_fortran_interface/t8_test_cmesh.f90 b/test/api/t8_fortran_interface/t8_test_cmesh.f90 new file mode 100644 index 0000000000..f6428ae72f --- /dev/null +++ b/test/api/t8_fortran_interface/t8_test_cmesh.f90 @@ -0,0 +1,76 @@ +!! 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, cmesh, geometry + real(c_double), target :: vertices(12) + + 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) + + cmesh = t8_cmesh_new_periodic_tri_f (ccomm) +!! call t8_cmesh_vtk_write_file_f(cmesh, 'test_mpi_init', 0) + call t8_cmesh_destroy_f(cmesh) + + vertices = [0.0_c_double, 0.0_c_double, 0.0_c_double, & + 1.0_c_double, 0.0_c_double, 0.0_c_double, & + 0.0_c_double, 1.0_c_double, 0.0_c_double, & + 1.0_c_double, 1.0_c_double, 0.0_c_double] + + call t8_fortran_cmesh_init_f(cmesh) + geometry = t8_fortran_geometry_linear_new_f (2) + call t8_fortran_cmesh_register_geometry_f(cmesh, geometry) + call t8_fortran_cmesh_set_tree_class_f(cmesh, int(0, kind=8), 2) + call t8_fortran_cmesh_set_tree_vertices_f(cmesh, int(0, kind=8), c_loc(vertices), 4) + call t8_fortran_cmesh_commit_f(cmesh, ccomm) + call t8_cmesh_destroy_f(cmesh) + + call t8_fortran_finalize_f () + call t8_fortran_mpi_comm_delete_f(ccomm) + call MPI_Finalize(ierror) + + if (ierror /= 0) then + print *, 'MPI Finalize failed.' + stop 1 + endif + print *, 'All good!' + stop 0 + +end program From 6712f0356d8d39efc43488ccdd43c17fcd9514a7 Mon Sep 17 00:00:00 2001 From: David Knapp Date: Tue, 5 Aug 2025 16:58:28 +0200 Subject: [PATCH 02/20] Add function that tests the interface call to set_join_by_vertices --- .../t8_fortran_interface_mod.f90 | 5 +-- .../t8_fortran_interface/t8_test_cmesh.f90 | 36 ++++++++++++++++--- 2 files changed, 34 insertions(+), 7 deletions(-) diff --git a/api/t8_fortran_interface/t8_fortran_interface_mod.f90 b/api/t8_fortran_interface/t8_fortran_interface_mod.f90 index 3facffbb9a..7c74c08504 100644 --- a/api/t8_fortran_interface/t8_fortran_interface_mod.f90 +++ b/api/t8_fortran_interface/t8_fortran_interface_mod.f90 @@ -162,14 +162,15 @@ 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') + subroutine t8_fortran_cmesh_set_join_by_vertices_noConn_f (cmesh, ntrees, eclasses, vertices, & + connectivity, do_both_directions) bind (c, name = 't8_cmesh_set_join_by_vertices') 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 + type (c_ptr), value :: connectivity integer (c_int), value :: do_both_directions end subroutine t8_fortran_cmesh_set_join_by_vertices_noConn_f end Interface diff --git a/test/api/t8_fortran_interface/t8_test_cmesh.f90 b/test/api/t8_fortran_interface/t8_test_cmesh.f90 index f6428ae72f..ca7a51b140 100644 --- a/test/api/t8_fortran_interface/t8_test_cmesh.f90 +++ b/test/api/t8_fortran_interface/t8_test_cmesh.f90 @@ -32,7 +32,8 @@ program t8_test_mpi_init integer :: ierror, fcomm type(c_ptr) :: ccomm, cmesh, geometry - real(c_double), target :: vertices(12) + real(c_double), target :: vertices_tri_0(9), vertices_tri_1(9), vertices_total(18) + integer(c_int), target :: eclasses(2) call MPI_Init (ierror) @@ -49,16 +50,41 @@ program t8_test_mpi_init !! call t8_cmesh_vtk_write_file_f(cmesh, 'test_mpi_init', 0) call t8_cmesh_destroy_f(cmesh) - vertices = [0.0_c_double, 0.0_c_double, 0.0_c_double, & + vertices_tri_0 = [0.0_c_double, 0.0_c_double, 0.0_c_double, & 1.0_c_double, 0.0_c_double, 0.0_c_double, & - 0.0_c_double, 1.0_c_double, 0.0_c_double, & 1.0_c_double, 1.0_c_double, 0.0_c_double] + vertices_tri_1 = [0.0_c_double, 0.0_c_double, 0.0_c_double, & + 1.0_c_double, 1.0_c_double, 0.0_c_double, & + 0.0_c_double, 1.0_c_double, 0.0_c_double] + vertices_total = [vertices_tri_0, vertices_tri_1] + + !! Create a test quad mesh with 2 triangles in a square + call t8_fortran_cmesh_init_f(cmesh) + !! Create and register a geometry for linear triangles + geometry = t8_fortran_geometry_linear_new_f (2) + call t8_fortran_cmesh_register_geometry_f(cmesh, geometry) + !! Set tree class + call t8_fortran_cmesh_set_tree_class_f(cmesh, int(0, kind=8), 3) + call t8_fortran_cmesh_set_tree_class_f(cmesh, int(1, kind=8), 3) + !! Set tree vertices for the two triangles + call t8_fortran_cmesh_set_tree_vertices_f(cmesh, int(0, kind=8), c_loc(vertices_tri_0), 3) + call t8_fortran_cmesh_set_tree_vertices_f(cmesh, int(1, kind=8), c_loc(vertices_tri_1), 3) + !! Set connections between the two triangles + call t8_fortran_cmesh_set_join_f(cmesh, int(0, kind=8), int(1, kind=8), 1, 2, 0) + call t8_fortran_cmesh_commit_f(cmesh, ccomm) + call t8_cmesh_destroy_f(cmesh) + + !! Create the same mesh again, but let t8code find the connectivity + eclasses = [3, 3] call t8_fortran_cmesh_init_f(cmesh) geometry = t8_fortran_geometry_linear_new_f (2) call t8_fortran_cmesh_register_geometry_f(cmesh, geometry) - call t8_fortran_cmesh_set_tree_class_f(cmesh, int(0, kind=8), 2) - call t8_fortran_cmesh_set_tree_vertices_f(cmesh, int(0, kind=8), c_loc(vertices), 4) + call t8_fortran_cmesh_set_tree_class_f(cmesh, int(0, kind=8), 3) + call t8_fortran_cmesh_set_tree_class_f(cmesh, int(1, kind=8), 3) + call t8_fortran_cmesh_set_tree_vertices_f(cmesh, int(0, kind=8), c_loc(vertices_tri_0), 3) + call t8_fortran_cmesh_set_tree_vertices_f(cmesh, int(1, kind=8), c_loc(vertices_tri_1), 3) + call t8_fortran_cmesh_set_join_by_vertices_noConn_f(cmesh, 2, c_loc(eclasses), c_loc(vertices_total), C_NULL_PTR, 0) call t8_fortran_cmesh_commit_f(cmesh, ccomm) call t8_cmesh_destroy_f(cmesh) From f42f4f03fac1a51a779b0da6f65d6e93c888882b Mon Sep 17 00:00:00 2001 From: David Knapp Date: Fri, 8 Aug 2025 11:11:10 +0200 Subject: [PATCH 03/20] fix names --- api/t8_fortran_interface/t8_fortran_interface_mod.f90 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/api/t8_fortran_interface/t8_fortran_interface_mod.f90 b/api/t8_fortran_interface/t8_fortran_interface_mod.f90 index 7c74c08504..78179b3593 100644 --- a/api/t8_fortran_interface/t8_fortran_interface_mod.f90 +++ b/api/t8_fortran_interface/t8_fortran_interface_mod.f90 @@ -240,7 +240,7 @@ end function t8_forest_get_local_num_leaf_elements Interface integer (c_int) function t8_forest_get_global_num_elements (forest) & - bind (c, name = 't8_forest_get_global_num_elements') + bind (c, name = 't8_forest_get_global_num_leaf_elements') use, intrinsic :: ISO_C_BINDING, only: c_ptr, c_int IMPLICIT NONE type (c_ptr), value :: forest @@ -258,7 +258,7 @@ end function t8_forest_get_num_local_trees Interface integer (c_int) function t8_forest_get_tree_num_elements (forest, ltreeid) & - bind (c, name = 't8_forest_get_tree_num_elements') + bind (c, name = 't8_forest_get_tree_num_leaf_elements') use, intrinsic :: ISO_C_BINDING, only: c_ptr, c_int IMPLICIT NONE type (c_ptr), value :: forest @@ -268,7 +268,7 @@ end function t8_forest_get_tree_num_elements 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') + bind (c, name = 't8_forest_get_leaf_element_in_tree') use, intrinsic :: ISO_C_BINDING, only: c_ptr, c_int IMPLICIT NONE type (c_ptr), value :: forest From f6d6754b740998ece9a06da4aa13e5b208908ad1 Mon Sep 17 00:00:00 2001 From: David Knapp Date: Fri, 8 Aug 2025 11:11:25 +0200 Subject: [PATCH 04/20] fix memory leaks --- test/api/t8_fortran_interface/t8_test_cmesh.f90 | 7 ++++--- test/api/t8_fortran_interface/t8_test_mpi_init.f90 | 6 ++++++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/test/api/t8_fortran_interface/t8_test_cmesh.f90 b/test/api/t8_fortran_interface/t8_test_cmesh.f90 index ca7a51b140..6890abe017 100644 --- a/test/api/t8_fortran_interface/t8_test_cmesh.f90 +++ b/test/api/t8_fortran_interface/t8_test_cmesh.f90 @@ -20,10 +20,11 @@ !! Description: !! -!! This program tests if t8code can be initialized from Fortran -!! with given MPI communicator. Works only when MPI is enabled. +!! This program tests if the cmesh part of the Fortran +!! interface can be called. +!! Works only when MPI is enabled. -program t8_test_mpi_init +program t8_test_cmesh use mpi use iso_c_binding, only: c_ptr, c_int use t8_fortran_interface_mod diff --git a/test/api/t8_fortran_interface/t8_test_mpi_init.f90 b/test/api/t8_fortran_interface/t8_test_mpi_init.f90 index 665a6d0ec7..8283b62a1f 100644 --- a/test/api/t8_fortran_interface/t8_test_mpi_init.f90 +++ b/test/api/t8_fortran_interface/t8_test_mpi_init.f90 @@ -45,6 +45,12 @@ program t8_test_mpi_init call t8_fortran_init_all_f (ccomm) call t8_fortran_finalize_f () + call t8_fortran_mpi_comm_delete_f(ccomm) + call MPI_Finalize(ierror) + if (ierror /= 0) then + print *, 'MPI Finalize failed.' + stop 1 + endif print *, 'All good!' stop 0 From 5a7dda4af11f2619936e4f0d8c937e2c5671c624 Mon Sep 17 00:00:00 2001 From: David Knapp Date: Fri, 8 Aug 2025 11:11:46 +0200 Subject: [PATCH 05/20] Add new test --- test/CMakeLists.txt | 1 + .../t8_fortran_interface/t8_test_forest.f90 | 72 +++++++++++++++++++ 2 files changed, 73 insertions(+) create mode 100644 test/api/t8_fortran_interface/t8_test_forest.f90 diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index d4e4b73308..d26804f659 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -195,6 +195,7 @@ add_t8_cpp_test( NAME t8_gtest_elements_are_family_serial SOURCES t8_schemes/t 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 ) add_t8_test( NAME t8_test_fortran_mpi_interface_cmesh_parallel SOURCES api/t8_fortran_interface/t8_test_cmesh.f90 ) + add_t8_test( NAME t8_test_fortran_mpi_interface_forest_parallel SOURCES api/t8_fortran_interface/t8_test_forest.f90 ) endif() add_t8_cpp_test( NAME t8_gtest_vector_split_serial SOURCES t8_vector_helper/t8_gtest_vector_split.cxx ) diff --git a/test/api/t8_fortran_interface/t8_test_forest.f90 b/test/api/t8_fortran_interface/t8_test_forest.f90 new file mode 100644 index 0000000000..5779a25150 --- /dev/null +++ b/test/api/t8_fortran_interface/t8_test_forest.f90 @@ -0,0 +1,72 @@ +!! 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 the forest part of the Fortran +!! interface can be called. +!! Works only when MPI is enabled. + +program t8_test_forest + use mpi + use iso_c_binding, only: c_ptr, c_int + use t8_fortran_interface_mod + + implicit none + + integer :: ierror, fcomm + integer :: num_local_elements, num_global_elements, num_local_trees + type(c_ptr) :: ccomm, cmesh, forest, element + integer :: num_elems_in_tree + real(c_double) :: ref_coords(3), out_coords(3) + + 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) + + cmesh = t8_cmesh_new_periodic_tri_f (ccomm) + forest = t8_forest_new_uniform_default_f (cmesh, 2, 0, ccomm) + !! ierror = t8_forest_write_vtk_f (forest, 'test_forest') + num_local_elements = t8_forest_get_local_num_leaf_elements (forest) + num_global_elements = t8_forest_get_global_num_elements (forest) + num_local_trees = t8_forest_get_num_local_trees (forest) + num_elems_in_tree = t8_forest_get_tree_num_elements (forest, 0) + element = t8_forest_get_element_in_tree (forest, 0, 0) + ref_coords = [0.5_c_double, 0.5_c_double, 0.0_c_double] + call t8_forest_element_from_ref_coords (forest, 0, element, ref_coords, 1, out_coords) + call t8_forest_unref_f (forest) + call t8_fortran_finalize_f () + call t8_fortran_mpi_comm_delete_f(ccomm) + call MPI_Finalize(ierror) + if (ierror /= 0) then + print *, 'MPI Finalize failed.' + stop 1 + endif + + print *, 'All good!' + stop 0 +end program From a3def715b8257b4e12b188f9a290e6657b5069c7 Mon Sep 17 00:00:00 2001 From: David Knapp Date: Fri, 8 Aug 2025 12:24:36 +0200 Subject: [PATCH 06/20] output not working --- test/api/t8_fortran_interface/t8_test_forest.f90 | 1 + 1 file changed, 1 insertion(+) diff --git a/test/api/t8_fortran_interface/t8_test_forest.f90 b/test/api/t8_fortran_interface/t8_test_forest.f90 index 5779a25150..7dececc712 100644 --- a/test/api/t8_fortran_interface/t8_test_forest.f90 +++ b/test/api/t8_fortran_interface/t8_test_forest.f90 @@ -61,6 +61,7 @@ program t8_test_forest call t8_forest_unref_f (forest) call t8_fortran_finalize_f () call t8_fortran_mpi_comm_delete_f(ccomm) + !! call t8_global_productionf_noargs_f ('Finalize forest tests') call MPI_Finalize(ierror) if (ierror /= 0) then print *, 'MPI Finalize failed.' From 85b140c368a8210f362a0c6a4fb3700b01c9ac0e Mon Sep 17 00:00:00 2001 From: Thomas Spenke Date: Mon, 2 Feb 2026 10:34:36 +0100 Subject: [PATCH 07/20] Remove duplicated section in t8_test_mpi_init.f90 --- test/api/t8_fortran_interface/t8_test_mpi_init.f90 | 6 ------ 1 file changed, 6 deletions(-) diff --git a/test/api/t8_fortran_interface/t8_test_mpi_init.f90 b/test/api/t8_fortran_interface/t8_test_mpi_init.f90 index 18e1130128..4fb9bc1b0c 100644 --- a/test/api/t8_fortran_interface/t8_test_mpi_init.f90 +++ b/test/api/t8_fortran_interface/t8_test_mpi_init.f90 @@ -45,12 +45,6 @@ program t8_test_mpi_init call t8_fortran_init_all_f (ccomm) call t8_fortran_finalize_f () - call t8_fortran_mpi_comm_delete_f(ccomm) - call MPI_Finalize(ierror) - if (ierror /= 0) then - print *, 'MPI Finalize failed.' - stop 1 - endif call t8_fortran_mpi_comm_delete_f(ccomm) From caced0f64a10a8d1c6e67ad0dc6e3d8e64ee080d Mon Sep 17 00:00:00 2001 From: Thomas Spenke Date: Mon, 2 Feb 2026 10:36:44 +0100 Subject: [PATCH 08/20] Correct years of new files in Copyright statement --- test/api/t8_fortran_interface/t8_test_cmesh.f90 | 2 +- test/api/t8_fortran_interface/t8_test_forest.f90 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/api/t8_fortran_interface/t8_test_cmesh.f90 b/test/api/t8_fortran_interface/t8_test_cmesh.f90 index 6890abe017..2ad5b30ee5 100644 --- a/test/api/t8_fortran_interface/t8_test_cmesh.f90 +++ b/test/api/t8_fortran_interface/t8_test_cmesh.f90 @@ -2,7 +2,7 @@ !! 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 +!! Copyright (C) 2026 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 diff --git a/test/api/t8_fortran_interface/t8_test_forest.f90 b/test/api/t8_fortran_interface/t8_test_forest.f90 index 7dececc712..135dc965e7 100644 --- a/test/api/t8_fortran_interface/t8_test_forest.f90 +++ b/test/api/t8_fortran_interface/t8_test_forest.f90 @@ -2,7 +2,7 @@ !! 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 +!! Copyright (C) 2026 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 From 442b8155e18772955b8ddd6ff6e33144ee7d3939 Mon Sep 17 00:00:00 2001 From: Thomas Spenke Date: Mon, 2 Feb 2026 13:08:40 +0100 Subject: [PATCH 09/20] Try to add FORTRAN interface to code coverage --- .github/workflows/code_coverage.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/code_coverage.yml b/.github/workflows/code_coverage.yml index 8e9e664852..4320ddd32c 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 -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" + run: export CONFIG_OPTIONS="${TEST_LEVEL_FLAG} -DCMAKE_Fortran_FLAGS='-fprofile-arcs -ftest-coverage' -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 From 664e85605df76b7505fe01ce49d1dc8d3e5662d8 Mon Sep 17 00:00:00 2001 From: Thomas Spenke Date: Thu, 5 Feb 2026 09:33:33 +0100 Subject: [PATCH 10/20] Added tests for all fortran interface functions except iterate_replace --- api/t8_fortran_interface/CMakeLists.txt | 2 +- .../t8_fortran_example_adapt_mod.f90 | 48 +++++++++++++++++ .../t8_fortran_interface.c | 42 ++++++++------- .../t8_fortran_interface.h | 40 +++++++++------ .../t8_fortran_interface_mod.f90 | 51 +++++++++++-------- cmake/CodeCoverage.cmake | 10 +++- src/t8_vtk/t8_vtk_writer.h | 2 +- src/t8_vtk/t8_vtk_writer.hxx | 3 +- test/CMakeLists.txt | 1 + .../t8_fortran_interface/t8_test_cmesh.f90 | 12 ++++- .../t8_fortran_interface/t8_test_forest.f90 | 42 ++++++++++++--- .../t8_test_init_no_mpi.f90 | 45 ++++++++++++++++ 12 files changed, 230 insertions(+), 68 deletions(-) create mode 100644 api/t8_fortran_interface/t8_fortran_example_adapt_mod.f90 create mode 100644 test/api/t8_fortran_interface/t8_test_init_no_mpi.f90 diff --git a/api/t8_fortran_interface/CMakeLists.txt b/api/t8_fortran_interface/CMakeLists.txt index 808df5d56f..82f2ff74e0 100644 --- a/api/t8_fortran_interface/CMakeLists.txt +++ b/api/t8_fortran_interface/CMakeLists.txt @@ -1,6 +1,6 @@ # 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 ) +target_sources( T8 PRIVATE t8_fortran_interface_mod.f90 t8_fortran_example_adapt_mod.f90 ) # Add this directory to header search path. diff --git a/api/t8_fortran_interface/t8_fortran_example_adapt_mod.f90 b/api/t8_fortran_interface/t8_fortran_example_adapt_mod.f90 new file mode 100644 index 0000000000..448f175475 --- /dev/null +++ b/api/t8_fortran_interface/t8_fortran_example_adapt_mod.f90 @@ -0,0 +1,48 @@ +! 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) 2026 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 file contains a module with an example callback of the Fortran interface +! that refines and coarsenes some elements based on their centroids' coordinates. +module t8_fortran_example_adapt_mod + use t8_fortran_interface_mod + +contains + + ! Example callback for adapting based on the centroid coordinates x, y, z. + function example_fortran_adapt_by_coordinates_callback(x, y, z, is_family) & + & result(ret) bind(c, name="example_fortran_adapt_by_coordinates_callback") + use, intrinsic :: ISO_C_BINDING, only: c_int, c_double + real(c_double), value :: x + real(c_double), value :: y + real(c_double), value :: z + integer(c_int), value :: is_family + integer(c_int) :: ret + ret = 0 + if(x < 0.5d0 .and. y < 0.5d0 .and. z < 0.5d0) then + ret = 1 + elseif(x > 0.5d0 .and. y > 0.5d0) then + if(is_family.ne.0) then + ret = -1 + endif + endif + + end function example_fortran_adapt_by_coordinates_callback + +end module t8_fortran_example_adapt_mod \ No newline at end of file diff --git a/api/t8_fortran_interface/t8_fortran_interface.c b/api/t8_fortran_interface/t8_fortran_interface.c index 9cb3f408ac..d6ab684117 100644 --- a/api/t8_fortran_interface/t8_fortran_interface.c +++ b/api/t8_fortran_interface/t8_fortran_interface.c @@ -21,12 +21,14 @@ */ #include -#include -#include #include #include +#include +#include +#include #include #include +#include void t8_fortran_init_all_ (sc_MPI_Comm *comm) @@ -51,12 +53,6 @@ t8_fortran_cmesh_commit (t8_cmesh_t cmesh, sc_MPI_Comm *comm) t8_cmesh_commit (cmesh, *comm); } -void -t8_fortran_cmesh_set_join_by_stash_noConn (t8_cmesh_t cmesh, const int do_both_directions) -{ - t8_cmesh_set_join_by_stash (cmesh, NULL, do_both_directions); -} - void t8_fortran_init_all (sc_MPI_Comm *comm) { @@ -114,6 +110,18 @@ t8_cmesh_new_periodic_tri_wrap (sc_MPI_Comm *Ccomm) return t8_cmesh_new_periodic_tri (*Ccomm); } +int +t8_forest_write_vtk_wrap (t8_forest_t forest, const char *fileprefix) +{ + return t8_forest_write_vtk (forest, fileprefix) ? 0 : 1; +} + +int +t8_cmesh_vtk_write_file_wrap (t8_cmesh_t cmesh, const char *fileprefix) +{ + return t8_cmesh_vtk_write_file (cmesh, fileprefix) ? 0 : 1; +} + t8_forest_t t8_forest_new_uniform_default (t8_cmesh_t cmesh, int level, int do_face_ghost, sc_MPI_Comm *comm) { @@ -127,16 +135,14 @@ int t8_fortran_adapt_by_coordinates_callback (t8_forest_t forest, t8_forest_t forest_from, t8_locidx_t which_tree, const t8_eclass_t tree_class, __attribute__ ((unused)) t8_locidx_t lelement_id, const t8_scheme_c *scheme, - const int is_family, const int num_elements, t8_element_t *elements[]) + const int is_family, __attribute__ ((unused)) const int num_elements, + t8_element_t *elements[]) { t8_fortran_adapt_coordinate_callback callback = (t8_fortran_adapt_coordinate_callback) t8_forest_get_user_function (forest); double midpoint[3]; - t8_forest_element_centroid (forest_from, which_tree, elements[0], midpoint); - t8_debugf ("Coord: %.2f\n", midpoint[0]); - int ret = callback (midpoint[0], midpoint[1], midpoint[2], num_elements > 0); - /* Coarsen if a family was given and return value is negative. */ + /* If a family was given, form parent first to feed its centroid into the callback. */ if (is_family) { /* The elements form a family */ T8_ASSERT (t8_elements_are_family (scheme, tree_class, elements)); @@ -146,14 +152,16 @@ t8_fortran_adapt_by_coordinates_callback (t8_forest_t forest, t8_forest_t forest t8_element_get_parent (scheme, tree_class, elements[0], parent); /* Get the coordinates of the parent. */ t8_forest_element_centroid (forest_from, which_tree, parent, midpoint); - - ret = callback (midpoint[0], midpoint[1], midpoint[2], 1); + /* Deallocate parent element to avoid memory leakage. */ + t8_element_destroy (scheme, tree_class, 1, &parent); } else { /* The elements do not form a family. */ - /* Get the coordinates of the first element and call callback */ + /* Get the coordinates of the first element.*/ t8_forest_element_centroid (forest_from, which_tree, elements[0], midpoint); - ret = callback (midpoint[0], midpoint[1], midpoint[2], 0); + } + int ret = callback (midpoint[0], midpoint[1], midpoint[2], is_family); + if (!is_family) { T8_ASSERT (ret >= 0); } return ret; diff --git a/api/t8_fortran_interface/t8_fortran_interface.h b/api/t8_fortran_interface/t8_fortran_interface.h index b9a6a8c670..48fdda6d14 100644 --- a/api/t8_fortran_interface/t8_fortran_interface.h +++ b/api/t8_fortran_interface/t8_fortran_interface.h @@ -21,11 +21,11 @@ */ /** \file t8_fortran_interface.h - * In this file we provide a basic Fortran interface + * In this file we provide a basic Fortran interface * for some functions of t8code. * Mostly, the C functions here are wrappers around more complex * t8code function. - * We only export a minimum of the actual t8code functionality + * We only export a minimum of the actual t8code functionality * to Fortran. */ @@ -73,19 +73,6 @@ t8_fortran_finalize (); void t8_fortran_cmesh_commit (t8_cmesh_t cmesh, sc_MPI_Comm *comm); -/** This function calls t8_cmesh_set_join_by_stash with connectivity = NULL. - * \param[in,out] cmesh Pointer to a t8code cmesh object. If set to NULL this argument is ignored. - * \param[in] do_both_directions Compute the connectivity from both neighboring sides. - * Takes much longer to compute. - * - * \warning This routine might be too expensive for very large meshes. In this case, - * consider to use a fully featured mesh generator. - * - * \note This routine does not detect periodic boundaries. -*/ -void -t8_fortran_cmesh_set_join_by_stash_noConn (t8_cmesh_t cmesh, const int do_both_directions); - /** Translate a fortran MPI communicator into a C MPI communicator * and return a pointer to it. * \param [in] Fcomm Fortran MPI Communicator @@ -112,6 +99,27 @@ t8_fortran_MPI_Comm_delete (sc_MPI_Comm *Ccomm); t8_cmesh_t t8_cmesh_new_periodic_tri_wrap (sc_MPI_Comm *Ccomm); +/** + * Wraps t8_forest_write_vtk, passing back an error flag instead of true/false, so non-zero means + * fail, zero success. + * \param [in] forest The forest + * \param [in] fileprefix The file name prefix + * \return 0 if successful, 1 otherwise + */ +int +t8_forest_write_vtk_wrap (t8_forest_t forest, const char *fileprefix); + +/** + * Wraps t8_cmesh_vtk_write_file, passing back an error flag instead of true/false, so non-zero means + * fail, zero success. + * + * \param[in] cmesh The cmesh + * \param[in] fileprefix The prefix of the output files + * \return 0 if successful, 1 otherwise + */ +int +t8_cmesh_vtk_write_file_wrap (t8_cmesh_t cmesh, const char *fileprefix); + /** Wraps \ref t8_forest_new_uniform with the default scheme as scheme * and passes MPI communicator as pointer instead of by value. * Build a uniformly refined forest on a coarse mesh. @@ -125,7 +133,7 @@ t8_cmesh_new_periodic_tri_wrap (sc_MPI_Comm *Ccomm); t8_forest_t t8_forest_new_uniform_default (t8_cmesh_t cmesh, int level, int do_face_ghost, sc_MPI_Comm *comm); -/** +/** * \param [in, out] forest The forest * \param [in] recursive A flag specifying whether adaptation is to be done recursively * or not. If the value is zero, adaptation is not recursive diff --git a/api/t8_fortran_interface/t8_fortran_interface_mod.f90 b/api/t8_fortran_interface/t8_fortran_interface_mod.f90 index 78179b3593..71715c5488 100644 --- a/api/t8_fortran_interface/t8_fortran_interface_mod.f90 +++ b/api/t8_fortran_interface/t8_fortran_interface_mod.f90 @@ -18,11 +18,10 @@ !! along with t8code; if not, write to the Free Software Foundation, Inc., !! 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +!! This file contains the module with t8code's Fortran interface. 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. @@ -49,7 +48,7 @@ subroutine t8_fortran_mpi_comm_delete_f (Ccomm) & 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) & @@ -60,7 +59,7 @@ subroutine t8_fortran_init_all_f (Ccomm) & END subroutine t8_fortran_init_all_f end Interface - !!! Initialize sc and t8code with a given C MPI Communicator + !!! 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') @@ -77,13 +76,12 @@ 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') + integer (c_int) function t8_cmesh_vtk_write_file_f (cmesh, fileprefix) & + bind (c, name = 't8_cmesh_vtk_write_file_wrap') 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 @@ -160,7 +158,7 @@ subroutine t8_fortran_cmesh_set_join_f (cmesh, gtree1, gtree2, face1, face2, ori 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, & connectivity, do_both_directions) bind (c, name = 't8_cmesh_set_join_by_vertices') @@ -210,7 +208,7 @@ end subroutine t8_forest_unref_f Interface integer (c_int) function t8_forest_write_vtk_f (forest, fileprefix) & - bind (c, name = 't8_forest_write_vtk') + bind (c, name = 't8_forest_write_vtk_wrap') use, intrinsic :: ISO_C_BINDING, only: c_ptr, c_int, c_char, c_double IMPLICIT NONE type (c_ptr), value :: forest @@ -219,6 +217,7 @@ end function t8_forest_write_vtk_f end Interface Interface + ! TODO: Not covered 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 @@ -303,19 +302,31 @@ subroutine t8_fortran_finalize_f () & 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 + function t8_fortran_adapt(forest, fortran_callback, recursive) result(new_forest) & + bind (c, name = 't8_fortran_adapt_c') + import :: c_funptr, c_ptr, c_int + type(c_ptr), value :: forest + type(c_funptr), value :: fortran_callback + integer (c_int), value :: recursive + type (c_ptr) :: new_forest + end function t8_fortran_adapt + end interface + + Interface + function t8_fortran_adapt_by_coordinates_f (forest, recursive, callback) result(new_forest) & + bind (c, name = 't8_forest_adapt_by_coordinates') + use, intrinsic :: ISO_C_BINDING, only : c_ptr, c_int, c_funptr + IMPLICIT NONE + type (c_ptr), value :: forest + integer (c_int), value :: recursive + type(c_funptr), value :: callback + type (c_ptr) :: new_forest + end function t8_fortran_adapt_by_coordinates_f + end Interface Interface - subroutine t8_fortran_element_volume_f (forest, ltreeid, element) & + 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 diff --git a/cmake/CodeCoverage.cmake b/cmake/CodeCoverage.cmake index a08a300b16..6931b6c4d0 100644 --- a/cmake/CodeCoverage.cmake +++ b/cmake/CodeCoverage.cmake @@ -103,6 +103,12 @@ endfunction() # setup_target_for_coverage append_coverage_compiler_flags() setup_target_for_coverage( NAME coverage - EXCLUDE "${CMAKE_SOURCE_DIR}/sc*" "${CMAKE_SOURCE_DIR}/p4est*" "${CMAKE_SOURCE_DIR}/test*" "${CMAKE_SOURCE_DIR}/thirdparty*" "${CMAKE_SOURCE_DIR}/tutorials*" "${CMAKE_SOURCE_DIR}/example*" "${CMAKE_SOURCE_DIR}/benchmarks*" - LCOV_ARGS --no-external --ignore-errors gcov + # EXCLUDE "${CMAKE_SOURCE_DIR}/sc*" "${CMAKE_SOURCE_DIR}/p4est*" "${CMAKE_SOURCE_DIR}/test*" "${CMAKE_SOURCE_DIR}/thirdparty*" "${CMAKE_SOURCE_DIR}/tutorials*" "${CMAKE_SOURCE_DIR}/example*" "${CMAKE_SOURCE_DIR}/benchmarks*" "${CMAKE_SOURCE_DIR}/CMakeFortranCompilerId.F" + # # EXCLUDE "${CMAKE_SOURCE_DIR}/sc*" "${CMAKE_SOURCE_DIR}/p4est*" "${CMAKE_SOURCE_DIR}/test*" "${CMAKE_SOURCE_DIR}/thirdparty*" "${CMAKE_SOURCE_DIR}/tutorials*" "${CMAKE_SOURCE_DIR}/example*" "${CMAKE_SOURCE_DIR}/benchmarks*" "${CMAKE_SOURCE_DIR}/CMakeFortranCompilerId.F" "${CMAKE_BINARY_DIR}/*" + # LCOV_ARGS --no-external --ignore-errors gcov,mismatch,unused,unmapped + # EXCLUDE "${CMAKE_SOURCE_DIR}/sc*" "${CMAKE_SOURCE_DIR}/p4est*" "${CMAKE_SOURCE_DIR}/test*" "${CMAKE_SOURCE_DIR}/thirdparty*" "${CMAKE_SOURCE_DIR}/tutorials*" "${CMAKE_SOURCE_DIR}/example*" "${CMAKE_SOURCE_DIR}/benchmarks*" "${CMAKE_SOURCE_DIR}/CMakeFortranCompilerId.F" + EXCLUDE "${CMAKE_SOURCE_DIR}/sc*" "${CMAKE_SOURCE_DIR}/p4est*" "${CMAKE_SOURCE_DIR}/test*" "${CMAKE_SOURCE_DIR}/thirdparty*" "${CMAKE_SOURCE_DIR}/tutorials*" "${CMAKE_SOURCE_DIR}/example*" "${CMAKE_SOURCE_DIR}/benchmarks*" "${CMAKE_SOURCE_DIR}/CMakeFortranCompilerId.F" "${CMAKE_BINARY_DIR}/*" + LCOV_ARGS --no-external --ignore-errors gcov,mismatch,unused + # EXCLUDE "${CMAKE_SOURCE_DIR}/sc*" "${CMAKE_SOURCE_DIR}/p4est*" "${CMAKE_SOURCE_DIR}/test*" "${CMAKE_SOURCE_DIR}/thirdparty*" "${CMAKE_SOURCE_DIR}/tutorials*" "${CMAKE_SOURCE_DIR}/example*" "${CMAKE_SOURCE_DIR}/benchmarks*" + # LCOV_ARGS --no-external --ignore-errors gcov,mismatch,unused ) \ No newline at end of file diff --git a/src/t8_vtk/t8_vtk_writer.h b/src/t8_vtk/t8_vtk_writer.h index 4b8d47a884..6fd1396562 100644 --- a/src/t8_vtk/t8_vtk_writer.h +++ b/src/t8_vtk/t8_vtk_writer.h @@ -140,7 +140,7 @@ t8_cmesh_vtk_write_file_via_API (t8_cmesh_t cmesh, const char *fileprefix, sc_MP * * \param[in] cmesh The cmesh * \param[in] fileprefix The prefix of the output files - * \return int + * \return True (nonzero) if successful, false (zero) otherwise */ int t8_cmesh_vtk_write_file (t8_cmesh_t cmesh, const char *fileprefix); diff --git a/src/t8_vtk/t8_vtk_writer.hxx b/src/t8_vtk/t8_vtk_writer.hxx index 2e8c1b8aa0..aae073b48a 100644 --- a/src/t8_vtk/t8_vtk_writer.hxx +++ b/src/t8_vtk/t8_vtk_writer.hxx @@ -131,8 +131,7 @@ struct vtk_writer * A vtk-writer function that uses the vtk API * * \param[in] grid The forest or cmesh that is translated - * \return true - * \return false + * \return True if successful, false if not */ bool write_ASCII (const grid_t grid); diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 2bf8bac8a4..d7644efbd1 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -203,6 +203,7 @@ add_t8_cpp_test( NAME t8_gtest_face_corner_serial SOURCES t8_schemes/t add_t8_cpp_test( NAME t8_gtest_set_linear_id_serial SOURCES t8_schemes/t8_gtest_set_linear_id.cxx ) add_t8_cpp_test( NAME t8_gtest_elements_are_family_serial SOURCES t8_schemes/t8_gtest_elements_are_family.cxx ) if( T8CODE_BUILD_FORTRAN_INTERFACE AND T8CODE_ENABLE_MPI ) + add_t8_test( NAME t8_test_fortran_mpi_interface_init_serial SOURCES api/t8_fortran_interface/t8_test_init_no_mpi.f90 ) add_t8_test( NAME t8_test_fortran_mpi_interface_init_parallel SOURCES api/t8_fortran_interface/t8_test_mpi_init.f90 ) add_t8_test( NAME t8_test_fortran_mpi_interface_cmesh_parallel SOURCES api/t8_fortran_interface/t8_test_cmesh.f90 ) add_t8_test( NAME t8_test_fortran_mpi_interface_forest_parallel SOURCES api/t8_fortran_interface/t8_test_forest.f90 ) diff --git a/test/api/t8_fortran_interface/t8_test_cmesh.f90 b/test/api/t8_fortran_interface/t8_test_cmesh.f90 index 2ad5b30ee5..0cdac333b9 100644 --- a/test/api/t8_fortran_interface/t8_test_cmesh.f90 +++ b/test/api/t8_fortran_interface/t8_test_cmesh.f90 @@ -26,7 +26,7 @@ program t8_test_cmesh use mpi - use iso_c_binding, only: c_ptr, c_int + use iso_c_binding, only: c_ptr, c_int, c_char, c_double use t8_fortran_interface_mod implicit none @@ -35,6 +35,7 @@ program t8_test_cmesh type(c_ptr) :: ccomm, cmesh, geometry real(c_double), target :: vertices_tri_0(9), vertices_tri_1(9), vertices_total(18) integer(c_int), target :: eclasses(2) + character(len=256, kind=c_char) :: vtk_prefix call MPI_Init (ierror) @@ -48,6 +49,15 @@ program t8_test_cmesh call t8_fortran_init_all_f (ccomm) cmesh = t8_cmesh_new_periodic_tri_f (ccomm) + + ! Test vtk output + vtk_prefix = "fortran_cmesh_to_vtk" // c_null_char + ierror = t8_cmesh_vtk_write_file_f(cmesh, vtk_prefix) + if (ierror /= 0) then + print *, 'cmesh VTK output failed.' + stop 1 + endif + !! call t8_cmesh_vtk_write_file_f(cmesh, 'test_mpi_init', 0) call t8_cmesh_destroy_f(cmesh) diff --git a/test/api/t8_fortran_interface/t8_test_forest.f90 b/test/api/t8_fortran_interface/t8_test_forest.f90 index 135dc965e7..4ed571fc20 100644 --- a/test/api/t8_fortran_interface/t8_test_forest.f90 +++ b/test/api/t8_fortran_interface/t8_test_forest.f90 @@ -26,21 +26,24 @@ program t8_test_forest use mpi - use iso_c_binding, only: c_ptr, c_int + use iso_c_binding, only: c_ptr, c_int, c_char use t8_fortran_interface_mod + use t8_fortran_example_adapt_mod implicit none integer :: ierror, fcomm integer :: num_local_elements, num_global_elements, num_local_trees - type(c_ptr) :: ccomm, cmesh, forest, element - integer :: num_elems_in_tree + type(c_ptr) :: ccomm, cmesh, forest, element, adapted_forest + integer :: num_elems_in_tree, ltree_id real(c_double) :: ref_coords(3), out_coords(3) + character(len=256, kind=c_char) :: vtk_prefix + type(c_funptr) :: c_adapt_callback_ptr call MPI_Init (ierror) if (ierror /= 0) then - print *, 'MPI initialization failed.' + write(*,*) 'MPI initialization failed.' stop 1 endif @@ -58,16 +61,39 @@ program t8_test_forest element = t8_forest_get_element_in_tree (forest, 0, 0) ref_coords = [0.5_c_double, 0.5_c_double, 0.0_c_double] call t8_forest_element_from_ref_coords (forest, 0, element, ref_coords, 1, out_coords) - call t8_forest_unref_f (forest) + ltree_id = 0 + call t8_fortran_element_volume_f(forest, ltree_id, element) + + ! Cast adapt callback into C-compatible function pointer. + c_adapt_callback_ptr = c_funloc(example_fortran_adapt_by_coordinates_callback) + + ! Adapt the forest using the Fortran-defined callback. + write(*,*) '*** Start forest adaptation!' + adapted_forest = t8_fortran_adapt_by_coordinates_f(forest, 0, c_adapt_callback_ptr) + write(*,*) '*** Finished forest adaptation!' + + ! Write out forest + write(*,*) '*** Start forest vtk output!' + vtk_prefix = "fortran_forest_to_vtk" // c_null_char + ierror = t8_forest_write_vtk_f(adapted_forest, vtk_prefix) + if (ierror /= 0) then + write(*,*) 'forest VTK output failed.' + stop 1 + endif + write(*,*) '*** Finished forest vtk output!' + + write(*,*) 'Finalize forest tests.' + call t8_forest_unref_f (adapted_forest) call t8_fortran_finalize_f () call t8_fortran_mpi_comm_delete_f(ccomm) - !! call t8_global_productionf_noargs_f ('Finalize forest tests') + call MPI_Finalize(ierror) if (ierror /= 0) then - print *, 'MPI Finalize failed.' + write(*,*) 'MPI Finalize failed.' stop 1 endif - print *, 'All good!' + write(*,*) '' + write(*,*) 'All good!' stop 0 end program diff --git a/test/api/t8_fortran_interface/t8_test_init_no_mpi.f90 b/test/api/t8_fortran_interface/t8_test_init_no_mpi.f90 new file mode 100644 index 0000000000..22fbe9347c --- /dev/null +++ b/test/api/t8_fortran_interface/t8_test_init_no_mpi.f90 @@ -0,0 +1,45 @@ +!! 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 +!! without MPI communicator. + +program t8_test_init_no_mpi + use mpi + use iso_c_binding, only: c_ptr, c_int + use t8_fortran_interface_mod + + implicit none + + ! Init Fortran interface without MPI, i.e., sc_MPI_COMM_NULL communicator. + call t8_fortran_init_all_noMPI_f() + + ! Test t8_global_productionf_noargs_f + call t8_global_productionf_noargs_f("This string was written by t8_global_productionf_noargs_f()") + + ! Finalize + call t8_fortran_finalize_f () + + print *, 'All good!' + stop 0 + +end program From 9e1477ea3428acf165fb7757a835aff32a8f823c Mon Sep 17 00:00:00 2001 From: Thomas Spenke Date: Thu, 5 Feb 2026 09:44:27 +0100 Subject: [PATCH 11/20] Unified upper- and lowercase of t8_fortran_interface_mod.f90 --- .../t8_fortran_interface_mod.f90 | 252 +++++++++--------- 1 file changed, 125 insertions(+), 127 deletions(-) diff --git a/api/t8_fortran_interface/t8_fortran_interface_mod.f90 b/api/t8_fortran_interface/t8_fortran_interface_mod.f90 index 71715c5488..412752a4e2 100644 --- a/api/t8_fortran_interface/t8_fortran_interface_mod.f90 +++ b/api/t8_fortran_interface/t8_fortran_interface_mod.f90 @@ -20,136 +20,136 @@ !! This file contains the module with t8code's Fortran interface. module t8_fortran_interface_mod - use, intrinsic :: ISO_C_BINDING + use, intrinsic :: iso_c_binding - !!! Interface for t8_fortran_MPI_Comm_new + !!! 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 + 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 + 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 + 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 + 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 + end subroutine t8_fortran_mpi_comm_delete_f + end interface !!! Initialize sc and t8code with a given C MPI Communicator - Interface + 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 + 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 + end subroutine t8_fortran_init_all_f + end interface !!! Initialize sc and t8code with a given C MPI Communicator - Interface + 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 + bind(C, NAME='t8_fortran_init_all_noMPI') + end subroutine t8_fortran_init_all_noMPI_f + end interface - 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 + 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 + end interface - Interface + interface integer (c_int) function t8_cmesh_vtk_write_file_f (cmesh, fileprefix) & bind (c, name = 't8_cmesh_vtk_write_file_wrap') - use, intrinsic :: ISO_C_BINDING, only: c_ptr, c_int, c_char, c_double - IMPLICIT NONE + 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 end function t8_cmesh_vtk_write_file_f - end Interface + end interface - Interface + interface subroutine t8_cmesh_destroy_f (cmesh) & bind (c, name = 't8_cmesh_destroy') - use, intrinsic :: ISO_C_BINDING, only: c_ptr - IMPLICIT NONE + use, intrinsic :: iso_c_binding, only: c_ptr + implicit none type (c_ptr) :: cmesh end subroutine t8_cmesh_destroy_f - end Interface + end interface - 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 + use, intrinsic :: iso_c_binding, only: c_ptr + implicit none type (c_ptr) :: cmesh end subroutine t8_fortran_cmesh_init_f - end Interface + end interface - 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 + 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 + end interface - 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 + 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 + end interface - 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 + 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 + end interface - 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 + 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 + end interface - 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 + 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 @@ -157,13 +157,13 @@ subroutine t8_fortran_cmesh_set_join_f (cmesh, gtree1, gtree2, face1, face2, ori integer (c_int), value :: face2 integer (c_int), value :: orientation end subroutine t8_fortran_cmesh_set_join_f - end Interface + end interface - Interface + interface subroutine t8_fortran_cmesh_set_join_by_vertices_noConn_f (cmesh, ntrees, eclasses, vertices, & connectivity, do_both_directions) bind (c, name = 't8_cmesh_set_join_by_vertices') - use, intrinsic :: ISO_C_BINDING, only: c_ptr, c_int - IMPLICIT NONE + 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 @@ -171,136 +171,134 @@ subroutine t8_fortran_cmesh_set_join_by_vertices_noConn_f (cmesh, ntrees, eclass type (c_ptr), value :: connectivity integer (c_int), value :: do_both_directions end subroutine t8_fortran_cmesh_set_join_by_vertices_noConn_f - end Interface + end interface - 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 + 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 + end interface - 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 + 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 - + end interface - Interface + interface subroutine t8_forest_unref_f (forest) & bind (c, name = 't8_forest_unref') - use, intrinsic :: ISO_C_BINDING, only: c_ptr - IMPLICIT NONE + use, intrinsic :: iso_c_binding, only: c_ptr + implicit none type (c_ptr) :: forest end subroutine t8_forest_unref_f - end Interface - + end interface - Interface + interface integer (c_int) function t8_forest_write_vtk_f (forest, fileprefix) & bind (c, name = 't8_forest_write_vtk_wrap') - use, intrinsic :: ISO_C_BINDING, only: c_ptr, c_int, c_char, c_double - IMPLICIT NONE + 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 + end interface - Interface + interface ! TODO: Not covered 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 + 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 + end interface - Interface + interface integer (c_int) function t8_forest_get_local_num_leaf_elements (forest) & bind (c, name = 't8_forest_get_local_num_leaf_elements') - use, intrinsic :: ISO_C_BINDING, only: c_ptr, c_int - IMPLICIT NONE + use, intrinsic :: iso_c_binding, only: c_ptr, c_int + implicit none type (c_ptr), value :: forest end function t8_forest_get_local_num_leaf_elements - end Interface + end interface - Interface + interface integer (c_int) function t8_forest_get_global_num_elements (forest) & bind (c, name = 't8_forest_get_global_num_leaf_elements') - use, intrinsic :: ISO_C_BINDING, only: c_ptr, c_int - IMPLICIT NONE + 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 + end interface - 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 + 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 + end interface - Interface + interface integer (c_int) function t8_forest_get_tree_num_elements (forest, ltreeid) & bind (c, name = 't8_forest_get_tree_num_leaf_elements') - use, intrinsic :: ISO_C_BINDING, only: c_ptr, c_int - IMPLICIT NONE + 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 + end interface - Interface + interface type (c_ptr) function t8_forest_get_element_in_tree (forest, ltreeid, leid_in_tree) & bind (c, name = 't8_forest_get_leaf_element_in_tree') - use, intrinsic :: ISO_C_BINDING, only: c_ptr, c_int - IMPLICIT NONE + 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 + end interface - 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 + 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 + end interface - 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 + use, intrinsic :: iso_c_binding, only: c_char + implicit none character (c_char) :: string end subroutine t8_global_productionf_noargs_f - end Interface + end interface - Interface + interface subroutine t8_fortran_finalize_f () & bind (c, name = 't8_fortran_finalize') - IMPLICIT NONE + implicit none end subroutine t8_fortran_finalize_f - end Interface + end interface interface function t8_fortran_adapt(forest, fortran_callback, recursive) result(new_forest) & @@ -313,27 +311,27 @@ function t8_fortran_adapt(forest, fortran_callback, recursive) result(new_forest end function t8_fortran_adapt end interface - Interface + interface function t8_fortran_adapt_by_coordinates_f (forest, recursive, callback) result(new_forest) & bind (c, name = 't8_forest_adapt_by_coordinates') - use, intrinsic :: ISO_C_BINDING, only : c_ptr, c_int, c_funptr - IMPLICIT NONE + use, intrinsic :: iso_c_binding, only : c_ptr, c_int, c_funptr + implicit none type (c_ptr), value :: forest integer (c_int), value :: recursive type(c_funptr), value :: callback type (c_ptr) :: new_forest end function t8_fortran_adapt_by_coordinates_f - end Interface + end interface - 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 + 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 interface -End module t8_fortran_interface_mod +end module t8_fortran_interface_mod From 18499165181a251a2cb6adf0c655109f35f8520a Mon Sep 17 00:00:00 2001 From: Thomas Spenke Date: Thu, 5 Feb 2026 09:49:40 +0100 Subject: [PATCH 12/20] Remove incomplete version of t8_forest_iterate_replace_f from Fortran interface --- .../t8_fortran_interface_mod.f90 | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/api/t8_fortran_interface/t8_fortran_interface_mod.f90 b/api/t8_fortran_interface/t8_fortran_interface_mod.f90 index 412752a4e2..5d76990e82 100644 --- a/api/t8_fortran_interface/t8_fortran_interface_mod.f90 +++ b/api/t8_fortran_interface/t8_fortran_interface_mod.f90 @@ -214,18 +214,6 @@ integer (c_int) function t8_forest_write_vtk_f (forest, fileprefix) & end function t8_forest_write_vtk_f end interface - interface - ! TODO: Not covered - 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_leaf_elements (forest) & bind (c, name = 't8_forest_get_local_num_leaf_elements') From 84be940df8adedfa505e2bdf4b1cd18fdfe9d5e4 Mon Sep 17 00:00:00 2001 From: Thomas Spenke Date: Thu, 5 Feb 2026 09:51:41 +0100 Subject: [PATCH 13/20] Clean up cmake/CodeCoverage.cmake --- cmake/CodeCoverage.cmake | 6 ------ 1 file changed, 6 deletions(-) diff --git a/cmake/CodeCoverage.cmake b/cmake/CodeCoverage.cmake index 6931b6c4d0..aaa2c85b57 100644 --- a/cmake/CodeCoverage.cmake +++ b/cmake/CodeCoverage.cmake @@ -103,12 +103,6 @@ endfunction() # setup_target_for_coverage append_coverage_compiler_flags() setup_target_for_coverage( NAME coverage - # EXCLUDE "${CMAKE_SOURCE_DIR}/sc*" "${CMAKE_SOURCE_DIR}/p4est*" "${CMAKE_SOURCE_DIR}/test*" "${CMAKE_SOURCE_DIR}/thirdparty*" "${CMAKE_SOURCE_DIR}/tutorials*" "${CMAKE_SOURCE_DIR}/example*" "${CMAKE_SOURCE_DIR}/benchmarks*" "${CMAKE_SOURCE_DIR}/CMakeFortranCompilerId.F" - # # EXCLUDE "${CMAKE_SOURCE_DIR}/sc*" "${CMAKE_SOURCE_DIR}/p4est*" "${CMAKE_SOURCE_DIR}/test*" "${CMAKE_SOURCE_DIR}/thirdparty*" "${CMAKE_SOURCE_DIR}/tutorials*" "${CMAKE_SOURCE_DIR}/example*" "${CMAKE_SOURCE_DIR}/benchmarks*" "${CMAKE_SOURCE_DIR}/CMakeFortranCompilerId.F" "${CMAKE_BINARY_DIR}/*" - # LCOV_ARGS --no-external --ignore-errors gcov,mismatch,unused,unmapped - # EXCLUDE "${CMAKE_SOURCE_DIR}/sc*" "${CMAKE_SOURCE_DIR}/p4est*" "${CMAKE_SOURCE_DIR}/test*" "${CMAKE_SOURCE_DIR}/thirdparty*" "${CMAKE_SOURCE_DIR}/tutorials*" "${CMAKE_SOURCE_DIR}/example*" "${CMAKE_SOURCE_DIR}/benchmarks*" "${CMAKE_SOURCE_DIR}/CMakeFortranCompilerId.F" EXCLUDE "${CMAKE_SOURCE_DIR}/sc*" "${CMAKE_SOURCE_DIR}/p4est*" "${CMAKE_SOURCE_DIR}/test*" "${CMAKE_SOURCE_DIR}/thirdparty*" "${CMAKE_SOURCE_DIR}/tutorials*" "${CMAKE_SOURCE_DIR}/example*" "${CMAKE_SOURCE_DIR}/benchmarks*" "${CMAKE_SOURCE_DIR}/CMakeFortranCompilerId.F" "${CMAKE_BINARY_DIR}/*" LCOV_ARGS --no-external --ignore-errors gcov,mismatch,unused - # EXCLUDE "${CMAKE_SOURCE_DIR}/sc*" "${CMAKE_SOURCE_DIR}/p4est*" "${CMAKE_SOURCE_DIR}/test*" "${CMAKE_SOURCE_DIR}/thirdparty*" "${CMAKE_SOURCE_DIR}/tutorials*" "${CMAKE_SOURCE_DIR}/example*" "${CMAKE_SOURCE_DIR}/benchmarks*" - # LCOV_ARGS --no-external --ignore-errors gcov,mismatch,unused ) \ No newline at end of file From 3cbc593acb1f129f1cb06e403fb50dd752e7d51c Mon Sep 17 00:00:00 2001 From: Thomas Spenke Date: Thu, 5 Feb 2026 10:02:41 +0100 Subject: [PATCH 14/20] Add Fortran Flags to code_coverage.yml --- .github/workflows/code_coverage.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/code_coverage.yml b/.github/workflows/code_coverage.yml index 4320ddd32c..822417394e 100644 --- a/.github/workflows/code_coverage.yml +++ b/.github/workflows/code_coverage.yml @@ -91,7 +91,11 @@ 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} -DCMAKE_Fortran_FLAGS='-fprofile-arcs -ftest-coverage' -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" + run: export CONFIG_OPTIONS="${TEST_LEVEL_FLAG} -DT8CODE_CODE_COVERAGE=ON -DT8CODE_BUILD_FORTRAN_INTERFACE=ON -DT8CODE_BUILD_MESH_HANDLE=ON \ + -DT8CODE_BUILD_DOCUMENTATION=OFF -DT8CODE_BUILD_EXAMPLES=OFF -DT8CODE_BUILD_TUTORIALS=OFF -DT8CODE_BUILD_BENCHMARKS=OFF \ + -DT8CODE_USE_SYSTEM_SC=ON -DSC_DIR=$SC_PATH/install/cmake -DT8CODE_USE_SYSTEM_P4EST=ON -DP4EST_DIR=$P4EST_PATH/install/cmake \ + -DT8CODE_ENABLE_MPI=$MPI -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DT8CODE_BUILD_PEDANTIC=ON -DT8CODE_BUILD_WALL=ON -DT8CODE_BUILD_WERROR=ON \ + -DCMAKE_Fortran_COMPILER=mpifort -DCMAKE_Fortran_FLAGS=\"${CMAKE_Fortran_FLAGS} -fprofile-arcs -ftest-coverage\" " && echo CONFIG_OPTIONS="$CONFIG_OPTIONS" >> $GITHUB_ENV # cmake - name: echo cmake line From 3a2ed560d3d26e51b3f35860bf2f0718db4c4396 Mon Sep 17 00:00:00 2001 From: Thomas Spenke Date: Thu, 5 Feb 2026 11:06:16 +0100 Subject: [PATCH 15/20] Try fortran code coverage --- .github/workflows/code_coverage.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/code_coverage.yml b/.github/workflows/code_coverage.yml index 822417394e..4c796196d0 100644 --- a/.github/workflows/code_coverage.yml +++ b/.github/workflows/code_coverage.yml @@ -95,13 +95,13 @@ jobs: -DT8CODE_BUILD_DOCUMENTATION=OFF -DT8CODE_BUILD_EXAMPLES=OFF -DT8CODE_BUILD_TUTORIALS=OFF -DT8CODE_BUILD_BENCHMARKS=OFF \ -DT8CODE_USE_SYSTEM_SC=ON -DSC_DIR=$SC_PATH/install/cmake -DT8CODE_USE_SYSTEM_P4EST=ON -DP4EST_DIR=$P4EST_PATH/install/cmake \ -DT8CODE_ENABLE_MPI=$MPI -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DT8CODE_BUILD_PEDANTIC=ON -DT8CODE_BUILD_WALL=ON -DT8CODE_BUILD_WERROR=ON \ - -DCMAKE_Fortran_COMPILER=mpifort -DCMAKE_Fortran_FLAGS=\"${CMAKE_Fortran_FLAGS} -fprofile-arcs -ftest-coverage\" " + -DCMAKE_Fortran_COMPILER=mpifort" && echo CONFIG_OPTIONS="$CONFIG_OPTIONS" >> $GITHUB_ENV # cmake - name: echo cmake line - run: echo cmake ../ $CONFIG_OPTIONS + run: echo cmake ../ $CONFIG_OPTIONS -DCMAKE_Fortran_FLAGS="-fprofile-arcs -ftest-coverage" - name: cmake - run: mkdir build && cd build && cmake ../ $CONFIG_OPTIONS + run: mkdir build && cd build && cmake ../ $CONFIG_OPTIONS -DCMAKE_Fortran_FLAGS="-fprofile-arcs -ftest-coverage" - name: OnFailUploadLog if: failure() uses: actions/upload-artifact@v6 From 5d16a6db47b80d4d444a33ef3b02813a7af922fe Mon Sep 17 00:00:00 2001 From: Thomas Spenke Date: Thu, 5 Feb 2026 11:29:17 +0100 Subject: [PATCH 16/20] Try code coverage again --- .github/workflows/code_coverage.yml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/.github/workflows/code_coverage.yml b/.github/workflows/code_coverage.yml index 4c796196d0..4ca5806879 100644 --- a/.github/workflows/code_coverage.yml +++ b/.github/workflows/code_coverage.yml @@ -91,11 +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_BUILD_FORTRAN_INTERFACE=ON -DT8CODE_BUILD_MESH_HANDLE=ON \ - -DT8CODE_BUILD_DOCUMENTATION=OFF -DT8CODE_BUILD_EXAMPLES=OFF -DT8CODE_BUILD_TUTORIALS=OFF -DT8CODE_BUILD_BENCHMARKS=OFF \ - -DT8CODE_USE_SYSTEM_SC=ON -DSC_DIR=$SC_PATH/install/cmake -DT8CODE_USE_SYSTEM_P4EST=ON -DP4EST_DIR=$P4EST_PATH/install/cmake \ - -DT8CODE_ENABLE_MPI=$MPI -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DT8CODE_BUILD_PEDANTIC=ON -DT8CODE_BUILD_WALL=ON -DT8CODE_BUILD_WERROR=ON \ - -DCMAKE_Fortran_COMPILER=mpifort" + run: export CONFIG_OPTIONS="${TEST_LEVEL_FLAG} -DCMAKE_Fortran_COMPILER=mpifort -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 From 9faa0e3076495686bced03c0749f2cfcc50dbb64 Mon Sep 17 00:00:00 2001 From: Thomas Spenke Date: Thu, 5 Feb 2026 12:17:01 +0100 Subject: [PATCH 17/20] Fix issues with vtk header and C usability --- .../t8_fortran_interface.c | 13 -- .../t8_fortran_interface.h | 149 ++++++++---------- .../t8_fortran_interface_mod.f90 | 87 +++++++--- .../t8_fortran_interface/t8_test_forest.f90 | 1 - 4 files changed, 131 insertions(+), 119 deletions(-) diff --git a/api/t8_fortran_interface/t8_fortran_interface.c b/api/t8_fortran_interface/t8_fortran_interface.c index d6ab684117..98a44b9bc4 100644 --- a/api/t8_fortran_interface/t8_fortran_interface.c +++ b/api/t8_fortran_interface/t8_fortran_interface.c @@ -28,7 +28,6 @@ #include #include #include -#include void t8_fortran_init_all_ (sc_MPI_Comm *comm) @@ -110,18 +109,6 @@ t8_cmesh_new_periodic_tri_wrap (sc_MPI_Comm *Ccomm) return t8_cmesh_new_periodic_tri (*Ccomm); } -int -t8_forest_write_vtk_wrap (t8_forest_t forest, const char *fileprefix) -{ - return t8_forest_write_vtk (forest, fileprefix) ? 0 : 1; -} - -int -t8_cmesh_vtk_write_file_wrap (t8_cmesh_t cmesh, const char *fileprefix) -{ - return t8_cmesh_vtk_write_file (cmesh, fileprefix) ? 0 : 1; -} - t8_forest_t t8_forest_new_uniform_default (t8_cmesh_t cmesh, int level, int do_face_ghost, sc_MPI_Comm *comm) { diff --git a/api/t8_fortran_interface/t8_fortran_interface.h b/api/t8_fortran_interface/t8_fortran_interface.h index 48fdda6d14..80b8afc9cd 100644 --- a/api/t8_fortran_interface/t8_fortran_interface.h +++ b/api/t8_fortran_interface/t8_fortran_interface.h @@ -18,8 +18,8 @@ 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 t8_fortran_interface.h * In this file we provide a basic Fortran interface * for some functions of t8code. @@ -27,52 +27,52 @@ * t8code function. * We only export a minimum of the actual t8code functionality * to Fortran. - */ - -#ifndef T8_FORTRAN_INTERFACE_H -#define T8_FORTRAN_INTERFACE_H - -#include -#include -#include -#include - -typedef int (*t8_fortran_adapt_coordinate_callback) (double x, double y, double z, int is_family); - -/* A fallback type if t8code is not built with MPI */ -typedef -#if T8_ENABLE_MPI - MPI_Fint -#else - int -#endif - MPI_T8_Fint; - -T8_EXTERN_C_BEGIN (); - + */ + +#ifndef T8_FORTRAN_INTERFACE_H +#define T8_FORTRAN_INTERFACE_H + +#include +#include +#include +#include + +typedef int (*t8_fortran_adapt_coordinate_callback) (double x, double y, double z, int is_family); + +/* A fallback type if t8code is not built with MPI */ +typedef +#if T8_ENABLE_MPI + MPI_Fint +#else + int +#endif + MPI_T8_Fint; + +T8_EXTERN_C_BEGIN (); + /** Initialize sc and t8code with SC_MPI_COMM_WORLD communicator * and SC_LP_DEFAULT logging. * This call is equivalent to * sc_init (comm, 1, 1, NULL, SC_LP_ESSENTIAL); * t8_init (SC_LP_DEFAULT); * \param [in] comm The MPI communicator to use. - */ -void -t8_fortran_init_all (sc_MPI_Comm *comm); - + */ +void +t8_fortran_init_all (sc_MPI_Comm *comm); + /** Finalize sc. This wraps sc_finalize in order to have consistent * naming with t8_fortran_init_all. - */ -void -t8_fortran_finalize (); - + */ +void +t8_fortran_finalize (); + /** Commit cmesh. This wraps cmesh_commit in order to use the dereferenced communicator. * \param [in, out] cmesh Cmesh to commit * \param [in] Ccomm Pointer to a C MPI communicator. -*/ -void -t8_fortran_cmesh_commit (t8_cmesh_t cmesh, sc_MPI_Comm *comm); - +*/ +void +t8_fortran_cmesh_commit (t8_cmesh_t cmesh, sc_MPI_Comm *comm); + /** Translate a fortran MPI communicator into a C MPI communicator * and return a pointer to it. * \param [in] Fcomm Fortran MPI Communicator @@ -81,45 +81,24 @@ t8_fortran_cmesh_commit (t8_cmesh_t cmesh, sc_MPI_Comm *comm); * Call \ref t8_fortran_MPI_Comm_delete to free this memory. * \note t8code needs to be configured with MPI support to be able to use * this function. - */ -sc_MPI_Comm * -t8_fortran_MPI_Comm_new (MPI_T8_Fint Fcomm); - + */ +sc_MPI_Comm * +t8_fortran_MPI_Comm_new (MPI_T8_Fint Fcomm); + /** Free the memory of a C MPI Communicator pointer that was created * with \ref t8_fortran_MPI_Comm_new. * \param [in] Ccomm Pointer to a C MPI communicator. - */ -void -t8_fortran_MPI_Comm_delete (sc_MPI_Comm *Ccomm); - + */ +void +t8_fortran_MPI_Comm_delete (sc_MPI_Comm *Ccomm); + /** Wraps t8_cmesh_new_periodic_tri, passing the MPI communicator as pointer instead of by value * \param [in] Ccomm Pointer to a C MPI communicator. * \param [out] Example cmesh - */ -t8_cmesh_t -t8_cmesh_new_periodic_tri_wrap (sc_MPI_Comm *Ccomm); - -/** - * Wraps t8_forest_write_vtk, passing back an error flag instead of true/false, so non-zero means - * fail, zero success. - * \param [in] forest The forest - * \param [in] fileprefix The file name prefix - * \return 0 if successful, 1 otherwise - */ -int -t8_forest_write_vtk_wrap (t8_forest_t forest, const char *fileprefix); - -/** - * Wraps t8_cmesh_vtk_write_file, passing back an error flag instead of true/false, so non-zero means - * fail, zero success. - * - * \param[in] cmesh The cmesh - * \param[in] fileprefix The prefix of the output files - * \return 0 if successful, 1 otherwise - */ -int -t8_cmesh_vtk_write_file_wrap (t8_cmesh_t cmesh, const char *fileprefix); - + */ +t8_cmesh_t +t8_cmesh_new_periodic_tri_wrap (sc_MPI_Comm *Ccomm); + /** Wraps \ref t8_forest_new_uniform with the default scheme as scheme * and passes MPI communicator as pointer instead of by value. * Build a uniformly refined forest on a coarse mesh. @@ -129,26 +108,26 @@ t8_cmesh_vtk_write_file_wrap (t8_cmesh_t cmesh, const char *fileprefix); * \param [in] comm MPI communicator to use. * \return A uniform forest with coarse mesh \a cmesh, eclass_scheme * \a scheme and refinement level \a level. - */ -t8_forest_t -t8_forest_new_uniform_default (t8_cmesh_t cmesh, int level, int do_face_ghost, sc_MPI_Comm *comm); - + */ +t8_forest_t +t8_forest_new_uniform_default (t8_cmesh_t cmesh, int level, int do_face_ghost, sc_MPI_Comm *comm); + /** * \param [in, out] forest The forest * \param [in] recursive A flag specifying whether adaptation is to be done recursively * or not. If the value is zero, adaptation is not recursive * and it is recursive otherwise. * \param [in] callback A pointer to a user defined function. t8code will never touch the function. - */ -t8_forest_t -t8_forest_adapt_by_coordinates (t8_forest_t forest, int recursive, t8_fortran_adapt_coordinate_callback callback); - + */ +t8_forest_t +t8_forest_adapt_by_coordinates (t8_forest_t forest, int recursive, t8_fortran_adapt_coordinate_callback callback); + /** Log a message on the root rank with priority SC_LP_PRODUCTION. * \param [in] string String to log. - */ -void -t8_global_productionf_noargs (const char *string); - -T8_EXTERN_C_END (); - -#endif /* !T8_FORTRAN_INTERFACE_H */ + */ +void +t8_global_productionf_noargs (const char *string); + +T8_EXTERN_C_END (); + +#endif /* !T8_FORTRAN_INTERFACE_H */ diff --git a/api/t8_fortran_interface/t8_fortran_interface_mod.f90 b/api/t8_fortran_interface/t8_fortran_interface_mod.f90 index 5d76990e82..a66a502642 100644 --- a/api/t8_fortran_interface/t8_fortran_interface_mod.f90 +++ b/api/t8_fortran_interface/t8_fortran_interface_mod.f90 @@ -75,16 +75,6 @@ type (c_ptr) function t8_cmesh_new_periodic_tri_f (Ccomm) & end function t8_cmesh_new_periodic_tri_f end interface - interface - integer (c_int) function t8_cmesh_vtk_write_file_f (cmesh, fileprefix) & - bind (c, name = 't8_cmesh_vtk_write_file_wrap') - 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 - end function t8_cmesh_vtk_write_file_f - end interface - interface subroutine t8_cmesh_destroy_f (cmesh) & bind (c, name = 't8_cmesh_destroy') @@ -204,16 +194,6 @@ subroutine t8_forest_unref_f (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_wrap') - 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 integer (c_int) function t8_forest_get_local_num_leaf_elements (forest) & bind (c, name = 't8_forest_get_local_num_leaf_elements') @@ -322,4 +302,71 @@ subroutine t8_fortran_element_volume_f (forest, ltreeid, element) & end subroutine t8_fortran_element_volume_f end interface +contains + + ! This function wraps t8_forest_write_vtk, passing back an error flag instead of true/false, so non-zero means + ! fail, zero success. + function t8_forest_write_vtk_f(forest, fileprefix) result(ierror) + implicit none + type (c_ptr), value :: forest + character (c_char) :: fileprefix + integer (c_int) :: ierror + integer (c_int) :: retValue + + ! Local binding to C function t8_forest_write_vtk. + interface + integer (c_int) function t8_forest_write_vtk_c (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_c + end interface + + ! Call c function. + retValue = t8_forest_write_vtk_c(forest, fileprefix) + + ! Convert return value of C function to the error flag returned by the Fortran function. + if( retValue.eq.0) then + ierror = 1 + else + ierror = 0 + end if + + end function t8_forest_write_vtk_f + + ! This function wraps t8_cmesh_vtk_write_file, passing back an error flag instead of true/false, so non-zero means + ! fail, zero success. + function t8_cmesh_vtk_write_file_f(cmesh, fileprefix) result(ierror) + 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 + integer (c_int) :: ierror + integer (c_int) :: retValue + + ! Local binding to C function t8_cmesh_vtk_write_file. + interface + integer (c_int) function t8_cmesh_vtk_write_file_c (cmesh, fileprefix) & + 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 + end function t8_cmesh_vtk_write_file_c + end interface + + ! Call c function. + retValue = t8_cmesh_vtk_write_file_c(cmesh, fileprefix) + + ! Convert return value of C function to the error flag returned by the Fortran function. + if( retValue.eq.0) then + ierror = 1 + else + ierror = 0 + end if + + end function t8_cmesh_vtk_write_file_f + end module t8_fortran_interface_mod diff --git a/test/api/t8_fortran_interface/t8_test_forest.f90 b/test/api/t8_fortran_interface/t8_test_forest.f90 index 4ed571fc20..d729ad2389 100644 --- a/test/api/t8_fortran_interface/t8_test_forest.f90 +++ b/test/api/t8_fortran_interface/t8_test_forest.f90 @@ -53,7 +53,6 @@ program t8_test_forest cmesh = t8_cmesh_new_periodic_tri_f (ccomm) forest = t8_forest_new_uniform_default_f (cmesh, 2, 0, ccomm) - !! ierror = t8_forest_write_vtk_f (forest, 'test_forest') num_local_elements = t8_forest_get_local_num_leaf_elements (forest) num_global_elements = t8_forest_get_global_num_elements (forest) num_local_trees = t8_forest_get_num_local_trees (forest) From c834cc73a9f158724eccda77fba55e5c2f1e2ba8 Mon Sep 17 00:00:00 2001 From: Thomas Spenke Date: Thu, 5 Feb 2026 14:52:44 +0100 Subject: [PATCH 18/20] Make code coverage workflow include Fortran interface --- cmake/CodeCoverage.cmake | 2 +- test/api/t8_fortran_interface/t8_test_cmesh.f90 | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cmake/CodeCoverage.cmake b/cmake/CodeCoverage.cmake index aaa2c85b57..a78dbabdea 100644 --- a/cmake/CodeCoverage.cmake +++ b/cmake/CodeCoverage.cmake @@ -104,5 +104,5 @@ append_coverage_compiler_flags() setup_target_for_coverage( NAME coverage EXCLUDE "${CMAKE_SOURCE_DIR}/sc*" "${CMAKE_SOURCE_DIR}/p4est*" "${CMAKE_SOURCE_DIR}/test*" "${CMAKE_SOURCE_DIR}/thirdparty*" "${CMAKE_SOURCE_DIR}/tutorials*" "${CMAKE_SOURCE_DIR}/example*" "${CMAKE_SOURCE_DIR}/benchmarks*" "${CMAKE_SOURCE_DIR}/CMakeFortranCompilerId.F" "${CMAKE_BINARY_DIR}/*" - LCOV_ARGS --no-external --ignore-errors gcov,mismatch,unused + LCOV_ARGS --no-external --ignore-errors gcov ) \ No newline at end of file diff --git a/test/api/t8_fortran_interface/t8_test_cmesh.f90 b/test/api/t8_fortran_interface/t8_test_cmesh.f90 index 0cdac333b9..fc6c75196f 100644 --- a/test/api/t8_fortran_interface/t8_test_cmesh.f90 +++ b/test/api/t8_fortran_interface/t8_test_cmesh.f90 @@ -51,14 +51,14 @@ program t8_test_cmesh cmesh = t8_cmesh_new_periodic_tri_f (ccomm) ! Test vtk output + write(*,*) 'Start cmesh vtk output' vtk_prefix = "fortran_cmesh_to_vtk" // c_null_char ierror = t8_cmesh_vtk_write_file_f(cmesh, vtk_prefix) if (ierror /= 0) then print *, 'cmesh VTK output failed.' stop 1 endif - -!! call t8_cmesh_vtk_write_file_f(cmesh, 'test_mpi_init', 0) + write(*,*) 'Finished cmesh vtk output' call t8_cmesh_destroy_f(cmesh) vertices_tri_0 = [0.0_c_double, 0.0_c_double, 0.0_c_double, & From 3fe9734ae33d483ccc171978a9bdc34039eccde6 Mon Sep 17 00:00:00 2001 From: Thomas Spenke Date: Thu, 5 Feb 2026 15:46:00 +0100 Subject: [PATCH 19/20] Do not set Fortran compiler manually in code coverage workflow --- .github/workflows/code_coverage.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/code_coverage.yml b/.github/workflows/code_coverage.yml index 4ca5806879..10d01c1988 100644 --- a/.github/workflows/code_coverage.yml +++ b/.github/workflows/code_coverage.yml @@ -91,11 +91,12 @@ 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} -DCMAKE_Fortran_COMPILER=mpifort -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" + 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 run: echo cmake ../ $CONFIG_OPTIONS -DCMAKE_Fortran_FLAGS="-fprofile-arcs -ftest-coverage" + # Note: Adding DCMAKE_Fortran_FLAGS here is a workaround because the blank space between the compiler flags causes trouble otherwise. - name: cmake run: mkdir build && cd build && cmake ../ $CONFIG_OPTIONS -DCMAKE_Fortran_FLAGS="-fprofile-arcs -ftest-coverage" - name: OnFailUploadLog From 72c1e7cd00a9ac657a8e667166b4b38195574404 Mon Sep 17 00:00:00 2001 From: Thomas Spenke Date: Thu, 5 Feb 2026 17:07:54 +0100 Subject: [PATCH 20/20] Indentation --- .../t8_fortran_interface.h | 128 +++++++++--------- .../t8_fortran_interface_mod.f90 | 2 +- .../t8_fortran_interface/t8_test_cmesh.f90 | 4 + 3 files changed, 69 insertions(+), 65 deletions(-) diff --git a/api/t8_fortran_interface/t8_fortran_interface.h b/api/t8_fortran_interface/t8_fortran_interface.h index 80b8afc9cd..8953b36afd 100644 --- a/api/t8_fortran_interface/t8_fortran_interface.h +++ b/api/t8_fortran_interface/t8_fortran_interface.h @@ -18,8 +18,8 @@ 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 t8_fortran_interface.h * In this file we provide a basic Fortran interface * for some functions of t8code. @@ -27,52 +27,52 @@ * t8code function. * We only export a minimum of the actual t8code functionality * to Fortran. - */ - -#ifndef T8_FORTRAN_INTERFACE_H -#define T8_FORTRAN_INTERFACE_H - -#include -#include -#include -#include - -typedef int (*t8_fortran_adapt_coordinate_callback) (double x, double y, double z, int is_family); - -/* A fallback type if t8code is not built with MPI */ -typedef -#if T8_ENABLE_MPI - MPI_Fint -#else - int -#endif - MPI_T8_Fint; - -T8_EXTERN_C_BEGIN (); - + */ + +#ifndef T8_FORTRAN_INTERFACE_H +#define T8_FORTRAN_INTERFACE_H + +#include +#include +#include +#include + +typedef int (*t8_fortran_adapt_coordinate_callback) (double x, double y, double z, int is_family); + +/* A fallback type if t8code is not built with MPI */ +typedef +#if T8_ENABLE_MPI + MPI_Fint +#else + int +#endif + MPI_T8_Fint; + +T8_EXTERN_C_BEGIN (); + /** Initialize sc and t8code with SC_MPI_COMM_WORLD communicator * and SC_LP_DEFAULT logging. * This call is equivalent to * sc_init (comm, 1, 1, NULL, SC_LP_ESSENTIAL); * t8_init (SC_LP_DEFAULT); * \param [in] comm The MPI communicator to use. - */ -void -t8_fortran_init_all (sc_MPI_Comm *comm); - + */ +void +t8_fortran_init_all (sc_MPI_Comm *comm); + /** Finalize sc. This wraps sc_finalize in order to have consistent * naming with t8_fortran_init_all. - */ -void -t8_fortran_finalize (); - + */ +void +t8_fortran_finalize (); + /** Commit cmesh. This wraps cmesh_commit in order to use the dereferenced communicator. * \param [in, out] cmesh Cmesh to commit * \param [in] Ccomm Pointer to a C MPI communicator. -*/ -void -t8_fortran_cmesh_commit (t8_cmesh_t cmesh, sc_MPI_Comm *comm); - +*/ +void +t8_fortran_cmesh_commit (t8_cmesh_t cmesh, sc_MPI_Comm *comm); + /** Translate a fortran MPI communicator into a C MPI communicator * and return a pointer to it. * \param [in] Fcomm Fortran MPI Communicator @@ -81,24 +81,24 @@ t8_fortran_cmesh_commit (t8_cmesh_t cmesh, sc_MPI_Comm *comm); * Call \ref t8_fortran_MPI_Comm_delete to free this memory. * \note t8code needs to be configured with MPI support to be able to use * this function. - */ -sc_MPI_Comm * -t8_fortran_MPI_Comm_new (MPI_T8_Fint Fcomm); - + */ +sc_MPI_Comm * +t8_fortran_MPI_Comm_new (MPI_T8_Fint Fcomm); + /** Free the memory of a C MPI Communicator pointer that was created * with \ref t8_fortran_MPI_Comm_new. * \param [in] Ccomm Pointer to a C MPI communicator. - */ -void -t8_fortran_MPI_Comm_delete (sc_MPI_Comm *Ccomm); - + */ +void +t8_fortran_MPI_Comm_delete (sc_MPI_Comm *Ccomm); + /** Wraps t8_cmesh_new_periodic_tri, passing the MPI communicator as pointer instead of by value * \param [in] Ccomm Pointer to a C MPI communicator. * \param [out] Example cmesh - */ -t8_cmesh_t -t8_cmesh_new_periodic_tri_wrap (sc_MPI_Comm *Ccomm); - + */ +t8_cmesh_t +t8_cmesh_new_periodic_tri_wrap (sc_MPI_Comm *Ccomm); + /** Wraps \ref t8_forest_new_uniform with the default scheme as scheme * and passes MPI communicator as pointer instead of by value. * Build a uniformly refined forest on a coarse mesh. @@ -108,26 +108,26 @@ t8_cmesh_new_periodic_tri_wrap (sc_MPI_Comm *Ccomm); * \param [in] comm MPI communicator to use. * \return A uniform forest with coarse mesh \a cmesh, eclass_scheme * \a scheme and refinement level \a level. - */ -t8_forest_t -t8_forest_new_uniform_default (t8_cmesh_t cmesh, int level, int do_face_ghost, sc_MPI_Comm *comm); - + */ +t8_forest_t +t8_forest_new_uniform_default (t8_cmesh_t cmesh, int level, int do_face_ghost, sc_MPI_Comm *comm); + /** * \param [in, out] forest The forest * \param [in] recursive A flag specifying whether adaptation is to be done recursively * or not. If the value is zero, adaptation is not recursive * and it is recursive otherwise. * \param [in] callback A pointer to a user defined function. t8code will never touch the function. - */ -t8_forest_t -t8_forest_adapt_by_coordinates (t8_forest_t forest, int recursive, t8_fortran_adapt_coordinate_callback callback); - + */ +t8_forest_t +t8_forest_adapt_by_coordinates (t8_forest_t forest, int recursive, t8_fortran_adapt_coordinate_callback callback); + /** Log a message on the root rank with priority SC_LP_PRODUCTION. * \param [in] string String to log. - */ -void -t8_global_productionf_noargs (const char *string); - -T8_EXTERN_C_END (); - -#endif /* !T8_FORTRAN_INTERFACE_H */ + */ +void +t8_global_productionf_noargs (const char *string); + +T8_EXTERN_C_END (); + +#endif /* !T8_FORTRAN_INTERFACE_H */ diff --git a/api/t8_fortran_interface/t8_fortran_interface_mod.f90 b/api/t8_fortran_interface/t8_fortran_interface_mod.f90 index a66a502642..d999c8a360 100644 --- a/api/t8_fortran_interface/t8_fortran_interface_mod.f90 +++ b/api/t8_fortran_interface/t8_fortran_interface_mod.f90 @@ -34,7 +34,7 @@ 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 + integer (c_int), value :: Fcomm end function t8_fortran_mpi_comm_new_f end interface diff --git a/test/api/t8_fortran_interface/t8_test_cmesh.f90 b/test/api/t8_fortran_interface/t8_test_cmesh.f90 index fc6c75196f..a32de54c63 100644 --- a/test/api/t8_fortran_interface/t8_test_cmesh.f90 +++ b/test/api/t8_fortran_interface/t8_test_cmesh.f90 @@ -61,6 +61,7 @@ program t8_test_cmesh write(*,*) 'Finished cmesh vtk output' call t8_cmesh_destroy_f(cmesh) + write(*,*) 'Destroyed mesh' vertices_tri_0 = [0.0_c_double, 0.0_c_double, 0.0_c_double, & 1.0_c_double, 0.0_c_double, 0.0_c_double, & 1.0_c_double, 1.0_c_double, 0.0_c_double] @@ -72,6 +73,7 @@ program t8_test_cmesh !! Create a test quad mesh with 2 triangles in a square call t8_fortran_cmesh_init_f(cmesh) + write(*,*) 'initialized new mesh' !! Create and register a geometry for linear triangles geometry = t8_fortran_geometry_linear_new_f (2) call t8_fortran_cmesh_register_geometry_f(cmesh, geometry) @@ -85,6 +87,7 @@ program t8_test_cmesh call t8_fortran_cmesh_set_join_f(cmesh, int(0, kind=8), int(1, kind=8), 1, 2, 0) call t8_fortran_cmesh_commit_f(cmesh, ccomm) call t8_cmesh_destroy_f(cmesh) + write(*,*) 'destroyed mesh again' !! Create the same mesh again, but let t8code find the connectivity eclasses = [3, 3] @@ -98,6 +101,7 @@ program t8_test_cmesh call t8_fortran_cmesh_set_join_by_vertices_noConn_f(cmesh, 2, c_loc(eclasses), c_loc(vertices_total), C_NULL_PTR, 0) call t8_fortran_cmesh_commit_f(cmesh, ccomm) call t8_cmesh_destroy_f(cmesh) + write(*,*) 'destroyed mesh a third time' call t8_fortran_finalize_f () call t8_fortran_mpi_comm_delete_f(ccomm)