From d5ecc49df72ee10e475c81842cc1f9d1a66b9e22 Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Thu, 22 Feb 2024 17:49:17 +0100 Subject: [PATCH 01/89] add getter for number of dofs --- LibTrixi.jl/src/LibTrixi.jl | 10 ++++++-- LibTrixi.jl/src/api_c.jl | 30 ++++++++++++++++++++++++ LibTrixi.jl/src/api_jl.jl | 12 ++++++++++ src/api.c | 46 +++++++++++++++++++++++++++++++++++++ src/api.f90 | 26 +++++++++++++++++++++ src/trixi.h | 2 ++ 6 files changed, 124 insertions(+), 2 deletions(-) diff --git a/LibTrixi.jl/src/LibTrixi.jl b/LibTrixi.jl/src/LibTrixi.jl index 57d79722..bf14dd41 100644 --- a/LibTrixi.jl/src/LibTrixi.jl +++ b/LibTrixi.jl/src/LibTrixi.jl @@ -2,8 +2,8 @@ module LibTrixi using OrdinaryDiffEq: OrdinaryDiffEq, step!, check_error, DiscreteCallback using Trixi: Trixi, summary_callback, mesh_equations_solver_cache, nelements, - nelementsglobal, nvariables, nnodes, wrap_array, eachelement, cons2prim, - get_node_vars, eachnode + nelementsglobal, ndofs, ndofsglobal, nvariables, nnodes, wrap_array, + eachelement, cons2prim, get_node_vars, eachnode using MPI: MPI, run_init_hooks, set_default_error_handler_return using Pkg @@ -31,6 +31,12 @@ export trixi_nelements, export trixi_nelements_global, trixi_nelements_global_cfptr, trixi_nelements_global_jl +export trixi_ndofs, + trixi_ndofs_cfptr, + trixi_ndofs_jl +export trixi_ndofs_global, + trixi_ndofs_global_cfptr, + trixi_ndofs_global_jl export trixi_nvariables, trixi_nvariables_cfptr, trixi_nvariables_jl diff --git a/LibTrixi.jl/src/api_c.jl b/LibTrixi.jl/src/api_c.jl index e21ab685..148ce3d0 100644 --- a/LibTrixi.jl/src/api_c.jl +++ b/LibTrixi.jl/src/api_c.jl @@ -312,6 +312,36 @@ end trixi_nelements_global_cfptr() = @cfunction(trixi_nelements_global, Cint, (Cint,)) +""" + trixi_ndofs(simstate_handle::Cint)::Cint + +Return number of degrees of freedom (all quadrature points on all cells of current rank). +""" +function trixi_ndofs end + +Base.@ccallable function trixi_ndofs(simstate_handle::Cint)::Cint + simstate = load_simstate(simstate_handle) + return trixi_ndofs_jl(simstate) +end + +trixi_ndofs_cfptr() = @cfunction(trixi_ndofs, Cint, (Cint,)) + + +""" + trixi_ndofs_global(simstate_handle::Cint)::Cint + +Return number of global eldegrees of freedom (all quadrature points on all cells). +""" +function trixi_ndofs_global end + +Base.@ccallable function trixi_ndofs_global(simstate_handle::Cint)::Cint + simstate = load_simstate(simstate_handle) + return trixi_ndofs_global_jl(simstate) +end + +trixi_ndofs_global_cfptr() = @cfunction(trixi_ndofs_global, Cint, (Cint,)) + + """ trixi_nvariables(simstate_handle::Cint)::Cint diff --git a/LibTrixi.jl/src/api_jl.jl b/LibTrixi.jl/src/api_jl.jl index 3a31215b..4ca1ad60 100644 --- a/LibTrixi.jl/src/api_jl.jl +++ b/LibTrixi.jl/src/api_jl.jl @@ -82,6 +82,18 @@ function trixi_nelements_global_jl(simstate) end +function trixi_ndofs_jl(simstate) + mesh, _, solver, cache = mesh_equations_solver_cache(simstate.semi) + return ndofs(mesh, solver, cache) +end + + +function trixi_ndofs_global_jl(simstate) + mesh, _, solver, cache = mesh_equations_solver_cache(simstate.semi) + return ndofsglobal(mesh, solver, cache) +end + + function trixi_nvariables_jl(simstate) _, equations, _, _ = mesh_equations_solver_cache(simstate.semi) return nvariables(equations) diff --git a/src/api.c b/src/api.c index 0b9a0130..8bbb09ae 100644 --- a/src/api.c +++ b/src/api.c @@ -15,6 +15,8 @@ enum { TRIXI_FTPR_NDIMS, TRIXI_FPTR_NELEMENTS, TRIXI_FPTR_NELEMENTS_GLOBAL, + TRIXI_FPTR_NDOFS, + TRIXI_FPTR_NDOFS_GLOBAL, TRIXI_FTPR_NVARIABLES, TRIXI_FTPR_LOAD_CELL_AVERAGES, TRIXI_FTPR_VERSION_LIBRARY, @@ -44,6 +46,8 @@ static const char* trixi_function_pointer_names[] = { [TRIXI_FTPR_NDIMS] = "trixi_ndims_cfptr", [TRIXI_FPTR_NELEMENTS] = "trixi_nelements_cfptr", [TRIXI_FPTR_NELEMENTS_GLOBAL] = "trixi_nelements_global_cfptr", + [TRIXI_FPTR_NDOFS] = "trixi_ndofs_cfptr", + [TRIXI_FPTR_NDOFS_GLOBAL] = "trixi_ndofs_global_cfptr", [TRIXI_FTPR_NVARIABLES] = "trixi_nvariables_cfptr", [TRIXI_FTPR_LOAD_CELL_AVERAGES] = "trixi_load_cell_averages_cfptr", [TRIXI_FTPR_VERSION_LIBRARY] = "trixi_version_library_cfptr", @@ -488,6 +492,48 @@ int trixi_nelements_global(int handle) { } +/** + * @anchor trixi_ndofs_api_c + * + * @brief Return number of local degrees of freedom. + * + * These usually differ from the global count when doing parallel computations. + * + * @param[in] handle simulation handle + * + * @see trixi_ndofs_global_api_c + */ +int trixi_ndofs(int handle) { + + // Get function pointer + int (*ndofs)(int) = trixi_function_pointers[TRIXI_FPTR_NDOFS]; + + // Call function + return ndofs(handle); +} + + +/** + * @anchor trixi_ndofs_global_api_c + * + * @brief Return number of global degrees of freedom. + * + * These usually differ from the local count when doing parallel computations. + * + * @param[in] handle simulation handle + * + * @see trixi_ndofs_api_c + */ +int trixi_ndofs_global(int handle) { + + // Get function pointer + int (*ndofs_global)(int) = trixi_function_pointers[TRIXI_FPTR_NDOFS_GLOBAL]; + + // Call function + return ndofs_global(handle); +} + + /** * @anchor trixi_nvariables_api_c * diff --git a/src/api.f90 b/src/api.f90 index c75771aa..4ac643ea 100644 --- a/src/api.f90 +++ b/src/api.f90 @@ -271,6 +271,32 @@ integer(c_int) function trixi_nelements_global(handle) bind(c) integer(c_int), value, intent(in) :: handle end function + !> + !! @fn LibTrixi::trixi_ndofs::trixi_ndofs(handle) + !! + !! @brief Return number of local degrees of freedom + !! + !! @param[in] handle simulation handle + !! + !! @see @ref trixi_ndofs_api_c "trixi_ndofs (C API)" + integer(c_int) function trixi_ndofs(handle) bind(c) + use, intrinsic :: iso_c_binding, only: c_int + integer(c_int), value, intent(in) :: handle + end function + + !> + !! @fn LibTrixi::trixi_ndofs_global::trixi_ndofs_global(handle) + !! + !! @brief Return number of global degrees of freedom + !! + !! @param[in] handle simulation handle + !! + !! @see @ref trixi_ndofs_global_api_c "trixi_ndofs_global (C API)" + integer(c_int) function trixi_ndofs_global(handle) bind(c) + use, intrinsic :: iso_c_binding, only: c_int + integer(c_int), value, intent(in) :: handle + end function + !> !! @fn LibTrixi::trixi_nvariables::trixi_nvariables(handle) !! diff --git a/src/trixi.h b/src/trixi.h index 9d8be9bd..a7b23ebc 100644 --- a/src/trixi.h +++ b/src/trixi.h @@ -28,6 +28,8 @@ void trixi_step(int handle); int trixi_ndims(int handle); int trixi_nelements(int handle); int trixi_nelements_global(int handle); +int trixi_ndofs(int handle); +int trixi_ndofs_global(int handle); int trixi_nvariables(int handle); double trixi_calculate_dt(int handle); void trixi_load_cell_averages(double * data, int handle); From 72709e567227c4d7a31ab3bc2b05110bf0f61769 Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Thu, 22 Feb 2024 17:57:12 +0100 Subject: [PATCH 02/89] change trixi_load_cell_average add parameter index and only get averaged of the variable at position index --- LibTrixi.jl/src/api_c.jl | 13 +++---- LibTrixi.jl/src/api_jl.jl | 19 +++------- LibTrixi.jl/test/test_interface.jl | 8 ++-- examples/trixi_controller_data.c | 6 +-- examples/trixi_controller_data.f90 | 6 +-- src/api.c | 15 ++++---- src/api.f90 | 6 ++- src/trixi.h | 2 +- test/c/simulation.cpp | 55 +++++++++++++++------------- test/fortran/simulationRun_suite.f90 | 8 ++-- 10 files changed, 69 insertions(+), 69 deletions(-) diff --git a/LibTrixi.jl/src/api_c.jl b/LibTrixi.jl/src/api_c.jl index 148ce3d0..746d74bf 100644 --- a/LibTrixi.jl/src/api_c.jl +++ b/LibTrixi.jl/src/api_c.jl @@ -358,19 +358,18 @@ trixi_nvariables_cfptr() = @cfunction(trixi_nvariables, Cint, (Cint,)) """ - trixi_load_cell_averages(data::Ptr{Cdouble}, simstate_handle::Cint)::Cvoid + trixi_load_cell_averages(data::Ptr{Cdouble}, index::Cint, simstate_handle::Cint)::Cvoid Return cell averaged solution state. -Cell averaged values for each cell and each primitive variable are stored in a contiguous -array, where cell values for the first variable appear first and values for the other -variables subsequently (structure-of-arrays layout). +Cell averaged values for the primitive variable at position `index` for each cell are stored +in the given array `data`. The given array has to be of correct size and memory has to be allocated beforehand. """ function trixi_load_cell_averages end -Base.@ccallable function trixi_load_cell_averages(data::Ptr{Cdouble}, +Base.@ccallable function trixi_load_cell_averages(data::Ptr{Cdouble}, index::Cint, simstate_handle::Cint)::Cvoid simstate = load_simstate(simstate_handle) @@ -378,12 +377,12 @@ Base.@ccallable function trixi_load_cell_averages(data::Ptr{Cdouble}, size = trixi_nvariables_jl(simstate) * trixi_nelements_jl(simstate) data_jl = unsafe_wrap(Array, data, size) - trixi_load_cell_averages_jl(data_jl, simstate) + trixi_load_cell_averages_jl(data_jl, index, simstate) return nothing end trixi_load_cell_averages_cfptr() = - @cfunction(trixi_load_cell_averages, Cvoid, (Ptr{Cdouble}, Cint,)) + @cfunction(trixi_load_cell_averages, Cvoid, (Ptr{Cdouble}, Cint, Cint,)) """ diff --git a/LibTrixi.jl/src/api_jl.jl b/LibTrixi.jl/src/api_jl.jl index 4ca1ad60..30cf334e 100644 --- a/LibTrixi.jl/src/api_jl.jl +++ b/LibTrixi.jl/src/api_jl.jl @@ -100,10 +100,8 @@ function trixi_nvariables_jl(simstate) end -function trixi_load_cell_averages_jl(data, simstate) +function trixi_load_cell_averages_jl(data, index, simstate) mesh, equations, solver, cache = mesh_equations_solver_cache(simstate.semi) - n_elements = nelements(solver, cache) - n_variables = nvariables(equations) n_nodes = nnodes(solver) n_dims = ndims(mesh) @@ -113,15 +111,13 @@ function trixi_load_cell_averages_jl(data, simstate) # all permutations of nodes indices for arbitrary dimension node_cis = CartesianIndices(ntuple(i -> n_nodes, n_dims)) - # temporary storage for mean value on current element for all variables - u_mean = get_node_vars(u, equations, solver, node_cis[1], 1) - for element in eachelement(solver, cache) # compute mean value using nodal dg values and quadrature - u_mean = zero(u_mean) + u_mean = zero(eltype(u)) for node_ci in node_cis - u_node_prim = cons2prim(get_node_vars(u, equations, solver, node_ci, element), equations) + u_node_prim = cons2prim(get_node_vars(u, equations, solver, node_ci, element), + equations)[index] weight = 1. for node_index in Tuple(node_ci) weight *= solver.basis.weights[node_index] @@ -132,11 +128,8 @@ function trixi_load_cell_averages_jl(data, simstate) # normalize to unit element u_mean = u_mean / 2^n_dims - # copy to provided array - # all element values for first variable, then for second, ... - for ivar = 0:n_variables-1 - data[element + ivar * n_elements] = u_mean[ivar+1] - end + # write to provided array + data[element] = u_mean end return nothing diff --git a/LibTrixi.jl/test/test_interface.jl b/LibTrixi.jl/test/test_interface.jl index fd9f70a0..a50118c5 100644 --- a/LibTrixi.jl/test/test_interface.jl +++ b/LibTrixi.jl/test/test_interface.jl @@ -87,10 +87,10 @@ end @test nvariables_c == nvariables_jl # compare cell averaged values - data_c = zeros(nvariables_c * nelements_c) - trixi_load_cell_averages(pointer(data_c), handle) - data_jl = zeros(nvariables_jl * nelements_jl) - trixi_load_cell_averages_jl(data_jl, simstate_jl) + data_c = zeros(nelements_c) + trixi_load_cell_averages(pointer(data_c), 1, handle) + data_jl = zeros(nelements_jl) + trixi_load_cell_averages_jl(data_jl, 1, simstate_jl) @test data_c == data_jl end diff --git a/examples/trixi_controller_data.c b/examples/trixi_controller_data.c index 5e6d0f1f..242d29b4 100644 --- a/examples/trixi_controller_data.c +++ b/examples/trixi_controller_data.c @@ -46,10 +46,10 @@ int main ( int argc, char *argv[] ) { printf("\n*** Trixi controller *** nelements %d\n", nelements); // Allocate memory - data = realloc( data, sizeof(double) * nelements * nvariables ); + data = realloc( data, sizeof(double) * nelements ); - // Get averaged cell values for each variable - trixi_load_cell_averages(data, handle); + // Get averaged cell values for first variable + trixi_load_cell_averages(data, 1, handle); } } diff --git a/examples/trixi_controller_data.f90 b/examples/trixi_controller_data.f90 index cdb49ecf..ebf17cce 100644 --- a/examples/trixi_controller_data.f90 +++ b/examples/trixi_controller_data.f90 @@ -63,10 +63,10 @@ program trixi_controller_data_f ! allocate memory if ( associated(data) ) deallocate(data) - allocate( data(nelements*nvariables) ) + allocate( data(nelements) ) - ! get averaged cell values for each variable - call trixi_load_cell_averages(data, handle) + ! get averaged cell values for first variable + call trixi_load_cell_averages(data, 1, handle) end if end do diff --git a/src/api.c b/src/api.c index 8bbb09ae..b49cbf66 100644 --- a/src/api.c +++ b/src/api.c @@ -554,29 +554,30 @@ int trixi_nvariables(int handle) { /** * @anchor trixi_load_cell_averages_api_c * - * @brief Return cell averaged values + * @brief Return cell averaged solution state * - * Cell averaged values for each cell and each primitive variable are stored in a - * contiguous array, where cell values for the first variable appear first and values for - * the other variables subsequently (structure-of-arrays layout). + * Cell averaged values for the primitive variable at position index for each cell are + * stored in the given array `data`. * * The given array has to be of correct size and memory has to be allocated beforehand. * * @param[in] handle simulation handle + * @param[in] index index of variable * @param[out] data cell averaged values for all cells and all primitive variables */ -void trixi_load_cell_averages(double * data, int handle) { +void trixi_load_cell_averages(double * data, int index, int handle) { // Get function pointer - void (*load_cell_averages)(double *, int) = + void (*load_cell_averages)(double *, int, int) = trixi_function_pointers[TRIXI_FTPR_LOAD_CELL_AVERAGES]; // Call function - load_cell_averages(data, handle); + load_cell_averages(data, index, handle); } + /******************************************************************************************/ /* T8code */ /******************************************************************************************/ diff --git a/src/api.f90 b/src/api.f90 index 4ac643ea..201e1eba 100644 --- a/src/api.f90 +++ b/src/api.f90 @@ -311,17 +311,19 @@ integer(c_int) function trixi_nvariables(handle) bind(c) end function !> - !! @fn LibTrixi::trixi_load_cell_averages::trixi_load_cell_averages(data, handle) + !! @fn LibTrixi::trixi_load_cell_averages::trixi_load_cell_averages(data, index, handle) !! !! @brief Return cell averaged values !! !! @param[in] handle simulation handle + !! @param[in] index index of variable !! @param[out] data cell averaged values for all cells and all variables !! !! @see @ref trixi_load_cell_averages_api_c "trixi_load_cell_averages (C API)" - subroutine trixi_load_cell_averages(data, handle) bind(c) + subroutine trixi_load_cell_averages(data, index, handle) bind(c) use, intrinsic :: iso_c_binding, only: c_int, c_double real(c_double), dimension(*), intent(in) :: data + integer(c_int), value, intent(in) :: index integer(c_int), value, intent(in) :: handle end subroutine diff --git a/src/trixi.h b/src/trixi.h index a7b23ebc..c2972190 100644 --- a/src/trixi.h +++ b/src/trixi.h @@ -32,7 +32,7 @@ int trixi_ndofs(int handle); int trixi_ndofs_global(int handle); int trixi_nvariables(int handle); double trixi_calculate_dt(int handle); -void trixi_load_cell_averages(double * data, int handle); +void trixi_load_cell_averages(double * data, int index, int handle); // T8code #if !defined(T8_H) && !defined(T8_FOREST_GENERAL_H) diff --git a/test/c/simulation.cpp b/test/c/simulation.cpp index 0db32dc5..120d1db5 100644 --- a/test/c/simulation.cpp +++ b/test/c/simulation.cpp @@ -67,49 +67,54 @@ TEST(CInterfaceTest, SimulationRun) { EXPECT_EQ(nvariables, 4); // Check cell averaged values - int size = nelements * nvariables; - std::vector cell_averages(size); - trixi_load_cell_averages(cell_averages.data(), handle); + std::vector rho_averages(nelements); + std::vector v1_averages(nelements); + std::vector v2_averages(nelements); + std::vector e_averages(nelements); + trixi_load_cell_averages(rho_averages.data(), 1, handle); + trixi_load_cell_averages(v1_averages.data(), 2, handle); + trixi_load_cell_averages(v2_averages.data(), 3, handle); + trixi_load_cell_averages(e_averages.data(), 4, handle); if (nranks == 1) { // check memory boarders (densities at the beginning, energies at the end) - EXPECT_DOUBLE_EQ(cell_averages[0], 1.0); - EXPECT_DOUBLE_EQ(cell_averages[size-1], 1.0e-5); + EXPECT_DOUBLE_EQ(rho_averages[0], 1.0); + EXPECT_DOUBLE_EQ(e_averages[nelements-1], 1.0e-5); // check values somewhere near the center (expect symmetries) // densities - EXPECT_NEAR(cell_averages[93], 0.88263491354796, 1e-14); - EXPECT_NEAR(cell_averages[94], 0.88263491354796, 1e-14); - EXPECT_NEAR(cell_averages[161], 0.88263491354796, 1e-14); - EXPECT_NEAR(cell_averages[162], 0.88263491354796, 1e-14); + EXPECT_NEAR(rho_averages[ 93], 0.88263491354796, 1e-14); + EXPECT_NEAR(rho_averages[ 94], 0.88263491354796, 1e-14); + EXPECT_NEAR(rho_averages[161], 0.88263491354796, 1e-14); + EXPECT_NEAR(rho_averages[162], 0.88263491354796, 1e-14); // velocities - EXPECT_NEAR(cell_averages[ 93+ nelements], -0.14037267400591, 1e-14); - EXPECT_NEAR(cell_averages[ 94+2*nelements], -0.14037267400591, 1e-14); - EXPECT_NEAR(cell_averages[161+2*nelements], 0.14037267400591, 1e-14); - EXPECT_NEAR(cell_averages[162+ nelements], 0.14037267400591, 1e-14); + EXPECT_NEAR(v1_averages[ 93], -0.14037267400591, 1e-14); + EXPECT_NEAR(v2_averages[ 94], -0.14037267400591, 1e-14); + EXPECT_NEAR(v2_averages[161], 0.14037267400591, 1e-14); + EXPECT_NEAR(v1_averages[162], 0.14037267400591, 1e-14); } else if (nranks == 2) { if (rank == 0) { // check memory boarders (densities at the beginning, energies at the end) - EXPECT_DOUBLE_EQ(cell_averages[0], 1.0); - EXPECT_DOUBLE_EQ(cell_averages[size-1], 1.0e-5); + EXPECT_DOUBLE_EQ(rho_averages[0], 1.0); + EXPECT_DOUBLE_EQ(e_averages[nelements-1], 1.0e-5); // check values somewhere near the center (expect symmetries) // densities - EXPECT_NEAR(cell_averages[93], 0.88263491354796, 1e-14); - EXPECT_NEAR(cell_averages[94], 0.88263491354796, 1e-14); + EXPECT_NEAR(rho_averages[93], 0.88263491354796, 1e-14); + EXPECT_NEAR(rho_averages[94], 0.88263491354796, 1e-14); // velocities - EXPECT_NEAR(cell_averages[93+ nelements], -0.14037267400591, 1e-14); - EXPECT_NEAR(cell_averages[94+2*nelements], -0.14037267400591, 1e-14); + EXPECT_NEAR(v1_averages[93], -0.14037267400591, 1e-14); + EXPECT_NEAR(v2_averages[94], -0.14037267400591, 1e-14); } else { // check memory boarders (densities at the beginning, energies at the end) - EXPECT_DOUBLE_EQ(cell_averages[0], 1.0); - EXPECT_DOUBLE_EQ(cell_averages[size-1], 1.0e-5); + EXPECT_DOUBLE_EQ(rho_averages[0], 1.0); + EXPECT_DOUBLE_EQ(e_averages[nelements-1], 1.0e-5); // check values somewhere near the center (expect symmetries) // densities - EXPECT_NEAR(cell_averages[33], 0.88263491354796, 1e-14); - EXPECT_NEAR(cell_averages[34], 0.88263491354796, 1e-14); + EXPECT_NEAR(rho_averages[33], 0.88263491354796, 1e-14); + EXPECT_NEAR(rho_averages[34], 0.88263491354796, 1e-14); // velocities - EXPECT_NEAR(cell_averages[33+2*nelements], 0.14037267400591, 1e-14); - EXPECT_NEAR(cell_averages[34+ nelements], 0.14037267400591, 1e-14); + EXPECT_NEAR(v2_averages[33], 0.14037267400591, 1e-14); + EXPECT_NEAR(v1_averages[34], 0.14037267400591, 1e-14); } } else { diff --git a/test/fortran/simulationRun_suite.f90 b/test/fortran/simulationRun_suite.f90 index 1f81eb6f..5317c779 100644 --- a/test/fortran/simulationRun_suite.f90 +++ b/test/fortran/simulationRun_suite.f90 @@ -63,13 +63,13 @@ subroutine test_simulationRun(error) call check(error, nvariables, 4) ! Check cell averaged values - size = nelements*nvariables + size = nelements allocate(data(size)) - call trixi_load_cell_averages(data, handle) + call trixi_load_cell_averages(data, 1, handle) call check(error, data(1), 1.0_dp) - call check(error, data(929), 2.6605289164377273_dp) + call check(error, data(94), 0.88263491354796_dp) call check(error, data(size), 1e-5_dp) - + ! Finalize Trixi simulation call trixi_finalize_simulation(handle) From 71ba4bf0bba36e7c9869d92fe68be4fb1a2dfb3e Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Fri, 23 Feb 2024 12:44:55 +0100 Subject: [PATCH 03/89] fix: ensure Int32 --- LibTrixi.jl/test/test_interface.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LibTrixi.jl/test/test_interface.jl b/LibTrixi.jl/test/test_interface.jl index a50118c5..1d2d2b41 100644 --- a/LibTrixi.jl/test/test_interface.jl +++ b/LibTrixi.jl/test/test_interface.jl @@ -88,7 +88,7 @@ end # compare cell averaged values data_c = zeros(nelements_c) - trixi_load_cell_averages(pointer(data_c), 1, handle) + trixi_load_cell_averages(pointer(data_c), Int32(1), handle) data_jl = zeros(nelements_jl) trixi_load_cell_averages_jl(data_jl, 1, simstate_jl) @test data_c == data_jl From 9c83b056bd7cabb79f618555f82a6fe4772ffebb Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Fri, 23 Feb 2024 14:16:23 +0100 Subject: [PATCH 04/89] adapt reference value --- test/fortran/simulationRun_suite.f90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/fortran/simulationRun_suite.f90 b/test/fortran/simulationRun_suite.f90 index 5317c779..785937b1 100644 --- a/test/fortran/simulationRun_suite.f90 +++ b/test/fortran/simulationRun_suite.f90 @@ -67,7 +67,7 @@ subroutine test_simulationRun(error) allocate(data(size)) call trixi_load_cell_averages(data, 1, handle) call check(error, data(1), 1.0_dp) - call check(error, data(94), 0.88263491354796_dp) + call check(error, data(94), 0.99833232379996562_dp) call check(error, data(size), 1e-5_dp) ! Finalize Trixi simulation From 5b3960bbe3c578d85ad779dbe0b95ddf26dd94a4 Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Fri, 23 Feb 2024 14:23:31 +0100 Subject: [PATCH 05/89] add getter for all dofs values --- LibTrixi.jl/src/LibTrixi.jl | 3 +++ LibTrixi.jl/src/api_c.jl | 29 +++++++++++++++++++++++++++++ LibTrixi.jl/src/api_jl.jl | 25 +++++++++++++++++++++++++ src/api.c | 25 +++++++++++++++++++++++++ src/trixi.h | 1 + 5 files changed, 83 insertions(+) diff --git a/LibTrixi.jl/src/LibTrixi.jl b/LibTrixi.jl/src/LibTrixi.jl index bf14dd41..277f2d1d 100644 --- a/LibTrixi.jl/src/LibTrixi.jl +++ b/LibTrixi.jl/src/LibTrixi.jl @@ -43,6 +43,9 @@ export trixi_nvariables, export trixi_load_cell_averages, trixi_load_cell_averages_cfptr, trixi_load_cell_averages_jl +export trixi_load_prim, + trixi_load_prim_cfptr, + trixi_load_prim_jl export trixi_version_library, trixi_version_library_cfptr, trixi_version_library_jl diff --git a/LibTrixi.jl/src/api_c.jl b/LibTrixi.jl/src/api_c.jl index 746d74bf..143907fd 100644 --- a/LibTrixi.jl/src/api_c.jl +++ b/LibTrixi.jl/src/api_c.jl @@ -385,6 +385,35 @@ trixi_load_cell_averages_cfptr() = @cfunction(trixi_load_cell_averages, Cvoid, (Ptr{Cdouble}, Cint, Cint,)) +""" + trixi_load_prim(data::Ptr{Cdouble}, index::Cint, simstate_handle::Cint)::Cvoid + +Return primitive variable. + +The values for the primitive variable at position `index` at every degree of freedom for +the simulation given by `simstate_handle` is stored in the given array `data`. + +The given array has to be of correct size and memory has to be allocated beforehand. +""" +function trixi_load_prim end + +Base.@ccallable function trixi_load_prim(data::Ptr{Cdouble}, index::Cint, + simstate_handle::Cint)::Cvoid + simstate = load_simstate(simstate_handle) + + # convert C to Julia array + size = trixi_ndofs_jl(simstate) + data_jl = unsafe_wrap(Array, data, size) + + trixi_load_prim_jl(data_jl, index, simstate) + return nothing +end + +trixi_load_prim_cfptr() = + @cfunction(trixi_load_prim, Cvoid, (Ptr{Cdouble}, Cint, Cint,)) + + + """ trixi_get_t8code_forest(simstate_handle::Cint)::::Ptr{Trixi.t8_forest} diff --git a/LibTrixi.jl/src/api_jl.jl b/LibTrixi.jl/src/api_jl.jl index 30cf334e..59c74e13 100644 --- a/LibTrixi.jl/src/api_jl.jl +++ b/LibTrixi.jl/src/api_jl.jl @@ -136,6 +136,31 @@ function trixi_load_cell_averages_jl(data, index, simstate) end +function trixi_load_prim_jl(data, index, simstate) + mesh, equations, solver, cache = mesh_equations_solver_cache(simstate.semi) + n_nodes_per_dim = nnodes(solver) + n_dims = ndims(mesh) + n_nodes = n_nodes_per_dim^n_dims + + u_ode = simstate.integrator.u + u = wrap_array(u_ode, mesh, equations, solver, cache) + + # all permutations of nodes indices for arbitrary dimension + node_cis = CartesianIndices(ntuple(i -> n_nodes_per_dim, n_dims)) + node_lis = LinearIndices(node_cis) + + for element in eachelement(solver, cache) + for node_ci in node_cis + node_vars = get_node_vars(u, equations, solver, node_ci, element) + node_index = (element-1) * n_nodes + node_lis[node_ci] + data[node_index] = cons2prim(node_vars, equations)[index] + end + end + + return nothing +end + + function trixi_get_t8code_forest_jl(simstate) mesh, _, _, _ = Trixi.mesh_equations_solver_cache(simstate.semi) return mesh.forest diff --git a/src/api.c b/src/api.c index b49cbf66..a1ceb8e0 100644 --- a/src/api.c +++ b/src/api.c @@ -19,6 +19,7 @@ enum { TRIXI_FPTR_NDOFS_GLOBAL, TRIXI_FTPR_NVARIABLES, TRIXI_FTPR_LOAD_CELL_AVERAGES, + TRIXI_FTPR_LOAD_PRIM, TRIXI_FTPR_VERSION_LIBRARY, TRIXI_FTPR_VERSION_LIBRARY_MAJOR, TRIXI_FTPR_VERSION_LIBRARY_MINOR, @@ -50,6 +51,7 @@ static const char* trixi_function_pointer_names[] = { [TRIXI_FPTR_NDOFS_GLOBAL] = "trixi_ndofs_global_cfptr", [TRIXI_FTPR_NVARIABLES] = "trixi_nvariables_cfptr", [TRIXI_FTPR_LOAD_CELL_AVERAGES] = "trixi_load_cell_averages_cfptr", + [TRIXI_FTPR_LOAD_PRIM] = "trixi_load_prim_cfptr", [TRIXI_FTPR_VERSION_LIBRARY] = "trixi_version_library_cfptr", [TRIXI_FTPR_VERSION_LIBRARY_MAJOR] = "trixi_version_library_major_cfptr", [TRIXI_FTPR_VERSION_LIBRARY_MINOR] = "trixi_version_library_minor_cfptr", @@ -576,6 +578,29 @@ void trixi_load_cell_averages(double * data, int index, int handle) { } +/** + * @anchor trixi_load_prim_api_c + * + * @brief Return primitive variable + * + * The values for the primitive variable at position index at every degree of freedom for + * the simulation given by simstate_handle is stored in the given array data. + * + * The given array has to be of correct size and memory has to be allocated beforehand. + * + * @param[in] handle simulation handle + * @param[in] index index of variable + * @param[out] data cell averaged values for all cells and all primitive variables + */ +void trixi_load_prim(double * data, int index, int handle) { + + // Get function pointer + void (*load_prim)(double *, int, int) = + trixi_function_pointers[TRIXI_FTPR_LOAD_PRIM]; + + // Call function + load_prim(data, index, handle); +} /******************************************************************************************/ diff --git a/src/trixi.h b/src/trixi.h index c2972190..f9cfb571 100644 --- a/src/trixi.h +++ b/src/trixi.h @@ -33,6 +33,7 @@ int trixi_ndofs_global(int handle); int trixi_nvariables(int handle); double trixi_calculate_dt(int handle); void trixi_load_cell_averages(double * data, int index, int handle); +void trixi_load_prim(double * data, int index, int handle); // T8code #if !defined(T8_H) && !defined(T8_FOREST_GENERAL_H) From 3e31f4a86f6aa4cd1868bf249ad78eac8a2fbf0a Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Fri, 23 Feb 2024 14:41:43 +0100 Subject: [PATCH 06/89] adapt next value --- test/fortran/simulationRun_suite.f90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/fortran/simulationRun_suite.f90 b/test/fortran/simulationRun_suite.f90 index 785937b1..46993b4b 100644 --- a/test/fortran/simulationRun_suite.f90 +++ b/test/fortran/simulationRun_suite.f90 @@ -68,7 +68,7 @@ subroutine test_simulationRun(error) call trixi_load_cell_averages(data, 1, handle) call check(error, data(1), 1.0_dp) call check(error, data(94), 0.99833232379996562_dp) - call check(error, data(size), 1e-5_dp) + call check(error, data(size), 1.0_dp) ! Finalize Trixi simulation call trixi_finalize_simulation(handle) From 2d45c62c646d9a738bfbea707f50102976ad4d31 Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Mon, 26 Feb 2024 10:09:38 +0100 Subject: [PATCH 07/89] add trixi_store_in_database proof of concept for creating data vectors in libelixirs which can be filled later by external applications --- LibTrixi.jl/src/LibTrixi.jl | 4 ++ LibTrixi.jl/src/api_c.jl | 31 +++++++++++ LibTrixi.jl/src/api_jl.jl | 9 ++++ LibTrixi.jl/src/simulationstate.jl | 13 ++++- examples/CMakeLists.txt | 3 +- examples/trixi_controller_source_terms.c | 65 ++++++++++++++++++++++++ src/api.c | 34 +++++++++++++ src/trixi.h | 1 + 8 files changed, 157 insertions(+), 3 deletions(-) create mode 100644 examples/trixi_controller_source_terms.c diff --git a/LibTrixi.jl/src/LibTrixi.jl b/LibTrixi.jl/src/LibTrixi.jl index 277f2d1d..8be209d9 100644 --- a/LibTrixi.jl/src/LibTrixi.jl +++ b/LibTrixi.jl/src/LibTrixi.jl @@ -46,6 +46,9 @@ export trixi_load_cell_averages, export trixi_load_prim, trixi_load_prim_cfptr, trixi_load_prim_jl +export trixi_store_in_database, + trixi_store_in_database_cfptr, + trixi_store_in_database_jl export trixi_version_library, trixi_version_library_cfptr, trixi_version_library_jl @@ -72,6 +75,7 @@ export trixi_eval_julia, trixi_eval_julia_jl export SimulationState, store_simstate, load_simstate, delete_simstate! +export LibTrixiDataBaseType # global storage of name and version information of loaded packages diff --git a/LibTrixi.jl/src/api_c.jl b/LibTrixi.jl/src/api_c.jl index 143907fd..1c0b415c 100644 --- a/LibTrixi.jl/src/api_c.jl +++ b/LibTrixi.jl/src/api_c.jl @@ -413,6 +413,37 @@ trixi_load_prim_cfptr() = @cfunction(trixi_load_prim, Cvoid, (Ptr{Cdouble}, Cint, Cint,)) +""" + trixi_store_in_database(data::Ptr{Cdouble}, size::Cint, index::Cint, + simstate_handle::Cint)::Cvoid + +Store data vector in current simulation's database. + +A reference to the passed data array `data` will be stored in the database of the simulation +given by `simstate_handle` at given `index`. The database object has to be created in +`init_simstate()` of the running libelixir and can be used throughout the simulation. + +The database object has to exist, has to be of type `LibTrixiDataBaseType`, and has to hold +enough data references such that access at `index` is valid. + +The size of `data` has to match `size`. +""" +function trixi_store_in_database end + +Base.@ccallable function trixi_store_in_database(data::Ptr{Cdouble}, size::Cint, + index::Cint, simstate_handle::Cint)::Cvoid + simstate = load_simstate(simstate_handle) + + # convert C to Julia array + data_jl = unsafe_wrap(Array, data, size) + + trixi_store_in_database_jl(data_jl, index, simstate) + return nothing +end + +trixi_store_in_database_cfptr() = + @cfunction(trixi_store_in_database, Cvoid, (Ptr{Cdouble}, Cint, Cint, Cint,)) + """ trixi_get_t8code_forest(simstate_handle::Cint)::::Ptr{Trixi.t8_forest} diff --git a/LibTrixi.jl/src/api_jl.jl b/LibTrixi.jl/src/api_jl.jl index 59c74e13..30852e75 100644 --- a/LibTrixi.jl/src/api_jl.jl +++ b/LibTrixi.jl/src/api_jl.jl @@ -161,6 +161,15 @@ function trixi_load_prim_jl(data, index, simstate) end +function trixi_store_in_database_jl(data, index, simstate) + simstate.data[index] = Ref(data) + if show_debug_output() + println("New data vector stored at index ", index) + end + return nothing +end + + function trixi_get_t8code_forest_jl(simstate) mesh, _, _, _ = Trixi.mesh_equations_solver_cache(simstate.semi) return mesh.forest diff --git a/LibTrixi.jl/src/simulationstate.jl b/LibTrixi.jl/src/simulationstate.jl index 4ca4796c..dcfe52c5 100644 --- a/LibTrixi.jl/src/simulationstate.jl +++ b/LibTrixi.jl/src/simulationstate.jl @@ -1,12 +1,21 @@ """ SimulationState -Data structure to store a simulation state that consists of a semidiscretization -plus the time integrator. +Data structure to store a simulation state consisting of +- a semidiscretization +- the time integrator +- an optional array of data vectors """ +const LibTrixiDataBaseType = Array{Ref{Vector{Float64}}} + mutable struct SimulationState{SemiType, IntegratorType} semi::SemiType integrator::IntegratorType + data::LibTrixiDataBaseType + + function SimulationState(semi, integrator, data = nothing) + return new{typeof(semi), typeof(integrator)}(semi, integrator, data) + end end # Global variables to store different simulation states diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 327d4310..b9f02135 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -5,7 +5,8 @@ set ( EXAMPLES trixi_controller_mpi.f90 trixi_controller_data.c trixi_controller_data.f90 - trixi_controller_t8code.c ) + trixi_controller_t8code.c + trixi_controller_source_terms.c ) if ( NOT T8CODE_FOUND ) list( FILTER EXAMPLES EXCLUDE REGEX ".*(t|T)8(c|C)(o|O)(d|D)(e|E).*" ) diff --git a/examples/trixi_controller_source_terms.c b/examples/trixi_controller_source_terms.c new file mode 100644 index 00000000..f1b0f642 --- /dev/null +++ b/examples/trixi_controller_source_terms.c @@ -0,0 +1,65 @@ +#include +#include + +#include + +int main ( int argc, char *argv[] ) { + + if ( argc < 2 ) { + fprintf(stderr, "ERROR: missing arguments: PROJECT_DIR LIBELIXIR_PATH\n\n"); + fprintf(stderr, "usage: %s PROJECT_DIR LIBELIXIR_PATH\n", argv[0]); + return 2; + } else if ( argc < 3 ) { + fprintf(stderr, "ERROR: missing argument: LIBELIXIR_PATH\n\n"); + fprintf(stderr, "usage: %s PROJECT_DIR LIBELIXIR_PATH\n", argv[0]); + return 2; + } + + // Initialize Trixi + printf("\n*** Trixi controller *** Initialize Trixi\n"); + trixi_initialize( argv[1], NULL ); + + // Set up the Trixi simulation + // We get a handle to use subsequently + printf("\n*** Trixi controller *** Set up Trixi simulation\n"); + int handle = trixi_initialize_simulation( argv[2] ); + + // Get number of variables and elements + int ndofs = trixi_ndofs( handle ); + + // Allocate memory + double * rho = calloc( sizeof(double), ndofs ); + double * source = calloc( sizeof(double), ndofs ); + + // Main loop + printf("\n*** Trixi controller *** Entering main loop\n"); + while ( !trixi_is_finished( handle ) ) { + + // Get current solution at every DOF + trixi_load_prim(rho, 1, handle); + + // Compute source term + for ( int i = 0; i < ndofs; i++ ) { + source[i] = rho[i]; + } + + // Store source terms + trixi_store_in_database(source, ndofs, 1, handle); + + // Perform next step + trixi_step( handle ); + } + + // Finalize Trixi simulation + printf("\n*** Trixi controller *** Finalize Trixi simulation\n"); + trixi_finalize_simulation( handle ); + + // Finalize Trixi + printf("\n*** Trixi controller *** Finalize Trixi\n"); + trixi_finalize(); + + free(rho); + free(source); + + return 0; +} diff --git a/src/api.c b/src/api.c index a1ceb8e0..5ca9f066 100644 --- a/src/api.c +++ b/src/api.c @@ -20,6 +20,7 @@ enum { TRIXI_FTPR_NVARIABLES, TRIXI_FTPR_LOAD_CELL_AVERAGES, TRIXI_FTPR_LOAD_PRIM, + TRIXI_FTPR_STORE_IN_DATABASE, TRIXI_FTPR_VERSION_LIBRARY, TRIXI_FTPR_VERSION_LIBRARY_MAJOR, TRIXI_FTPR_VERSION_LIBRARY_MINOR, @@ -52,6 +53,7 @@ static const char* trixi_function_pointer_names[] = { [TRIXI_FTPR_NVARIABLES] = "trixi_nvariables_cfptr", [TRIXI_FTPR_LOAD_CELL_AVERAGES] = "trixi_load_cell_averages_cfptr", [TRIXI_FTPR_LOAD_PRIM] = "trixi_load_prim_cfptr", + [TRIXI_FTPR_STORE_IN_DATABASE] = "trixi_store_in_database_cfptr", [TRIXI_FTPR_VERSION_LIBRARY] = "trixi_version_library_cfptr", [TRIXI_FTPR_VERSION_LIBRARY_MAJOR] = "trixi_version_library_major_cfptr", [TRIXI_FTPR_VERSION_LIBRARY_MINOR] = "trixi_version_library_minor_cfptr", @@ -603,6 +605,38 @@ void trixi_load_prim(double * data, int index, int handle) { } +/** + * @anchor trixi_store_in_database_api_c + * + * @brief Store data vector in current simulation's database + * + * A reference to the passed data array data will be stored in the database of the + * simulation given by simstate_handle at given index. The database object has to be + * created in init_simstate() of the running libelixir and can be used throughout the + * simulation. + * + * The database object has to exist, has to be of type `LibTrixiDataBaseType`, and has to + * hold enough data references such that access at `index` is valid. + * + * The size of data has to match size. + * + * @param[in] data data vector to store + * @param[in] size size of given data vector + * @param[in] index index in database where data vector will be stored + * @param[in] handle simulation handle + */ +void trixi_store_in_database(double * data, int size, int index, int handle) { + + // Get function pointer + void (*store_in_database)(double *, int, int, int) = + trixi_function_pointers[TRIXI_FTPR_STORE_IN_DATABASE]; + + // Call function + store_in_database(data, size, index, handle); +} + + + /******************************************************************************************/ /* T8code */ /******************************************************************************************/ diff --git a/src/trixi.h b/src/trixi.h index f9cfb571..13114a9c 100644 --- a/src/trixi.h +++ b/src/trixi.h @@ -34,6 +34,7 @@ int trixi_nvariables(int handle); double trixi_calculate_dt(int handle); void trixi_load_cell_averages(double * data, int index, int handle); void trixi_load_prim(double * data, int index, int handle); +void trixi_store_in_database(double * data, int size, int index, int handle); // T8code #if !defined(T8_H) && !defined(T8_FOREST_GENERAL_H) From 92d817a8acace71a9859ae48b36697671bbbe1e7 Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Mon, 26 Feb 2024 11:04:10 +0100 Subject: [PATCH 08/89] add trixi_ndofs_element --- LibTrixi.jl/src/LibTrixi.jl | 5 ++++- LibTrixi.jl/src/api_c.jl | 15 +++++++++++++++ LibTrixi.jl/src/api_jl.jl | 6 ++++++ src/api.c | 19 +++++++++++++++++++ src/api.f90 | 10 ++++++++++ 5 files changed, 54 insertions(+), 1 deletion(-) diff --git a/LibTrixi.jl/src/LibTrixi.jl b/LibTrixi.jl/src/LibTrixi.jl index 277f2d1d..efabc624 100644 --- a/LibTrixi.jl/src/LibTrixi.jl +++ b/LibTrixi.jl/src/LibTrixi.jl @@ -1,7 +1,7 @@ module LibTrixi using OrdinaryDiffEq: OrdinaryDiffEq, step!, check_error, DiscreteCallback -using Trixi: Trixi, summary_callback, mesh_equations_solver_cache, nelements, +using Trixi: Trixi, summary_callback, mesh_equations_solver_cache, ndims, nelements, nelementsglobal, ndofs, ndofsglobal, nvariables, nnodes, wrap_array, eachelement, cons2prim, get_node_vars, eachnode using MPI: MPI, run_init_hooks, set_default_error_handler_return @@ -37,6 +37,9 @@ export trixi_ndofs, export trixi_ndofs_global, trixi_ndofs_global_cfptr, trixi_ndofs_global_jl +export trixi_ndofs_element, + trixi_ndofs_element_cfptr, + trixi_ndofs_element_jl export trixi_nvariables, trixi_nvariables_cfptr, trixi_nvariables_jl diff --git a/LibTrixi.jl/src/api_c.jl b/LibTrixi.jl/src/api_c.jl index 143907fd..9b1af564 100644 --- a/LibTrixi.jl/src/api_c.jl +++ b/LibTrixi.jl/src/api_c.jl @@ -342,6 +342,21 @@ end trixi_ndofs_global_cfptr() = @cfunction(trixi_ndofs_global, Cint, (Cint,)) +""" + trixi_ndofs_element(simstate_handle::Cint)::Cint + +Return number of degrees of freedom per element (cell). +""" +function trixi_ndofs_element end + +Base.@ccallable function trixi_ndofs_element(simstate_handle::Cint)::Cint + simstate = load_simstate(simstate_handle) + return trixi_ndofs_element_jl(simstate) +end + +trixi_ndofs_element_cfptr() = @cfunction(trixi_ndofs_element, Cint, (Cint,)) + + """ trixi_nvariables(simstate_handle::Cint)::Cint diff --git a/LibTrixi.jl/src/api_jl.jl b/LibTrixi.jl/src/api_jl.jl index 59c74e13..b5d0a247 100644 --- a/LibTrixi.jl/src/api_jl.jl +++ b/LibTrixi.jl/src/api_jl.jl @@ -94,6 +94,12 @@ function trixi_ndofs_global_jl(simstate) end +function trixi_ndofs_element_jl(simstate) + mesh, _, solver, _ = mesh_equations_solver_cache(simstate.semi) + return nnodes(solver)^ndims(mesh) +end + + function trixi_nvariables_jl(simstate) _, equations, _, _ = mesh_equations_solver_cache(simstate.semi) return nvariables(equations) diff --git a/src/api.c b/src/api.c index a1ceb8e0..cdb43e12 100644 --- a/src/api.c +++ b/src/api.c @@ -17,6 +17,7 @@ enum { TRIXI_FPTR_NELEMENTS_GLOBAL, TRIXI_FPTR_NDOFS, TRIXI_FPTR_NDOFS_GLOBAL, + TRIXI_FPTR_NDOFS_ELEMENT, TRIXI_FTPR_NVARIABLES, TRIXI_FTPR_LOAD_CELL_AVERAGES, TRIXI_FTPR_LOAD_PRIM, @@ -49,6 +50,7 @@ static const char* trixi_function_pointer_names[] = { [TRIXI_FPTR_NELEMENTS_GLOBAL] = "trixi_nelements_global_cfptr", [TRIXI_FPTR_NDOFS] = "trixi_ndofs_cfptr", [TRIXI_FPTR_NDOFS_GLOBAL] = "trixi_ndofs_global_cfptr", + [TRIXI_FPTR_NDOFS_ELEMENT] = "trixi_ndofs_element_cfptr", [TRIXI_FTPR_NVARIABLES] = "trixi_nvariables_cfptr", [TRIXI_FTPR_LOAD_CELL_AVERAGES] = "trixi_load_cell_averages_cfptr", [TRIXI_FTPR_LOAD_PRIM] = "trixi_load_prim_cfptr", @@ -536,6 +538,23 @@ int trixi_ndofs_global(int handle) { } +/** + * @anchor trixi_ndofs_element_api_c + * + * @brief Return number of degrees of freedom per element (cell). + * + * @param[in] handle simulation handle + */ +int trixi_ndofs_element(int handle) { + + // Get function pointer + int (*ndofs_element)(int) = trixi_function_pointers[TRIXI_FPTR_NDOFS_ELEMENT]; + + // Call function + return ndofs_element(handle); +} + + /** * @anchor trixi_nvariables_api_c * diff --git a/src/api.f90 b/src/api.f90 index 201e1eba..36fb6726 100644 --- a/src/api.f90 +++ b/src/api.f90 @@ -297,6 +297,16 @@ integer(c_int) function trixi_ndofs_global(handle) bind(c) integer(c_int), value, intent(in) :: handle end function + !! @anchor trixi_ndofs_element_api_c + !! + !! @brief Return number of degrees of freedom per element (cell). + !! + !! @param[in] handle simulation handle + integer(c_int) function trixi_ndofs_element(handle) bind(c) + use, intrinsic :: iso_c_binding, only: c_int + integer(c_int), value, intent(in) :: handle + end function + !> !! @fn LibTrixi::trixi_nvariables::trixi_nvariables(handle) !! From 530f5cce2698b5a936598cb3762456364d32c69c Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Mon, 26 Feb 2024 11:10:20 +0100 Subject: [PATCH 09/89] add tests --- LibTrixi.jl/test/test_interface.jl | 20 ++++++++++++++++++++ test/c/simulation.cpp | 28 ++++++++++++++++++++++++++++ test/fortran/simulationRun_suite.f90 | 10 ++++++++++ 3 files changed, 58 insertions(+) diff --git a/LibTrixi.jl/test/test_interface.jl b/LibTrixi.jl/test/test_interface.jl index 1d2d2b41..498fce4c 100644 --- a/LibTrixi.jl/test/test_interface.jl +++ b/LibTrixi.jl/test/test_interface.jl @@ -81,6 +81,19 @@ end nelements_global_jl = trixi_nelements_global_jl(simstate_jl) @test nelements_global_c == nelements_global_jl + # compare number of dofs + ndofs_c = trixi_ndofs(handle) + ndofs_jl = trixi_ndofs_jl(simstate_jl) + @test ndofs_c == ndofs_jl + + ndofs_global_c = trixi_ndofs_global(handle) + ndofs_global_jl = trixi_ndofs_global_jl(simstate_jl) + @test ndofs_global_c == ndofs_global_jl + + ndofs_element_c = trixi_ndofs_element(handle) + ndofs_element_jl = trixi_ndofs_element_jl(simstate_jl) + @test ndofs_element_c == ndofs_element_jl + # compare number of variables nvariables_c = trixi_nvariables(handle) nvariables_jl = trixi_nvariables_jl(simstate_jl) @@ -92,6 +105,13 @@ end data_jl = zeros(nelements_jl) trixi_load_cell_averages_jl(data_jl, 1, simstate_jl) @test data_c == data_jl + + # compare primitive variable values on all dofs + data_c = zeros(ndofs_c) + trixi_load_prim(pointer(data_c), Int32(1), handle) + data_jl = zeros(ndofs_jl) + trixi_load_prim_jl(data_jl, 1, simstate_jl) + @test data_c == data_jl end diff --git a/test/c/simulation.cpp b/test/c/simulation.cpp index 120d1db5..b8fee50e 100644 --- a/test/c/simulation.cpp +++ b/test/c/simulation.cpp @@ -62,6 +62,15 @@ TEST(CInterfaceTest, SimulationRun) { int nelements_global = trixi_nelements_global(handle); EXPECT_EQ(nelements * nranks, nelements_global); + // Check number of dofs + int ndofs = trixi_ndofs(handle); + int ndofs_global = trixi_ndofs_global(handle); + EXPECT_EQ(ndofs * nranks, ndofs_global); + + int ndofs_element = trixi_ndofs_element(handle); + EXPECT_EQ(nelements * ndofs_element, ndofs); + EXPECT_EQ(nelements_global * ndofs_element, ndofs_global); + // Check number of variables int nvariables = trixi_nvariables(handle); EXPECT_EQ(nvariables, 4); @@ -120,6 +129,25 @@ TEST(CInterfaceTest, SimulationRun) { else { FAIL() << "Test cannot be run with " << nranks << " ranks."; } + + // Check primitive variable values on all dofs + std::vector rho(ndofs); + std::vector energy(ndofs); + trixi_load_prim(rho.data(), 1, handle); + trixi_load_prim(energy.data(), 4, handle); + if (nranks == 1) { + // check memory boarders (densities at the beginning, energies at the end) + EXPECT_DOUBLE_EQ(rho[0], 1.0); + EXPECT_DOUBLE_EQ(rho[ndofs-1], 1.0); + EXPECT_DOUBLE_EQ(energy[0], 1.0e-5); + EXPECT_DOUBLE_EQ(energy[ndofs-1], 1.0e-5); + } + else if (nranks == 2) { + + } + else { + FAIL() << "Test cannot be run with " << nranks << " ranks."; + } // Finalize Trixi simulation trixi_finalize_simulation(handle); diff --git a/test/fortran/simulationRun_suite.f90 b/test/fortran/simulationRun_suite.f90 index 46993b4b..00a73940 100644 --- a/test/fortran/simulationRun_suite.f90 +++ b/test/fortran/simulationRun_suite.f90 @@ -58,6 +58,16 @@ subroutine test_simulationRun(error) nelements_global = trixi_nelements_global(handle) call check(error, nelements_global, 256) + ! Check number of dofs + ndofs_element = trixi_ndofs_element(handle) + call check(error, ndofs_element, 16) + + ndofs = trixi_ndofs(handle) + call check(error, ndofs, nelements * ndofs_element) + + ndofs_global = trixi_ndofs_global(handle) + call check(error, ndofs_global, nelements_global * ndofs_element) + ! Check number of variables nvariables = trixi_nvariables(handle) call check(error, nvariables, 4) From c7d38d46fabb786949dc2174055d1301446f41b0 Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Mon, 26 Feb 2024 11:57:03 +0100 Subject: [PATCH 10/89] add missing parts in tests --- src/trixi.h | 1 + test/c/simulation.cpp | 13 ++++++++----- test/fortran/simulationRun_suite.f90 | 11 ++++++++++- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/src/trixi.h b/src/trixi.h index f9cfb571..2a9d7cae 100644 --- a/src/trixi.h +++ b/src/trixi.h @@ -30,6 +30,7 @@ int trixi_nelements(int handle); int trixi_nelements_global(int handle); int trixi_ndofs(int handle); int trixi_ndofs_global(int handle); +int trixi_ndofs_element(int handle); int trixi_nvariables(int handle); double trixi_calculate_dt(int handle); void trixi_load_cell_averages(double * data, int index, int handle); diff --git a/test/c/simulation.cpp b/test/c/simulation.cpp index b8fee50e..c244e0d5 100644 --- a/test/c/simulation.cpp +++ b/test/c/simulation.cpp @@ -135,15 +135,18 @@ TEST(CInterfaceTest, SimulationRun) { std::vector energy(ndofs); trixi_load_prim(rho.data(), 1, handle); trixi_load_prim(energy.data(), 4, handle); + // check memory boarders if (nranks == 1) { - // check memory boarders (densities at the beginning, energies at the end) - EXPECT_DOUBLE_EQ(rho[0], 1.0); - EXPECT_DOUBLE_EQ(rho[ndofs-1], 1.0); - EXPECT_DOUBLE_EQ(energy[0], 1.0e-5); + EXPECT_DOUBLE_EQ(rho[0], 1.0); + EXPECT_DOUBLE_EQ(rho[ndofs-1], 1.0); + EXPECT_DOUBLE_EQ(energy[0], 1.0e-5); EXPECT_DOUBLE_EQ(energy[ndofs-1], 1.0e-5); } else if (nranks == 2) { - + EXPECT_DOUBLE_EQ(rho[0], 1.0); + EXPECT_DOUBLE_EQ(rho[ndofs-1], 1.0); + EXPECT_DOUBLE_EQ(energy[0], 1.0e-5); + EXPECT_DOUBLE_EQ(energy[ndofs-1], 1.0e-5); } else { FAIL() << "Test cannot be run with " << nranks << " ranks."; diff --git a/test/fortran/simulationRun_suite.f90 b/test/fortran/simulationRun_suite.f90 index 00a73940..2e9f00bf 100644 --- a/test/fortran/simulationRun_suite.f90 +++ b/test/fortran/simulationRun_suite.f90 @@ -22,7 +22,8 @@ end subroutine collect_simulationRun_suite subroutine test_simulationRun(error) type(error_type), allocatable, intent(out) :: error - integer :: handle, ndims, nelements, nelements_global, nvariables, size + integer :: handle, ndims, nelements, nelements_global, nvariables, ndofs_global, & + ndofs_element, ndofs, size logical :: finished_status ! dp as defined in test-drive integer, parameter :: dp = selected_real_kind(15) @@ -80,6 +81,14 @@ subroutine test_simulationRun(error) call check(error, data(94), 0.99833232379996562_dp) call check(error, data(size), 1.0_dp) + ! Check primitive variable values + size = ndofs + allocate(data(size)) + call trixi_load_prim(data, 1, handle) + call check(error, data(1), 1.0_dp) + call check(error, data(94), 0.99833232379996562_dp) + call check(error, data(size), 1.0_dp) + ! Finalize Trixi simulation call trixi_finalize_simulation(handle) From ba00c6fcfc6ac4c37da492d0cd4dbe062c3bdf67 Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Mon, 26 Feb 2024 12:24:52 +0100 Subject: [PATCH 11/89] fix tests --- test/c/simulation.cpp | 21 +++++---------------- test/fortran/simulationRun_suite.f90 | 10 +++++----- 2 files changed, 10 insertions(+), 21 deletions(-) diff --git a/test/c/simulation.cpp b/test/c/simulation.cpp index c244e0d5..fff3e7e8 100644 --- a/test/c/simulation.cpp +++ b/test/c/simulation.cpp @@ -136,22 +136,11 @@ TEST(CInterfaceTest, SimulationRun) { trixi_load_prim(rho.data(), 1, handle); trixi_load_prim(energy.data(), 4, handle); // check memory boarders - if (nranks == 1) { - EXPECT_DOUBLE_EQ(rho[0], 1.0); - EXPECT_DOUBLE_EQ(rho[ndofs-1], 1.0); - EXPECT_DOUBLE_EQ(energy[0], 1.0e-5); - EXPECT_DOUBLE_EQ(energy[ndofs-1], 1.0e-5); - } - else if (nranks == 2) { - EXPECT_DOUBLE_EQ(rho[0], 1.0); - EXPECT_DOUBLE_EQ(rho[ndofs-1], 1.0); - EXPECT_DOUBLE_EQ(energy[0], 1.0e-5); - EXPECT_DOUBLE_EQ(energy[ndofs-1], 1.0e-5); - } - else { - FAIL() << "Test cannot be run with " << nranks << " ranks."; - } - + EXPECT_DOUBLE_EQ(rho[0], 1.0); + EXPECT_DOUBLE_EQ(rho[ndofs-1], 1.0); + EXPECT_DOUBLE_EQ(energy[0], 1.0e-5); + EXPECT_DOUBLE_EQ(energy[ndofs-1], 1.0e-5); + // Finalize Trixi simulation trixi_finalize_simulation(handle); diff --git a/test/fortran/simulationRun_suite.f90 b/test/fortran/simulationRun_suite.f90 index 2e9f00bf..734d1f9c 100644 --- a/test/fortran/simulationRun_suite.f90 +++ b/test/fortran/simulationRun_suite.f90 @@ -61,7 +61,7 @@ subroutine test_simulationRun(error) ! Check number of dofs ndofs_element = trixi_ndofs_element(handle) - call check(error, ndofs_element, 16) + call check(error, ndofs_element, 25) ndofs = trixi_ndofs(handle) call check(error, ndofs, nelements * ndofs_element) @@ -77,16 +77,16 @@ subroutine test_simulationRun(error) size = nelements allocate(data(size)) call trixi_load_cell_averages(data, 1, handle) - call check(error, data(1), 1.0_dp) - call check(error, data(94), 0.99833232379996562_dp) + call check(error, data(1), 1.0_dp) + call check(error, data(94), 0.99833232379996562_dp) call check(error, data(size), 1.0_dp) ! Check primitive variable values size = ndofs allocate(data(size)) call trixi_load_prim(data, 1, handle) - call check(error, data(1), 1.0_dp) - call check(error, data(94), 0.99833232379996562_dp) + call check(error, data(1), 1.0_dp) + call check(error, data(3200), 0.99833232379996562_dp) call check(error, data(size), 1.0_dp) ! Finalize Trixi simulation From cdf6e5e7c08be586b7e2257ac02d84c79045342b Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Mon, 26 Feb 2024 13:06:04 +0100 Subject: [PATCH 12/89] deallocate first --- test/fortran/simulationRun_suite.f90 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/fortran/simulationRun_suite.f90 b/test/fortran/simulationRun_suite.f90 index 734d1f9c..e02a28b6 100644 --- a/test/fortran/simulationRun_suite.f90 +++ b/test/fortran/simulationRun_suite.f90 @@ -80,6 +80,7 @@ subroutine test_simulationRun(error) call check(error, data(1), 1.0_dp) call check(error, data(94), 0.99833232379996562_dp) call check(error, data(size), 1.0_dp) + deallocate(data) ! Check primitive variable values size = ndofs @@ -88,6 +89,7 @@ subroutine test_simulationRun(error) call check(error, data(1), 1.0_dp) call check(error, data(3200), 0.99833232379996562_dp) call check(error, data(size), 1.0_dp) + deallocate(data) ! Finalize Trixi simulation call trixi_finalize_simulation(handle) From aa6d8c75b2b3c52ba1e27d886ae58dd2e865f79f Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Mon, 26 Feb 2024 14:47:08 +0100 Subject: [PATCH 13/89] add trixi_load_prim to Fortran API --- src/api.f90 | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/api.f90 b/src/api.f90 index 36fb6726..7a8c7b8f 100644 --- a/src/api.f90 +++ b/src/api.f90 @@ -337,6 +337,23 @@ subroutine trixi_load_cell_averages(data, index, handle) bind(c) integer(c_int), value, intent(in) :: handle end subroutine + !> + !! @fn LibTrixi::trixi_load_prim::trixi_load_prim(data, index, handle) + !! + !! @brief Return primitive variable values + !! + !! @param[in] handle simulation handle + !! @param[in] index index of variable + !! @param[out] data primitive variable values for all degrees of freedom + !! + !! @see @ref trixi_load_prim_api_c "trixi_load_prim (C API)" + subroutine trixi_load_prim(data, index, handle) bind(c) + use, intrinsic :: iso_c_binding, only: c_int, c_double + real(c_double), dimension(*), intent(in) :: data + integer(c_int), value, intent(in) :: index + integer(c_int), value, intent(in) :: handle + end subroutine + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! From cf437956c55f5b4dbbb5ff740fffb7e3f544ce5d Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Mon, 26 Feb 2024 15:22:16 +0100 Subject: [PATCH 14/89] reference value --- test/fortran/simulationRun_suite.f90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/fortran/simulationRun_suite.f90 b/test/fortran/simulationRun_suite.f90 index e02a28b6..b5d71e5b 100644 --- a/test/fortran/simulationRun_suite.f90 +++ b/test/fortran/simulationRun_suite.f90 @@ -87,7 +87,7 @@ subroutine test_simulationRun(error) allocate(data(size)) call trixi_load_prim(data, 1, handle) call check(error, data(1), 1.0_dp) - call check(error, data(3200), 0.99833232379996562_dp) + call check(error, data(3200), 1.0_dp) call check(error, data(size), 1.0_dp) deallocate(data) From dda491a0d7364240ce57a308dc5d74685e346396 Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Mon, 26 Feb 2024 16:01:43 +0100 Subject: [PATCH 15/89] get doxygen right --- src/api.f90 | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/api.f90 b/src/api.f90 index 7a8c7b8f..915f7935 100644 --- a/src/api.f90 +++ b/src/api.f90 @@ -297,11 +297,14 @@ integer(c_int) function trixi_ndofs_global(handle) bind(c) integer(c_int), value, intent(in) :: handle end function - !! @anchor trixi_ndofs_element_api_c + !> + !! @fn LibTrixi::trixi_ndofs_element::trixi_ndofs_element(handle) !! !! @brief Return number of degrees of freedom per element (cell). !! !! @param[in] handle simulation handle + !! + !! @see @ref trixi_ndofs_element_api_c "trixi_ndofs_element (C API)" integer(c_int) function trixi_ndofs_element(handle) bind(c) use, intrinsic :: iso_c_binding, only: c_int integer(c_int), value, intent(in) :: handle From 895282ad0ebf94ed3e717802892b006d77607f26 Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Wed, 28 Feb 2024 11:30:25 +0100 Subject: [PATCH 16/89] add example source_term library --- examples/CMakeLists.txt | 8 ++++++++ examples/source_terms.c | 27 +++++++++++++++++++++++++++ examples/source_terms.h | 2 ++ 3 files changed, 37 insertions(+) create mode 100644 examples/source_terms.c create mode 100644 examples/source_terms.h diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 327d4310..2e72548c 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -11,6 +11,14 @@ if ( NOT T8CODE_FOUND ) list( FILTER EXAMPLES EXCLUDE REGEX ".*(t|T)8(c|C)(o|O)(d|D)(e|E).*" ) endif() +# example standalone library with callback +add_library ( source_terms SHARED + source_terms.h + source_terms.c +) +install( TARGETS source_terms ) + + foreach ( EXAMPLE ${EXAMPLES} ) get_filename_component ( EXAMPLE_EXT ${EXAMPLE} EXT ) diff --git a/examples/source_terms.c b/examples/source_terms.c new file mode 100644 index 00000000..3357b758 --- /dev/null +++ b/examples/source_terms.c @@ -0,0 +1,27 @@ +#include +#include + +/* + * Example for an external source term evaluation + * Diagonally running wave, taken from Trixi.jl's source_terms_convergence_test + */ +void source_term_wave(const double * u, const double * x, const double t, + const double gamma, double * sourceterm) { + + const double c = 2.0; + const double A = 0.1; + const double L = 2.0; + const double f = 1.0 / L; + const double omega = 2 * M_PI * f; + + const double si = sin(omega * (x[0] + x[1] - t)); + const double co = cos(omega * (x[0] + x[1] - t)); + const double rho = c + A * si; + const double rho_x = omega * A * co; + const double tmp = (2 * rho - 1) * (gamma - 1); + + sourceterm[0] = rho_x; + sourceterm[1] = rho_x * (1 + tmp); + sourceterm[2] = sourceterm[1]; + sourceterm[3] = 2 * rho_x * (rho + tmp); +} diff --git a/examples/source_terms.h b/examples/source_terms.h new file mode 100644 index 00000000..cdddc196 --- /dev/null +++ b/examples/source_terms.h @@ -0,0 +1,2 @@ +void source_term_wave(const double * u, const double * x, const double t, + const double gamma, double * sourceterm); From eb95ae0e6bd5ce1fd7b2efb5c294a1561ff29e98 Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Wed, 28 Feb 2024 11:31:31 +0100 Subject: [PATCH 17/89] new libelixir demonstrating callback --- ...ixir_structured2d_source_terms_callback.jl | 86 +++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 LibTrixi.jl/examples/libelixir_structured2d_source_terms_callback.jl diff --git a/LibTrixi.jl/examples/libelixir_structured2d_source_terms_callback.jl b/LibTrixi.jl/examples/libelixir_structured2d_source_terms_callback.jl new file mode 100644 index 00000000..fcbde0fd --- /dev/null +++ b/LibTrixi.jl/examples/libelixir_structured2d_source_terms_callback.jl @@ -0,0 +1,86 @@ +using LibTrixi +using Trixi +using OrdinaryDiffEq +using Libdl + +# TODO: hard-coded path for SO +so_handle = dlopen("/home/bene/trixi/libtrixi/build/examples/libsource_terms.so") +println("") +println(pwd()) +println("Opened library ", dlpath(so_handle)) +source_term_fptr = dlsym(so_handle, "source_term_wave") +println("Obtained function pointer ", source_term_fptr) + +# TODO: global buffer to avoid allocation of temporary storage in source_term_callback +sources_tmp::Vector{Cdouble} = Vector{Cdouble}(undef, 4) + +function source_term_callback(u, x, t, equations::CompressibleEulerEquations2D) + @ccall $source_term_fptr(u::Ptr{Cdouble}, x::Ptr{Cdouble}, t::Cdouble, + equations.gamma::Cdouble, + sources_tmp::Ptr{Cdouble})::Cvoid + return SVector(sources_tmp[1], sources_tmp[2], sources_tmp[3], sources_tmp[4]) +end + +# The function to create the simulation state needs to be named `init_simstate` +function init_simstate() + + ############################################################################### + # semidiscretization of the compressible Euler equations + + equations = CompressibleEulerEquations2D(1.4) + + initial_condition = initial_condition_convergence_test + + solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) + + coordinates_min = (0.0, 0.0) + coordinates_max = (2.0, 2.0) + + cells_per_dimension = (16, 16) + + mesh = StructuredMesh(cells_per_dimension, coordinates_min, coordinates_max) + + semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, + source_terms = source_term_callback) + + ############################################################################### + # ODE solvers, callbacks etc. + + tspan = (0.0, 2.0) + ode = semidiscretize(semi, tspan) + + summary_callback = SummaryCallback() + + analysis_interval = 100 + analysis_callback = AnalysisCallback(semi, interval = analysis_interval) + + alive_callback = AliveCallback(analysis_interval = analysis_interval) + + save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) + + stepsize_callback = StepsizeCallback(cfl = 1.0) + + callbacks = CallbackSet(summary_callback, + analysis_callback, alive_callback, + save_solution, + stepsize_callback) + + ############################################################################### + # create OrdinaryDiffEq's `integrator` + + integrator = init(ode, + CarpenterKennedy2N54(williamson_condition=false), + dt=1.0, # will be overwritten by the stepsize_callback + save_everystep=false, + callback=callbacks); + + ############################################################################### + # Create simulation state + + simstate = SimulationState(semi, integrator) + + return simstate +end From e15a9bbe8de5183d697d58f4add25d8dbcf05f6e Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Wed, 28 Feb 2024 11:57:04 +0100 Subject: [PATCH 18/89] use path relative to install directory --- .../examples/libelixir_structured2d_source_terms_callback.jl | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/LibTrixi.jl/examples/libelixir_structured2d_source_terms_callback.jl b/LibTrixi.jl/examples/libelixir_structured2d_source_terms_callback.jl index fcbde0fd..80dbe7ca 100644 --- a/LibTrixi.jl/examples/libelixir_structured2d_source_terms_callback.jl +++ b/LibTrixi.jl/examples/libelixir_structured2d_source_terms_callback.jl @@ -4,9 +4,7 @@ using OrdinaryDiffEq using Libdl # TODO: hard-coded path for SO -so_handle = dlopen("/home/bene/trixi/libtrixi/build/examples/libsource_terms.so") -println("") -println(pwd()) +so_handle = dlopen("./lib/libsource_terms.so") println("Opened library ", dlpath(so_handle)) source_term_fptr = dlsym(so_handle, "source_term_wave") println("Obtained function pointer ", source_term_fptr) From b8648508d08f87ccd56f9a331c95e6d5de826180 Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Thu, 29 Feb 2024 16:36:32 +0100 Subject: [PATCH 19/89] add trixi_get_time, trixi_load_node_coordinates required in this PR, subject to change --- LibTrixi.jl/src/LibTrixi.jl | 9 ++++++- LibTrixi.jl/src/api_c.jl | 35 +++++++++++++++++++++++++++ LibTrixi.jl/src/api_jl.jl | 32 +++++++++++++++++++++++++ src/api.c | 48 ++++++++++++++++++++++++++++++++++++- src/api.f90 | 35 +++++++++++++++++++++++++++ src/trixi.h | 2 ++ 6 files changed, 159 insertions(+), 2 deletions(-) diff --git a/LibTrixi.jl/src/LibTrixi.jl b/LibTrixi.jl/src/LibTrixi.jl index 8be209d9..0dd37eb5 100644 --- a/LibTrixi.jl/src/LibTrixi.jl +++ b/LibTrixi.jl/src/LibTrixi.jl @@ -3,7 +3,7 @@ module LibTrixi using OrdinaryDiffEq: OrdinaryDiffEq, step!, check_error, DiscreteCallback using Trixi: Trixi, summary_callback, mesh_equations_solver_cache, nelements, nelementsglobal, ndofs, ndofsglobal, nvariables, nnodes, wrap_array, - eachelement, cons2prim, get_node_vars, eachnode + eachelement, cons2prim, get_node_vars, get_node_coords, eachnode using MPI: MPI, run_init_hooks, set_default_error_handler_return using Pkg @@ -73,6 +73,13 @@ export trixi_get_t8code_forest, export trixi_eval_julia, trixi_eval_julia_cfptr, trixi_eval_julia_jl +export trixi_get_time, + trixi_get_time_cfptr, + trixi_get_time_jl +export trixi_load_node_coordinates, + trixi_load_node_coordinates_cfptr, + trixi_load_node_coordinates_jl + export SimulationState, store_simstate, load_simstate, delete_simstate! export LibTrixiDataBaseType diff --git a/LibTrixi.jl/src/api_c.jl b/LibTrixi.jl/src/api_c.jl index 1c0b415c..b6cf2f48 100644 --- a/LibTrixi.jl/src/api_c.jl +++ b/LibTrixi.jl/src/api_c.jl @@ -444,6 +444,41 @@ end trixi_store_in_database_cfptr() = @cfunction(trixi_store_in_database, Cvoid, (Ptr{Cdouble}, Cint, Cint, Cint,)) +""" + trixi_get_time(simstate_handle::Cint)::Cdouble + +Return current physical time. +""" +function trixi_get_time end + +Base.@ccallable function trixi_get_time(simstate_handle::Cint)::Cdouble + simstate = load_simstate(simstate_handle) + return trixi_get_time_jl(simstate) +end + +trixi_get_time_cfptr() = @cfunction(trixi_get_time, Cdouble, (Cint,)) + + +""" + trixi_load_node_coordinates(simstate_handle::Cint, x::Ptr{Cdouble})::Cvoid + +Get coordinates of all nodes (degrees of freedom). +""" +function trixi_load_node_coordinates end + +Base.@ccallable function trixi_load_node_coordinates(simstate_handle::Cint, + x::Ptr{Cdouble})::Cvoid + simstate = load_simstate(simstate_handle) + + # convert C to Julia array + size = trixi_ndofs_jl(simstate) * trixi_ndims_jl(simstate) + x_jl = unsafe_wrap(Array, x, size) + + return trixi_load_node_coordinates_jl(simstate, x_jl) +end + +trixi_load_node_coordinates_cfptr() = @cfunction(trixi_load_node_coordinates, Cvoid, (Cint, Ptr{Cdouble},)) + """ trixi_get_t8code_forest(simstate_handle::Cint)::::Ptr{Trixi.t8_forest} diff --git a/LibTrixi.jl/src/api_jl.jl b/LibTrixi.jl/src/api_jl.jl index 30852e75..b4699d6d 100644 --- a/LibTrixi.jl/src/api_jl.jl +++ b/LibTrixi.jl/src/api_jl.jl @@ -170,6 +170,38 @@ function trixi_store_in_database_jl(data, index, simstate) end +function trixi_get_time_jl(simstate) + return simstate.integrator.t +end + + +function trixi_load_node_coordinates_jl(simstate, x) + mesh, equations, solver, cache = mesh_equations_solver_cache(simstate.semi) + + n_nodes_per_dim = nnodes(solver) + n_dims = ndims(mesh) + n_nodes = n_nodes_per_dim^n_dims + n_dofs = ndofs(mesh, solver, cache) + + # all permutations of nodes indices for arbitrary dimension + node_cis = CartesianIndices(ntuple(i -> n_nodes_per_dim, n_dims)) + node_lis = LinearIndices(node_cis) + + for element in eachelement(solver, cache) + for node_ci in node_cis + x_local = get_node_coords(cache.elements.node_coordinates, equations, solver, + node_ci, element) + node_index = (element-1) * n_nodes + node_lis[node_ci] + for d in 1:n_dims + x[(d-1)*n_dofs + node_index] = x_local[d] + end + end + end + + return nothing +end + + function trixi_get_t8code_forest_jl(simstate) mesh, _, _, _ = Trixi.mesh_equations_solver_cache(simstate.semi) return mesh.forest diff --git a/src/api.c b/src/api.c index 5ca9f066..d40e707f 100644 --- a/src/api.c +++ b/src/api.c @@ -29,6 +29,8 @@ enum { TRIXI_FTPR_VERSION_JULIA_EXTENDED, TRIXI_FTPR_EVAL_JULIA, TRIXI_FTPR_GET_T8CODE_FOREST, + TRIXI_FPTR_GET_TIME, + TRIXI_FPTR_LOAD_NODE_COORDINATES, // The last one is for the array size TRIXI_NUM_FPTRS @@ -61,7 +63,9 @@ static const char* trixi_function_pointer_names[] = { [TRIXI_FTPR_VERSION_JULIA] = "trixi_version_julia_cfptr", [TRIXI_FTPR_VERSION_JULIA_EXTENDED] = "trixi_version_julia_extended_cfptr", [TRIXI_FTPR_EVAL_JULIA] = "trixi_eval_julia_cfptr", - [TRIXI_FTPR_GET_T8CODE_FOREST] = "trixi_get_t8code_forest_cfptr" + [TRIXI_FTPR_GET_T8CODE_FOREST] = "trixi_get_t8code_forest_cfptr", + [TRIXI_FPTR_GET_TIME] = "trixi_get_time_cfptr", + [TRIXI_FPTR_LOAD_NODE_COORDINATES] = "trixi_load_node_coordinates_cfptr" }; // Track initialization/finalization status to prevent unhelpful errors @@ -636,6 +640,48 @@ void trixi_store_in_database(double * data, int size, int index, int handle) { } +/** + * @anchor trixi_get_time_api_c + * + * @brief Return current physical time. + * + * @param[in] handle simulation handle + * + * @return physical time + */ +double trixi_get_time(int handle) { + + // Get function pointer + double (*get_time)(int) = trixi_function_pointers[TRIXI_FPTR_GET_TIME]; + + // Call function + return get_time(handle); +} + + +/** + * @anchor trixi_load_node_coordinates_api_c + * + * @brief Get coordinates of all nodes (degrees of freedom). + * + * The coordinates of all nodes (degress of freedom in the DG method) are stored dimension- + * wise in the provided array `x`, i.e. x-coordinates will be in the beginning and so on. + * The given array has to be of correct size, i.e. number of nodes times dimension, and + * memory has to be allocated beforehand. + * + * @param[in] handle simulation handle + * @param[out] x node coordinates + */ +void trixi_load_node_coordinates(int handle, double* x) { + + // Get function pointer + void (*load_node_coordinates)(int, double*) = trixi_function_pointers[TRIXI_FPTR_LOAD_NODE_COORDINATES]; + + // Call function + return load_node_coordinates(handle, x); +} + + /******************************************************************************************/ /* T8code */ diff --git a/src/api.f90 b/src/api.f90 index 201e1eba..7dd42192 100644 --- a/src/api.f90 +++ b/src/api.f90 @@ -327,6 +327,41 @@ subroutine trixi_load_cell_averages(data, index, handle) bind(c) integer(c_int), value, intent(in) :: handle end subroutine + !> + !! @fn LibTrixi::trixi_get_time::trixi_get_time(handle) + !! + !! @brief Return current physical time. + !! + !! @param[in] handle simulation handle + !! + !! @return physical time + !! + !! @see @ref trixi_get_time_api_c "trixi_get_time (C API)" + real(c_double) function trixi_get_time(handle) bind(c) + use, intrinsic :: iso_c_binding, only: c_int, c_double + integer(c_int), value, intent(in) :: handle + end function + + !> + !! @fn LibTrixi::trixi_load_node_coordinates::trixi_load_node_coordinates(handle, x) + !! + !! @brief Get coordinates of all nodes (degrees of freedom). + !! + !! The coordinates of all nodes (degress of freedom in the DG method) are stored dimension- + !! wise in the provided array `x`, i.e. x-coordinates will be in the beginning and so on. + !! The given array has to be of correct size, i.e. number of nodes times dimension, and + !! memory has to be allocated beforehand. + !! + !! @param[in] handle simulation handle + !! @param[out] x node coordinates + !! + !! @see @ref trixi_load_node_coordinates_api_c "trixi_load_node_coordinates (C API)" + subroutine trixi_load_node_coordinates(handle, x) bind(c) + use, intrinsic :: iso_c_binding, only: c_int, c_double + integer(c_int), value, intent(in) :: handle + real(c_double), dimension(*), intent(out) :: x + end subroutine + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! diff --git a/src/trixi.h b/src/trixi.h index 13114a9c..c71ff725 100644 --- a/src/trixi.h +++ b/src/trixi.h @@ -35,6 +35,8 @@ double trixi_calculate_dt(int handle); void trixi_load_cell_averages(double * data, int index, int handle); void trixi_load_prim(double * data, int index, int handle); void trixi_store_in_database(double * data, int size, int index, int handle); +double trixi_get_time(int handle); +void trixi_load_node_coordinates(int handle, double* x); // T8code #if !defined(T8_H) && !defined(T8_FOREST_GENERAL_H) From 9430f2d3980f004fc99c967fc38e1039ed56e05c Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Thu, 29 Feb 2024 16:38:14 +0100 Subject: [PATCH 20/89] implement source terms controller demonstrates source terms via database --- examples/CMakeLists.txt | 2 +- examples/trixi_controller_source_terms.c | 61 ++++++++++++++++++------ 2 files changed, 48 insertions(+), 15 deletions(-) diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index b9f02135..171d4bf8 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -34,7 +34,7 @@ foreach ( EXAMPLE ${EXAMPLES} ) # set libraries to link target_link_libraries( ${TARGET_NAME} - PRIVATE MPI::MPI_${EXAMPLE_LANG} ${PROJECT_NAME} + PRIVATE MPI::MPI_${EXAMPLE_LANG} ${PROJECT_NAME} m ) if ( NOT USE_PACKAGE_COMPILER ) target_link_libraries( ${TARGET_NAME} PRIVATE ${PROJECT_NAME}_tls ) diff --git a/examples/trixi_controller_source_terms.c b/examples/trixi_controller_source_terms.c index f1b0f642..9a846005 100644 --- a/examples/trixi_controller_source_terms.c +++ b/examples/trixi_controller_source_terms.c @@ -1,8 +1,33 @@ #include #include +#include #include +void source_term_wave(int ndofs, const double * x, const double t, + double * du1, double * du2, double * du4) { + + const double c = 2.0; + const double A = 0.1; + const double L = 2.0; + const double f = 1.0 / L; + const double omega = 2 * M_PI * f; + const double gamma = 1.4; + + for (int i = 0; i < ndofs; ++i) { + + const double si = sin(omega * (x[i] + x[i+ndofs] - t)); + const double co = cos(omega * (x[i] + x[i+ndofs] - t)); + const double rho = c + A * si; + const double rho_x = omega * A * co; + const double tmp = (2 * rho - 1) * (gamma - 1); + + du1[i] = rho_x; + du2[i] = rho_x * (1 + tmp); + du4[i] = 2 * rho_x * (rho + tmp); + } +} + int main ( int argc, char *argv[] ) { if ( argc < 2 ) { @@ -27,24 +52,30 @@ int main ( int argc, char *argv[] ) { // Get number of variables and elements int ndofs = trixi_ndofs( handle ); - // Allocate memory - double * rho = calloc( sizeof(double), ndofs ); - double * source = calloc( sizeof(double), ndofs ); + // Allocate memory for source terms + double * du1 = calloc( sizeof(double), ndofs ); + double * du2 = calloc( sizeof(double), ndofs ); + double * du4 = calloc( sizeof(double), ndofs ); + + // Store source term vectors in Trixi + trixi_store_in_database(du1, ndofs, 1, handle); + trixi_store_in_database(du2, ndofs, 2, handle); + trixi_store_in_database(du4, ndofs, 3, handle); + + // Get node coordinates + double * x = calloc( sizeof(double), 2*ndofs ); + trixi_load_node_coordinates( handle, x ); // Main loop printf("\n*** Trixi controller *** Entering main loop\n"); + double t = 0.0; while ( !trixi_is_finished( handle ) ) { - // Get current solution at every DOF - trixi_load_prim(rho, 1, handle); - - // Compute source term - for ( int i = 0; i < ndofs; i++ ) { - source[i] = rho[i]; - } + // Get current time + t = trixi_get_time( handle ); - // Store source terms - trixi_store_in_database(source, ndofs, 1, handle); + // Compute source terms + source_term_wave(ndofs, x, t, du1, du2, du4); // Perform next step trixi_step( handle ); @@ -58,8 +89,10 @@ int main ( int argc, char *argv[] ) { printf("\n*** Trixi controller *** Finalize Trixi\n"); trixi_finalize(); - free(rho); - free(source); + free(x); + free(du1); + free(du2); + free(du4); return 0; } From 5956a78bf1314dac2b046d69ac40a0bb911fc356 Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Thu, 29 Feb 2024 16:40:14 +0100 Subject: [PATCH 21/89] libelixir with source terms via database --- ...ixir_structured2d_source_terms_database.jl | 97 +++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 LibTrixi.jl/examples/libelixir_structured2d_source_terms_database.jl diff --git a/LibTrixi.jl/examples/libelixir_structured2d_source_terms_database.jl b/LibTrixi.jl/examples/libelixir_structured2d_source_terms_database.jl new file mode 100644 index 00000000..c43c1dc0 --- /dev/null +++ b/LibTrixi.jl/examples/libelixir_structured2d_source_terms_database.jl @@ -0,0 +1,97 @@ +using LibTrixi +using Trixi +using OrdinaryDiffEq + +# Callable struct holding vectors with source termshydrostatic base state +struct SourceTerm + nnodesdim::Int + nnodes::Int + database::Vector{Ref{Vector{Float64}}} +end + +@inline function (source::SourceTerm)(u, element, i, j, t, + equations::CompressibleEulerEquations2D) + @unpack nnodesdim, nnodes = source + index_global = (element-1) * nnodes + (j-1) * nnodesdim + i + # massive allocations occur when directly accessing source.database[1][][1] + du1::Vector{Float64} = source.database[1][] + du2::Vector{Float64} = source.database[2][] + du4::Vector{Float64} = source.database[3][] + return SVector(du1[index_global], du2[index_global], + du2[index_global], du4[index_global]) +end + +# The function to create the simulation state needs to be named `init_simstate` +function init_simstate() + + ############################################################################### + # semidiscretization of the compressible Euler equations + + equations = CompressibleEulerEquations2D(1.4) + + initial_condition = initial_condition_convergence_test + + solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) + nnodesdim = Trixi.nnodes(solver) + nnodes = nnodesdim^2 + + coordinates_min = (0.0, 0.0) + coordinates_max = (2.0, 2.0) + + cells_per_dimension = (16, 16) + + mesh = StructuredMesh(cells_per_dimension, coordinates_min, coordinates_max) + nelements = prod(size(mesh)) + + # create the database and three vectors for the source terms + database = LibTrixiDataBaseType(undef, 3) + database[1] = Ref(Vector{Float64}(undef, nelements*nnodes)) + database[2] = Ref(Vector{Float64}(undef, nelements*nnodes)) + database[3] = Ref(Vector{Float64}(undef, nelements*nnodes)) + + source_term_database = SourceTerm(nnodesdim, nnodes, database) + + semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, + source_terms = source_term_database) + + ############################################################################### + # ODE solvers, callbacks etc. + + tspan = (0.0, 2.0) + ode = semidiscretize(semi, tspan) + + summary_callback = SummaryCallback() + + analysis_interval = 100 + analysis_callback = AnalysisCallback(semi, interval = analysis_interval) + + alive_callback = AliveCallback(analysis_interval = analysis_interval) + + save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) + + stepsize_callback = StepsizeCallback(cfl = 1.0) + + callbacks = CallbackSet(summary_callback, + analysis_callback, alive_callback, + save_solution, + stepsize_callback) + + ############################################################################### + # create OrdinaryDiffEq's `integrator` + + integrator = init(ode, + CarpenterKennedy2N54(williamson_condition=false), + dt=1.0, # will be overwritten by the stepsize_callback + save_everystep=false, + callback=callbacks); + + ############################################################################### + # Create simulation state + + simstate = SimulationState(semi, integrator, database) + + return simstate +end From ccd23fc18e031c65eaeb9a264ad2e9283d556175 Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Thu, 29 Feb 2024 16:41:26 +0100 Subject: [PATCH 22/89] change Array to Vector --- LibTrixi.jl/src/simulationstate.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LibTrixi.jl/src/simulationstate.jl b/LibTrixi.jl/src/simulationstate.jl index dcfe52c5..213fd32f 100644 --- a/LibTrixi.jl/src/simulationstate.jl +++ b/LibTrixi.jl/src/simulationstate.jl @@ -6,7 +6,7 @@ Data structure to store a simulation state consisting of - the time integrator - an optional array of data vectors """ -const LibTrixiDataBaseType = Array{Ref{Vector{Float64}}} +const LibTrixiDataBaseType = Vector{Ref{Vector{Float64}}} mutable struct SimulationState{SemiType, IntegratorType} semi::SemiType From 1be73d99862dd0ec6cf94b4b0e5633edf7075773 Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Thu, 29 Feb 2024 17:00:05 +0100 Subject: [PATCH 23/89] spelling --- src/api.f90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api.f90 b/src/api.f90 index 7dd42192..fd208e8d 100644 --- a/src/api.f90 +++ b/src/api.f90 @@ -347,7 +347,7 @@ real(c_double) function trixi_get_time(handle) bind(c) !! !! @brief Get coordinates of all nodes (degrees of freedom). !! - !! The coordinates of all nodes (degress of freedom in the DG method) are stored dimension- + !! The coordinates of all nodes (degrees of freedom in the DG method) are stored dimension- !! wise in the provided array `x`, i.e. x-coordinates will be in the beginning and so on. !! The given array has to be of correct size, i.e. number of nodes times dimension, and !! memory has to be allocated beforehand. From 584a6747e1c0e8fb7e1a71e4ad21f4739f2cae60 Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Thu, 29 Feb 2024 21:53:42 +0100 Subject: [PATCH 24/89] libelixir for baroclinic instability --- ...ir_p4est3d_euler_baroclinic_instability.jl | 281 ++++++++++++++++++ 1 file changed, 281 insertions(+) create mode 100644 LibTrixi.jl/examples/libelixir_p4est3d_euler_baroclinic_instability.jl diff --git a/LibTrixi.jl/examples/libelixir_p4est3d_euler_baroclinic_instability.jl b/LibTrixi.jl/examples/libelixir_p4est3d_euler_baroclinic_instability.jl new file mode 100644 index 00000000..cf399fcc --- /dev/null +++ b/LibTrixi.jl/examples/libelixir_p4est3d_euler_baroclinic_instability.jl @@ -0,0 +1,281 @@ +# An idealized baroclinic instability test case +# +# References: +# - Paul A. Ullrich, Thomas Melvin, Christiane Jablonowski, Andrew Staniforth (2013) +# A proposed baroclinic wave test case for deep- and shallow-atmosphere dynamical cores +# https://doi.org/10.1002/qj.2241 + +using OrdinaryDiffEq +using Trixi +using LinearAlgebra +using LibTrixi + + +# Initial condition for an idealized baroclinic instability test +# https://doi.org/10.1002/qj.2241, Section 3.2 and Appendix A +function initial_condition_baroclinic_instability(x, t, + equations::CompressibleEulerEquations3D) + lon, lat, r = cartesian_to_sphere(x) + radius_earth = 6.371229e6 + # Make sure that the r is not smaller than radius_earth + z = max(r - radius_earth, 0.0) + + # Unperturbed basic state + rho, u, p = basic_state_baroclinic_instability_longitudinal_velocity(lon, lat, z) + + # Stream function type perturbation + u_perturbation, v_perturbation = perturbation_stream_function(lon, lat, z) + + u += u_perturbation + v = v_perturbation + + # Convert spherical velocity to Cartesian + v1 = -sin(lon) * u - sin(lat) * cos(lon) * v + v2 = cos(lon) * u - sin(lat) * sin(lon) * v + v3 = cos(lat) * v + + return prim2cons(SVector(rho, v1, v2, v3, p), equations) +end + +# Steady state for RHS correction below +function steady_state_baroclinic_instability(x, t, equations::CompressibleEulerEquations3D) + lon, lat, r = cartesian_to_sphere(x) + radius_earth = 6.371229e6 + # Make sure that the r is not smaller than radius_earth + z = max(r - radius_earth, 0.0) + + # Unperturbed basic state + rho, u, p = basic_state_baroclinic_instability_longitudinal_velocity(lon, lat, z) + + # Convert spherical velocity to Cartesian + v1 = -sin(lon) * u + v2 = cos(lon) * u + v3 = 0.0 + + return prim2cons(SVector(rho, v1, v2, v3, p), equations) +end + +function cartesian_to_sphere(x) + r = norm(x) + lambda = atan(x[2], x[1]) + if lambda < 0 + lambda += 2 * pi + end + phi = asin(x[3] / r) + + return lambda, phi, r +end + +# Unperturbed balanced steady-state. +# Returns primitive variables with only the velocity in longitudinal direction (rho, u, p). +# The other velocity components are zero. +function basic_state_baroclinic_instability_longitudinal_velocity(lon, lat, z) + # Parameters from Table 1 in the paper + # Corresponding names in the paper are commented + radius_earth = 6.371229e6 # a + half_width_parameter = 2 # b + gravitational_acceleration = 9.80616 # g + k = 3 # k + surface_pressure = 1e5 # p₀ + gas_constant = 287 # R + surface_equatorial_temperature = 310.0 # T₀ᴱ + surface_polar_temperature = 240.0 # T₀ᴾ + lapse_rate = 0.005 # Γ + angular_velocity = 7.29212e-5 # Ω + + # Distance to the center of the Earth + r = z + radius_earth + + # In the paper: T₀ + temperature0 = 0.5 * (surface_equatorial_temperature + surface_polar_temperature) + # In the paper: A, B, C, H + const_a = 1 / lapse_rate + const_b = (temperature0 - surface_polar_temperature) / + (temperature0 * surface_polar_temperature) + const_c = 0.5 * (k + 2) * (surface_equatorial_temperature - surface_polar_temperature) / + (surface_equatorial_temperature * surface_polar_temperature) + const_h = gas_constant * temperature0 / gravitational_acceleration + + # In the paper: (r - a) / bH + scaled_z = z / (half_width_parameter * const_h) + + # Temporary variables + temp1 = exp(lapse_rate / temperature0 * z) + temp2 = exp(-scaled_z^2) + + # In the paper: ̃τ₁, ̃τ₂ + tau1 = const_a * lapse_rate / temperature0 * temp1 + + const_b * (1 - 2 * scaled_z^2) * temp2 + tau2 = const_c * (1 - 2 * scaled_z^2) * temp2 + + # In the paper: ∫τ₁(r') dr', ∫τ₂(r') dr' + inttau1 = const_a * (temp1 - 1) + const_b * z * temp2 + inttau2 = const_c * z * temp2 + + # Temporary variables + temp3 = r / radius_earth * cos(lat) + temp4 = temp3^k - k / (k + 2) * temp3^(k + 2) + + # In the paper: T + temperature = 1 / ((r / radius_earth)^2 * (tau1 - tau2 * temp4)) + + # In the paper: U, u (zonal wind, first component of spherical velocity) + big_u = gravitational_acceleration / radius_earth * k * temperature * inttau2 * + (temp3^(k - 1) - temp3^(k + 1)) + temp5 = radius_earth * cos(lat) + u = -angular_velocity * temp5 + sqrt(angular_velocity^2 * temp5^2 + temp5 * big_u) + + # Hydrostatic pressure + p = surface_pressure * + exp(-gravitational_acceleration / gas_constant * (inttau1 - inttau2 * temp4)) + + # Density (via ideal gas law) + rho = p / (gas_constant * temperature) + + return rho, u, p +end + +# Perturbation as in Equations 25 and 26 of the paper (analytical derivative) +function perturbation_stream_function(lon, lat, z) + # Parameters from Table 1 in the paper + # Corresponding names in the paper are commented + perturbation_radius = 1 / 6 # d₀ / a + perturbed_wind_amplitude = 1.0 # Vₚ + perturbation_lon = pi / 9 # Longitude of perturbation location + perturbation_lat = 2 * pi / 9 # Latitude of perturbation location + pertz = 15000 # Perturbation height cap + + # Great circle distance (d in the paper) divided by a (radius of the Earth) + # because we never actually need d without dividing by a + great_circle_distance_by_a = acos(sin(perturbation_lat) * sin(lat) + + cos(perturbation_lat) * cos(lat) * + cos(lon - perturbation_lon)) + + # In the first case, the vertical taper function is per definition zero. + # In the second case, the stream function is per definition zero. + if z > pertz || great_circle_distance_by_a > perturbation_radius + return 0.0, 0.0 + end + + # Vertical tapering of stream function + perttaper = 1.0 - 3 * z^2 / pertz^2 + 2 * z^3 / pertz^3 + + # sin/cos(pi * d / (2 * d_0)) in the paper + sin_, cos_ = sincos(0.5 * pi * great_circle_distance_by_a / perturbation_radius) + + # Common factor for both u and v + factor = 16 / (3 * sqrt(3)) * perturbed_wind_amplitude * perttaper * cos_^3 * sin_ + + u_perturbation = -factor * (-sin(perturbation_lat) * cos(lat) + + cos(perturbation_lat) * sin(lat) * cos(lon - perturbation_lon)) / + sin(great_circle_distance_by_a) + + v_perturbation = factor * cos(perturbation_lat) * sin(lon - perturbation_lon) / + sin(great_circle_distance_by_a) + + return u_perturbation, v_perturbation +end + +@inline function source_terms_baroclinic_instability(u, x, t, + equations::CompressibleEulerEquations3D) + radius_earth = 6.371229e6 # a + gravitational_acceleration = 9.80616 # g + angular_velocity = 7.29212e-5 # Ω + + r = norm(x) + # Make sure that r is not smaller than radius_earth + z = max(r - radius_earth, 0.0) + r = z + radius_earth + + du1 = zero(eltype(u)) + + # Gravity term + temp = -gravitational_acceleration * radius_earth^2 / r^3 + du2 = temp * u[1] * x[1] + du3 = temp * u[1] * x[2] + du4 = temp * u[1] * x[3] + du5 = temp * (u[2] * x[1] + u[3] * x[2] + u[4] * x[3]) + + # Coriolis term, -2Ω × ρv = -2 * angular_velocity * (0, 0, 1) × u[2:4] + du2 -= -2 * angular_velocity * u[3] + du3 -= 2 * angular_velocity * u[2] + + return SVector(du1, du2, du3, du4, du5) +end + + +# The function to create the simulation state needs to be named `init_simstate` +function init_simstate() + + ############################################################################### + # Setup for the baroclinic instability test + gamma = 1.4 + equations = CompressibleEulerEquations3D(gamma) + + ############################################################################### + # semidiscretization of the problem + + initial_condition = initial_condition_baroclinic_instability + + boundary_conditions = Dict(:inside => boundary_condition_slip_wall, + :outside => boundary_condition_slip_wall) + + # This is a good estimate for the speed of sound in this example. + # Other values between 300 and 400 should work as well. + surface_flux = FluxLMARS(340) + volume_flux = flux_kennedy_gruber + solver = DGSEM(polydeg = 5, surface_flux = surface_flux, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) + + trees_per_cube_face = (16, 8) + mesh = Trixi.P4estMeshCubedSphere(trees_per_cube_face..., 6.371229e6, 30000.0, + polydeg = 5, initial_refinement_level = 0) + + semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, + source_terms = source_terms_baroclinic_instability, + boundary_conditions = boundary_conditions) + + ############################################################################### + # ODE solvers, callbacks etc. + + tspan = (0.0, 12 * 24 * 60 * 60.0) # time in seconds for 12 days# + + ode = semidiscretize(semi, tspan) + + summary_callback = SummaryCallback() + + analysis_interval = 5000 + analysis_callback = AnalysisCallback(semi, interval = analysis_interval) + + alive_callback = AliveCallback(analysis_interval = analysis_interval) + + save_solution = SaveSolutionCallback(interval = 5000, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim, + output_directory = "out_baroclinic",) + + callbacks = CallbackSet(summary_callback, + analysis_callback, + alive_callback, + save_solution) + + + ############################################################################### + # create the time integrator + + # OrdinaryDiffEq's `integrator` + # Use a Runge-Kutta method with automatic (error based) time step size control + integrator = init(ode, RDPK3SpFSAL49(); + abstol = 1.0e-6, reltol = 1.0e-6, + ode_default_options()..., + callback = callbacks, + maxiters=5e5); + + ############################################################################### + # Create simulation state + + simstate = SimulationState(semi, integrator) + + return simstate +end From 7c82c90af4791e33046c640568e5a5f176aa15dc Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Mon, 4 Mar 2024 10:27:38 +0100 Subject: [PATCH 25/89] remove method only required by steady state correction --- ...xir_p4est3d_euler_baroclinic_instability.jl | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/LibTrixi.jl/examples/libelixir_p4est3d_euler_baroclinic_instability.jl b/LibTrixi.jl/examples/libelixir_p4est3d_euler_baroclinic_instability.jl index cf399fcc..dd8cdbca 100644 --- a/LibTrixi.jl/examples/libelixir_p4est3d_euler_baroclinic_instability.jl +++ b/LibTrixi.jl/examples/libelixir_p4est3d_euler_baroclinic_instability.jl @@ -37,24 +37,6 @@ function initial_condition_baroclinic_instability(x, t, return prim2cons(SVector(rho, v1, v2, v3, p), equations) end -# Steady state for RHS correction below -function steady_state_baroclinic_instability(x, t, equations::CompressibleEulerEquations3D) - lon, lat, r = cartesian_to_sphere(x) - radius_earth = 6.371229e6 - # Make sure that the r is not smaller than radius_earth - z = max(r - radius_earth, 0.0) - - # Unperturbed basic state - rho, u, p = basic_state_baroclinic_instability_longitudinal_velocity(lon, lat, z) - - # Convert spherical velocity to Cartesian - v1 = -sin(lon) * u - v2 = cos(lon) * u - v3 = 0.0 - - return prim2cons(SVector(rho, v1, v2, v3, p), equations) -end - function cartesian_to_sphere(x) r = norm(x) lambda = atan(x[2], x[1]) From d1850a79a3d5a3867a62c66048104bcf02ba6a8e Mon Sep 17 00:00:00 2001 From: Benedict <135045760+bgeihe@users.noreply.github.com> Date: Mon, 4 Mar 2024 10:29:31 +0100 Subject: [PATCH 26/89] Update LibTrixi.jl/examples/libelixir_p4est3d_euler_baroclinic_instability.jl Co-authored-by: Michael Schlottke-Lakemper --- .../libelixir_p4est3d_euler_baroclinic_instability.jl | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/LibTrixi.jl/examples/libelixir_p4est3d_euler_baroclinic_instability.jl b/LibTrixi.jl/examples/libelixir_p4est3d_euler_baroclinic_instability.jl index dd8cdbca..58e057c2 100644 --- a/LibTrixi.jl/examples/libelixir_p4est3d_euler_baroclinic_instability.jl +++ b/LibTrixi.jl/examples/libelixir_p4est3d_euler_baroclinic_instability.jl @@ -1,5 +1,9 @@ # An idealized baroclinic instability test case # +# Note that this libelixir is based on the original baroclinic instability elixir by +# Erik Faulhaber for Trixi.jl +# Source: https://github.com/trixi-framework/Trixi.jl/blob/main/examples/p4est_3d_dgsem/elixir_euler_baroclinic_instability.jl +# # References: # - Paul A. Ullrich, Thomas Melvin, Christiane Jablonowski, Andrew Staniforth (2013) # A proposed baroclinic wave test case for deep- and shallow-atmosphere dynamical cores From 7dbb2c6aec8a6024316de609c596d5856c01644f Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Thu, 7 Mar 2024 19:33:11 +0100 Subject: [PATCH 27/89] make everything more consistent! --- LibTrixi.jl/src/LibTrixi.jl | 30 +++--- LibTrixi.jl/src/api_c.jl | 92 +++++++++--------- LibTrixi.jl/src/api_jl.jl | 60 ++++++------ LibTrixi.jl/test/test_interface.jl | 28 +++--- examples/trixi_controller_data.c | 6 +- examples/trixi_controller_data.f90 | 6 +- src/api.c | 136 ++++++++++++++------------- src/api.f90 | 62 ++++++------ src/trixi.h | 10 +- test/c/simulation.cpp | 46 ++++----- test/fortran/simulationRun_suite.f90 | 34 +++---- 11 files changed, 257 insertions(+), 253 deletions(-) diff --git a/LibTrixi.jl/src/LibTrixi.jl b/LibTrixi.jl/src/LibTrixi.jl index efabc624..1f802b3d 100644 --- a/LibTrixi.jl/src/LibTrixi.jl +++ b/LibTrixi.jl/src/LibTrixi.jl @@ -28,27 +28,27 @@ export trixi_ndims, export trixi_nelements, trixi_nelements_cfptr, trixi_nelements_jl -export trixi_nelements_global, - trixi_nelements_global_cfptr, - trixi_nelements_global_jl +export trixi_nelementsglobal, + trixi_nelementsglobal_cfptr, + trixi_nelementsglobal_jl export trixi_ndofs, trixi_ndofs_cfptr, trixi_ndofs_jl -export trixi_ndofs_global, - trixi_ndofs_global_cfptr, - trixi_ndofs_global_jl -export trixi_ndofs_element, - trixi_ndofs_element_cfptr, - trixi_ndofs_element_jl +export trixi_ndofsglobal, + trixi_ndofsglobal_cfptr, + trixi_ndofsglobal_jl +export trixi_ndofselement, + trixi_ndofselement_cfptr, + trixi_ndofselement_jl export trixi_nvariables, trixi_nvariables_cfptr, trixi_nvariables_jl -export trixi_load_cell_averages, - trixi_load_cell_averages_cfptr, - trixi_load_cell_averages_jl -export trixi_load_prim, - trixi_load_prim_cfptr, - trixi_load_prim_jl +export trixi_load_primitive_vars, + trixi_load_primitive_vars_cfptr, + trixi_load_primitive_vars_jl +export trixi_load_element_averaged_primitive_vars, + trixi_load_element_averaged_primitive_vars_cfptr, + trixi_load_element_averaged_primitive_vars_jl export trixi_version_library, trixi_version_library_cfptr, trixi_version_library_jl diff --git a/LibTrixi.jl/src/api_c.jl b/LibTrixi.jl/src/api_c.jl index 9b1af564..e0655a40 100644 --- a/LibTrixi.jl/src/api_c.jl +++ b/LibTrixi.jl/src/api_c.jl @@ -285,7 +285,7 @@ trixi_ndims_cfptr() = @cfunction(trixi_ndims, Cint, (Cint,)) """ trixi_nelements(simstate_handle::Cint)::Cint -Return number of local elements (cells). +Return number of local elements. """ function trixi_nelements end @@ -298,24 +298,24 @@ trixi_nelements_cfptr() = @cfunction(trixi_nelements, Cint, (Cint,)) """ - trixi_nelements_global(simstate_handle::Cint)::Cint + trixi_nelementsglobal(simstate_handle::Cint)::Cint -Return number of global elements (cells). +Return global number of elements. """ -function trixi_nelements_global end +function trixi_nelementsglobal end -Base.@ccallable function trixi_nelements_global(simstate_handle::Cint)::Cint +Base.@ccallable function trixi_nelementsglobal(simstate_handle::Cint)::Cint simstate = load_simstate(simstate_handle) - return trixi_nelements_global_jl(simstate) + return trixi_nelementsglobal_jl(simstate) end -trixi_nelements_global_cfptr() = @cfunction(trixi_nelements_global, Cint, (Cint,)) +trixi_nelementsglobal_cfptr() = @cfunction(trixi_nelementsglobal, Cint, (Cint,)) """ trixi_ndofs(simstate_handle::Cint)::Cint -Return number of degrees of freedom (all quadrature points on all cells of current rank). +Return number of degrees of freedom (all quadrature points on all elements of current rank). """ function trixi_ndofs end @@ -328,33 +328,33 @@ trixi_ndofs_cfptr() = @cfunction(trixi_ndofs, Cint, (Cint,)) """ - trixi_ndofs_global(simstate_handle::Cint)::Cint + trixi_ndofsglobal(simstate_handle::Cint)::Cint -Return number of global eldegrees of freedom (all quadrature points on all cells). +Return global number of degrees of freedom (all quadrature points on all elements). """ -function trixi_ndofs_global end +function trixi_ndofsglobal end -Base.@ccallable function trixi_ndofs_global(simstate_handle::Cint)::Cint +Base.@ccallable function trixi_ndofsglobal(simstate_handle::Cint)::Cint simstate = load_simstate(simstate_handle) - return trixi_ndofs_global_jl(simstate) + return trixi_ndofsglobal_jl(simstate) end -trixi_ndofs_global_cfptr() = @cfunction(trixi_ndofs_global, Cint, (Cint,)) +trixi_ndofsglobal_cfptr() = @cfunction(trixi_ndofsglobal, Cint, (Cint,)) """ - trixi_ndofs_element(simstate_handle::Cint)::Cint + trixi_ndofselement(simstate_handle::Cint)::Cint -Return number of degrees of freedom per element (cell). +Return number of degrees of freedom per element. """ -function trixi_ndofs_element end +function trixi_ndofselement end -Base.@ccallable function trixi_ndofs_element(simstate_handle::Cint)::Cint +Base.@ccallable function trixi_ndofselement(simstate_handle::Cint)::Cint simstate = load_simstate(simstate_handle) - return trixi_ndofs_element_jl(simstate) + return trixi_ndofselement_jl(simstate) end -trixi_ndofs_element_cfptr() = @cfunction(trixi_ndofs_element, Cint, (Cint,)) +trixi_ndofselement_cfptr() = @cfunction(trixi_ndofselement, Cint, (Cint,)) """ @@ -373,60 +373,62 @@ trixi_nvariables_cfptr() = @cfunction(trixi_nvariables, Cint, (Cint,)) """ - trixi_load_cell_averages(data::Ptr{Cdouble}, index::Cint, simstate_handle::Cint)::Cvoid + trixi_load_primitive_vars(simstate_handle::Cint, variable_id::Cint, + data::Ptr{Cdouble})::Cvoid -Return cell averaged solution state. +Load primitive variable. -Cell averaged values for the primitive variable at position `index` for each cell are stored -in the given array `data`. +The values for the primitive variable at position `variable_id` at every degree of freedom +for are stored in the given array `data`. -The given array has to be of correct size and memory has to be allocated beforehand. +The given array has to be of correct size (ndofs) and memory has to be allocated beforehand. """ -function trixi_load_cell_averages end +function trixi_load_primitive_vars end -Base.@ccallable function trixi_load_cell_averages(data::Ptr{Cdouble}, index::Cint, - simstate_handle::Cint)::Cvoid +Base.@ccallable function trixi_load_primitive_vars(simstate_handle::Cint, variable_id::Cint, + data::Ptr{Cdouble})::Cvoid simstate = load_simstate(simstate_handle) # convert C to Julia array - size = trixi_nvariables_jl(simstate) * trixi_nelements_jl(simstate) + size = trixi_ndofs_jl(simstate) data_jl = unsafe_wrap(Array, data, size) - trixi_load_cell_averages_jl(data_jl, index, simstate) + trixi_load_primitive_vars_jl(simstate, variable_id, data_jl) return nothing end -trixi_load_cell_averages_cfptr() = - @cfunction(trixi_load_cell_averages, Cvoid, (Ptr{Cdouble}, Cint, Cint,)) +trixi_load_primitive_vars_cfptr() = + @cfunction(trixi_load_primitive_vars, Cvoid, (Cint, Cint, Ptr{Cdouble})) """ - trixi_load_prim(data::Ptr{Cdouble}, index::Cint, simstate_handle::Cint)::Cvoid + trixi_load_element_averaged_primitive_vars(simstate_handle::Cint, variable_id::Cint, + data::Ptr{Cdouble})::Cvoid -Return primitive variable. +Load element averages for primitive variable. -The values for the primitive variable at position `index` at every degree of freedom for -the simulation given by `simstate_handle` is stored in the given array `data`. +Element averaged values for the primitive variable at position `variable_id` for each +element are stored in the given array `data`. -The given array has to be of correct size and memory has to be allocated beforehand. +The given array has to be of correct size (nelements) and memory has to be allocated +beforehand. """ -function trixi_load_prim end +function trixi_load_element_averaged_primitive_vars end -Base.@ccallable function trixi_load_prim(data::Ptr{Cdouble}, index::Cint, - simstate_handle::Cint)::Cvoid +Base.@ccallable function trixi_load_element_averaged_primitive_vars(simstate_handle::Cint, + variable_id::Cint, data::Ptr{Cdouble})::Cvoid simstate = load_simstate(simstate_handle) # convert C to Julia array - size = trixi_ndofs_jl(simstate) + size = trixi_nelements_jl(simstate) data_jl = unsafe_wrap(Array, data, size) - trixi_load_prim_jl(data_jl, index, simstate) + trixi_load_element_averaged_primitive_vars_jl(simstate, variable_id, data_jl) return nothing end -trixi_load_prim_cfptr() = - @cfunction(trixi_load_prim, Cvoid, (Ptr{Cdouble}, Cint, Cint,)) - +trixi_load_element_averaged_primitive_vars_cfptr() = + @cfunction(trixi_load_element_averaged_primitive_vars, Cvoid, (Cint, Cint, Ptr{Cdouble})) """ diff --git a/LibTrixi.jl/src/api_jl.jl b/LibTrixi.jl/src/api_jl.jl index b5d0a247..3ced7a46 100644 --- a/LibTrixi.jl/src/api_jl.jl +++ b/LibTrixi.jl/src/api_jl.jl @@ -76,7 +76,7 @@ function trixi_nelements_jl(simstate) end -function trixi_nelements_global_jl(simstate) +function trixi_nelementsglobal_jl(simstate) _, _, solver, cache = mesh_equations_solver_cache(simstate.semi) return nelementsglobal(solver, cache) end @@ -88,13 +88,13 @@ function trixi_ndofs_jl(simstate) end -function trixi_ndofs_global_jl(simstate) +function trixi_ndofsglobal_jl(simstate) mesh, _, solver, cache = mesh_equations_solver_cache(simstate.semi) return ndofsglobal(mesh, solver, cache) end -function trixi_ndofs_element_jl(simstate) +function trixi_ndofselement_jl(simstate) mesh, _, solver, _ = mesh_equations_solver_cache(simstate.semi) return nnodes(solver)^ndims(mesh) end @@ -106,61 +106,61 @@ function trixi_nvariables_jl(simstate) end -function trixi_load_cell_averages_jl(data, index, simstate) +function trixi_load_primitive_vars_jl(simstate, variable_id, data) mesh, equations, solver, cache = mesh_equations_solver_cache(simstate.semi) - n_nodes = nnodes(solver) + n_nodes_per_dim = nnodes(solver) n_dims = ndims(mesh) + n_nodes = n_nodes_per_dim^n_dims u_ode = simstate.integrator.u u = wrap_array(u_ode, mesh, equations, solver, cache) # all permutations of nodes indices for arbitrary dimension - node_cis = CartesianIndices(ntuple(i -> n_nodes, n_dims)) + node_cis = CartesianIndices(ntuple(i -> n_nodes_per_dim, n_dims)) + node_lis = LinearIndices(node_cis) for element in eachelement(solver, cache) - - # compute mean value using nodal dg values and quadrature - u_mean = zero(eltype(u)) for node_ci in node_cis - u_node_prim = cons2prim(get_node_vars(u, equations, solver, node_ci, element), - equations)[index] - weight = 1. - for node_index in Tuple(node_ci) - weight *= solver.basis.weights[node_index] - end - u_mean += u_node_prim * weight + node_vars = get_node_vars(u, equations, solver, node_ci, element) + node_index = (element-1) * n_nodes + node_lis[node_ci] + data[node_index] = cons2prim(node_vars, equations)[variable_id] end - - # normalize to unit element - u_mean = u_mean / 2^n_dims - - # write to provided array - data[element] = u_mean end return nothing end -function trixi_load_prim_jl(data, index, simstate) +function trixi_load_element_averaged_primitive_vars_jl(simstate, variable_id, data) mesh, equations, solver, cache = mesh_equations_solver_cache(simstate.semi) - n_nodes_per_dim = nnodes(solver) + n_nodes = nnodes(solver) n_dims = ndims(mesh) - n_nodes = n_nodes_per_dim^n_dims u_ode = simstate.integrator.u u = wrap_array(u_ode, mesh, equations, solver, cache) # all permutations of nodes indices for arbitrary dimension - node_cis = CartesianIndices(ntuple(i -> n_nodes_per_dim, n_dims)) - node_lis = LinearIndices(node_cis) + node_cis = CartesianIndices(ntuple(i -> n_nodes, n_dims)) for element in eachelement(solver, cache) + + # compute mean value using nodal dg values and quadrature + u_mean = zero(eltype(u)) for node_ci in node_cis - node_vars = get_node_vars(u, equations, solver, node_ci, element) - node_index = (element-1) * n_nodes + node_lis[node_ci] - data[node_index] = cons2prim(node_vars, equations)[index] + u_node_prim = cons2prim(get_node_vars(u, equations, solver, node_ci, element), + equations)[variable_id] + weight = 1. + for node_index in Tuple(node_ci) + weight *= solver.basis.weights[node_index] + end + u_mean += u_node_prim * weight end + + # normalize to unit element + u_mean = u_mean / 2^n_dims + + # write to provided array + data[element] = u_mean end return nothing diff --git a/LibTrixi.jl/test/test_interface.jl b/LibTrixi.jl/test/test_interface.jl index 498fce4c..aab67ce1 100644 --- a/LibTrixi.jl/test/test_interface.jl +++ b/LibTrixi.jl/test/test_interface.jl @@ -77,40 +77,40 @@ end nelements_jl = trixi_nelements_jl(simstate_jl) @test nelements_c == nelements_jl - nelements_global_c = trixi_nelements_global(handle) - nelements_global_jl = trixi_nelements_global_jl(simstate_jl) - @test nelements_global_c == nelements_global_jl + nelementsglobal_c = trixi_nelementsglobal(handle) + nelementsglobal_jl = trixi_nelementsglobal_jl(simstate_jl) + @test nelementsglobal_c == nelementsglobal_jl # compare number of dofs ndofs_c = trixi_ndofs(handle) ndofs_jl = trixi_ndofs_jl(simstate_jl) @test ndofs_c == ndofs_jl - ndofs_global_c = trixi_ndofs_global(handle) - ndofs_global_jl = trixi_ndofs_global_jl(simstate_jl) - @test ndofs_global_c == ndofs_global_jl + ndofsglobal_c = trixi_ndofsglobal(handle) + ndofsglobal_jl = trixi_ndofsglobal_jl(simstate_jl) + @test ndofsglobal_c == ndofsglobal_jl - ndofs_element_c = trixi_ndofs_element(handle) - ndofs_element_jl = trixi_ndofs_element_jl(simstate_jl) - @test ndofs_element_c == ndofs_element_jl + ndofselement_c = trixi_ndofselement(handle) + ndofselement_jl = trixi_ndofselement_jl(simstate_jl) + @test ndofselement_c == ndofselement_jl # compare number of variables nvariables_c = trixi_nvariables(handle) nvariables_jl = trixi_nvariables_jl(simstate_jl) @test nvariables_c == nvariables_jl - # compare cell averaged values + # compare element averaged values data_c = zeros(nelements_c) - trixi_load_cell_averages(pointer(data_c), Int32(1), handle) + trixi_load_element_averaged_primitive_vars(handle, Int32(1), pointer(data_c)) data_jl = zeros(nelements_jl) - trixi_load_cell_averages_jl(data_jl, 1, simstate_jl) + trixi_load_element_averaged_primitive_vars_jl(simstate_jl, 1, data_jl) @test data_c == data_jl # compare primitive variable values on all dofs data_c = zeros(ndofs_c) - trixi_load_prim(pointer(data_c), Int32(1), handle) + trixi_load_primitive_vars(handle, Int32(1), pointer(data_c)) data_jl = zeros(ndofs_jl) - trixi_load_prim_jl(data_jl, 1, simstate_jl) + trixi_load_primitive_vars_jl(simstate_jl, 1, data_jl) @test data_c == data_jl end diff --git a/examples/trixi_controller_data.c b/examples/trixi_controller_data.c index 242d29b4..35e88cdd 100644 --- a/examples/trixi_controller_data.c +++ b/examples/trixi_controller_data.c @@ -48,14 +48,14 @@ int main ( int argc, char *argv[] ) { // Allocate memory data = realloc( data, sizeof(double) * nelements ); - // Get averaged cell values for first variable - trixi_load_cell_averages(data, 1, handle); + // Get element averaged values for first variable + trixi_load_element_averaged_primitive_vars(handle, 1, data); } } // Print first variable for (int i = 0; i < nelements; ++i) { - printf("u[cell %3d] = %f\n", i, data[i]); + printf("u[element %3d] = %f\n", i, data[i]); } // Finalize Trixi simulation diff --git a/examples/trixi_controller_data.f90 b/examples/trixi_controller_data.f90 index ebf17cce..d5d09667 100644 --- a/examples/trixi_controller_data.f90 +++ b/examples/trixi_controller_data.f90 @@ -65,14 +65,14 @@ program trixi_controller_data_f if ( associated(data) ) deallocate(data) allocate( data(nelements) ) - ! get averaged cell values for first variable - call trixi_load_cell_averages(data, 1, handle) + ! get element averaged values for first variable + call trixi_load_element_averaged_primitive_vars(handle, 1, data) end if end do ! print first variable do i = 1,nelements - print "('u[cell ', i4, '] = ', e14.8)", i, data(i) + print "('u[element ', i4, '] = ', e14.8)", i, data(i) end do ! Finalize Trixi simulation diff --git a/src/api.c b/src/api.c index cdb43e12..45e9353e 100644 --- a/src/api.c +++ b/src/api.c @@ -19,8 +19,8 @@ enum { TRIXI_FPTR_NDOFS_GLOBAL, TRIXI_FPTR_NDOFS_ELEMENT, TRIXI_FTPR_NVARIABLES, - TRIXI_FTPR_LOAD_CELL_AVERAGES, - TRIXI_FTPR_LOAD_PRIM, + TRIXI_FTPR_LOAD_PRIMITIVE_VARS, + TRIXI_FTPR_LOAD_ELEMENT_AVERAGED_PRIMITIVE_VARS, TRIXI_FTPR_VERSION_LIBRARY, TRIXI_FTPR_VERSION_LIBRARY_MAJOR, TRIXI_FTPR_VERSION_LIBRARY_MINOR, @@ -40,28 +40,28 @@ static void* trixi_function_pointers[TRIXI_NUM_FPTRS]; // List of function names to obtain C function pointers from Julia // OBS! If any name is longer than 250 characters, adjust buffer sizes in setup.c static const char* trixi_function_pointer_names[] = { - [TRIXI_FTPR_INITIALIZE_SIMULATION] = "trixi_initialize_simulation_cfptr", - [TRIXI_FTPR_CALCULATE_DT] = "trixi_calculate_dt_cfptr", - [TRIXI_FTPR_IS_FINISHED] = "trixi_is_finished_cfptr", - [TRIXI_FTPR_STEP] = "trixi_step_cfptr", - [TRIXI_FTPR_FINALIZE_SIMULATION] = "trixi_finalize_simulation_cfptr", - [TRIXI_FTPR_NDIMS] = "trixi_ndims_cfptr", - [TRIXI_FPTR_NELEMENTS] = "trixi_nelements_cfptr", - [TRIXI_FPTR_NELEMENTS_GLOBAL] = "trixi_nelements_global_cfptr", - [TRIXI_FPTR_NDOFS] = "trixi_ndofs_cfptr", - [TRIXI_FPTR_NDOFS_GLOBAL] = "trixi_ndofs_global_cfptr", - [TRIXI_FPTR_NDOFS_ELEMENT] = "trixi_ndofs_element_cfptr", - [TRIXI_FTPR_NVARIABLES] = "trixi_nvariables_cfptr", - [TRIXI_FTPR_LOAD_CELL_AVERAGES] = "trixi_load_cell_averages_cfptr", - [TRIXI_FTPR_LOAD_PRIM] = "trixi_load_prim_cfptr", - [TRIXI_FTPR_VERSION_LIBRARY] = "trixi_version_library_cfptr", - [TRIXI_FTPR_VERSION_LIBRARY_MAJOR] = "trixi_version_library_major_cfptr", - [TRIXI_FTPR_VERSION_LIBRARY_MINOR] = "trixi_version_library_minor_cfptr", - [TRIXI_FTPR_VERSION_LIBRARY_PATCH] = "trixi_version_library_patch_cfptr", - [TRIXI_FTPR_VERSION_JULIA] = "trixi_version_julia_cfptr", - [TRIXI_FTPR_VERSION_JULIA_EXTENDED] = "trixi_version_julia_extended_cfptr", - [TRIXI_FTPR_EVAL_JULIA] = "trixi_eval_julia_cfptr", - [TRIXI_FTPR_GET_T8CODE_FOREST] = "trixi_get_t8code_forest_cfptr" + [TRIXI_FTPR_INITIALIZE_SIMULATION] = "trixi_initialize_simulation_cfptr", + [TRIXI_FTPR_CALCULATE_DT] = "trixi_calculate_dt_cfptr", + [TRIXI_FTPR_IS_FINISHED] = "trixi_is_finished_cfptr", + [TRIXI_FTPR_STEP] = "trixi_step_cfptr", + [TRIXI_FTPR_FINALIZE_SIMULATION] = "trixi_finalize_simulation_cfptr", + [TRIXI_FTPR_NDIMS] = "trixi_ndims_cfptr", + [TRIXI_FPTR_NELEMENTS] = "trixi_nelements_cfptr", + [TRIXI_FPTR_NELEMENTS_GLOBAL] = "trixi_nelementsglobal_cfptr", + [TRIXI_FPTR_NDOFS] = "trixi_ndofs_cfptr", + [TRIXI_FPTR_NDOFS_GLOBAL] = "trixi_ndofsglobal_cfptr", + [TRIXI_FPTR_NDOFS_ELEMENT] = "trixi_ndofselement_cfptr", + [TRIXI_FTPR_NVARIABLES] = "trixi_nvariables_cfptr", + [TRIXI_FTPR_LOAD_PRIMITIVE_VARS] = "trixi_load_primitive_vars_cfptr", + [TRIXI_FTPR_LOAD_ELEMENT_AVERAGED_PRIMITIVE_VARS] = "trixi_load_element_averaged_primitive_vars_cfptr", + [TRIXI_FTPR_VERSION_LIBRARY] = "trixi_version_library_cfptr", + [TRIXI_FTPR_VERSION_LIBRARY_MAJOR] = "trixi_version_library_major_cfptr", + [TRIXI_FTPR_VERSION_LIBRARY_MINOR] = "trixi_version_library_minor_cfptr", + [TRIXI_FTPR_VERSION_LIBRARY_PATCH] = "trixi_version_library_patch_cfptr", + [TRIXI_FTPR_VERSION_JULIA] = "trixi_version_julia_cfptr", + [TRIXI_FTPR_VERSION_JULIA_EXTENDED] = "trixi_version_julia_extended_cfptr", + [TRIXI_FTPR_EVAL_JULIA] = "trixi_eval_julia_cfptr", + [TRIXI_FTPR_GET_T8CODE_FOREST] = "trixi_get_t8code_forest_cfptr" }; // Track initialization/finalization status to prevent unhelpful errors @@ -457,13 +457,13 @@ int trixi_ndims(int handle) { /** * @anchor trixi_nelements_api_c * - * @brief Return number of local elements (cells). + * @brief Return number of local elements. * * These usually differ from the global count when doing parallel computations. * * @param[in] handle simulation handle * - * @see trixi_nelements_global_api_c + * @see trixi_nelementsglobal_api_c */ int trixi_nelements(int handle) { @@ -476,9 +476,9 @@ int trixi_nelements(int handle) { /** - * @anchor trixi_nelements_global_api_c + * @anchor trixi_nelementsglobal_api_c * - * @brief Return number of global elements (cells). + * @brief Return global number of elements. * * These usually differ from the local count when doing parallel computations. * @@ -486,13 +486,13 @@ int trixi_nelements(int handle) { * * @see trixi_nelements_api_c */ -int trixi_nelements_global(int handle) { +int trixi_nelementsglobal(int handle) { // Get function pointer - int (*nelements_global)(int) = trixi_function_pointers[TRIXI_FPTR_NELEMENTS_GLOBAL]; + int (*nelementsglobal)(int) = trixi_function_pointers[TRIXI_FPTR_NELEMENTS_GLOBAL]; // Call function - return nelements_global(handle); + return nelementsglobal(handle); } @@ -505,7 +505,7 @@ int trixi_nelements_global(int handle) { * * @param[in] handle simulation handle * - * @see trixi_ndofs_global_api_c + * @see trixi_ndofsglobal_api_c */ int trixi_ndofs(int handle) { @@ -518,9 +518,9 @@ int trixi_ndofs(int handle) { /** - * @anchor trixi_ndofs_global_api_c + * @anchor trixi_ndofsglobal_api_c * - * @brief Return number of global degrees of freedom. + * @brief Return global number of degrees of freedom. * * These usually differ from the local count when doing parallel computations. * @@ -528,30 +528,30 @@ int trixi_ndofs(int handle) { * * @see trixi_ndofs_api_c */ -int trixi_ndofs_global(int handle) { +int trixi_ndofsglobal(int handle) { // Get function pointer - int (*ndofs_global)(int) = trixi_function_pointers[TRIXI_FPTR_NDOFS_GLOBAL]; + int (*ndofsglobal)(int) = trixi_function_pointers[TRIXI_FPTR_NDOFS_GLOBAL]; // Call function - return ndofs_global(handle); + return ndofsglobal(handle); } /** - * @anchor trixi_ndofs_element_api_c + * @anchor trixi_ndofselement_api_c * - * @brief Return number of degrees of freedom per element (cell). + * @brief Return number of degrees of freedom per element. * * @param[in] handle simulation handle */ -int trixi_ndofs_element(int handle) { +int trixi_ndofselement(int handle) { // Get function pointer - int (*ndofs_element)(int) = trixi_function_pointers[TRIXI_FPTR_NDOFS_ELEMENT]; + int (*ndofselement)(int) = trixi_function_pointers[TRIXI_FPTR_NDOFS_ELEMENT]; // Call function - return ndofs_element(handle); + return ndofselement(handle); } @@ -572,53 +572,55 @@ int trixi_nvariables(int handle) { } -/** - * @anchor trixi_load_cell_averages_api_c +/** + * @anchor trixi_load_primitive_vars_api_c * - * @brief Return cell averaged solution state + * @brief Load primitive variable * - * Cell averaged values for the primitive variable at position index for each cell are - * stored in the given array `data`. + * The values for the primitive variable at position `variable_id` at every degree of + * freedom for are stored in the given array `data`. * - * The given array has to be of correct size and memory has to be allocated beforehand. + * The given array has to be of correct size (ndofs) and memory has to be allocated + * beforehand. * - * @param[in] handle simulation handle - * @param[in] index index of variable - * @param[out] data cell averaged values for all cells and all primitive variables + * @param[in] handle simulation handle + * @param[in] variable_id index of variable + * @param[out] data values for all degrees of freedom */ -void trixi_load_cell_averages(double * data, int index, int handle) { +void trixi_load_primitive_vars(int handle, int variable_id, double * data) { // Get function pointer - void (*load_cell_averages)(double *, int, int) = - trixi_function_pointers[TRIXI_FTPR_LOAD_CELL_AVERAGES]; + void (*load_primitive_vars)(int, int, double *) = + trixi_function_pointers[TRIXI_FTPR_LOAD_PRIMITIVE_VARS]; // Call function - load_cell_averages(data, index, handle); + load_primitive_vars(handle, variable_id, data); } /** - * @anchor trixi_load_prim_api_c + * @anchor trixi_load_element_averaged_primitive_vars_api_c * - * @brief Return primitive variable + * @brief Load element averages for primitive variable * - * The values for the primitive variable at position index at every degree of freedom for - * the simulation given by simstate_handle is stored in the given array data. + * Element averaged values for the primitive variable at position `variable_id` for each + * element are stored in the given array `data`. * - * The given array has to be of correct size and memory has to be allocated beforehand. + * The given array has to be of correct size (nelements) and memory has to be allocated + * beforehand. * - * @param[in] handle simulation handle - * @param[in] index index of variable - * @param[out] data cell averaged values for all cells and all primitive variables + * @param[in] handle simulation handle + * @param[in] variable_id index of variable + * @param[out] data element averaged values for all elements */ -void trixi_load_prim(double * data, int index, int handle) { +void trixi_load_element_averaged_primitive_vars(int handle, int variable_id, double * data) { // Get function pointer - void (*load_prim)(double *, int, int) = - trixi_function_pointers[TRIXI_FTPR_LOAD_PRIM]; + void (*load_element_averaged_primitive_vars)(int, int, double *) = + trixi_function_pointers[TRIXI_FTPR_LOAD_ELEMENT_AVERAGED_PRIMITIVE_VARS]; // Call function - load_prim(data, index, handle); + load_element_averaged_primitive_vars(handle, variable_id, data); } diff --git a/src/api.f90 b/src/api.f90 index 915f7935..776152b2 100644 --- a/src/api.f90 +++ b/src/api.f90 @@ -248,7 +248,7 @@ integer(c_int) function trixi_ndims(handle) bind(c) !> !! @fn LibTrixi::trixi_nelements::trixi_nelements(handle) !! - !! @brief Return number of local elements (cells) + !! @brief Return number of local elements !! !! @param[in] handle simulation handle !! @@ -259,14 +259,14 @@ integer(c_int) function trixi_nelements(handle) bind(c) end function !> - !! @fn LibTrixi::trixi_nelements_global::trixi_nelements_global(handle) + !! @fn LibTrixi::trixi_nelementsglobal::trixi_nelementsglobal(handle) !! - !! @brief Return number of global elements (cells) + !! @brief Return global number of elements !! !! @param[in] handle simulation handle !! - !! @see @ref trixi_nelements_global_api_c "trixi_nelements_global (C API)" - integer(c_int) function trixi_nelements_global(handle) bind(c) + !! @see @ref trixi_nelementsglobal_api_c "trixi_nelementsglobal (C API)" + integer(c_int) function trixi_nelementsglobal(handle) bind(c) use, intrinsic :: iso_c_binding, only: c_int integer(c_int), value, intent(in) :: handle end function @@ -285,27 +285,27 @@ integer(c_int) function trixi_ndofs(handle) bind(c) end function !> - !! @fn LibTrixi::trixi_ndofs_global::trixi_ndofs_global(handle) + !! @fn LibTrixi::trixi_ndofsglobal::trixi_ndofsglobal(handle) !! - !! @brief Return number of global degrees of freedom + !! @brief Return global number of degrees of freedom !! !! @param[in] handle simulation handle !! - !! @see @ref trixi_ndofs_global_api_c "trixi_ndofs_global (C API)" - integer(c_int) function trixi_ndofs_global(handle) bind(c) + !! @see @ref trixi_ndofsglobal_api_c "trixi_ndofsglobal (C API)" + integer(c_int) function trixi_ndofsglobal(handle) bind(c) use, intrinsic :: iso_c_binding, only: c_int integer(c_int), value, intent(in) :: handle end function !> - !! @fn LibTrixi::trixi_ndofs_element::trixi_ndofs_element(handle) + !! @fn LibTrixi::trixi_ndofselement::trixi_ndofselement(handle) !! - !! @brief Return number of degrees of freedom per element (cell). + !! @brief Return number of degrees of freedom per element. !! !! @param[in] handle simulation handle !! - !! @see @ref trixi_ndofs_element_api_c "trixi_ndofs_element (C API)" - integer(c_int) function trixi_ndofs_element(handle) bind(c) + !! @see @ref trixi_ndofselement_api_c "trixi_ndofselement (C API)" + integer(c_int) function trixi_ndofselement(handle) bind(c) use, intrinsic :: iso_c_binding, only: c_int integer(c_int), value, intent(in) :: handle end function @@ -324,37 +324,37 @@ integer(c_int) function trixi_nvariables(handle) bind(c) end function !> - !! @fn LibTrixi::trixi_load_cell_averages::trixi_load_cell_averages(data, index, handle) + !! @fn LibTrixi::trixi_load_primitive_vars::trixi_load_primitive_vars(handle, variable_id, data) !! - !! @brief Return cell averaged values + !! @brief Load primitive variable !! - !! @param[in] handle simulation handle - !! @param[in] index index of variable - !! @param[out] data cell averaged values for all cells and all variables + !! @param[in] handle simulation handle + !! @param[in] variable_id index of variable + !! @param[out] data primitive variable values for all degrees of freedom !! - !! @see @ref trixi_load_cell_averages_api_c "trixi_load_cell_averages (C API)" - subroutine trixi_load_cell_averages(data, index, handle) bind(c) + !! @see @ref trixi_load_primitive_vars_api_c "trixi_load_primitive_vars (C API)" + subroutine trixi_load_primitive_vars(handle, variable_id, data) bind(c) use, intrinsic :: iso_c_binding, only: c_int, c_double - real(c_double), dimension(*), intent(in) :: data - integer(c_int), value, intent(in) :: index integer(c_int), value, intent(in) :: handle + integer(c_int), value, intent(in) :: variable_id + real(c_double), dimension(*), intent(in) :: data end subroutine !> - !! @fn LibTrixi::trixi_load_prim::trixi_load_prim(data, index, handle) + !! @fn LibTrixi::trixi_load_element_averaged_primitive_vars::trixi_load_element_averaged_primitive_vars(handle, variable_id, data) !! - !! @brief Return primitive variable values + !! @brief Load element averages for primitive variable !! - !! @param[in] handle simulation handle - !! @param[in] index index of variable - !! @param[out] data primitive variable values for all degrees of freedom + !! @param[in] handle simulation handle + !! @param[in] variable_id index of variable + !! @param[out] data averaged values for all elements !! - !! @see @ref trixi_load_prim_api_c "trixi_load_prim (C API)" - subroutine trixi_load_prim(data, index, handle) bind(c) + !! @see @ref trixi_load_element_averaged_primitive_vars_api_c "trixi_load_element_averaged_primitive_vars (C API)" + subroutine trixi_load_element_averaged_primitive_vars(handle, variable_id, data) bind(c) use, intrinsic :: iso_c_binding, only: c_int, c_double - real(c_double), dimension(*), intent(in) :: data - integer(c_int), value, intent(in) :: index integer(c_int), value, intent(in) :: handle + integer(c_int), value, intent(in) :: variable_id + real(c_double), dimension(*), intent(in) :: data end subroutine diff --git a/src/trixi.h b/src/trixi.h index 2a9d7cae..1ec58ba6 100644 --- a/src/trixi.h +++ b/src/trixi.h @@ -27,14 +27,14 @@ void trixi_step(int handle); // Simulation data int trixi_ndims(int handle); int trixi_nelements(int handle); -int trixi_nelements_global(int handle); +int trixi_nelementsglobal(int handle); int trixi_ndofs(int handle); -int trixi_ndofs_global(int handle); -int trixi_ndofs_element(int handle); +int trixi_ndofsglobal(int handle); +int trixi_ndofselement(int handle); int trixi_nvariables(int handle); double trixi_calculate_dt(int handle); -void trixi_load_cell_averages(double * data, int index, int handle); -void trixi_load_prim(double * data, int index, int handle); +void trixi_load_primitive_vars(int handle, int variable_id, double * data); +void trixi_load_element_averaged_primitive_vars(int handle, int variable_id, double * data); // T8code #if !defined(T8_H) && !defined(T8_FOREST_GENERAL_H) diff --git a/test/c/simulation.cpp b/test/c/simulation.cpp index fff3e7e8..221070f9 100644 --- a/test/c/simulation.cpp +++ b/test/c/simulation.cpp @@ -59,31 +59,42 @@ TEST(CInterfaceTest, SimulationRun) { // Check number of elements int nelements = trixi_nelements(handle); - int nelements_global = trixi_nelements_global(handle); - EXPECT_EQ(nelements * nranks, nelements_global); + int nelementsglobal = trixi_nelementsglobal(handle); + EXPECT_EQ(nelements * nranks, nelementsglobal); // Check number of dofs int ndofs = trixi_ndofs(handle); - int ndofs_global = trixi_ndofs_global(handle); - EXPECT_EQ(ndofs * nranks, ndofs_global); + int ndofsglobal = trixi_ndofsglobal(handle); + EXPECT_EQ(ndofs * nranks, ndofsglobal); - int ndofs_element = trixi_ndofs_element(handle); - EXPECT_EQ(nelements * ndofs_element, ndofs); - EXPECT_EQ(nelements_global * ndofs_element, ndofs_global); + int ndofselement = trixi_ndofselement(handle); + EXPECT_EQ(nelements * ndofselement, ndofs); + EXPECT_EQ(nelementsglobal * ndofselement, ndofsglobal); // Check number of variables int nvariables = trixi_nvariables(handle); EXPECT_EQ(nvariables, 4); - // Check cell averaged values + // Check primitive variable values on all dofs + std::vector rho(ndofs); + std::vector energy(ndofs); + trixi_load_primitive_vars(handle, 1, rho.data()); + trixi_load_primitive_vars(handle, 4, energy.data()); + // check memory boarders + EXPECT_DOUBLE_EQ(rho[0], 1.0); + EXPECT_DOUBLE_EQ(rho[ndofs-1], 1.0); + EXPECT_DOUBLE_EQ(energy[0], 1.0e-5); + EXPECT_DOUBLE_EQ(energy[ndofs-1], 1.0e-5); + + // Check element averaged values std::vector rho_averages(nelements); std::vector v1_averages(nelements); std::vector v2_averages(nelements); std::vector e_averages(nelements); - trixi_load_cell_averages(rho_averages.data(), 1, handle); - trixi_load_cell_averages(v1_averages.data(), 2, handle); - trixi_load_cell_averages(v2_averages.data(), 3, handle); - trixi_load_cell_averages(e_averages.data(), 4, handle); + trixi_load_element_averaged_primitive_vars(handle, 1, rho_averages.data()); + trixi_load_element_averaged_primitive_vars(handle, 2, v1_averages.data()); + trixi_load_element_averaged_primitive_vars(handle, 3, v2_averages.data()); + trixi_load_element_averaged_primitive_vars(handle, 4, e_averages.data()); if (nranks == 1) { // check memory boarders (densities at the beginning, energies at the end) EXPECT_DOUBLE_EQ(rho_averages[0], 1.0); @@ -130,17 +141,6 @@ TEST(CInterfaceTest, SimulationRun) { FAIL() << "Test cannot be run with " << nranks << " ranks."; } - // Check primitive variable values on all dofs - std::vector rho(ndofs); - std::vector energy(ndofs); - trixi_load_prim(rho.data(), 1, handle); - trixi_load_prim(energy.data(), 4, handle); - // check memory boarders - EXPECT_DOUBLE_EQ(rho[0], 1.0); - EXPECT_DOUBLE_EQ(rho[ndofs-1], 1.0); - EXPECT_DOUBLE_EQ(energy[0], 1.0e-5); - EXPECT_DOUBLE_EQ(energy[ndofs-1], 1.0e-5); - // Finalize Trixi simulation trixi_finalize_simulation(handle); diff --git a/test/fortran/simulationRun_suite.f90 b/test/fortran/simulationRun_suite.f90 index b5d71e5b..079704fd 100644 --- a/test/fortran/simulationRun_suite.f90 +++ b/test/fortran/simulationRun_suite.f90 @@ -22,8 +22,8 @@ end subroutine collect_simulationRun_suite subroutine test_simulationRun(error) type(error_type), allocatable, intent(out) :: error - integer :: handle, ndims, nelements, nelements_global, nvariables, ndofs_global, & - ndofs_element, ndofs, size + integer :: handle, ndims, nelements, nelementsglobal, nvariables, ndofsglobal, & + ndofselement, ndofs, size logical :: finished_status ! dp as defined in test-drive integer, parameter :: dp = selected_real_kind(15) @@ -56,38 +56,38 @@ subroutine test_simulationRun(error) nelements = trixi_nelements(handle) call check(error, nelements, 256) - nelements_global = trixi_nelements_global(handle) - call check(error, nelements_global, 256) + nelementsglobal = trixi_nelementsglobal(handle) + call check(error, nelementsglobal, 256) ! Check number of dofs - ndofs_element = trixi_ndofs_element(handle) - call check(error, ndofs_element, 25) + ndofselement = trixi_ndofselement(handle) + call check(error, ndofselement, 25) ndofs = trixi_ndofs(handle) - call check(error, ndofs, nelements * ndofs_element) + call check(error, ndofs, nelements * ndofselement) - ndofs_global = trixi_ndofs_global(handle) - call check(error, ndofs_global, nelements_global * ndofs_element) + ndofsglobal = trixi_ndofsglobal(handle) + call check(error, ndofsglobal, nelementsglobal * ndofselement) ! Check number of variables nvariables = trixi_nvariables(handle) call check(error, nvariables, 4) - ! Check cell averaged values - size = nelements + ! Check primitive variable values + size = ndofs allocate(data(size)) - call trixi_load_cell_averages(data, 1, handle) + call trixi_load_primitive_vars(handle, 1, data) call check(error, data(1), 1.0_dp) - call check(error, data(94), 0.99833232379996562_dp) + call check(error, data(3200), 1.0_dp) call check(error, data(size), 1.0_dp) deallocate(data) - ! Check primitive variable values - size = ndofs + ! Check element averaged values + size = nelements allocate(data(size)) - call trixi_load_prim(data, 1, handle) + call trixi_load_element_averaged_primitive_vars(handle, 1, data) call check(error, data(1), 1.0_dp) - call check(error, data(3200), 1.0_dp) + call check(error, data(94), 0.99833232379996562_dp) call check(error, data(size), 1.0_dp) deallocate(data) From 7906080c9e806370f6416edd6b82502f18b8dae6 Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Fri, 8 Mar 2024 17:10:41 +0100 Subject: [PATCH 28/89] use const double * --- LibTrixi.jl/src/api_c.jl | 8 ++++---- LibTrixi.jl/src/api_jl.jl | 2 +- examples/trixi_controller_source_terms.c | 6 +++--- src/api.c | 12 ++++++------ src/trixi.h | 4 +--- 5 files changed, 15 insertions(+), 17 deletions(-) diff --git a/LibTrixi.jl/src/api_c.jl b/LibTrixi.jl/src/api_c.jl index b6cf2f48..979bb000 100644 --- a/LibTrixi.jl/src/api_c.jl +++ b/LibTrixi.jl/src/api_c.jl @@ -430,19 +430,19 @@ The size of `data` has to match `size`. """ function trixi_store_in_database end -Base.@ccallable function trixi_store_in_database(data::Ptr{Cdouble}, size::Cint, - index::Cint, simstate_handle::Cint)::Cvoid +Base.@ccallable function trixi_store_in_database(simstate_handle::Cint, index::Cint, + size::Cint, data::Ptr{Cdouble})::Cvoid simstate = load_simstate(simstate_handle) # convert C to Julia array data_jl = unsafe_wrap(Array, data, size) - trixi_store_in_database_jl(data_jl, index, simstate) + trixi_store_in_database_jl(simstate, index, data_jl) return nothing end trixi_store_in_database_cfptr() = - @cfunction(trixi_store_in_database, Cvoid, (Ptr{Cdouble}, Cint, Cint, Cint,)) + @cfunction(trixi_store_in_database, Cvoid, (Cint, Cint, Cint, Ptr{Cdouble},)) """ trixi_get_time(simstate_handle::Cint)::Cdouble diff --git a/LibTrixi.jl/src/api_jl.jl b/LibTrixi.jl/src/api_jl.jl index b4699d6d..e308d799 100644 --- a/LibTrixi.jl/src/api_jl.jl +++ b/LibTrixi.jl/src/api_jl.jl @@ -161,7 +161,7 @@ function trixi_load_prim_jl(data, index, simstate) end -function trixi_store_in_database_jl(data, index, simstate) +function trixi_store_in_database_jl(simstate, index, data) simstate.data[index] = Ref(data) if show_debug_output() println("New data vector stored at index ", index) diff --git a/examples/trixi_controller_source_terms.c b/examples/trixi_controller_source_terms.c index 9a846005..7cc48e3d 100644 --- a/examples/trixi_controller_source_terms.c +++ b/examples/trixi_controller_source_terms.c @@ -58,9 +58,9 @@ int main ( int argc, char *argv[] ) { double * du4 = calloc( sizeof(double), ndofs ); // Store source term vectors in Trixi - trixi_store_in_database(du1, ndofs, 1, handle); - trixi_store_in_database(du2, ndofs, 2, handle); - trixi_store_in_database(du4, ndofs, 3, handle); + trixi_store_in_database(handle, 1, ndofs, du1); + trixi_store_in_database(handle, 2, ndofs, du2); + trixi_store_in_database(handle, 3, ndofs, du4); // Get node coordinates double * x = calloc( sizeof(double), 2*ndofs ); diff --git a/src/api.c b/src/api.c index d40e707f..2d67c5e9 100644 --- a/src/api.c +++ b/src/api.c @@ -624,19 +624,19 @@ void trixi_load_prim(double * data, int index, int handle) { * * The size of data has to match size. * - * @param[in] data data vector to store - * @param[in] size size of given data vector - * @param[in] index index in database where data vector will be stored * @param[in] handle simulation handle + * @param[in] index index in database where data vector will be stored + * @param[in] size size of given data vector + * @param[in] data data vector to store */ -void trixi_store_in_database(double * data, int size, int index, int handle) { +void trixi_store_in_database(int handle, int index, int size, const double * data) { // Get function pointer - void (*store_in_database)(double *, int, int, int) = + void (*store_in_database)(int, int, int, const double *) = trixi_function_pointers[TRIXI_FTPR_STORE_IN_DATABASE]; // Call function - store_in_database(data, size, index, handle); + store_in_database(handle, index, size, data); } diff --git a/src/trixi.h b/src/trixi.h index c71ff725..ce28bad6 100644 --- a/src/trixi.h +++ b/src/trixi.h @@ -32,9 +32,7 @@ int trixi_ndofs(int handle); int trixi_ndofs_global(int handle); int trixi_nvariables(int handle); double trixi_calculate_dt(int handle); -void trixi_load_cell_averages(double * data, int index, int handle); -void trixi_load_prim(double * data, int index, int handle); -void trixi_store_in_database(double * data, int size, int index, int handle); +void trixi_store_in_database(int handle, int index, int size, const double * data); double trixi_get_time(int handle); void trixi_load_node_coordinates(int handle, double* x); From f96436bf7268f12a5b44643c383a27a177b05082 Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Mon, 13 May 2024 14:29:04 +0200 Subject: [PATCH 29/89] missed merge conflict --- src/api.c | 33 ++++----------------------------- 1 file changed, 4 insertions(+), 29 deletions(-) diff --git a/src/api.c b/src/api.c index 8522636e..e21b490a 100644 --- a/src/api.c +++ b/src/api.c @@ -43,33 +43,6 @@ static void* trixi_function_pointers[TRIXI_NUM_FPTRS]; // List of function names to obtain C function pointers from Julia // OBS! If any name is longer than 250 characters, adjust buffer sizes in setup.c static const char* trixi_function_pointer_names[] = { -<<<<<<< HEAD - [TRIXI_FTPR_INITIALIZE_SIMULATION] = "trixi_initialize_simulation_cfptr", - [TRIXI_FTPR_CALCULATE_DT] = "trixi_calculate_dt_cfptr", - [TRIXI_FTPR_IS_FINISHED] = "trixi_is_finished_cfptr", - [TRIXI_FTPR_STEP] = "trixi_step_cfptr", - [TRIXI_FTPR_FINALIZE_SIMULATION] = "trixi_finalize_simulation_cfptr", - [TRIXI_FTPR_NDIMS] = "trixi_ndims_cfptr", - [TRIXI_FPTR_NELEMENTS] = "trixi_nelements_cfptr", - [TRIXI_FPTR_NELEMENTS_GLOBAL] = "trixi_nelements_global_cfptr", - [TRIXI_FPTR_NDOFS] = "trixi_ndofs_cfptr", - [TRIXI_FPTR_NDOFS_GLOBAL] = "trixi_ndofs_global_cfptr", - [TRIXI_FPTR_NDOFS_ELEMENT] = "trixi_ndofs_element_cfptr", - [TRIXI_FTPR_NVARIABLES] = "trixi_nvariables_cfptr", - [TRIXI_FTPR_LOAD_CELL_AVERAGES] = "trixi_load_cell_averages_cfptr", - [TRIXI_FTPR_LOAD_PRIM] = "trixi_load_prim_cfptr", - [TRIXI_FTPR_STORE_IN_DATABASE] = "trixi_store_in_database_cfptr", - [TRIXI_FTPR_VERSION_LIBRARY] = "trixi_version_library_cfptr", - [TRIXI_FTPR_VERSION_LIBRARY_MAJOR] = "trixi_version_library_major_cfptr", - [TRIXI_FTPR_VERSION_LIBRARY_MINOR] = "trixi_version_library_minor_cfptr", - [TRIXI_FTPR_VERSION_LIBRARY_PATCH] = "trixi_version_library_patch_cfptr", - [TRIXI_FTPR_VERSION_JULIA] = "trixi_version_julia_cfptr", - [TRIXI_FTPR_VERSION_JULIA_EXTENDED] = "trixi_version_julia_extended_cfptr", - [TRIXI_FTPR_EVAL_JULIA] = "trixi_eval_julia_cfptr", - [TRIXI_FTPR_GET_T8CODE_FOREST] = "trixi_get_t8code_forest_cfptr", - [TRIXI_FPTR_GET_TIME] = "trixi_get_time_cfptr", - [TRIXI_FPTR_LOAD_NODE_COORDINATES] = "trixi_load_node_coordinates_cfptr" -======= [TRIXI_FTPR_INITIALIZE_SIMULATION] = "trixi_initialize_simulation_cfptr", [TRIXI_FTPR_CALCULATE_DT] = "trixi_calculate_dt_cfptr", [TRIXI_FTPR_IS_FINISHED] = "trixi_is_finished_cfptr", @@ -84,6 +57,7 @@ static const char* trixi_function_pointer_names[] = { [TRIXI_FTPR_NVARIABLES] = "trixi_nvariables_cfptr", [TRIXI_FTPR_LOAD_PRIMITIVE_VARS] = "trixi_load_primitive_vars_cfptr", [TRIXI_FTPR_LOAD_ELEMENT_AVERAGED_PRIMITIVE_VARS] = "trixi_load_element_averaged_primitive_vars_cfptr", + [TRIXI_FTPR_STORE_IN_DATABASE] = "trixi_store_in_database_cfptr", [TRIXI_FTPR_VERSION_LIBRARY] = "trixi_version_library_cfptr", [TRIXI_FTPR_VERSION_LIBRARY_MAJOR] = "trixi_version_library_major_cfptr", [TRIXI_FTPR_VERSION_LIBRARY_MINOR] = "trixi_version_library_minor_cfptr", @@ -91,8 +65,9 @@ static const char* trixi_function_pointer_names[] = { [TRIXI_FTPR_VERSION_JULIA] = "trixi_version_julia_cfptr", [TRIXI_FTPR_VERSION_JULIA_EXTENDED] = "trixi_version_julia_extended_cfptr", [TRIXI_FTPR_EVAL_JULIA] = "trixi_eval_julia_cfptr", - [TRIXI_FTPR_GET_T8CODE_FOREST] = "trixi_get_t8code_forest_cfptr" ->>>>>>> more-data-access + [TRIXI_FTPR_GET_T8CODE_FOREST] = "trixi_get_t8code_forest_cfptr", + [TRIXI_FPTR_GET_TIME] = "trixi_get_time_cfptr", + [TRIXI_FPTR_LOAD_NODE_COORDINATES] = "trixi_load_node_coordinates_cfptr" }; // Track initialization/finalization status to prevent unhelpful errors From b76ca70d10e78d852ed2033fdbdb955600b5c783 Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Mon, 13 May 2024 14:29:47 +0200 Subject: [PATCH 30/89] transpose calloc args --- examples/trixi_controller_source_terms.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/trixi_controller_source_terms.c b/examples/trixi_controller_source_terms.c index 7cc48e3d..22b53dce 100644 --- a/examples/trixi_controller_source_terms.c +++ b/examples/trixi_controller_source_terms.c @@ -53,9 +53,9 @@ int main ( int argc, char *argv[] ) { int ndofs = trixi_ndofs( handle ); // Allocate memory for source terms - double * du1 = calloc( sizeof(double), ndofs ); - double * du2 = calloc( sizeof(double), ndofs ); - double * du4 = calloc( sizeof(double), ndofs ); + double * du1 = calloc( ndofs, sizeof(double) ); + double * du2 = calloc( ndofs, sizeof(double) ); + double * du4 = calloc( ndofs, sizeof(double) ); // Store source term vectors in Trixi trixi_store_in_database(handle, 1, ndofs, du1); @@ -63,7 +63,7 @@ int main ( int argc, char *argv[] ) { trixi_store_in_database(handle, 3, ndofs, du4); // Get node coordinates - double * x = calloc( sizeof(double), 2*ndofs ); + double * x = calloc( 2*ndofs, sizeof(double) ); trixi_load_node_coordinates( handle, x ); // Main loop From b40a2a1d10ed081a943548a4ad099ca7bf73f773 Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Wed, 24 Jul 2024 21:46:17 +0200 Subject: [PATCH 31/89] add functions to get quadrature information --- LibTrixi.jl/src/LibTrixi.jl | 9 ++++ LibTrixi.jl/src/api_c.jl | 62 ++++++++++++++++++++++++- LibTrixi.jl/src/api_jl.jl | 22 +++++++++ LibTrixi.jl/test/test_interface.jl | 19 ++++++++ src/api.c | 69 +++++++++++++++++++++++++++- src/api.f90 | 51 ++++++++++++++++++++ src/trixi.h | 3 ++ test/c/simulation.cpp | 15 ++++++ test/fortran/simulationRun_suite.f90 | 23 ++++++++-- 9 files changed, 268 insertions(+), 5 deletions(-) diff --git a/LibTrixi.jl/src/LibTrixi.jl b/LibTrixi.jl/src/LibTrixi.jl index 1f802b3d..ab855489 100644 --- a/LibTrixi.jl/src/LibTrixi.jl +++ b/LibTrixi.jl/src/LibTrixi.jl @@ -43,6 +43,15 @@ export trixi_ndofselement, export trixi_nvariables, trixi_nvariables_cfptr, trixi_nvariables_jl +export trixi_nnodes, + trixi_nnodes_cfptr, + trixi_nnodes_jl +export trixi_load_node_reference_coordinates, + trixi_load_node_reference_coordinates_cfptr, + trixi_load_node_reference_coordinates_jl +export trixi_load_node_weights, + trixi_load_node_weights_cfptr, + trixi_load_node_weights_jl export trixi_load_primitive_vars, trixi_load_primitive_vars_cfptr, trixi_load_primitive_vars_jl diff --git a/LibTrixi.jl/src/api_c.jl b/LibTrixi.jl/src/api_c.jl index e0655a40..78f560a7 100644 --- a/LibTrixi.jl/src/api_c.jl +++ b/LibTrixi.jl/src/api_c.jl @@ -372,6 +372,66 @@ end trixi_nvariables_cfptr() = @cfunction(trixi_nvariables, Cint, (Cint,)) +""" + trixi_nnodes(simstate_handle::Cint)::Cint + +Return number of quadrature nodes per dimension. +""" +function trixi_nnodes end + +Base.@ccallable function trixi_nnodes(simstate_handle::Cint)::Cint + simstate = load_simstate(simstate_handle) + return trixi_nnodes_jl(simstate) +end + +trixi_nnodes_cfptr() = @cfunction(trixi_nnodes, Cint, (Cint,)) + + +""" + trixi_load_node_reference_coordinates(simstate_handle::Cint, data::Ptr{Cdouble})::Cvoid + +Get reference coordinates of 1D quadrature nodes. +""" +function trixi_load_node_reference_coordinates end + +Base.@ccallable function trixi_load_node_reference_coordinates(simstate_handle::Cint, + data::Ptr{Cdouble})::Cvoid + simstate = load_simstate(simstate_handle) + + # convert C to Julia array + size = trixi_nnodes_jl(simstate) + data_jl = unsafe_wrap(Array, data, size) + + trixi_load_node_reference_coordinates_jl(simstate, data_jl) + return nothing +end + +trixi_load_node_reference_coordinates_cfptr() = + @cfunction(trixi_load_node_reference_coordinates, Cvoid, (Cint, Ptr{Cdouble})) + + +""" + trixi_load_node_weights(simstate_handle::Cint, data::Ptr{Cdouble})::Cvoid + +Get weights of 1D quadrature nodes. +""" +function trixi_load_node_weights end + +Base.@ccallable function trixi_load_node_weights(simstate_handle::Cint, + data::Ptr{Cdouble})::Cvoid + simstate = load_simstate(simstate_handle) + + # convert C to Julia array + size = trixi_nnodes_jl(simstate) + data_jl = unsafe_wrap(Array, data, size) + + return trixi_load_node_weights_jl(simstate, data_jl) +end + +trixi_load_node_weights_cfptr() = + @cfunction(trixi_load_node_weights, Cvoid, (Cint, Ptr{Cdouble})) + + """ trixi_load_primitive_vars(simstate_handle::Cint, variable_id::Cint, data::Ptr{Cdouble})::Cvoid @@ -379,7 +439,7 @@ trixi_nvariables_cfptr() = @cfunction(trixi_nvariables, Cint, (Cint,)) Load primitive variable. The values for the primitive variable at position `variable_id` at every degree of freedom -for are stored in the given array `data`. +are stored in the given array `data`. The given array has to be of correct size (ndofs) and memory has to be allocated beforehand. """ diff --git a/LibTrixi.jl/src/api_jl.jl b/LibTrixi.jl/src/api_jl.jl index 741f635d..bb52ef78 100644 --- a/LibTrixi.jl/src/api_jl.jl +++ b/LibTrixi.jl/src/api_jl.jl @@ -106,6 +106,28 @@ function trixi_nvariables_jl(simstate) end +function trixi_nnodes_jl(simstate) + _, _, solver, _ = mesh_equations_solver_cache(simstate.semi) + return nnodes(solver) +end + + +function trixi_load_node_reference_coordinates_jl(simstate, data) + _, _, solver, _ = mesh_equations_solver_cache(simstate.semi) + for i in eachnode(solver) + data[i] = solver.basis.nodes[i] + end +end + + +function trixi_load_node_weights_jl(simstate, data) + _, _, solver, _ = mesh_equations_solver_cache(simstate.semi) + for i in eachnode(solver) + data[i] = solver.basis.weights[i] + end +end + + function trixi_load_primitive_vars_jl(simstate, variable_id, data) mesh, equations, solver, cache = mesh_equations_solver_cache(simstate.semi) n_nodes_per_dim = nnodes(solver) diff --git a/LibTrixi.jl/test/test_interface.jl b/LibTrixi.jl/test/test_interface.jl index aab67ce1..4cfec875 100644 --- a/LibTrixi.jl/test/test_interface.jl +++ b/LibTrixi.jl/test/test_interface.jl @@ -99,6 +99,25 @@ end nvariables_jl = trixi_nvariables_jl(simstate_jl) @test nvariables_c == nvariables_jl + # compare number of quadrature nodes + nnodes_c = trixi_nnodes(handle) + nnodes_jl = trixi_nnodes_jl(simstate_jl) + @test nnodes_c == nnodes_jl + + # compare coordinates of quadrature nodes + data_c = zeros(nnodes_c) + trixi_load_node_reference_coordinates(handle, pointer(data_c)) + data_jl = zeros(nnodes_jl) + trixi_load_node_reference_coordinates_jl(simstate_jl, data_jl) + @test data_c == data_jl + + # compare weights of quadrature nodes + data_c = zeros(nnodes_c) + trixi_load_node_weights(handle, pointer(data_c)) + data_jl = zeros(nnodes_jl) + trixi_load_node_weights_jl(simstate_jl, data_jl) + @test data_c == data_jl + # compare element averaged values data_c = zeros(nelements_c) trixi_load_element_averaged_primitive_vars(handle, Int32(1), pointer(data_c)) diff --git a/src/api.c b/src/api.c index 45e9353e..b6465c1a 100644 --- a/src/api.c +++ b/src/api.c @@ -19,6 +19,9 @@ enum { TRIXI_FPTR_NDOFS_GLOBAL, TRIXI_FPTR_NDOFS_ELEMENT, TRIXI_FTPR_NVARIABLES, + TRIXI_FPTR_NNODES, + TRIXI_FPTR_LOAD_NODE_REFERENCE_COORDINATES, + TRIXI_FPTR_LOAD_NODE_WEIGHTS, TRIXI_FTPR_LOAD_PRIMITIVE_VARS, TRIXI_FTPR_LOAD_ELEMENT_AVERAGED_PRIMITIVE_VARS, TRIXI_FTPR_VERSION_LIBRARY, @@ -52,6 +55,9 @@ static const char* trixi_function_pointer_names[] = { [TRIXI_FPTR_NDOFS_GLOBAL] = "trixi_ndofsglobal_cfptr", [TRIXI_FPTR_NDOFS_ELEMENT] = "trixi_ndofselement_cfptr", [TRIXI_FTPR_NVARIABLES] = "trixi_nvariables_cfptr", + [TRIXI_FPTR_NNODES] = "trixi_nnodes_cfptr", + [TRIXI_FPTR_LOAD_NODE_REFERENCE_COORDINATES] = "trixi_load_node_reference_coordinates_cfptr", + [TRIXI_FPTR_LOAD_NODE_WEIGHTS] = "trixi_load_node_weights_cfptr", [TRIXI_FTPR_LOAD_PRIMITIVE_VARS] = "trixi_load_primitive_vars_cfptr", [TRIXI_FTPR_LOAD_ELEMENT_AVERAGED_PRIMITIVE_VARS] = "trixi_load_element_averaged_primitive_vars_cfptr", [TRIXI_FTPR_VERSION_LIBRARY] = "trixi_version_library_cfptr", @@ -572,13 +578,74 @@ int trixi_nvariables(int handle) { } +/** + * @anchor trixi_nnodes_api_c + * + * @brief Return number of quadrature nodes per dimension. + * + * @param[in] handle simulation handle + */ +int trixi_nnodes(int handle) { + + // Get function pointer + int (*nnodes)(int) = trixi_function_pointers[TRIXI_FPTR_NNODES]; + + // Call function + return nnodes(handle); +} + + +/** + * @anchor trixi_load_node_reference_coordinates_api_c + * + * @brief Get reference coordinates of 1D quadrature nodes. + * + * The reference coordinates in [-1,1] of the quadrature nodes in the current DG scheme are + * stored in the provided array `node_coords`. The given array has to be of correct size, + * i.e. `nnodes`, and memory has to be allocated beforehand. + * + * @param[in] handle simulation handle + * @param[out] node_coords node reference coordinates + */ +void trixi_load_node_reference_coordinates(int handle, double* node_coords) { + + // Get function pointer + void (*load_node_reference_coordinates)(int, double *) = trixi_function_pointers[TRIXI_FPTR_LOAD_NODE_REFERENCE_COORDINATES]; + + // Call function + return load_node_reference_coordinates(handle, node_coords); +} + + +/** + * @anchor trixi_load_node_weights_api_c + * + * @brief Get weights of 1D quadrature nodes. + * + * The weights of the quadrature nodes in the current DG scheme are stored in the provided + * array `node_weights`. The given array has to be of correct size, i.e. `nnodes`, and + * memory has to be allocated beforehand. + * + * @param[in] handle simulation handle + * @param[out] node_weights node weights + */ +void trixi_load_node_weights(int handle, double* node_weights) { + + // Get function pointer + void (*load_node_weights)(int, double *) = trixi_function_pointers[TRIXI_FPTR_LOAD_NODE_WEIGHTS]; + + // Call function + return load_node_weights(handle, node_weights); +} + + /** * @anchor trixi_load_primitive_vars_api_c * * @brief Load primitive variable * * The values for the primitive variable at position `variable_id` at every degree of - * freedom for are stored in the given array `data`. + * freedom are stored in the given array `data`. * * The given array has to be of correct size (ndofs) and memory has to be allocated * beforehand. diff --git a/src/api.f90 b/src/api.f90 index 776152b2..ac090d9a 100644 --- a/src/api.f90 +++ b/src/api.f90 @@ -323,6 +323,57 @@ integer(c_int) function trixi_nvariables(handle) bind(c) integer(c_int), value, intent(in) :: handle end function + !> + !! @fn LibTrixi::trixi_nnodes::trixi_nnodes(handle) + !! + !! @brief Return number of quadrature nodes per dimension. + !! + !! @param[in] handle simulation handle + !! + !! @see @ref trixi_nnodes_api_c "trixi_nnodes (C API)" + integer(c_int) function trixi_nnodes(handle) bind(c) + use, intrinsic :: iso_c_binding, only: c_int + integer(c_int), value, intent(in) :: handle + end function + + !> + !! @fn LibTrixi::trixi_load_node_reference_coordinates::trixi_load_node_reference_coordinates(handle, node_coords) + !! + !! @brief Get reference coordinates of 1D quadrature nodes. + !! + !! The reference coordinates in [-1,1] of the quadrature nodes in the current DG scheme are + !! stored in the provided array `node_coords`. The given array has to be of correct size, + !! i.e. `nnodes`, and memory has to be allocated beforehand. + !! + !! @param[in] handle simulation handle + !! @param[out] node_coords node reference coordinates + !! + !! @see @ref trixi_load_node_reference_coordinates_api_c "trixi_load_node_reference_coordinates (C API)" + subroutine trixi_load_node_reference_coordinates(handle, node_coords) bind(c) + use, intrinsic :: iso_c_binding, only: c_int, c_double + integer(c_int), value, intent(in) :: handle + real(c_double), dimension(*), intent(out) :: node_coords + end subroutine + + !> + !! @fn LibTrixi::trixi_load_node_weights::trixi_load_node_weights(handle, node_weights) + !! + !! @brief Get weights of 1D quadrature nodes. + !! + !! The weights of the quadrature nodes in the current DG scheme are stored in the provided + !! array `node_weights`. The given array has to be of correct size, i.e. `nnodes`, and + !! memory has to be allocated beforehand. + !! + !! @param[in] handle simulation handle + !! @param[out] node_weights node weights + !! + !! @see @ref trixi_load_node_weights_api_c "trixi_load_node_weights (C API)" + subroutine trixi_load_node_weights(handle, node_weights) bind(c) + use, intrinsic :: iso_c_binding, only: c_int, c_double + integer(c_int), value, intent(in) :: handle + real(c_double), dimension(*), intent(out) :: node_weights + end subroutine + !> !! @fn LibTrixi::trixi_load_primitive_vars::trixi_load_primitive_vars(handle, variable_id, data) !! diff --git a/src/trixi.h b/src/trixi.h index 1ec58ba6..93315148 100644 --- a/src/trixi.h +++ b/src/trixi.h @@ -32,7 +32,10 @@ int trixi_ndofs(int handle); int trixi_ndofsglobal(int handle); int trixi_ndofselement(int handle); int trixi_nvariables(int handle); +int trixi_nnodes(int handle); double trixi_calculate_dt(int handle); +void trixi_load_node_reference_coordinates(int handle, double* node_coords); +void trixi_load_node_weights(int handle, double* node_weights); void trixi_load_primitive_vars(int handle, int variable_id, double * data); void trixi_load_element_averaged_primitive_vars(int handle, int variable_id, double * data); diff --git a/test/c/simulation.cpp b/test/c/simulation.cpp index 221070f9..ff732d1e 100644 --- a/test/c/simulation.cpp +++ b/test/c/simulation.cpp @@ -75,6 +75,21 @@ TEST(CInterfaceTest, SimulationRun) { int nvariables = trixi_nvariables(handle); EXPECT_EQ(nvariables, 4); + // Check number of quadrature nodes + int nnodes = trixi_nnodes(handle); + EXPECT_EQ(nnodes, 5); + + // Check quadrature, integrate f(x) = x^4 over [-1,1] + std::vector nodes(nnodes); + std::vector weights(nnodes); + trixi_load_node_reference_coordinates(handle, nodes.data()); + trixi_load_node_weights(handle, weights.data()); + double integral = 0.0; + for (int i = 0; i < nnodes; ++i) { + integral += weights[i] * nodes[i] * nodes[i] * nodes[i]* nodes[i]; + } + EXPECT_NEAR(integral, 0.4, 1e-17); + // Check primitive variable values on all dofs std::vector rho(ndofs); std::vector energy(ndofs); diff --git a/test/fortran/simulationRun_suite.f90 b/test/fortran/simulationRun_suite.f90 index 079704fd..9dc5e57d 100644 --- a/test/fortran/simulationRun_suite.f90 +++ b/test/fortran/simulationRun_suite.f90 @@ -23,12 +23,12 @@ end subroutine collect_simulationRun_suite subroutine test_simulationRun(error) type(error_type), allocatable, intent(out) :: error integer :: handle, ndims, nelements, nelementsglobal, nvariables, ndofsglobal, & - ndofselement, ndofs, size + ndofselement, ndofs, size, nnodes, i logical :: finished_status ! dp as defined in test-drive integer, parameter :: dp = selected_real_kind(15) - real(dp) :: dt - real(dp), dimension(:), allocatable :: data + real(dp) :: dt, integral + real(dp), dimension(:), allocatable :: data, weights ! Initialize Trixi call trixi_initialize(julia_project_path) @@ -73,6 +73,23 @@ subroutine test_simulationRun(error) nvariables = trixi_nvariables(handle) call check(error, nvariables, 4) + ! Check number of quadrature nodes + nnodes = trixi_nnodes(handle) + call check(error, nnodes, 5) + + ! Check quadrature, integrate f(x) = x^4 over [-1,1] + size = nnodes + allocate(data(size)) + allocate(weights(size)) + call trixi_load_node_reference_coordinates(handle, data) + call trixi_load_node_weights(handle, weights) + integral = 0.0_dp + do i = 1, size + integral = integral + weights(i) * data(i) * data(i) * data(i)* data(i) + end do + call check(error, integral, 0.4_dp) + deallocate(data) + ! Check primitive variable values size = ndofs allocate(data(size)) From e4d69015104705219cfcf1d1a184d1261aac6295 Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Wed, 24 Jul 2024 21:46:45 +0200 Subject: [PATCH 32/89] update CI badge URL --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3d8c018e..4a810aef 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![Docs-stable](https://img.shields.io/badge/docs-stable-blue.svg)](https://trixi-framework.github.io/libtrixi/stable) [![Docs-dev](https://img.shields.io/badge/docs-dev-blue.svg)](https://trixi-framework.github.io/libtrixi/dev) -[![Build Status](https://github.com/trixi-framework/libtrixi/workflows/CI/badge.svg)](https://github.com/trixi-framework/libtrixi/actions?query=workflow%3ACI) +[![Build Status](https://github.com/trixi-framework/libtrixi/actions/workflows/ci.yml/badge.svg)](https://github.com/trixi-framework/libtrixi/actions?query=workflow%3ACI) [![Coveralls](https://coveralls.io/repos/github/trixi-framework/libtrixi/badge.svg)](https://coveralls.io/github/trixi-framework/libtrixi) [![Codecov](https://codecov.io/gh/trixi-framework/libtrixi/branch/main/graph/badge.svg)](https://codecov.io/gh/trixi-framework/libtrixi) [![License: MIT](https://img.shields.io/badge/License-MIT-success.svg)](https://opensource.org/licenses/MIT) From 3a0387b4675be17d5651fc6a2eb5f394e7bd96b4 Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Wed, 24 Jul 2024 23:15:11 +0200 Subject: [PATCH 33/89] remove load_node_coordinates --- LibTrixi.jl/src/api_c.jl | 21 +---- LibTrixi.jl/src/api_jl.jl | 27 ------- examples/CMakeLists.txt | 3 +- examples/trixi_controller_source_terms.c | 98 ------------------------ src/api.f90 | 20 ----- 5 files changed, 2 insertions(+), 167 deletions(-) delete mode 100644 examples/trixi_controller_source_terms.c diff --git a/LibTrixi.jl/src/api_c.jl b/LibTrixi.jl/src/api_c.jl index a3b613f4..9171631c 100644 --- a/LibTrixi.jl/src/api_c.jl +++ b/LibTrixi.jl/src/api_c.jl @@ -492,6 +492,7 @@ end trixi_store_in_database_cfptr() = @cfunction(trixi_store_in_database, Cvoid, (Cint, Cint, Cint, Ptr{Cdouble},)) + """ trixi_get_time(simstate_handle::Cint)::Cdouble @@ -507,26 +508,6 @@ end trixi_get_time_cfptr() = @cfunction(trixi_get_time, Cdouble, (Cint,)) -""" - trixi_load_node_coordinates(simstate_handle::Cint, x::Ptr{Cdouble})::Cvoid - -Get coordinates of all nodes (degrees of freedom). -""" -function trixi_load_node_coordinates end - -Base.@ccallable function trixi_load_node_coordinates(simstate_handle::Cint, - x::Ptr{Cdouble})::Cvoid - simstate = load_simstate(simstate_handle) - - # convert C to Julia array - size = trixi_ndofs_jl(simstate) * trixi_ndims_jl(simstate) - x_jl = unsafe_wrap(Array, x, size) - - return trixi_load_node_coordinates_jl(simstate, x_jl) -end - -trixi_load_node_coordinates_cfptr() = @cfunction(trixi_load_node_coordinates, Cvoid, (Cint, Ptr{Cdouble},)) - """ trixi_load_element_averaged_primitive_vars(simstate_handle::Cint, variable_id::Cint, data::Ptr{Cdouble})::Cvoid diff --git a/LibTrixi.jl/src/api_jl.jl b/LibTrixi.jl/src/api_jl.jl index a0649485..fcf15f59 100644 --- a/LibTrixi.jl/src/api_jl.jl +++ b/LibTrixi.jl/src/api_jl.jl @@ -203,33 +203,6 @@ function trixi_get_time_jl(simstate) end -function trixi_load_node_coordinates_jl(simstate, x) - mesh, equations, solver, cache = mesh_equations_solver_cache(simstate.semi) - - n_nodes_per_dim = nnodes(solver) - n_dims = ndims(mesh) - n_nodes = n_nodes_per_dim^n_dims - n_dofs = ndofs(mesh, solver, cache) - - # all permutations of nodes indices for arbitrary dimension - node_cis = CartesianIndices(ntuple(i -> n_nodes_per_dim, n_dims)) - node_lis = LinearIndices(node_cis) - - for element in eachelement(solver, cache) - for node_ci in node_cis - x_local = get_node_coords(cache.elements.node_coordinates, equations, solver, - node_ci, element) - node_index = (element-1) * n_nodes + node_lis[node_ci] - for d in 1:n_dims - x[(d-1)*n_dofs + node_index] = x_local[d] - end - end - end - - return nothing -end - - function trixi_get_t8code_forest_jl(simstate) mesh, _, _, _ = Trixi.mesh_equations_solver_cache(simstate.semi) return mesh.forest diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 171d4bf8..25bef49f 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -5,8 +5,7 @@ set ( EXAMPLES trixi_controller_mpi.f90 trixi_controller_data.c trixi_controller_data.f90 - trixi_controller_t8code.c - trixi_controller_source_terms.c ) + trixi_controller_t8code.c ) if ( NOT T8CODE_FOUND ) list( FILTER EXAMPLES EXCLUDE REGEX ".*(t|T)8(c|C)(o|O)(d|D)(e|E).*" ) diff --git a/examples/trixi_controller_source_terms.c b/examples/trixi_controller_source_terms.c deleted file mode 100644 index 22b53dce..00000000 --- a/examples/trixi_controller_source_terms.c +++ /dev/null @@ -1,98 +0,0 @@ -#include -#include -#include - -#include - -void source_term_wave(int ndofs, const double * x, const double t, - double * du1, double * du2, double * du4) { - - const double c = 2.0; - const double A = 0.1; - const double L = 2.0; - const double f = 1.0 / L; - const double omega = 2 * M_PI * f; - const double gamma = 1.4; - - for (int i = 0; i < ndofs; ++i) { - - const double si = sin(omega * (x[i] + x[i+ndofs] - t)); - const double co = cos(omega * (x[i] + x[i+ndofs] - t)); - const double rho = c + A * si; - const double rho_x = omega * A * co; - const double tmp = (2 * rho - 1) * (gamma - 1); - - du1[i] = rho_x; - du2[i] = rho_x * (1 + tmp); - du4[i] = 2 * rho_x * (rho + tmp); - } -} - -int main ( int argc, char *argv[] ) { - - if ( argc < 2 ) { - fprintf(stderr, "ERROR: missing arguments: PROJECT_DIR LIBELIXIR_PATH\n\n"); - fprintf(stderr, "usage: %s PROJECT_DIR LIBELIXIR_PATH\n", argv[0]); - return 2; - } else if ( argc < 3 ) { - fprintf(stderr, "ERROR: missing argument: LIBELIXIR_PATH\n\n"); - fprintf(stderr, "usage: %s PROJECT_DIR LIBELIXIR_PATH\n", argv[0]); - return 2; - } - - // Initialize Trixi - printf("\n*** Trixi controller *** Initialize Trixi\n"); - trixi_initialize( argv[1], NULL ); - - // Set up the Trixi simulation - // We get a handle to use subsequently - printf("\n*** Trixi controller *** Set up Trixi simulation\n"); - int handle = trixi_initialize_simulation( argv[2] ); - - // Get number of variables and elements - int ndofs = trixi_ndofs( handle ); - - // Allocate memory for source terms - double * du1 = calloc( ndofs, sizeof(double) ); - double * du2 = calloc( ndofs, sizeof(double) ); - double * du4 = calloc( ndofs, sizeof(double) ); - - // Store source term vectors in Trixi - trixi_store_in_database(handle, 1, ndofs, du1); - trixi_store_in_database(handle, 2, ndofs, du2); - trixi_store_in_database(handle, 3, ndofs, du4); - - // Get node coordinates - double * x = calloc( 2*ndofs, sizeof(double) ); - trixi_load_node_coordinates( handle, x ); - - // Main loop - printf("\n*** Trixi controller *** Entering main loop\n"); - double t = 0.0; - while ( !trixi_is_finished( handle ) ) { - - // Get current time - t = trixi_get_time( handle ); - - // Compute source terms - source_term_wave(ndofs, x, t, du1, du2, du4); - - // Perform next step - trixi_step( handle ); - } - - // Finalize Trixi simulation - printf("\n*** Trixi controller *** Finalize Trixi simulation\n"); - trixi_finalize_simulation( handle ); - - // Finalize Trixi - printf("\n*** Trixi controller *** Finalize Trixi\n"); - trixi_finalize(); - - free(x); - free(du1); - free(du2); - free(du4); - - return 0; -} diff --git a/src/api.f90 b/src/api.f90 index 9fa92c51..1a4b61c5 100644 --- a/src/api.f90 +++ b/src/api.f90 @@ -406,26 +406,6 @@ real(c_double) function trixi_get_time(handle) bind(c) integer(c_int), value, intent(in) :: handle end function - !> - !! @fn LibTrixi::trixi_load_node_coordinates::trixi_load_node_coordinates(handle, x) - !! - !! @brief Get coordinates of all nodes (degrees of freedom). - !! - !! The coordinates of all nodes (degrees of freedom in the DG method) are stored dimension- - !! wise in the provided array `x`, i.e. x-coordinates will be in the beginning and so on. - !! The given array has to be of correct size, i.e. number of nodes times dimension, and - !! memory has to be allocated beforehand. - !! - !! @param[in] handle simulation handle - !! @param[out] x node coordinates - !! - !! @see @ref trixi_load_node_coordinates_api_c "trixi_load_node_coordinates (C API)" - subroutine trixi_load_node_coordinates(handle, x) bind(c) - use, intrinsic :: iso_c_binding, only: c_int, c_double - integer(c_int), value, intent(in) :: handle - real(c_double), dimension(*), intent(out) :: x - end subroutine - !> !! @fn LibTrixi::trixi_load_element_averaged_primitive_vars::trixi_load_element_averaged_primitive_vars(handle, variable_id, data) !! From 9bc76b45459da01f59c0b70ef9ca358130161efb Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Wed, 24 Jul 2024 23:32:38 +0200 Subject: [PATCH 34/89] add baroclinic instability elixir and controller --- ...r_t8code3d_euler_baroclinic_instability.jl | 328 ++++++++++++++++++ examples/CMakeLists.txt | 3 +- examples/trixi_controller_baroclinic.c | 170 +++++++++ 3 files changed, 500 insertions(+), 1 deletion(-) create mode 100644 LibTrixi.jl/examples/libelixir_t8code3d_euler_baroclinic_instability.jl create mode 100644 examples/trixi_controller_baroclinic.c diff --git a/LibTrixi.jl/examples/libelixir_t8code3d_euler_baroclinic_instability.jl b/LibTrixi.jl/examples/libelixir_t8code3d_euler_baroclinic_instability.jl new file mode 100644 index 00000000..63c2e930 --- /dev/null +++ b/LibTrixi.jl/examples/libelixir_t8code3d_euler_baroclinic_instability.jl @@ -0,0 +1,328 @@ +# An idealized baroclinic instability test case +# +# Note that this libelixir is based on the original baroclinic instability elixir by +# Erik Faulhaber for Trixi.jl +# Source: https://github.com/trixi-framework/Trixi.jl/blob/main/examples/p4est_3d_dgsem/elixir_euler_baroclinic_instability.jl +# +# References: +# - Paul A. Ullrich, Thomas Melvin, Christiane Jablonowski, Andrew Staniforth (2013) +# A proposed baroclinic wave test case for deep- and shallow-atmosphere dynamical cores +# https://doi.org/10.1002/qj.2241 + +# CAVE: only for development +# in particular this libelixir uses a way too small fixed time step + +using OrdinaryDiffEq +using Trixi +using LinearAlgebra +using LibTrixi + + +# Callable struct holding vectors with source terms +struct SourceTerm + nnodesdim::Int + database::Vector{Ref{Vector{Float64}}} +end + +# We overwrite Trixi.jl's internal method here such that it calls source_terms with indicies +function Trixi.calc_sources!(du, u, t, source_terms::SourceTerm, + equations::CompressibleEulerEquations3D, dg::DG, cache) + @unpack node_coordinates = cache.elements + Trixi.@threaded for element in eachelement(dg, cache) + for k in eachnode(dg), j in eachnode(dg), i in eachnode(dg) + u_local = Trixi.get_node_vars(u, equations, dg, i, j, k, element) + x_local = Trixi.get_node_coords(node_coordinates, equations, dg, + i, j, k, element) + du_local = source_terms(u_local, i, j, k, element, t, equations) + du_local_ref = source_terms_baroclinic_instability(u_local, x_local, t, + equations) + println(norm(du_local-du_local_ref)) + #println((du_local[2]-u_local[1])^2+(du_local[3]-u_local[2])^2+(du_local[4]-u_local[3])^2+(du_local[5]-u_local[4])^2) + println(du_local) + println(du_local_ref) + Trixi.add_to_node_vars!(du, du_local_ref, equations, dg, i, j, k, element) + end + end + return nothing +end + +@inline function (source::SourceTerm)(u, i, j, k, element, t, + equations::CompressibleEulerEquations3D) + @unpack nnodesdim = source + index_global = (element-1) * nnodesdim^3 + (k-1) * nnodesdim^2 + (j-1) * nnodesdim + i + println("*** Index ", index_global) + # massive allocations occur when directly accessing source.database[1][][1] + du2::Vector{Float64} = source.database[1][] + du3::Vector{Float64} = source.database[2][] + du4::Vector{Float64} = source.database[3][] + du5::Vector{Float64} = source.database[4][] + return SVector(zero(eltype(u)), du2[index_global], du3[index_global], + du4[index_global], du5[index_global]) +end + + +# Initial condition for an idealized baroclinic instability test +# https://doi.org/10.1002/qj.2241, Section 3.2 and Appendix A +function initial_condition_baroclinic_instability(x, t, + equations::CompressibleEulerEquations3D) + lon, lat, r = cartesian_to_sphere(x) + radius_earth = 6.371229e6 + # Make sure that the r is not smaller than radius_earth + z = max(r - radius_earth, 0.0) + + # Unperturbed basic state + rho, u, p = basic_state_baroclinic_instability_longitudinal_velocity(lon, lat, z) + + # Stream function type perturbation + u_perturbation, v_perturbation = perturbation_stream_function(lon, lat, z) + + u += u_perturbation + v = v_perturbation + + # Convert spherical velocity to Cartesian + v1 = -sin(lon) * u - sin(lat) * cos(lon) * v + v2 = cos(lon) * u - sin(lat) * sin(lon) * v + v3 = cos(lat) * v + + return prim2cons(SVector(rho, v1, v2, v3, p), equations) +end + +function cartesian_to_sphere(x) + r = norm(x) + lambda = atan(x[2], x[1]) + if lambda < 0 + lambda += 2 * pi + end + phi = asin(x[3] / r) + + return lambda, phi, r +end + +# Unperturbed balanced steady-state. +# Returns primitive variables with only the velocity in longitudinal direction (rho, u, p). +# The other velocity components are zero. +function basic_state_baroclinic_instability_longitudinal_velocity(lon, lat, z) + # Parameters from Table 1 in the paper + # Corresponding names in the paper are commented + radius_earth = 6.371229e6 # a + half_width_parameter = 2 # b + gravitational_acceleration = 9.80616 # g + k = 3 # k + surface_pressure = 1e5 # p₀ + gas_constant = 287 # R + surface_equatorial_temperature = 310.0 # T₀ᴱ + surface_polar_temperature = 240.0 # T₀ᴾ + lapse_rate = 0.005 # Γ + angular_velocity = 7.29212e-5 # Ω + + # Distance to the center of the Earth + r = z + radius_earth + + # In the paper: T₀ + temperature0 = 0.5 * (surface_equatorial_temperature + surface_polar_temperature) + # In the paper: A, B, C, H + const_a = 1 / lapse_rate + const_b = (temperature0 - surface_polar_temperature) / + (temperature0 * surface_polar_temperature) + const_c = 0.5 * (k + 2) * (surface_equatorial_temperature - surface_polar_temperature) / + (surface_equatorial_temperature * surface_polar_temperature) + const_h = gas_constant * temperature0 / gravitational_acceleration + + # In the paper: (r - a) / bH + scaled_z = z / (half_width_parameter * const_h) + + # Temporary variables + temp1 = exp(lapse_rate / temperature0 * z) + temp2 = exp(-scaled_z^2) + + # In the paper: ̃τ₁, ̃τ₂ + tau1 = const_a * lapse_rate / temperature0 * temp1 + + const_b * (1 - 2 * scaled_z^2) * temp2 + tau2 = const_c * (1 - 2 * scaled_z^2) * temp2 + + # In the paper: ∫τ₁(r') dr', ∫τ₂(r') dr' + inttau1 = const_a * (temp1 - 1) + const_b * z * temp2 + inttau2 = const_c * z * temp2 + + # Temporary variables + temp3 = r / radius_earth * cos(lat) + temp4 = temp3^k - k / (k + 2) * temp3^(k + 2) + + # In the paper: T + temperature = 1 / ((r / radius_earth)^2 * (tau1 - tau2 * temp4)) + + # In the paper: U, u (zonal wind, first component of spherical velocity) + big_u = gravitational_acceleration / radius_earth * k * temperature * inttau2 * + (temp3^(k - 1) - temp3^(k + 1)) + temp5 = radius_earth * cos(lat) + u = -angular_velocity * temp5 + sqrt(angular_velocity^2 * temp5^2 + temp5 * big_u) + + # Hydrostatic pressure + p = surface_pressure * + exp(-gravitational_acceleration / gas_constant * (inttau1 - inttau2 * temp4)) + + # Density (via ideal gas law) + rho = p / (gas_constant * temperature) + + return rho, u, p +end + +# Perturbation as in Equations 25 and 26 of the paper (analytical derivative) +function perturbation_stream_function(lon, lat, z) + # Parameters from Table 1 in the paper + # Corresponding names in the paper are commented + perturbation_radius = 1 / 6 # d₀ / a + perturbed_wind_amplitude = 1.0 # Vₚ + perturbation_lon = pi / 9 # Longitude of perturbation location + perturbation_lat = 2 * pi / 9 # Latitude of perturbation location + pertz = 15000 # Perturbation height cap + + # Great circle distance (d in the paper) divided by a (radius of the Earth) + # because we never actually need d without dividing by a + great_circle_distance_by_a = acos(sin(perturbation_lat) * sin(lat) + + cos(perturbation_lat) * cos(lat) * + cos(lon - perturbation_lon)) + + # In the first case, the vertical taper function is per definition zero. + # In the second case, the stream function is per definition zero. + if z > pertz || great_circle_distance_by_a > perturbation_radius + return 0.0, 0.0 + end + + # Vertical tapering of stream function + perttaper = 1.0 - 3 * z^2 / pertz^2 + 2 * z^3 / pertz^3 + + # sin/cos(pi * d / (2 * d_0)) in the paper + sin_, cos_ = sincos(0.5 * pi * great_circle_distance_by_a / perturbation_radius) + + # Common factor for both u and v + factor = 16 / (3 * sqrt(3)) * perturbed_wind_amplitude * perttaper * cos_^3 * sin_ + + u_perturbation = -factor * (-sin(perturbation_lat) * cos(lat) + + cos(perturbation_lat) * sin(lat) * cos(lon - perturbation_lon)) / + sin(great_circle_distance_by_a) + + v_perturbation = factor * cos(perturbation_lat) * sin(lon - perturbation_lon) / + sin(great_circle_distance_by_a) + + return u_perturbation, v_perturbation +end + +@inline function source_terms_baroclinic_instability(u, x, t, + equations::CompressibleEulerEquations3D) + radius_earth = 6.371229e6 # a + gravitational_acceleration = 9.80616 # g + angular_velocity = 7.29212e-5 # Ω + + r = norm(x) + # Make sure that r is not smaller than radius_earth + z = max(r - radius_earth, 0.0) + r = z + radius_earth + + du1 = zero(eltype(u)) + + # Gravity term + temp = -gravitational_acceleration * radius_earth^2 / r^3 + du2 = temp * u[1] * x[1] + du3 = temp * u[1] * x[2] + du4 = temp * u[1] * x[3] + du5 = temp * (u[2] * x[1] + u[3] * x[2] + u[4] * x[3]) + + # Coriolis term, -2Ω × ρv = -2 * angular_velocity * (0, 0, 1) × u[2:4] + du2 -= -2 * angular_velocity * u[3] + du3 -= 2 * angular_velocity * u[2] + + return SVector(du1, du2, du3, du4, du5) +end + + +# The function to create the simulation state needs to be named `init_simstate` +function init_simstate() + + ############################################################################### + # Setup for the baroclinic instability test + gamma = 1.4 + equations = CompressibleEulerEquations3D(gamma) + + ############################################################################### + # semidiscretization of the problem + + initial_condition = initial_condition_baroclinic_instability + + boundary_conditions = Dict(:inside => boundary_condition_slip_wall, + :outside => boundary_condition_slip_wall) + + # This is a good estimate for the speed of sound in this example. + # Other values between 300 and 400 should work as well. + surface_flux = FluxLMARS(340) + volume_flux = flux_kennedy_gruber + solver = DGSEM(polydeg = 3, surface_flux = surface_flux, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) + + lat_lon_levels = 2 + layers = 2 + mesh = Trixi.T8codeMeshCubedSphere(lat_lon_levels, layers, 6.371229e6, 30000.0, + polydeg = 3, initial_refinement_level = 0) + + # create the database and three vectors for the source terms + database = LibTrixiDataBaseType(undef, 4) + + nnodesdim = Trixi.nnodes(solver) + nnodes = nnodesdim^3 + nelements = Trixi.ncells(mesh) + + database[1] = Ref(Vector{Float64}(undef, nelements*nnodes)) + database[2] = Ref(Vector{Float64}(undef, nelements*nnodes)) + database[3] = Ref(Vector{Float64}(undef, nelements*nnodes)) + database[4] = Ref(Vector{Float64}(undef, nelements*nnodes)) + + source_term_database = SourceTerm(nnodesdim, database) + + semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, + source_terms = source_term_database, + boundary_conditions = boundary_conditions) + + ############################################################################### + # ODE solvers, callbacks etc. + + tspan = (0.0, 10.0) + + ode = semidiscretize(semi, tspan) + + summary_callback = SummaryCallback() + + analysis_interval = 5000 + analysis_callback = AnalysisCallback(semi, interval = analysis_interval) + + alive_callback = AliveCallback(analysis_interval = analysis_interval) + + save_solution = SaveSolutionCallback(interval = 50, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim, + output_directory = "out_baroclinic",) + + callbacks = CallbackSet(summary_callback, + analysis_callback, + alive_callback, + save_solution) + + + ############################################################################### + # create the time integrator + + # OrdinaryDiffEq's `integrator` + # Use a Runge-Kutta method with automatic (error based) time step size control + integrator = init(ode, CarpenterKennedy2N54(williamson_condition=false); + dt = 0.1, + abstol = 1.0e-6, reltol = 1.0e-6, + ode_default_options()..., + callback = callbacks, + maxiters=5e5); + + ############################################################################### + # Create simulation state + simstate = SimulationState(semi, integrator, database) + + return simstate +end diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 25bef49f..80c10566 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -5,7 +5,8 @@ set ( EXAMPLES trixi_controller_mpi.f90 trixi_controller_data.c trixi_controller_data.f90 - trixi_controller_t8code.c ) + trixi_controller_t8code.c + trixi_controller_baroclinic.c ) if ( NOT T8CODE_FOUND ) list( FILTER EXAMPLES EXCLUDE REGEX ".*(t|T)8(c|C)(o|O)(d|D)(e|E).*" ) diff --git a/examples/trixi_controller_baroclinic.c b/examples/trixi_controller_baroclinic.c new file mode 100644 index 00000000..c4e21359 --- /dev/null +++ b/examples/trixi_controller_baroclinic.c @@ -0,0 +1,170 @@ +#include +#include +#include + +#include +#include +#include + +#include + +void source_terms_baroclinic(int nnodes, double * nodes, t8_forest_t forest, + const double /*t*/, + const double * u1, const double * u2, const double * u3, + const double * u4, + double * du2, double * du3, double * du4, double * du5) { + + const double radius_earth = 6.371229e6; + const double gravitational_acceleration = 9.80616; + const double angular_velocity = 7.29212e-5; + const double g_r2 = -gravitational_acceleration * radius_earth * radius_earth; + + double local_coords[3]; + double global_coords[3]; + + // Get the number of trees that have elements + t8_locidx_t num_local_trees = t8_forest_get_num_local_trees (forest); + // Iterates through all local trees + for (t8_locidx_t itree = 0, index = 0; itree < num_local_trees; ++itree) { + // Get number of elements of this tree + t8_locidx_t num_elements_in_tree = t8_forest_get_tree_num_elements (forest, itree); + // Iterate through all the local elements + // TODO: What happens in parallel computations with MPI? + for (t8_locidx_t ielement = 0; ielement < num_elements_in_tree; ++ielement) { + // Get a pointer to the current element + const t8_element_t *element = t8_forest_get_element_in_tree (forest, itree, ielement); + for (int k = 0; k < nnodes; ++k) { + for (int j = 0; j < nnodes; ++j) { + for (int i = 0; i < nnodes; ++i, ++index) { + // Get global coordinates of local quad point + local_coords[0] = 0.5 + 0.5 * nodes[i]; + local_coords[1] = 0.5 + 0.5 * nodes[j]; + local_coords[2] = 0.5 + 0.5 * nodes[k]; + t8_forest_element_from_ref_coords(forest, itree, element, local_coords, 1, global_coords); + + // The acutual computation of source terms + const double ele = sqrt( global_coords[0]*global_coords[0] + + global_coords[1]*global_coords[1] + + global_coords[2]*global_coords[2] ); + + const double ele_corrected = fmax( ele - radius_earth, 0.0) + radius_earth; + // Gravity term + const double temp = g_r2 / (ele_corrected*ele_corrected*ele_corrected); + du2[index] = temp * u1[index] * global_coords[0]; + du3[index] = temp * u1[index] * global_coords[1]; + du4[index] = temp * u1[index] * global_coords[2]; + du5[index] = temp * u1[index] * (u2[index] * global_coords[0] + + u3[index] * global_coords[1] + + u4[index] * global_coords[2]); + // Coriolis term + du2[index] += 2.0 * angular_velocity * u3[index] * u1[index]; + du3[index] -= 2.0 * angular_velocity * u2[index] * u1[index]; + } + } + } + } + } +} + +int main ( int argc, char *argv[] ) { + + if ( argc < 2 ) { + fprintf(stderr, "ERROR: missing arguments: PROJECT_DIR LIBELIXIR_PATH\n\n"); + fprintf(stderr, "usage: %s PROJECT_DIR LIBELIXIR_PATH\n", argv[0]); + return 2; + } else if ( argc < 3 ) { + fprintf(stderr, "ERROR: missing argument: LIBELIXIR_PATH\n\n"); + fprintf(stderr, "usage: %s PROJECT_DIR LIBELIXIR_PATH\n", argv[0]); + return 2; + } + + // Initialize Trixi + printf("\n*** Trixi controller *** Initialize Trixi\n"); + trixi_initialize( argv[1], NULL ); + + // Set up the Trixi simulation + // We get a handle to use subsequently + printf("\n*** Trixi controller *** Set up Trixi simulation\n"); + int handle = trixi_initialize_simulation( argv[2] ); + + // Get number of degrees of freedom + int ndofs = trixi_ndofs( handle ); + + // Allocate memory for current state + double * u1 = calloc( ndofs, sizeof(double) ); + double * u2 = calloc( ndofs, sizeof(double) ); + double * u3 = calloc( ndofs, sizeof(double) ); + double * u4 = calloc( ndofs, sizeof(double) ); + + // Allocate memory for source terms + double * du2 = calloc( ndofs, sizeof(double) ); + double * du3 = calloc( ndofs, sizeof(double) ); + double * du4 = calloc( ndofs, sizeof(double) ); + double * du5 = calloc( ndofs, sizeof(double) ); + + // Store source term vectors in Trixi + trixi_store_in_database(handle, 1, ndofs, du2); + trixi_store_in_database(handle, 2, ndofs, du3); + trixi_store_in_database(handle, 3, ndofs, du4); + trixi_store_in_database(handle, 4, ndofs, du5); + + // Get number of quadrature nodes + int nnodes = trixi_nnodes( handle ); + + // Allocate memory for quadrature node coordinates + double * nodes = calloc( nnodes, sizeof(double) ); + + // Get quadrature node coordinates + trixi_load_node_reference_coordinates( handle, nodes ); + + // Transform coordinates from [-1,1] to [0,1] + for (int i = 0; i < nnodes; ++i, ++index) { + nodes[i] = 0.5 * (nodes[i] + 1.0); + } + + // Get t8code forest + t8_forest_t forest = trixi_get_t8code_forest(handle); + + // Main loop + printf("\n*** Trixi controller *** Entering main loop\n"); + double t = 0.0; + //while ( !trixi_is_finished( handle ) ) { + + // Get current time + t = trixi_get_time( handle ); + + // Get current state + trixi_load_primitive_vars( handle, 1, u1 ); + trixi_load_primitive_vars( handle, 2, u2 ); + trixi_load_primitive_vars( handle, 3, u3 ); + trixi_load_primitive_vars( handle, 4, u4 ); + + fprintf(stderr, "Tick: %f\n", t); + + // Compute source terms + source_terms_baroclinic(nnodes, nodes, forest, t, + u1, u2, u3, u4, du2, du3, du4, du5); + + // Perform next step + trixi_step( handle ); + //} + + // Finalize Trixi simulation + printf("\n*** Trixi controller *** Finalize Trixi simulation\n"); + trixi_finalize_simulation( handle ); + + // Finalize Trixi + printf("\n*** Trixi controller *** Finalize Trixi\n"); + trixi_finalize(); + + free(u1); + free(u2); + free(u3); + free(u4); + free(du2); + free(du3); + free(du4); + free(du5); + + return 0; +} From 110219dc0a994da33d8d2fc71b4c56b19b67b3e0 Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Thu, 25 Jul 2024 16:18:29 +0200 Subject: [PATCH 35/89] fix --- examples/trixi_controller_baroclinic.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/trixi_controller_baroclinic.c b/examples/trixi_controller_baroclinic.c index c4e21359..d7534df5 100644 --- a/examples/trixi_controller_baroclinic.c +++ b/examples/trixi_controller_baroclinic.c @@ -37,9 +37,9 @@ void source_terms_baroclinic(int nnodes, double * nodes, t8_forest_t forest, for (int j = 0; j < nnodes; ++j) { for (int i = 0; i < nnodes; ++i, ++index) { // Get global coordinates of local quad point - local_coords[0] = 0.5 + 0.5 * nodes[i]; - local_coords[1] = 0.5 + 0.5 * nodes[j]; - local_coords[2] = 0.5 + 0.5 * nodes[k]; + local_coords[0] = nodes[i]; + local_coords[1] = nodes[j]; + local_coords[2] = nodes[k]; t8_forest_element_from_ref_coords(forest, itree, element, local_coords, 1, global_coords); // The acutual computation of source terms @@ -118,7 +118,7 @@ int main ( int argc, char *argv[] ) { trixi_load_node_reference_coordinates( handle, nodes ); // Transform coordinates from [-1,1] to [0,1] - for (int i = 0; i < nnodes; ++i, ++index) { + for (int i = 0; i < nnodes; ++i) { nodes[i] = 0.5 * (nodes[i] + 1.0); } From ade7e73305ce815e37b88941368d2e105907bdf9 Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Thu, 25 Jul 2024 16:18:53 +0200 Subject: [PATCH 36/89] clean up --- ...lixir_t8code3d_euler_baroclinic_instability.jl | 15 +++++---------- examples/trixi_controller_baroclinic.c | 6 ++---- 2 files changed, 7 insertions(+), 14 deletions(-) diff --git a/LibTrixi.jl/examples/libelixir_t8code3d_euler_baroclinic_instability.jl b/LibTrixi.jl/examples/libelixir_t8code3d_euler_baroclinic_instability.jl index 63c2e930..7a79cbef 100644 --- a/LibTrixi.jl/examples/libelixir_t8code3d_euler_baroclinic_instability.jl +++ b/LibTrixi.jl/examples/libelixir_t8code3d_euler_baroclinic_instability.jl @@ -34,13 +34,9 @@ function Trixi.calc_sources!(du, u, t, source_terms::SourceTerm, x_local = Trixi.get_node_coords(node_coordinates, equations, dg, i, j, k, element) du_local = source_terms(u_local, i, j, k, element, t, equations) - du_local_ref = source_terms_baroclinic_instability(u_local, x_local, t, - equations) - println(norm(du_local-du_local_ref)) - #println((du_local[2]-u_local[1])^2+(du_local[3]-u_local[2])^2+(du_local[4]-u_local[3])^2+(du_local[5]-u_local[4])^2) - println(du_local) - println(du_local_ref) - Trixi.add_to_node_vars!(du, du_local_ref, equations, dg, i, j, k, element) + #du_local_ref = source_terms_baroclinic_instability(u_local, x_local, t, + # equations) + Trixi.add_to_node_vars!(du, du_local, equations, dg, i, j, k, element) end end return nothing @@ -50,7 +46,6 @@ end equations::CompressibleEulerEquations3D) @unpack nnodesdim = source index_global = (element-1) * nnodesdim^3 + (k-1) * nnodesdim^2 + (j-1) * nnodesdim + i - println("*** Index ", index_global) # massive allocations occur when directly accessing source.database[1][][1] du2::Vector{Float64} = source.database[1][] du3::Vector{Float64} = source.database[2][] @@ -259,8 +254,8 @@ function init_simstate() solver = DGSEM(polydeg = 3, surface_flux = surface_flux, volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) - lat_lon_levels = 2 - layers = 2 + lat_lon_levels = 3 + layers = 4 mesh = Trixi.T8codeMeshCubedSphere(lat_lon_levels, layers, 6.371229e6, 30000.0, polydeg = 3, initial_refinement_level = 0) diff --git a/examples/trixi_controller_baroclinic.c b/examples/trixi_controller_baroclinic.c index d7534df5..eb947d34 100644 --- a/examples/trixi_controller_baroclinic.c +++ b/examples/trixi_controller_baroclinic.c @@ -128,7 +128,7 @@ int main ( int argc, char *argv[] ) { // Main loop printf("\n*** Trixi controller *** Entering main loop\n"); double t = 0.0; - //while ( !trixi_is_finished( handle ) ) { + while ( !trixi_is_finished( handle ) ) { // Get current time t = trixi_get_time( handle ); @@ -139,15 +139,13 @@ int main ( int argc, char *argv[] ) { trixi_load_primitive_vars( handle, 3, u3 ); trixi_load_primitive_vars( handle, 4, u4 ); - fprintf(stderr, "Tick: %f\n", t); - // Compute source terms source_terms_baroclinic(nnodes, nodes, forest, t, u1, u2, u3, u4, du2, du3, du4, du5); // Perform next step trixi_step( handle ); - //} + } // Finalize Trixi simulation printf("\n*** Trixi controller *** Finalize Trixi simulation\n"); From 6627b97eac20d43e512892c4f456a76ca5a758cc Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Fri, 26 Jul 2024 10:16:38 +0200 Subject: [PATCH 37/89] add get_t8code_forest to Fortran interface --- examples/CMakeLists.txt | 3 +- examples/trixi_controller_t8code.f90 | 82 ++++++++++++++++++++++++++++ src/api.f90 | 20 +++++++ test/fortran/CMakeLists.txt | 10 ++++ test/fortran/main.f90 | 2 + test/fortran/t8code_suite.f90 | 49 +++++++++++++++++ 6 files changed, 165 insertions(+), 1 deletion(-) create mode 100644 examples/trixi_controller_t8code.f90 create mode 100644 test/fortran/t8code_suite.f90 diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 327d4310..264dbc11 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -5,7 +5,8 @@ set ( EXAMPLES trixi_controller_mpi.f90 trixi_controller_data.c trixi_controller_data.f90 - trixi_controller_t8code.c ) + trixi_controller_t8code.c + trixi_controller_t8code.f90 ) if ( NOT T8CODE_FOUND ) list( FILTER EXAMPLES EXCLUDE REGEX ".*(t|T)8(c|C)(o|O)(d|D)(e|E).*" ) diff --git a/examples/trixi_controller_t8code.f90 b/examples/trixi_controller_t8code.f90 new file mode 100644 index 00000000..51d6c318 --- /dev/null +++ b/examples/trixi_controller_t8code.f90 @@ -0,0 +1,82 @@ +! Print the local and global number of elements of a forest. +subroutine t8_print_forest_information(forest) + use t8_mo_fortran_interface + use, intrinsic :: iso_c_binding, only: c_ptr, c_int + + implicit none + + type(c_ptr) :: forest + integer(c_int) :: local_num_elements, global_num_elements + + ! Check that forest is a committed, that is valid and usable, forest. + ! T8_ASSERT (t8_forest_is_committed (forest)); + + ! Get the local number of elements. + local_num_elements = t8_forest_get_local_num_elements (forest) + + ! Get the global number of elements. + global_num_elements = t8_forest_get_global_num_elements (forest) + + write(*, '(a,i6)') "*** T8code *** Local number of elements: ", local_num_elements + write(*, '(a,i6)') "*** T8code *** Global number of elements: ", global_num_elements +end subroutine + + +program trixi_controller_simple_f + use LibTrixi + use, intrinsic :: iso_fortran_env, only: error_unit + use, intrinsic :: iso_c_binding, only: c_int, c_ptr + + implicit none + + integer(c_int) :: handle, nelements + character(len=256) :: argument + type(c_ptr) :: forest + + if (command_argument_count() < 1) then + call get_command_argument(0, argument) + write(error_unit, '(a)') "ERROR: missing arguments: PROJECT_DIR LIBELIXIR_PATH" + write(error_unit, '(a)') "" + write(error_unit, '(3a)') "usage: ", trim(argument), " PROJECT_DIR LIBELIXIR_PATH" + call exit(2) + else if (command_argument_count() < 2) then + call get_command_argument(0, argument) + write(error_unit, '(a)') "ERROR: missing argument: LIBELIXIR_PATH" + write(error_unit, '(a)') "" + write(error_unit, '(3a)') "usage: ", trim(argument), " PROJECT_DIR LIBELIXIR_PATH" + call exit(2) + end if + + ! Initialize Trixi + call get_command_argument(1, argument) + call trixi_initialize(argument) + + ! Set up the Trixi simulation + ! We get a handle to use subsequently + call get_command_argument(2, argument) + handle = trixi_initialize_simulation(argument) + + ! Main loop + do + ! Exit loop once simulation is completed + if ( trixi_is_finished(handle) ) exit + + call trixi_step(handle) + end do + + ! get number of elements + nelements = trixi_nelements( handle ); + write(*, '(a)') "" + write(*, '(a,i6)') "*** Trixi controller *** nelements ", nelements + write(*, '(a)') "" + + ! get t8code forest + forest = trixi_get_t8code_forest( handle ) + call t8_print_forest_information ( forest ) + + ! Finalize Trixi simulation + call trixi_finalize_simulation(handle) + + ! Finalize Trixi + call trixi_finalize() +end program diff --git a/src/api.f90 b/src/api.f90 index ac090d9a..6526bd0c 100644 --- a/src/api.f90 +++ b/src/api.f90 @@ -410,6 +410,26 @@ subroutine trixi_load_element_averaged_primitive_vars(handle, variable_id, data) + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! t8code !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !> + !! @fn LibTrixi::trixi_get_t8code_forest::trixi_get_t8code_forest(handle) + !! + !! @brief Get t8code forest + !! + !! @param[in] handle simulation handle + !! + !! @return t8code forest + !! + !! @see @ref trixi_get_t8code_forest_api_c "trixi_get_t8code_forest (C API)" + type (c_ptr) function trixi_get_t8code_forest(handle) bind(c) + use, intrinsic :: iso_c_binding, only: c_int, c_ptr + integer(c_int), value, intent(in) :: handle + end function + + + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !! Misc !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! diff --git a/test/fortran/CMakeLists.txt b/test/fortran/CMakeLists.txt index 115cbee9..311634a7 100644 --- a/test/fortran/CMakeLists.txt +++ b/test/fortran/CMakeLists.txt @@ -3,6 +3,10 @@ set ( TESTS simulationRun_suite versionInfo_suite ) +if ( T8CODE_FOUND ) + list( APPEND TESTS t8code_suite ) +endif() + set ( TEST_SRCS "main.f90" ) @@ -20,12 +24,18 @@ target_link_libraries( ${TARGET_NAME} PRIVATE MPI::MPI_Fortran ${PROJECT_NAME} ${PROJECT_NAME}_tls "test-drive::test-drive" ) +if ( T8CODE_FOUND ) + target_link_libraries( ${TARGET_NAME} PRIVATE ${T8CODE_LIBRARIES} ) +endif() # set include directories target_include_directories( ${TARGET_NAME} PRIVATE ${CMAKE_SOURCE_DIR}/src ) +if ( T8CODE_FOUND ) + target_include_directories( ${TARGET_NAME} PRIVATE ${T8CODE_INCLUDE_DIR} ) +endif() # enable warnings target_compile_options( ${TARGET_NAME} PRIVATE -cpp -Wall -Wextra -Werror -Wno-uninitialized ) diff --git a/test/fortran/main.f90 b/test/fortran/main.f90 index 5f5e13f1..3197f203 100644 --- a/test/fortran/main.f90 +++ b/test/fortran/main.f90 @@ -18,6 +18,7 @@ program tester & select_suite, run_selected, get_argument use juliaCode_suite, only : collect_juliaCode_suite use simulationRun_suite, only : collect_simulationRun_suite + use t8code_suite, only : collect_t8code_suite use versionInfo_suite, only : collect_versionInfo_suite implicit none integer :: stat, is @@ -29,6 +30,7 @@ program tester testsuites = [ new_testsuite("juliaCode_suite", collect_juliaCode_suite), & new_testsuite("simulationRun_suite", collect_simulationRun_suite), & + new_testsuite("t8code_suite", collect_t8code_suite), & new_testsuite("versionInfo_suite", collect_versionInfo_suite) ] call get_argument(1, suite_name) diff --git a/test/fortran/t8code_suite.f90 b/test/fortran/t8code_suite.f90 new file mode 100644 index 00000000..863510b7 --- /dev/null +++ b/test/fortran/t8code_suite.f90 @@ -0,0 +1,49 @@ +module t8code_suite + use LibTrixi + use testdrive, only : new_unittest, unittest_type, error_type, check + use, intrinsic :: iso_c_binding, only: c_ptr, c_null_ptr, c_associated + + implicit none + private + + public :: collect_t8code_suite + + character(len=*), parameter, public :: julia_project_path = JULIA_PROJECT_PATH + character(len=*), parameter, public :: libelixir_path = & + "../../../LibTrixi.jl/examples/libelixir_t8code_2d_dgsem_advection_amr.jl" + + contains + + !> Collect all exported unit tests + subroutine collect_t8code_suite(testsuite) + !> Collection of tests + type(unittest_type), allocatable, intent(out) :: testsuite(:) + + testsuite = [ new_unittest("t8code", test_t8code) ] + end subroutine collect_t8code_suite + + subroutine test_t8code(error) + type(error_type), allocatable, intent(out) :: error + integer :: handle + type(c_ptr) :: forest + + ! Initialize Trixi + call trixi_initialize(julia_project_path) + + ! Set up the Trixi simulation, get a handle + handle = trixi_initialize_simulation(libelixir_path) + call check(error, handle, 1) + + ! Check t8code forest pointer + forest = c_null_ptr + forest = trixi_get_t8code_forest(handle) + call check(error, c_associated(forest)) + + ! Finalize Trixi simulation + call trixi_finalize_simulation(handle) + + ! Finalize Trixi + call trixi_finalize() + end subroutine test_t8code + +end module t8code_suite From 25508729a3fad30a8bad38747db8227e8da71e65 Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Fri, 26 Jul 2024 10:17:24 +0200 Subject: [PATCH 38/89] format --- examples/trixi_controller_t8code.f90 | 2 +- test/fortran/main.f90 | 2 +- test/fortran/t8code_suite.f90 | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/trixi_controller_t8code.f90 b/examples/trixi_controller_t8code.f90 index 51d6c318..3b8989c7 100644 --- a/examples/trixi_controller_t8code.f90 +++ b/examples/trixi_controller_t8code.f90 @@ -2,7 +2,7 @@ subroutine t8_print_forest_information(forest) use t8_mo_fortran_interface use, intrinsic :: iso_c_binding, only: c_ptr, c_int - + implicit none type(c_ptr) :: forest diff --git a/test/fortran/main.f90 b/test/fortran/main.f90 index 3197f203..fc679521 100644 --- a/test/fortran/main.f90 +++ b/test/fortran/main.f90 @@ -30,7 +30,7 @@ program tester testsuites = [ new_testsuite("juliaCode_suite", collect_juliaCode_suite), & new_testsuite("simulationRun_suite", collect_simulationRun_suite), & - new_testsuite("t8code_suite", collect_t8code_suite), & + new_testsuite("t8code_suite", collect_t8code_suite), & new_testsuite("versionInfo_suite", collect_versionInfo_suite) ] call get_argument(1, suite_name) diff --git a/test/fortran/t8code_suite.f90 b/test/fortran/t8code_suite.f90 index 863510b7..b3ae99cf 100644 --- a/test/fortran/t8code_suite.f90 +++ b/test/fortran/t8code_suite.f90 @@ -41,7 +41,7 @@ subroutine test_t8code(error) ! Finalize Trixi simulation call trixi_finalize_simulation(handle) - + ! Finalize Trixi call trixi_finalize() end subroutine test_t8code From 08daf22d452d70f198b98751db13d5970f237def Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Fri, 26 Jul 2024 10:29:58 +0200 Subject: [PATCH 39/89] add trixi_store_in_database to Fortran interface --- src/api.f90 | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/api.f90 b/src/api.f90 index 9f728877..51b20fbf 100644 --- a/src/api.f90 +++ b/src/api.f90 @@ -388,7 +388,7 @@ subroutine trixi_load_primitive_vars(handle, variable_id, data) bind(c) use, intrinsic :: iso_c_binding, only: c_int, c_double integer(c_int), value, intent(in) :: handle integer(c_int), value, intent(in) :: variable_id - real(c_double), dimension(*), intent(in) :: data + real(c_double), dimension(*), intent(out) :: data end subroutine !> @@ -420,6 +420,25 @@ subroutine trixi_load_element_averaged_primitive_vars(handle, variable_id, data) use, intrinsic :: iso_c_binding, only: c_int, c_double integer(c_int), value, intent(in) :: handle integer(c_int), value, intent(in) :: variable_id + real(c_double), dimension(*), intent(out) :: data + end subroutine + + !> + !! @fn LibTrixi::trixi_store_in_database::trixi_store_in_database(handle, variable_id, data) + !! + !! @brief Store data vector in current simulation's database + !! + !! @param[in] handle simulation handle + !! @param[in] index index in database where data vector will be stored + !! @param[in] size size of given data vector + !! @param[in] data data vector to store + !! + !! @see @ref trixi_store_in_database_api_c "trixi_store_in_database (C API)" + subroutine trixi_store_in_database(handle, index, size, data) bind(c) + use, intrinsic :: iso_c_binding, only: c_int, c_double + integer(c_int), value, intent(in) :: handle + integer(c_int), value, intent(in) :: index + integer(c_int), value, intent(in) :: size real(c_double), dimension(*), intent(in) :: data end subroutine From 6672d9cca85e1d6eb60082257a484eff89171ecb Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Fri, 26 Jul 2024 15:26:53 +0200 Subject: [PATCH 40/89] add fortran controller for baroclinic test case --- examples/CMakeLists.txt | 3 +- examples/trixi_controller_baroclinic.c | 12 +- examples/trixi_controller_baroclinic.f90 | 202 +++++++++++++++++++++++ 3 files changed, 210 insertions(+), 7 deletions(-) create mode 100644 examples/trixi_controller_baroclinic.f90 diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 5d295160..065b6e8e 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -7,7 +7,8 @@ set ( EXAMPLES trixi_controller_data.f90 trixi_controller_t8code.c trixi_controller_t8code.f90 - trixi_controller_baroclinic.c ) + trixi_controller_baroclinic.c + trixi_controller_baroclinic.f90 ) if ( NOT T8CODE_FOUND ) list( FILTER EXAMPLES EXCLUDE REGEX ".*(t|T)8(c|C)(o|O)(d|D)(e|E).*" ) diff --git a/examples/trixi_controller_baroclinic.c b/examples/trixi_controller_baroclinic.c index eb947d34..a58b7175 100644 --- a/examples/trixi_controller_baroclinic.c +++ b/examples/trixi_controller_baroclinic.c @@ -103,10 +103,10 @@ int main ( int argc, char *argv[] ) { double * du5 = calloc( ndofs, sizeof(double) ); // Store source term vectors in Trixi - trixi_store_in_database(handle, 1, ndofs, du2); - trixi_store_in_database(handle, 2, ndofs, du3); - trixi_store_in_database(handle, 3, ndofs, du4); - trixi_store_in_database(handle, 4, ndofs, du5); + trixi_store_in_database( handle, 1, ndofs, du2 ); + trixi_store_in_database( handle, 2, ndofs, du3 ); + trixi_store_in_database( handle, 3, ndofs, du4 ); + trixi_store_in_database( handle, 4, ndofs, du5 ); // Get number of quadrature nodes int nnodes = trixi_nnodes( handle ); @@ -140,8 +140,8 @@ int main ( int argc, char *argv[] ) { trixi_load_primitive_vars( handle, 4, u4 ); // Compute source terms - source_terms_baroclinic(nnodes, nodes, forest, t, - u1, u2, u3, u4, du2, du3, du4, du5); + source_terms_baroclinic( nnodes, nodes, forest, t, + u1, u2, u3, u4, du2, du3, du4, du5 ); // Perform next step trixi_step( handle ); diff --git a/examples/trixi_controller_baroclinic.f90 b/examples/trixi_controller_baroclinic.f90 new file mode 100644 index 00000000..aeee1320 --- /dev/null +++ b/examples/trixi_controller_baroclinic.f90 @@ -0,0 +1,202 @@ +subroutine source_terms_baroclinic( nnodes, nodes, forest, ndofs, & + u1, u2, u3, u4, du2, du3, du4, du5 ) + use t8_mo_fortran_interface + use, intrinsic :: iso_c_binding, only: c_ptr, c_int, c_double + + implicit none + + integer(c_int) :: nnodes, ndofs, num_local_trees, itree, num_elements_in_tree, ielement, & + index, i, j, k + type(c_ptr) :: forest, element + integer, parameter :: dp = selected_real_kind(12) + real(dp) :: radius_earth, gravitational_acceleration, angular_velocity, & + g_r2, ele, ele_corrected, temp + real(dp), dimension(3) :: local_coords, global_coords + real(dp), dimension(ndofs) :: u1, u2, u3, u4, du2, du3, du4, du5 + real(dp), dimension(nnodes) :: nodes + + radius_earth = 6.371229e6 + gravitational_acceleration = 9.80616 + angular_velocity = 7.29212e-5 + g_r2 = -gravitational_acceleration * radius_earth * radius_earth + + ! Get the number of trees that have elements + num_local_trees = t8_forest_get_num_local_trees (forest) + ! Iterate through all local trees + index = 1 + do itree = 1,num_local_trees + ! Get number of elements of this tree + num_elements_in_tree = t8_forest_get_tree_num_elements (forest, itree) + ! Iterate through all the local elements + do ielement = 1,num_elements_in_tree + ! Get a pointer to the current element + element = t8_forest_get_element_in_tree (forest, itree, ielement) + do k = 1,nnodes + do j = 1,nnodes + do i = 1,nnodes + ! Get global coordinates of local quad point + local_coords(1) = nodes(i) + local_coords(2) = nodes(j) + local_coords(3) = nodes(k) + call t8_forest_element_from_ref_coords(forest, itree, element, & + local_coords, 1, global_coords) + + ! The acutual computation of source terms + ele = sqrt( global_coords(1)*global_coords(1) + & + global_coords(2)*global_coords(2) + & + global_coords(3)*global_coords(3) ) + ele_corrected = max( ele - radius_earth, 0.0) + radius_earth + + ! Gravity term + temp = g_r2 / (ele_corrected*ele_corrected*ele_corrected) + du2(index) = temp * u1(index) * global_coords(1) + du3(index) = temp * u1(index) * global_coords(2) + du4(index) = temp * u1(index) * global_coords(3) + du5(index) = temp * u1(index) * (u2(index) * global_coords(1) + & + u3(index) * global_coords(2) + & + u4(index) * global_coords(3)) + + ! Coriolis term + du2(index) = du2(index) + 2.0 * angular_velocity * u3(index) * u1(index) + du3(index) = du2(index) - 2.0 * angular_velocity * u2(index) * u1(index) + + index = index + 1 + end do + end do + end do + end do + end do +end subroutine + +program trixi_controller_baroclinic_f + use LibTrixi + use, intrinsic :: iso_fortran_env, only: error_unit + use, intrinsic :: iso_c_binding, only: c_int, c_double, c_ptr + + implicit none + + integer(c_int) :: handle, nnodes, ndofs, i + character(len=256) :: argument + type(c_ptr) :: forest + integer, parameter :: dp = selected_real_kind(12) + real(c_double) :: t + real(dp), dimension(:), pointer :: u1, u2, u3, u4, du2, du3, du4, du5, nodes => null() + + + if (command_argument_count() < 1) then + call get_command_argument(0, argument) + write(error_unit, '(a)') "ERROR: missing arguments: PROJECT_DIR LIBELIXIR_PATH" + write(error_unit, '(a)') "" + write(error_unit, '(3a)') "usage: ", trim(argument), " PROJECT_DIR LIBELIXIR_PATH" + call exit(2) + else if (command_argument_count() < 2) then + call get_command_argument(0, argument) + write(error_unit, '(a)') "ERROR: missing argument: LIBELIXIR_PATH" + write(error_unit, '(a)') "" + write(error_unit, '(3a)') "usage: ", trim(argument), " PROJECT_DIR LIBELIXIR_PATH" + call exit(2) + end if + + + ! Initialize Trixi + write(*, '(a)') "" + write(*, '(a)') "*** Trixi controller *** Initialize Trixi" + call get_command_argument( 1, argument ) + call trixi_initialize( argument ) + + ! Set up the Trixi simulation + ! We get a handle to use subsequently + write(*, '(a)') "*** Trixi controller *** Set up Trixi simulation" + call get_command_argument( 2, argument ) + handle = trixi_initialize_simulation( argument ) + + ! Get number of degrees of freedom + ndofs = trixi_ndofs( handle ); + + ! Allocate memory for current state + allocate( u1(ndofs) ) + allocate( u2(ndofs) ) + allocate( u3(ndofs) ) + allocate( u4(ndofs) ) + + ! Allocate memory for source terms + allocate( du2(ndofs) ) + allocate( du3(ndofs) ) + allocate( du4(ndofs) ) + allocate( du5(ndofs) ) + + ! Store source term vectors in Trixi + call trixi_store_in_database( handle, 1, ndofs, du2 ) + call trixi_store_in_database( handle, 2, ndofs, du3 ) + call trixi_store_in_database( handle, 3, ndofs, du4 ) + call trixi_store_in_database( handle, 4, ndofs, du5 ) + + ! Get number of quadrature nodes + nnodes = trixi_nnodes( handle ) + + ! Allocate memory for quadrature node coordinates + allocate( nodes(nnodes) ) + + ! Get quadrature node coordinates + call trixi_load_node_reference_coordinates( handle, nodes ); + + ! Transform coordinates from [-1,1] to [0,1] + do i = 1,nnodes + nodes(i) = 0.5 * (nodes(i) + 1.0) + end do + + ! Get t8code forest + forest = trixi_get_t8code_forest( handle ) + + ! Main loop + write(*, '(a)') "*** Trixi controller *** Entering main loop" + + do + ! Exit loop once simulation is completed + if ( trixi_is_finished(handle) ) exit + + ! Get current time + t = trixi_get_time( handle ); + + ! Get current state + call trixi_load_primitive_vars( handle, 1, u1 ) + call trixi_load_primitive_vars( handle, 2, u2 ) + call trixi_load_primitive_vars( handle, 3, u3 ) + call trixi_load_primitive_vars( handle, 4, u4 ) + + ! Compute source terms + call source_terms_baroclinic( nnodes, nodes, forest, ndofs, & + u1, u2, u3, u4, du2, du3, du4, du5 ) + + call trixi_step(handle) + end do + + ! Finalize Trixi simulation + write(*, '(a)') "" + write(*, '(a)') "*** Trixi controller *** Finalize Trixi simulation" + call trixi_finalize_simulation(handle) + + ! Finalize Trixi + write(*, '(a)') "" + write(*, '(a)') "*** Trixi controller *** Finalize Trixi" + call trixi_finalize() + + deallocate(u1) + deallocate(u2) + deallocate(u3) + deallocate(u4) + deallocate(du2) + deallocate(du3) + deallocate(du4) + deallocate(du5) + deallocate(nodes) + nullify(u1) + nullify(u2) + nullify(u3) + nullify(u4) + nullify(du2) + nullify(du3) + nullify(du4) + nullify(du5) + nullify(nodes) +end program From e48dcb29ba52c91a712187ad1077c33e32de8b5c Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Thu, 29 Aug 2024 16:30:18 +0200 Subject: [PATCH 41/89] remove parameter t was not used and cause either omitted parameter error or unused parameter warning using older GCCs --- examples/trixi_controller_baroclinic.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/examples/trixi_controller_baroclinic.c b/examples/trixi_controller_baroclinic.c index a58b7175..ec0eab47 100644 --- a/examples/trixi_controller_baroclinic.c +++ b/examples/trixi_controller_baroclinic.c @@ -9,7 +9,6 @@ #include void source_terms_baroclinic(int nnodes, double * nodes, t8_forest_t forest, - const double /*t*/, const double * u1, const double * u2, const double * u3, const double * u4, double * du2, double * du3, double * du4, double * du5) { @@ -127,12 +126,8 @@ int main ( int argc, char *argv[] ) { // Main loop printf("\n*** Trixi controller *** Entering main loop\n"); - double t = 0.0; while ( !trixi_is_finished( handle ) ) { - // Get current time - t = trixi_get_time( handle ); - // Get current state trixi_load_primitive_vars( handle, 1, u1 ); trixi_load_primitive_vars( handle, 2, u2 ); @@ -140,7 +135,7 @@ int main ( int argc, char *argv[] ) { trixi_load_primitive_vars( handle, 4, u4 ); // Compute source terms - source_terms_baroclinic( nnodes, nodes, forest, t, + source_terms_baroclinic( nnodes, nodes, forest, u1, u2, u3, u4, du2, du3, du4, du5 ); // Perform next step From 00e4914b5b500150bce8b6f692e9cd9e42c3ab97 Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Thu, 29 Aug 2024 16:56:57 +0200 Subject: [PATCH 42/89] spelling --- .../examples/libelixir_t8code3d_euler_baroclinic_instability.jl | 2 +- examples/trixi_controller_baroclinic.c | 2 +- examples/trixi_controller_baroclinic.f90 | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/LibTrixi.jl/examples/libelixir_t8code3d_euler_baroclinic_instability.jl b/LibTrixi.jl/examples/libelixir_t8code3d_euler_baroclinic_instability.jl index 7a79cbef..8f665422 100644 --- a/LibTrixi.jl/examples/libelixir_t8code3d_euler_baroclinic_instability.jl +++ b/LibTrixi.jl/examples/libelixir_t8code3d_euler_baroclinic_instability.jl @@ -24,7 +24,7 @@ struct SourceTerm database::Vector{Ref{Vector{Float64}}} end -# We overwrite Trixi.jl's internal method here such that it calls source_terms with indicies +# We overwrite Trixi.jl's internal method here such that it calls source_terms with indices function Trixi.calc_sources!(du, u, t, source_terms::SourceTerm, equations::CompressibleEulerEquations3D, dg::DG, cache) @unpack node_coordinates = cache.elements diff --git a/examples/trixi_controller_baroclinic.c b/examples/trixi_controller_baroclinic.c index ec0eab47..49217605 100644 --- a/examples/trixi_controller_baroclinic.c +++ b/examples/trixi_controller_baroclinic.c @@ -41,7 +41,7 @@ void source_terms_baroclinic(int nnodes, double * nodes, t8_forest_t forest, local_coords[2] = nodes[k]; t8_forest_element_from_ref_coords(forest, itree, element, local_coords, 1, global_coords); - // The acutual computation of source terms + // The actual computation of source terms const double ele = sqrt( global_coords[0]*global_coords[0] + global_coords[1]*global_coords[1] + global_coords[2]*global_coords[2] ); diff --git a/examples/trixi_controller_baroclinic.f90 b/examples/trixi_controller_baroclinic.f90 index aeee1320..136ef0fe 100644 --- a/examples/trixi_controller_baroclinic.f90 +++ b/examples/trixi_controller_baroclinic.f90 @@ -41,7 +41,7 @@ subroutine source_terms_baroclinic( nnodes, nodes, forest, ndofs, & call t8_forest_element_from_ref_coords(forest, itree, element, & local_coords, 1, global_coords) - ! The acutual computation of source terms + ! The actual computation of source terms ele = sqrt( global_coords(1)*global_coords(1) + & global_coords(2)*global_coords(2) + & global_coords(3)*global_coords(3) ) From a175a04ffb4af6e383b4359aa22c8ed2a46b0fc5 Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Mon, 18 Nov 2024 22:58:22 +0100 Subject: [PATCH 43/89] adapt min version according to main CMakeLists.txt --- examples/external/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/external/CMakeLists.txt b/examples/external/CMakeLists.txt index 874c8511..7a05ed71 100644 --- a/examples/external/CMakeLists.txt +++ b/examples/external/CMakeLists.txt @@ -1,5 +1,5 @@ # Specify the minimum version -cmake_minimum_required ( VERSION 3.9 ) +cmake_minimum_required ( VERSION 3.12 ) # Specify a project name project(ExternalLibTrixi) From d5fd61f04ba3da51d7ed0126f664616ad7989a04 Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Mon, 18 Nov 2024 23:00:56 +0100 Subject: [PATCH 44/89] missed while merging --- src/api.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/api.c b/src/api.c index b9fa7911..935e64a7 100644 --- a/src/api.c +++ b/src/api.c @@ -596,7 +596,6 @@ int trixi_nnodes(int handle) { // Call function return nnodes(handle); -<<<<<<< HEAD } From 0a359b16f9cd6cebf65a2813742d17b3627b8cd3 Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Tue, 19 Nov 2024 10:51:35 +0100 Subject: [PATCH 45/89] change default argument for DataBase parameter --- LibTrixi.jl/src/simulationstate.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LibTrixi.jl/src/simulationstate.jl b/LibTrixi.jl/src/simulationstate.jl index 213fd32f..1a283d94 100644 --- a/LibTrixi.jl/src/simulationstate.jl +++ b/LibTrixi.jl/src/simulationstate.jl @@ -13,7 +13,7 @@ mutable struct SimulationState{SemiType, IntegratorType} integrator::IntegratorType data::LibTrixiDataBaseType - function SimulationState(semi, integrator, data = nothing) + function SimulationState(semi, integrator, data = LibTrixiDataBaseType()) return new{typeof(semi), typeof(integrator)}(semi, integrator, data) end end From a8d2058b9506453d3996eed3cad7b63a868077c0 Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Tue, 19 Nov 2024 11:24:27 +0100 Subject: [PATCH 46/89] fix merge fails --- LibTrixi.jl/src/api_c.jl | 45 --------------------- LibTrixi.jl/src/api_jl.jl | 18 --------- LibTrixi.jl/test/test_interface.jl | 13 ------ src/api.c | 59 ---------------------------- src/api.f90 | 39 ------------------ test/c/simulation.cpp | 9 ----- test/fortran/simulationRun_suite.f90 | 10 ----- 7 files changed, 193 deletions(-) diff --git a/LibTrixi.jl/src/api_c.jl b/LibTrixi.jl/src/api_c.jl index 440083a0..3609ea24 100644 --- a/LibTrixi.jl/src/api_c.jl +++ b/LibTrixi.jl/src/api_c.jl @@ -357,51 +357,6 @@ end trixi_ndofselement_cfptr() = @cfunction(trixi_ndofselement, Cint, (Cint,)) -""" - trixi_ndofs(simstate_handle::Cint)::Cint - -Return number of degrees of freedom (all quadrature points on all cells of current rank). -""" -function trixi_ndofs end - -Base.@ccallable function trixi_ndofs(simstate_handle::Cint)::Cint - simstate = load_simstate(simstate_handle) - return trixi_ndofs_jl(simstate) -end - -trixi_ndofs_cfptr() = @cfunction(trixi_ndofs, Cint, (Cint,)) - - -""" - trixi_ndofs_global(simstate_handle::Cint)::Cint - -Return number of global eldegrees of freedom (all quadrature points on all cells). -""" -function trixi_ndofs_global end - -Base.@ccallable function trixi_ndofs_global(simstate_handle::Cint)::Cint - simstate = load_simstate(simstate_handle) - return trixi_ndofs_global_jl(simstate) -end - -trixi_ndofs_global_cfptr() = @cfunction(trixi_ndofs_global, Cint, (Cint,)) - - -""" - trixi_ndofs_element(simstate_handle::Cint)::Cint - -Return number of degrees of freedom per element (cell). -""" -function trixi_ndofs_element end - -Base.@ccallable function trixi_ndofs_element(simstate_handle::Cint)::Cint - simstate = load_simstate(simstate_handle) - return trixi_ndofs_element_jl(simstate) -end - -trixi_ndofs_element_cfptr() = @cfunction(trixi_ndofs_element, Cint, (Cint,)) - - """ trixi_nvariables(simstate_handle::Cint)::Cint diff --git a/LibTrixi.jl/src/api_jl.jl b/LibTrixi.jl/src/api_jl.jl index 2752a5c0..649420a5 100644 --- a/LibTrixi.jl/src/api_jl.jl +++ b/LibTrixi.jl/src/api_jl.jl @@ -110,24 +110,6 @@ function trixi_ndofselement_jl(simstate) end -function trixi_ndofs_jl(simstate) - mesh, _, solver, cache = mesh_equations_solver_cache(simstate.semi) - return ndofs(mesh, solver, cache) -end - - -function trixi_ndofs_global_jl(simstate) - mesh, _, solver, cache = mesh_equations_solver_cache(simstate.semi) - return ndofsglobal(mesh, solver, cache) -end - - -function trixi_ndofs_element_jl(simstate) - mesh, _, solver, _ = mesh_equations_solver_cache(simstate.semi) - return nnodes(solver)^ndims(mesh) -end - - function trixi_nvariables_jl(simstate) _, equations, _, _ = mesh_equations_solver_cache(simstate.semi) return nvariables(equations) diff --git a/LibTrixi.jl/test/test_interface.jl b/LibTrixi.jl/test/test_interface.jl index 48e51f40..4cfec875 100644 --- a/LibTrixi.jl/test/test_interface.jl +++ b/LibTrixi.jl/test/test_interface.jl @@ -94,19 +94,6 @@ end ndofselement_jl = trixi_ndofselement_jl(simstate_jl) @test ndofselement_c == ndofselement_jl - # compare number of dofs - ndofs_c = trixi_ndofs(handle) - ndofs_jl = trixi_ndofs_jl(simstate_jl) - @test ndofs_c == ndofs_jl - - ndofs_global_c = trixi_ndofs_global(handle) - ndofs_global_jl = trixi_ndofs_global_jl(simstate_jl) - @test ndofs_global_c == ndofs_global_jl - - ndofs_element_c = trixi_ndofs_element(handle) - ndofs_element_jl = trixi_ndofs_element_jl(simstate_jl) - @test ndofs_element_c == ndofs_element_jl - # compare number of variables nvariables_c = trixi_nvariables(handle) nvariables_jl = trixi_nvariables_jl(simstate_jl) diff --git a/src/api.c b/src/api.c index bcee4e3f..b6465c1a 100644 --- a/src/api.c +++ b/src/api.c @@ -561,65 +561,6 @@ int trixi_ndofselement(int handle) { } -/** - * @anchor trixi_ndofs_api_c - * - * @brief Return number of local degrees of freedom. - * - * These usually differ from the global count when doing parallel computations. - * - * @param[in] handle simulation handle - * - * @see trixi_ndofs_global_api_c - */ -int trixi_ndofs(int handle) { - - // Get function pointer - int (*ndofs)(int) = trixi_function_pointers[TRIXI_FPTR_NDOFS]; - - // Call function - return ndofs(handle); -} - - -/** - * @anchor trixi_ndofs_global_api_c - * - * @brief Return number of global degrees of freedom. - * - * These usually differ from the local count when doing parallel computations. - * - * @param[in] handle simulation handle - * - * @see trixi_ndofs_api_c - */ -int trixi_ndofs_global(int handle) { - - // Get function pointer - int (*ndofs_global)(int) = trixi_function_pointers[TRIXI_FPTR_NDOFS_GLOBAL]; - - // Call function - return ndofs_global(handle); -} - - -/** - * @anchor trixi_ndofs_element_api_c - * - * @brief Return number of degrees of freedom per element (cell). - * - * @param[in] handle simulation handle - */ -int trixi_ndofs_element(int handle) { - - // Get function pointer - int (*ndofs_element)(int) = trixi_function_pointers[TRIXI_FPTR_NDOFS_ELEMENT]; - - // Call function - return ndofs_element(handle); -} - - /** * @anchor trixi_nvariables_api_c * diff --git a/src/api.f90 b/src/api.f90 index dda84102..6526bd0c 100644 --- a/src/api.f90 +++ b/src/api.f90 @@ -310,45 +310,6 @@ integer(c_int) function trixi_ndofselement(handle) bind(c) integer(c_int), value, intent(in) :: handle end function - !> - !! @fn LibTrixi::trixi_ndofs::trixi_ndofs(handle) - !! - !! @brief Return number of local degrees of freedom - !! - !! @param[in] handle simulation handle - !! - !! @see @ref trixi_ndofs_api_c "trixi_ndofs (C API)" - integer(c_int) function trixi_ndofs(handle) bind(c) - use, intrinsic :: iso_c_binding, only: c_int - integer(c_int), value, intent(in) :: handle - end function - - !> - !! @fn LibTrixi::trixi_ndofs_global::trixi_ndofs_global(handle) - !! - !! @brief Return number of global degrees of freedom - !! - !! @param[in] handle simulation handle - !! - !! @see @ref trixi_ndofs_global_api_c "trixi_ndofs_global (C API)" - integer(c_int) function trixi_ndofs_global(handle) bind(c) - use, intrinsic :: iso_c_binding, only: c_int - integer(c_int), value, intent(in) :: handle - end function - - !> - !! @fn LibTrixi::trixi_ndofs_element::trixi_ndofs_element(handle) - !! - !! @brief Return number of degrees of freedom per element (cell). - !! - !! @param[in] handle simulation handle - !! - !! @see @ref trixi_ndofs_element_api_c "trixi_ndofs_element (C API)" - integer(c_int) function trixi_ndofs_element(handle) bind(c) - use, intrinsic :: iso_c_binding, only: c_int - integer(c_int), value, intent(in) :: handle - end function - !> !! @fn LibTrixi::trixi_nvariables::trixi_nvariables(handle) !! diff --git a/test/c/simulation.cpp b/test/c/simulation.cpp index 35de4053..ff732d1e 100644 --- a/test/c/simulation.cpp +++ b/test/c/simulation.cpp @@ -71,15 +71,6 @@ TEST(CInterfaceTest, SimulationRun) { EXPECT_EQ(nelements * ndofselement, ndofs); EXPECT_EQ(nelementsglobal * ndofselement, ndofsglobal); - // Check number of dofs - int ndofs = trixi_ndofs(handle); - int ndofs_global = trixi_ndofs_global(handle); - EXPECT_EQ(ndofs * nranks, ndofs_global); - - int ndofs_element = trixi_ndofs_element(handle); - EXPECT_EQ(nelements * ndofs_element, ndofs); - EXPECT_EQ(nelements_global * ndofs_element, ndofs_global); - // Check number of variables int nvariables = trixi_nvariables(handle); EXPECT_EQ(nvariables, 4); diff --git a/test/fortran/simulationRun_suite.f90 b/test/fortran/simulationRun_suite.f90 index 425e6a60..9dc5e57d 100644 --- a/test/fortran/simulationRun_suite.f90 +++ b/test/fortran/simulationRun_suite.f90 @@ -69,16 +69,6 @@ subroutine test_simulationRun(error) ndofsglobal = trixi_ndofsglobal(handle) call check(error, ndofsglobal, nelementsglobal * ndofselement) - ! Check number of dofs - ndofs_element = trixi_ndofs_element(handle) - call check(error, ndofs_element, 25) - - ndofs = trixi_ndofs(handle) - call check(error, ndofs, nelements * ndofs_element) - - ndofs_global = trixi_ndofs_global(handle) - call check(error, ndofs_global, nelements_global * ndofs_element) - ! Check number of variables nvariables = trixi_nvariables(handle) call check(error, nvariables, 4) From 7b654a451179049adfe2b7be6996c8bf59d4926b Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Tue, 19 Nov 2024 12:14:55 +0100 Subject: [PATCH 47/89] remove deprecated export --- LibTrixi.jl/src/LibTrixi.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LibTrixi.jl/src/LibTrixi.jl b/LibTrixi.jl/src/LibTrixi.jl index 070ddc0e..618a249d 100644 --- a/LibTrixi.jl/src/LibTrixi.jl +++ b/LibTrixi.jl/src/LibTrixi.jl @@ -3,7 +3,7 @@ module LibTrixi using OrdinaryDiffEq: OrdinaryDiffEq, step!, check_error, DiscreteCallback using Trixi: Trixi, summary_callback, mesh_equations_solver_cache, ndims, nelements, nelementsglobal, ndofs, ndofsglobal, nvariables, nnodes, wrap_array, - eachelement, cons2prim, get_node_vars, get_node_coords, eachnode + eachelement, cons2prim, get_node_vars, eachnode using MPI: MPI, run_init_hooks, set_default_error_handler_return using Pkg From 41ab02a167792848a6802328a4fa60cec664d4e4 Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Tue, 19 Nov 2024 12:15:22 +0100 Subject: [PATCH 48/89] test for get_time --- LibTrixi.jl/test/test_interface.jl | 5 +++++ test/c/simulation.cpp | 4 ++++ test/fortran/simulationRun_suite.f90 | 4 ++++ 3 files changed, 13 insertions(+) diff --git a/LibTrixi.jl/test/test_interface.jl b/LibTrixi.jl/test/test_interface.jl index 4cfec875..249370b9 100644 --- a/LibTrixi.jl/test/test_interface.jl +++ b/LibTrixi.jl/test/test_interface.jl @@ -59,6 +59,11 @@ end dt_jl = trixi_calculate_dt_jl(simstate_jl) @test dt_c == dt_jl + # compare time + time_c = trixi_get_time(handle) + time_jl = trixi_get_time_jl(simstate_jl) + @test time_c == time_jl + # compare finished status @test trixi_is_finished(handle) == 0 @test !trixi_is_finished_jl(simstate_jl) diff --git a/test/c/simulation.cpp b/test/c/simulation.cpp index ff732d1e..785b2e9d 100644 --- a/test/c/simulation.cpp +++ b/test/c/simulation.cpp @@ -48,6 +48,10 @@ TEST(CInterfaceTest, SimulationRun) { // Check time step length double dt = trixi_calculate_dt(handle); EXPECT_NEAR(dt, 0.0028566952356658794, 1e-17); + + // Check time + double time = trixi_get_time(handle); + EXPECT_NEAR(dt, 0.028566952356658794, 1e-17); // Check finished status int finished_status = trixi_is_finished(handle); diff --git a/test/fortran/simulationRun_suite.f90 b/test/fortran/simulationRun_suite.f90 index 9dc5e57d..e12a753c 100644 --- a/test/fortran/simulationRun_suite.f90 +++ b/test/fortran/simulationRun_suite.f90 @@ -43,6 +43,10 @@ subroutine test_simulationRun(error) ! Check time step length dt = trixi_calculate_dt(handle) call check(error, dt, 0.0032132984504400627_dp) + + ! Check time step length + time = trixi_get_time(handle) + call check(error, time, 0.0032132984504400627_dp) ! Check finished status finished_status = trixi_is_finished(handle) From 6bda6694221606db6a41fafbd24e5c3414bfa87f Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Tue, 19 Nov 2024 13:35:25 +0100 Subject: [PATCH 49/89] add tests for trixi_store_in_database --- .../libelixir_p4est2d_dgsem_euler_sedov.jl | 4 +++- LibTrixi.jl/test/test_interface.jl | 12 ++++++++++++ examples/CMakeLists.txt | 2 +- test/c/interface_c.cpp | 5 ----- test/c/simulation.cpp | 16 +++++++++++----- test/fortran/simulationRun_suite.f90 | 9 +++++++-- 6 files changed, 34 insertions(+), 14 deletions(-) diff --git a/LibTrixi.jl/examples/libelixir_p4est2d_dgsem_euler_sedov.jl b/LibTrixi.jl/examples/libelixir_p4est2d_dgsem_euler_sedov.jl index 11cc22cc..f067f539 100644 --- a/LibTrixi.jl/examples/libelixir_p4est2d_dgsem_euler_sedov.jl +++ b/LibTrixi.jl/examples/libelixir_p4est2d_dgsem_euler_sedov.jl @@ -106,7 +106,9 @@ function init_simstate() ############################################################################### # Create simulation state - simstate = SimulationState(semi, integrator) + # database only used for tests + database = LibTrixiDataBaseType(undef, 1) + simstate = SimulationState(semi, integrator, database) return simstate end diff --git a/LibTrixi.jl/test/test_interface.jl b/LibTrixi.jl/test/test_interface.jl index 249370b9..81508816 100644 --- a/LibTrixi.jl/test/test_interface.jl +++ b/LibTrixi.jl/test/test_interface.jl @@ -67,6 +67,18 @@ end # compare finished status @test trixi_is_finished(handle) == 0 @test !trixi_is_finished_jl(simstate_jl) + + # manually increase databases (for testing only!) + push!(simstate_jl.data, Vector{Float64}()) + push!(LibTrixi.simstates[handle].data, Vector{Float64}()) + # store a vector + test_data = [1.0, 2.0, 3.0] + trixi_store_in_database(handle, 1, 3, pointer(test_data)) + trixi_store_in_database_jl(simstate_jl, 1, test_data) + # check that references are the same + @test simstate_jl.data[1] == LibTrixi.simstates[handle].data[1] + # check for correct values + @test simstate_jl.data[1][] == LibTrixi.simstates[handle].data[1][] == test_data end diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 956bf901..361eb198 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -34,7 +34,7 @@ foreach ( EXAMPLE ${EXAMPLES} ) # set libraries to link target_link_libraries( ${TARGET_NAME} - PRIVATE MPI::MPI_${EXAMPLE_LANG} ${PROJECT_NAME} m + PRIVATE MPI::MPI_${EXAMPLE_LANG} ${PROJECT_NAME} ) if ( NOT USE_PACKAGE_COMPILER ) target_link_libraries( ${TARGET_NAME} PRIVATE ${PROJECT_NAME}_tls ) diff --git a/test/c/interface_c.cpp b/test/c/interface_c.cpp index a625e6c5..3382a19c 100644 --- a/test/c/interface_c.cpp +++ b/test/c/interface_c.cpp @@ -9,11 +9,6 @@ extern "C" { // Julia project path defined via cmake const char * julia_project_path = JULIA_PROJECT_PATH; -// Example libexlixir -const char * libelixir_path = - "../../../LibTrixi.jl/examples/libelixir_p4est2d_dgsem_euler_sedov.jl"; - - TEST(CInterfaceTest, JuliaProject) { // be evil diff --git a/test/c/simulation.cpp b/test/c/simulation.cpp index 785b2e9d..d78f9798 100644 --- a/test/c/simulation.cpp +++ b/test/c/simulation.cpp @@ -40,6 +40,12 @@ TEST(CInterfaceTest, SimulationRun) { EXPECT_DEATH(trixi_is_finished(42), "the provided handle was not found in the stored simulation states: 42"); + // Store a vector in database + std::vector test_data(3); + trixi_store_in_database(handle, 1, 3, test_data.data()); + EXPECT_DEATH(trixi_store_in_database(handle, 2, 3, test_data.data()), + "BoundsError"); + // Do 10 simulation steps for (int i = 0; i < 10; ++i) { trixi_step(handle); @@ -51,7 +57,7 @@ TEST(CInterfaceTest, SimulationRun) { // Check time double time = trixi_get_time(handle); - EXPECT_NEAR(dt, 0.028566952356658794, 1e-17); + EXPECT_NEAR(time, 0.0304927240859461, 1e-17); // Check finished status int finished_status = trixi_is_finished(handle); @@ -99,7 +105,7 @@ TEST(CInterfaceTest, SimulationRun) { std::vector energy(ndofs); trixi_load_primitive_vars(handle, 1, rho.data()); trixi_load_primitive_vars(handle, 4, energy.data()); - // check memory boarders + // check memory borders EXPECT_DOUBLE_EQ(rho[0], 1.0); EXPECT_DOUBLE_EQ(rho[ndofs-1], 1.0); EXPECT_DOUBLE_EQ(energy[0], 1.0e-5); @@ -115,7 +121,7 @@ TEST(CInterfaceTest, SimulationRun) { trixi_load_element_averaged_primitive_vars(handle, 3, v2_averages.data()); trixi_load_element_averaged_primitive_vars(handle, 4, e_averages.data()); if (nranks == 1) { - // check memory boarders (densities at the beginning, energies at the end) + // check memory borders (densities at the beginning, energies at the end) EXPECT_DOUBLE_EQ(rho_averages[0], 1.0); EXPECT_DOUBLE_EQ(e_averages[nelements-1], 1.0e-5); // check values somewhere near the center (expect symmetries) @@ -132,7 +138,7 @@ TEST(CInterfaceTest, SimulationRun) { } else if (nranks == 2) { if (rank == 0) { - // check memory boarders (densities at the beginning, energies at the end) + // check memory borders (densities at the beginning, energies at the end) EXPECT_DOUBLE_EQ(rho_averages[0], 1.0); EXPECT_DOUBLE_EQ(e_averages[nelements-1], 1.0e-5); // check values somewhere near the center (expect symmetries) @@ -144,7 +150,7 @@ TEST(CInterfaceTest, SimulationRun) { EXPECT_NEAR(v2_averages[94], -0.14037267400591, 1e-14); } else { - // check memory boarders (densities at the beginning, energies at the end) + // check memory borders (densities at the beginning, energies at the end) EXPECT_DOUBLE_EQ(rho_averages[0], 1.0); EXPECT_DOUBLE_EQ(e_averages[nelements-1], 1.0e-5); // check values somewhere near the center (expect symmetries) diff --git a/test/fortran/simulationRun_suite.f90 b/test/fortran/simulationRun_suite.f90 index e12a753c..7459a3a7 100644 --- a/test/fortran/simulationRun_suite.f90 +++ b/test/fortran/simulationRun_suite.f90 @@ -27,7 +27,7 @@ subroutine test_simulationRun(error) logical :: finished_status ! dp as defined in test-drive integer, parameter :: dp = selected_real_kind(15) - real(dp) :: dt, integral + real(dp) :: dt, time, integral real(dp), dimension(:), allocatable :: data, weights ! Initialize Trixi @@ -37,6 +37,11 @@ subroutine test_simulationRun(error) handle = trixi_initialize_simulation(libelixir_path) call check(error, handle, 1) + ! Store a vector in database + allocate(data(3)) + call trixi_store_in_database(handle, 1, 3, data) + deallocate(data) + ! Do a simulation step call trixi_step(handle) @@ -46,7 +51,7 @@ subroutine test_simulationRun(error) ! Check time step length time = trixi_get_time(handle) - call check(error, time, 0.0032132984504400627_dp) + call check(error, time, 0.0032382397675568731_dp) ! Check finished status finished_status = trixi_is_finished(handle) From a8c573ea83fc26831ab345c61045b07c6b2bbd72 Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Tue, 19 Nov 2024 13:48:22 +0100 Subject: [PATCH 50/89] need Int32 --- LibTrixi.jl/src/simulationstate.jl | 4 ++-- LibTrixi.jl/test/test_interface.jl | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/LibTrixi.jl/src/simulationstate.jl b/LibTrixi.jl/src/simulationstate.jl index 1a283d94..6c3965f6 100644 --- a/LibTrixi.jl/src/simulationstate.jl +++ b/LibTrixi.jl/src/simulationstate.jl @@ -1,3 +1,5 @@ +const LibTrixiDataBaseType = Vector{Ref{Vector{Float64}}} + """ SimulationState @@ -6,8 +8,6 @@ Data structure to store a simulation state consisting of - the time integrator - an optional array of data vectors """ -const LibTrixiDataBaseType = Vector{Ref{Vector{Float64}}} - mutable struct SimulationState{SemiType, IntegratorType} semi::SemiType integrator::IntegratorType diff --git a/LibTrixi.jl/test/test_interface.jl b/LibTrixi.jl/test/test_interface.jl index 81508816..b7bce17f 100644 --- a/LibTrixi.jl/test/test_interface.jl +++ b/LibTrixi.jl/test/test_interface.jl @@ -73,7 +73,7 @@ end push!(LibTrixi.simstates[handle].data, Vector{Float64}()) # store a vector test_data = [1.0, 2.0, 3.0] - trixi_store_in_database(handle, 1, 3, pointer(test_data)) + trixi_store_in_database(handle, Int32(1), Int32(3), pointer(test_data)) trixi_store_in_database_jl(simstate_jl, 1, test_data) # check that references are the same @test simstate_jl.data[1] == LibTrixi.simstates[handle].data[1] From 5a33b95590aef8a91b71d3542bec1e3fc9539432 Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Tue, 19 Nov 2024 14:04:43 +0100 Subject: [PATCH 51/89] cannot compare Refs --- LibTrixi.jl/test/test_interface.jl | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/LibTrixi.jl/test/test_interface.jl b/LibTrixi.jl/test/test_interface.jl index b7bce17f..3f898fdc 100644 --- a/LibTrixi.jl/test/test_interface.jl +++ b/LibTrixi.jl/test/test_interface.jl @@ -75,10 +75,8 @@ end test_data = [1.0, 2.0, 3.0] trixi_store_in_database(handle, Int32(1), Int32(3), pointer(test_data)) trixi_store_in_database_jl(simstate_jl, 1, test_data) - # check that references are the same - @test simstate_jl.data[1] == LibTrixi.simstates[handle].data[1] - # check for correct values - @test simstate_jl.data[1][] == LibTrixi.simstates[handle].data[1][] == test_data + # check that the same object is referenced + @test simstate_jl.data[1][] === LibTrixi.simstates[handle].data[1][] end From 378dc90a08152df1cdc2f19bb61ae0cbd09799be Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Tue, 19 Nov 2024 14:19:51 +0100 Subject: [PATCH 52/89] check based on address --- LibTrixi.jl/test/test_interface.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/LibTrixi.jl/test/test_interface.jl b/LibTrixi.jl/test/test_interface.jl index 3f898fdc..3b03efd1 100644 --- a/LibTrixi.jl/test/test_interface.jl +++ b/LibTrixi.jl/test/test_interface.jl @@ -75,8 +75,8 @@ end test_data = [1.0, 2.0, 3.0] trixi_store_in_database(handle, Int32(1), Int32(3), pointer(test_data)) trixi_store_in_database_jl(simstate_jl, 1, test_data) - # check that the same object is referenced - @test simstate_jl.data[1][] === LibTrixi.simstates[handle].data[1][] + # check that the same memory is referenced + @test pointer(simstate_jl.data[1][]) == pointer(LibTrixi.simstates[handle].data[1][]) end From 8c364558f0dd386e1e9a5e8c3110f7e54a8b22b8 Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Tue, 19 Nov 2024 15:00:04 +0100 Subject: [PATCH 53/89] relax error tolerance --- test/c/simulation.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/c/simulation.cpp b/test/c/simulation.cpp index d78f9798..2deb9bf9 100644 --- a/test/c/simulation.cpp +++ b/test/c/simulation.cpp @@ -57,7 +57,7 @@ TEST(CInterfaceTest, SimulationRun) { // Check time double time = trixi_get_time(handle); - EXPECT_NEAR(time, 0.0304927240859461, 1e-17); + EXPECT_NEAR(time, 0.0304927240859461, 1e-16); // Check finished status int finished_status = trixi_is_finished(handle); From f28d8025483fa153011a89aaa2266ac275f0572b Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Tue, 19 Nov 2024 15:05:44 +0100 Subject: [PATCH 54/89] remove deprecated example --- ...ixir_structured2d_source_terms_database.jl | 97 ------------------- 1 file changed, 97 deletions(-) delete mode 100644 LibTrixi.jl/examples/libelixir_structured2d_source_terms_database.jl diff --git a/LibTrixi.jl/examples/libelixir_structured2d_source_terms_database.jl b/LibTrixi.jl/examples/libelixir_structured2d_source_terms_database.jl deleted file mode 100644 index c43c1dc0..00000000 --- a/LibTrixi.jl/examples/libelixir_structured2d_source_terms_database.jl +++ /dev/null @@ -1,97 +0,0 @@ -using LibTrixi -using Trixi -using OrdinaryDiffEq - -# Callable struct holding vectors with source termshydrostatic base state -struct SourceTerm - nnodesdim::Int - nnodes::Int - database::Vector{Ref{Vector{Float64}}} -end - -@inline function (source::SourceTerm)(u, element, i, j, t, - equations::CompressibleEulerEquations2D) - @unpack nnodesdim, nnodes = source - index_global = (element-1) * nnodes + (j-1) * nnodesdim + i - # massive allocations occur when directly accessing source.database[1][][1] - du1::Vector{Float64} = source.database[1][] - du2::Vector{Float64} = source.database[2][] - du4::Vector{Float64} = source.database[3][] - return SVector(du1[index_global], du2[index_global], - du2[index_global], du4[index_global]) -end - -# The function to create the simulation state needs to be named `init_simstate` -function init_simstate() - - ############################################################################### - # semidiscretization of the compressible Euler equations - - equations = CompressibleEulerEquations2D(1.4) - - initial_condition = initial_condition_convergence_test - - solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) - nnodesdim = Trixi.nnodes(solver) - nnodes = nnodesdim^2 - - coordinates_min = (0.0, 0.0) - coordinates_max = (2.0, 2.0) - - cells_per_dimension = (16, 16) - - mesh = StructuredMesh(cells_per_dimension, coordinates_min, coordinates_max) - nelements = prod(size(mesh)) - - # create the database and three vectors for the source terms - database = LibTrixiDataBaseType(undef, 3) - database[1] = Ref(Vector{Float64}(undef, nelements*nnodes)) - database[2] = Ref(Vector{Float64}(undef, nelements*nnodes)) - database[3] = Ref(Vector{Float64}(undef, nelements*nnodes)) - - source_term_database = SourceTerm(nnodesdim, nnodes, database) - - semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms = source_term_database) - - ############################################################################### - # ODE solvers, callbacks etc. - - tspan = (0.0, 2.0) - ode = semidiscretize(semi, tspan) - - summary_callback = SummaryCallback() - - analysis_interval = 100 - analysis_callback = AnalysisCallback(semi, interval = analysis_interval) - - alive_callback = AliveCallback(analysis_interval = analysis_interval) - - save_solution = SaveSolutionCallback(interval = 100, - save_initial_solution = true, - save_final_solution = true, - solution_variables = cons2prim) - - stepsize_callback = StepsizeCallback(cfl = 1.0) - - callbacks = CallbackSet(summary_callback, - analysis_callback, alive_callback, - save_solution, - stepsize_callback) - - ############################################################################### - # create OrdinaryDiffEq's `integrator` - - integrator = init(ode, - CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # will be overwritten by the stepsize_callback - save_everystep=false, - callback=callbacks); - - ############################################################################### - # Create simulation state - - simstate = SimulationState(semi, integrator, database) - - return simstate -end From 492d1c491b5b7b82565258c64561f5910c4ce1a2 Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Wed, 20 Nov 2024 15:09:13 +0100 Subject: [PATCH 55/89] new cubed sphere examples --- ...ir_p4est3d_euler_baroclinic_instability.jl | 267 ------------------ ...r_t8code3d_euler_baroclinic_instability.jl | 38 +-- .../libelixir_t8code3d_euler_tracer.jl | 124 ++++++++ 3 files changed, 135 insertions(+), 294 deletions(-) delete mode 100644 LibTrixi.jl/examples/libelixir_p4est3d_euler_baroclinic_instability.jl create mode 100644 LibTrixi.jl/examples/libelixir_t8code3d_euler_tracer.jl diff --git a/LibTrixi.jl/examples/libelixir_p4est3d_euler_baroclinic_instability.jl b/LibTrixi.jl/examples/libelixir_p4est3d_euler_baroclinic_instability.jl deleted file mode 100644 index 58e057c2..00000000 --- a/LibTrixi.jl/examples/libelixir_p4est3d_euler_baroclinic_instability.jl +++ /dev/null @@ -1,267 +0,0 @@ -# An idealized baroclinic instability test case -# -# Note that this libelixir is based on the original baroclinic instability elixir by -# Erik Faulhaber for Trixi.jl -# Source: https://github.com/trixi-framework/Trixi.jl/blob/main/examples/p4est_3d_dgsem/elixir_euler_baroclinic_instability.jl -# -# References: -# - Paul A. Ullrich, Thomas Melvin, Christiane Jablonowski, Andrew Staniforth (2013) -# A proposed baroclinic wave test case for deep- and shallow-atmosphere dynamical cores -# https://doi.org/10.1002/qj.2241 - -using OrdinaryDiffEq -using Trixi -using LinearAlgebra -using LibTrixi - - -# Initial condition for an idealized baroclinic instability test -# https://doi.org/10.1002/qj.2241, Section 3.2 and Appendix A -function initial_condition_baroclinic_instability(x, t, - equations::CompressibleEulerEquations3D) - lon, lat, r = cartesian_to_sphere(x) - radius_earth = 6.371229e6 - # Make sure that the r is not smaller than radius_earth - z = max(r - radius_earth, 0.0) - - # Unperturbed basic state - rho, u, p = basic_state_baroclinic_instability_longitudinal_velocity(lon, lat, z) - - # Stream function type perturbation - u_perturbation, v_perturbation = perturbation_stream_function(lon, lat, z) - - u += u_perturbation - v = v_perturbation - - # Convert spherical velocity to Cartesian - v1 = -sin(lon) * u - sin(lat) * cos(lon) * v - v2 = cos(lon) * u - sin(lat) * sin(lon) * v - v3 = cos(lat) * v - - return prim2cons(SVector(rho, v1, v2, v3, p), equations) -end - -function cartesian_to_sphere(x) - r = norm(x) - lambda = atan(x[2], x[1]) - if lambda < 0 - lambda += 2 * pi - end - phi = asin(x[3] / r) - - return lambda, phi, r -end - -# Unperturbed balanced steady-state. -# Returns primitive variables with only the velocity in longitudinal direction (rho, u, p). -# The other velocity components are zero. -function basic_state_baroclinic_instability_longitudinal_velocity(lon, lat, z) - # Parameters from Table 1 in the paper - # Corresponding names in the paper are commented - radius_earth = 6.371229e6 # a - half_width_parameter = 2 # b - gravitational_acceleration = 9.80616 # g - k = 3 # k - surface_pressure = 1e5 # p₀ - gas_constant = 287 # R - surface_equatorial_temperature = 310.0 # T₀ᴱ - surface_polar_temperature = 240.0 # T₀ᴾ - lapse_rate = 0.005 # Γ - angular_velocity = 7.29212e-5 # Ω - - # Distance to the center of the Earth - r = z + radius_earth - - # In the paper: T₀ - temperature0 = 0.5 * (surface_equatorial_temperature + surface_polar_temperature) - # In the paper: A, B, C, H - const_a = 1 / lapse_rate - const_b = (temperature0 - surface_polar_temperature) / - (temperature0 * surface_polar_temperature) - const_c = 0.5 * (k + 2) * (surface_equatorial_temperature - surface_polar_temperature) / - (surface_equatorial_temperature * surface_polar_temperature) - const_h = gas_constant * temperature0 / gravitational_acceleration - - # In the paper: (r - a) / bH - scaled_z = z / (half_width_parameter * const_h) - - # Temporary variables - temp1 = exp(lapse_rate / temperature0 * z) - temp2 = exp(-scaled_z^2) - - # In the paper: ̃τ₁, ̃τ₂ - tau1 = const_a * lapse_rate / temperature0 * temp1 + - const_b * (1 - 2 * scaled_z^2) * temp2 - tau2 = const_c * (1 - 2 * scaled_z^2) * temp2 - - # In the paper: ∫τ₁(r') dr', ∫τ₂(r') dr' - inttau1 = const_a * (temp1 - 1) + const_b * z * temp2 - inttau2 = const_c * z * temp2 - - # Temporary variables - temp3 = r / radius_earth * cos(lat) - temp4 = temp3^k - k / (k + 2) * temp3^(k + 2) - - # In the paper: T - temperature = 1 / ((r / radius_earth)^2 * (tau1 - tau2 * temp4)) - - # In the paper: U, u (zonal wind, first component of spherical velocity) - big_u = gravitational_acceleration / radius_earth * k * temperature * inttau2 * - (temp3^(k - 1) - temp3^(k + 1)) - temp5 = radius_earth * cos(lat) - u = -angular_velocity * temp5 + sqrt(angular_velocity^2 * temp5^2 + temp5 * big_u) - - # Hydrostatic pressure - p = surface_pressure * - exp(-gravitational_acceleration / gas_constant * (inttau1 - inttau2 * temp4)) - - # Density (via ideal gas law) - rho = p / (gas_constant * temperature) - - return rho, u, p -end - -# Perturbation as in Equations 25 and 26 of the paper (analytical derivative) -function perturbation_stream_function(lon, lat, z) - # Parameters from Table 1 in the paper - # Corresponding names in the paper are commented - perturbation_radius = 1 / 6 # d₀ / a - perturbed_wind_amplitude = 1.0 # Vₚ - perturbation_lon = pi / 9 # Longitude of perturbation location - perturbation_lat = 2 * pi / 9 # Latitude of perturbation location - pertz = 15000 # Perturbation height cap - - # Great circle distance (d in the paper) divided by a (radius of the Earth) - # because we never actually need d without dividing by a - great_circle_distance_by_a = acos(sin(perturbation_lat) * sin(lat) + - cos(perturbation_lat) * cos(lat) * - cos(lon - perturbation_lon)) - - # In the first case, the vertical taper function is per definition zero. - # In the second case, the stream function is per definition zero. - if z > pertz || great_circle_distance_by_a > perturbation_radius - return 0.0, 0.0 - end - - # Vertical tapering of stream function - perttaper = 1.0 - 3 * z^2 / pertz^2 + 2 * z^3 / pertz^3 - - # sin/cos(pi * d / (2 * d_0)) in the paper - sin_, cos_ = sincos(0.5 * pi * great_circle_distance_by_a / perturbation_radius) - - # Common factor for both u and v - factor = 16 / (3 * sqrt(3)) * perturbed_wind_amplitude * perttaper * cos_^3 * sin_ - - u_perturbation = -factor * (-sin(perturbation_lat) * cos(lat) + - cos(perturbation_lat) * sin(lat) * cos(lon - perturbation_lon)) / - sin(great_circle_distance_by_a) - - v_perturbation = factor * cos(perturbation_lat) * sin(lon - perturbation_lon) / - sin(great_circle_distance_by_a) - - return u_perturbation, v_perturbation -end - -@inline function source_terms_baroclinic_instability(u, x, t, - equations::CompressibleEulerEquations3D) - radius_earth = 6.371229e6 # a - gravitational_acceleration = 9.80616 # g - angular_velocity = 7.29212e-5 # Ω - - r = norm(x) - # Make sure that r is not smaller than radius_earth - z = max(r - radius_earth, 0.0) - r = z + radius_earth - - du1 = zero(eltype(u)) - - # Gravity term - temp = -gravitational_acceleration * radius_earth^2 / r^3 - du2 = temp * u[1] * x[1] - du3 = temp * u[1] * x[2] - du4 = temp * u[1] * x[3] - du5 = temp * (u[2] * x[1] + u[3] * x[2] + u[4] * x[3]) - - # Coriolis term, -2Ω × ρv = -2 * angular_velocity * (0, 0, 1) × u[2:4] - du2 -= -2 * angular_velocity * u[3] - du3 -= 2 * angular_velocity * u[2] - - return SVector(du1, du2, du3, du4, du5) -end - - -# The function to create the simulation state needs to be named `init_simstate` -function init_simstate() - - ############################################################################### - # Setup for the baroclinic instability test - gamma = 1.4 - equations = CompressibleEulerEquations3D(gamma) - - ############################################################################### - # semidiscretization of the problem - - initial_condition = initial_condition_baroclinic_instability - - boundary_conditions = Dict(:inside => boundary_condition_slip_wall, - :outside => boundary_condition_slip_wall) - - # This is a good estimate for the speed of sound in this example. - # Other values between 300 and 400 should work as well. - surface_flux = FluxLMARS(340) - volume_flux = flux_kennedy_gruber - solver = DGSEM(polydeg = 5, surface_flux = surface_flux, - volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) - - trees_per_cube_face = (16, 8) - mesh = Trixi.P4estMeshCubedSphere(trees_per_cube_face..., 6.371229e6, 30000.0, - polydeg = 5, initial_refinement_level = 0) - - semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms = source_terms_baroclinic_instability, - boundary_conditions = boundary_conditions) - - ############################################################################### - # ODE solvers, callbacks etc. - - tspan = (0.0, 12 * 24 * 60 * 60.0) # time in seconds for 12 days# - - ode = semidiscretize(semi, tspan) - - summary_callback = SummaryCallback() - - analysis_interval = 5000 - analysis_callback = AnalysisCallback(semi, interval = analysis_interval) - - alive_callback = AliveCallback(analysis_interval = analysis_interval) - - save_solution = SaveSolutionCallback(interval = 5000, - save_initial_solution = true, - save_final_solution = true, - solution_variables = cons2prim, - output_directory = "out_baroclinic",) - - callbacks = CallbackSet(summary_callback, - analysis_callback, - alive_callback, - save_solution) - - - ############################################################################### - # create the time integrator - - # OrdinaryDiffEq's `integrator` - # Use a Runge-Kutta method with automatic (error based) time step size control - integrator = init(ode, RDPK3SpFSAL49(); - abstol = 1.0e-6, reltol = 1.0e-6, - ode_default_options()..., - callback = callbacks, - maxiters=5e5); - - ############################################################################### - # Create simulation state - - simstate = SimulationState(semi, integrator) - - return simstate -end diff --git a/LibTrixi.jl/examples/libelixir_t8code3d_euler_baroclinic_instability.jl b/LibTrixi.jl/examples/libelixir_t8code3d_euler_baroclinic_instability.jl index 8f665422..7c358a3c 100644 --- a/LibTrixi.jl/examples/libelixir_t8code3d_euler_baroclinic_instability.jl +++ b/LibTrixi.jl/examples/libelixir_t8code3d_euler_baroclinic_instability.jl @@ -9,9 +9,6 @@ # A proposed baroclinic wave test case for deep- and shallow-atmosphere dynamical cores # https://doi.org/10.1002/qj.2241 -# CAVE: only for development -# in particular this libelixir uses a way too small fixed time step - using OrdinaryDiffEq using Trixi using LinearAlgebra @@ -234,26 +231,23 @@ end # The function to create the simulation state needs to be named `init_simstate` function init_simstate() - ############################################################################### - # Setup for the baroclinic instability test + # compressible euler equations gamma = 1.4 equations = CompressibleEulerEquations3D(gamma) - ############################################################################### - # semidiscretization of the problem - + # setup of the problem initial_condition = initial_condition_baroclinic_instability boundary_conditions = Dict(:inside => boundary_condition_slip_wall, :outside => boundary_condition_slip_wall) - # This is a good estimate for the speed of sound in this example. - # Other values between 300 and 400 should work as well. + # estimate for the speed of sound surface_flux = FluxLMARS(340) volume_flux = flux_kennedy_gruber solver = DGSEM(polydeg = 3, surface_flux = surface_flux, volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) + # for nice results, use 4 and 8 here lat_lon_levels = 3 layers = 4 mesh = Trixi.T8codeMeshCubedSphere(lat_lon_levels, layers, 6.371229e6, 30000.0, @@ -277,10 +271,9 @@ function init_simstate() source_terms = source_term_database, boundary_conditions = boundary_conditions) - ############################################################################### - # ODE solvers, callbacks etc. - - tspan = (0.0, 10.0) + # for nice results use 10 day + days = 0.1 + tspan = (0.0, days * 24 * 60 * 60.0) ode = semidiscretize(semi, tspan) @@ -302,21 +295,12 @@ function init_simstate() alive_callback, save_solution) - - ############################################################################### - # create the time integrator - - # OrdinaryDiffEq's `integrator` - # Use a Runge-Kutta method with automatic (error based) time step size control - integrator = init(ode, CarpenterKennedy2N54(williamson_condition=false); - dt = 0.1, + # use a Runge-Kutta method with automatic (error based) time step size control + integrator = init(ode, RDPK3SpFSAL49(thread = OrdinaryDiffEq.False()); abstol = 1.0e-6, reltol = 1.0e-6, - ode_default_options()..., - callback = callbacks, - maxiters=5e5); + ode_default_options()..., callback = callbacks, maxiters=1e7); - ############################################################################### - # Create simulation state + # create simulation state simstate = SimulationState(semi, integrator, database) return simstate diff --git a/LibTrixi.jl/examples/libelixir_t8code3d_euler_tracer.jl b/LibTrixi.jl/examples/libelixir_t8code3d_euler_tracer.jl new file mode 100644 index 00000000..1c7df858 --- /dev/null +++ b/LibTrixi.jl/examples/libelixir_t8code3d_euler_tracer.jl @@ -0,0 +1,124 @@ +# A manufactured solution of a circular wind with constant angular velocity +# on a planetary-sized cubed sphere mesh with a blob detected by AMR +# +# Note that this libelixir is based on an elixir by Erik Faulhaber for Trixi.jl +# Source: https://github.com/trixi-framework/Trixi.jl/blob/main/examples/p4est_3d_dgsem/elixir_euler_circular_wind_nonconforming.jl + +using OrdinaryDiffEq +using Trixi +using LinearAlgebra +using LibTrixi + + +function initial_condition_circular_wind(x, t, equations::CompressibleEulerEquations3D) + radius_earth = 6.371229e6 + lambda, phi, r = cart_to_sphere(x) + + p = 1e5 + v1 = -10 * x[2] / radius_earth + v2 = 10 * x[1] / radius_earth + v3 = 0.0 + rho = 1.0 + 0.1 * exp(-50 * ((lambda-1.0)^2/2.0 + (phi-0.4)^2)) + + 0.08 * exp(-100 * ((lambda-0.8)^2/4.0 + (phi-0.5)^2)) + + return prim2cons(SVector(rho, v1, v2, v3, p), equations) +end + +@inline function source_terms_circular_wind(u, x, t, + equations::CompressibleEulerEquations3D) + radius_earth = 6.371229e6 + rho = u[1] + + du1 = 0.0 + du2 = -rho * (10 / radius_earth) * (10 * x[1] / radius_earth) + du3 = -rho * (10 / radius_earth) * (10 * x[2] / radius_earth) + du4 = 0.0 + du5 = 0.0 + + return SVector(du1, du2, du3, du4, du5) +end + +function cart_to_sphere(x) + r = norm(x) + lambda = atan(x[2], x[1]) + if lambda < 0 + lambda += 2 * pi + end + phi = asin(x[3] / r) + + return lambda, phi, r +end + + +# The function to create the simulation state needs to be named `init_simstate` +function init_simstate() + + # compressible Euler equations + gamma = 1.4 + equations = CompressibleEulerEquations3D(gamma) + + # setup of the problem + initial_condition = initial_condition_circular_wind + + boundary_conditions = Dict(:inside => boundary_condition_slip_wall, + :outside => boundary_condition_slip_wall) + + # estimate for speed of sound + surface_flux = FluxLMARS(374) + solver = DGSEM(polydeg = 3, surface_flux = surface_flux) + + # increase trees_per_cube_face or initial_refinement_level to get nicer results + lat_lon_levels = 2 + layers = 1 + mesh = Trixi.T8codeMeshCubedSphere(lat_lon_levels, layers, 6.371229e6, 30000.0, + polydeg = 3, initial_refinement_level = 0) + + semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, + source_terms = source_terms_circular_wind, + boundary_conditions = boundary_conditions) + + # increase number of days + days = 0.1 + tspan = (0.0, days * 24 * 60 * 60.0) + + ode = semidiscretize(semi, tspan) + + summary_callback = SummaryCallback() + + analysis_interval = 5000 + analysis_callback = AnalysisCallback(semi, interval = analysis_interval) + + alive_callback = AliveCallback(analysis_interval = analysis_interval) + + save_solution = SaveSolutionCallback(interval = 2000, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim, + output_directory = "out_tracer") + + amr_controller = ControllerThreeLevel(semi, IndicatorMax(semi, variable = first), + base_level = 0, + med_level = 1, med_threshold = 1.004, + max_level = 3, max_threshold = 1.11) + + amr_callback = AMRCallback(semi, amr_controller, + interval = 2000, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) + + callbacks = CallbackSet(summary_callback, + analysis_callback, + alive_callback, + amr_callback, + save_solution) + + # use a Runge-Kutta method with automatic (error based) time step size control + integrator = init(ode, RDPK3SpFSAL49(thread = OrdinaryDiffEq.False()); + abstol = 1.0e-6, reltol = 1.0e-6, + ode_default_options()..., callback = callbacks, maxiters=1e7); + + # create simulation state + simstate = SimulationState(semi, integrator) + + return simstate +end From 272a0a21f1566071e25d0585bf51157818591d21 Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Wed, 20 Nov 2024 15:10:16 +0100 Subject: [PATCH 56/89] remove deprecated libelixir --- .../examples/libelixir_tree2d_warm_bubble.jl | 178 ------------------ 1 file changed, 178 deletions(-) delete mode 100644 LibTrixi.jl/examples/libelixir_tree2d_warm_bubble.jl diff --git a/LibTrixi.jl/examples/libelixir_tree2d_warm_bubble.jl b/LibTrixi.jl/examples/libelixir_tree2d_warm_bubble.jl deleted file mode 100644 index 226affc2..00000000 --- a/LibTrixi.jl/examples/libelixir_tree2d_warm_bubble.jl +++ /dev/null @@ -1,178 +0,0 @@ -using LibTrixi -using OrdinaryDiffEq -using Trixi - -# Warm bubble test case from -# - Wicker, L. J., and Skamarock, W. C. (1998) -# A time-splitting scheme for the elastic equations incorporating -# second-order Runge–Kutta time differencing -# [DOI: 10.1175/1520-0493(1998)126%3C1992:ATSSFT%3E2.0.CO;2](https://doi.org/10.1175/1520-0493(1998)126%3C1992:ATSSFT%3E2.0.CO;2) -# See also -# - Bryan and Fritsch (2002) -# A Benchmark Simulation for Moist Nonhydrostatic Numerical Models -# [DOI: 10.1175/1520-0493(2002)130<2917:ABSFMN>2.0.CO;2](https://doi.org/10.1175/1520-0493(2002)130<2917:ABSFMN>2.0.CO;2) -# - Carpenter, Droegemeier, Woodward, Hane (1990) -# Application of the Piecewise Parabolic Method (PPM) to -# Meteorological Modeling -# [DOI: 10.1175/1520-0493(1990)118<0586:AOTPPM>2.0.CO;2](https://doi.org/10.1175/1520-0493(1990)118<0586:AOTPPM>2.0.CO;2) -struct WarmBubbleSetup - # Physical constants - g::Float64 # gravity of earth - c_p::Float64 # heat capacity for constant pressure (dry air) - c_v::Float64 # heat capacity for constant volume (dry air) - gamma::Float64 # heat capacity ratio (dry air) - - function WarmBubbleSetup(; g = 9.81, c_p = 1004.0, c_v = 717.0, gamma = c_p / c_v) - new(g, c_p, c_v, gamma) - end -end - -# Initial condition -function (setup::WarmBubbleSetup)(x, t, equations::CompressibleEulerEquations2D) - @unpack g, c_p, c_v = setup - - # center of perturbation - center_x = 10000.0 - center_z = 2000.0 - # radius of perturbation - radius = 2000.0 - # distance of current x to center of perturbation - r = sqrt((x[1] - center_x)^2 + (x[2] - center_z)^2) - - # perturbation in potential temperature - potential_temperature_ref = 300.0 - potential_temperature_perturbation = 0.0 - if r <= radius - potential_temperature_perturbation = 2 * cospi(0.5 * r / radius)^2 - end - potential_temperature = potential_temperature_ref + potential_temperature_perturbation - - # Exner pressure, solves hydrostatic equation for x[2] - exner = 1 - g / (c_p * potential_temperature) * x[2] - - # pressure - p_0 = 100_000.0 # reference pressure - R = c_p - c_v # gas constant (dry air) - p = p_0 * exner^(c_p / R) - - # temperature - T = potential_temperature * exner - - # density - rho = p / (R * T) - - v1 = 20.0 - v2 = 0.0 - E = c_v * T + 0.5 * (v1^2 + v2^2) - return SVector(rho, rho * v1, rho * v2, rho * E) -end - -# Source terms -@inline function (setup::WarmBubbleSetup)(u, x, t, equations::CompressibleEulerEquations2D) - @unpack g = setup - rho, _, rho_v2, _ = u - return SVector(zero(eltype(u)), zero(eltype(u)), -g * rho, -g * rho_v2) -end - - -# The function to create the simulation state needs to be named `init_simstate` -function init_simstate() - - ############################################################################### - # semidiscretization of the compressible Euler equations - warm_bubble_setup = WarmBubbleSetup() - - equations = CompressibleEulerEquations2D(warm_bubble_setup.gamma) - - boundary_conditions = (x_neg = boundary_condition_periodic, - x_pos = boundary_condition_periodic, - y_neg = boundary_condition_slip_wall, - y_pos = boundary_condition_slip_wall) - - polydeg = 3 - basis = LobattoLegendreBasis(polydeg) - - # This is a good estimate for the speed of sound in this example. - # Other values between 300 and 400 should work as well. - surface_flux = FluxLMARS(340.0) - - volume_flux = flux_kennedy_gruber - volume_integral = VolumeIntegralFluxDifferencing(volume_flux) - - solver = DGSEM(basis, surface_flux, volume_integral) - - coordinates_min = (0.0, 0.0) - coordinates_max = (20_000.0, 10_000.0) - - # Same coordinates as in examples/structured_2d_dgsem/elixir_euler_warm_bubble.jl - # However TreeMesh will generate a 20_000 x 20_000 square domain instead - mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level = 6, - n_cells_max = 100_000, - periodicity = (true, false)) - - semi = SemidiscretizationHyperbolic(mesh, equations, warm_bubble_setup, solver, - source_terms = warm_bubble_setup, - boundary_conditions = boundary_conditions) - - ############################################################################### - # ODE solvers, callbacks etc. - - tspan = (0.0, 1000.0) # 1000 seconds final time - - ode = semidiscretize(semi, tspan) - - summary_callback = SummaryCallback() - - analysis_interval = 1000 - - analysis_callback = AnalysisCallback(semi, interval = analysis_interval, - extra_analysis_errors = (:entropy_conservation_error,)) - - alive_callback = AliveCallback(analysis_interval = analysis_interval) - - save_solution = SaveSolutionCallback(interval = analysis_interval, - save_initial_solution = true, - save_final_solution = true, - output_directory = "out_bubble", - solution_variables = cons2prim) - - @inline function Tpot(u, equations::CompressibleEulerEquations2D) - rho, _, _, p = cons2prim(u, equations) - exner = (p / 100_000)^(1-inv(warm_bubble_setup.gamma)) - T = p / rho / (warm_bubble_setup.c_p - warm_bubble_setup.c_v) - return T / exner - end - amr_indicator = IndicatorLöhner(semi, variable = Tpot) - amr_controller = ControllerThreeLevel(semi, amr_indicator, - base_level = 4, - med_level = 6, med_threshold = 0.0002, - max_level = 8, max_threshold = 0.0005) - amr_callback = AMRCallback(semi, amr_controller, - interval = 50, - adapt_initial_condition = true, - adapt_initial_condition_only_refine = true) - - stepsize_callback = StepsizeCallback(cfl = 1.0) - - callbacks = CallbackSet(summary_callback, - analysis_callback, - alive_callback, - save_solution, - amr_callback, - stepsize_callback) - - ############################################################################### - # create OrdinaryDiffEq's time integrator - integrator = init(ode, - CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, - callback=callbacks); - - ############################################################################### - # Create simulation state - simstate = SimulationState(semi, integrator) - - return simstate -end From 9e36f4ee6dda4a6e9256d2849151a208db0d6f07 Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Wed, 20 Nov 2024 15:17:05 +0100 Subject: [PATCH 57/89] unify naming of libelixirs --- .github/workflows/ci.yml | 29 ++++++++++--------- LibTrixi.jl/README.md | 4 +-- ...ov.jl => libelixir_p4est2d_euler_sedov.jl} | 0 ...jl => libelixir_t8code2d_advection_amr.jl} | 0 ...jl => libelixir_tree1d_advection_basic.jl} | 0 LibTrixi.jl/test/test_interface.jl | 2 +- LibTrixi.jl/test/test_t8code.jl | 2 +- README.md | 6 ++-- test/c/simulation.cpp | 2 +- test/c/t8code.cpp | 2 +- test/fortran/simulationRun_suite.f90 | 2 +- test/fortran/t8code_suite.f90 | 2 +- 12 files changed, 27 insertions(+), 24 deletions(-) rename LibTrixi.jl/examples/{libelixir_p4est2d_dgsem_euler_sedov.jl => libelixir_p4est2d_euler_sedov.jl} (100%) rename LibTrixi.jl/examples/{libelixir_t8code_2d_dgsem_advection_amr.jl => libelixir_t8code2d_advection_amr.jl} (100%) rename LibTrixi.jl/examples/{libelixir_tree1d_dgsem_advection_basic.jl => libelixir_tree1d_advection_basic.jl} (100%) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c259b60e..e88bc704 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -164,9 +164,7 @@ jobs: --t8code-library ../t8code-local/prefix/lib/libt8.so \ --julia-depot ~/.julia \ --force - cp ../install/share/libtrixi/LibTrixi.jl/examples/libelixir_tree1d_dgsem_advection_basic.jl . - cp ../install/share/libtrixi/LibTrixi.jl/examples/libelixir_p4est2d_dgsem_euler_sedov.jl . - cp ../install/share/libtrixi/LibTrixi.jl/examples/libelixir_t8code_2d_dgsem_advection_amr.jl . + cp ../install/share/libtrixi/LibTrixi.jl/examples/libelixir_* . - name: Initialize project directory (test_type == 'package-compiler') if: ${{ matrix.test_type == 'package-compiler' }} @@ -209,7 +207,7 @@ jobs: ./build.sh mpirun -n 2 ./build/trixi_controller_simple_c \ ../../libtrixi-julia \ - ../../LibTrixi.jl/examples/libelixir_p4est2d_dgsem_euler_sedov.jl + ../../LibTrixi.jl/examples/libelixir_p4est2d_euler_sedov.jl env: LIBTRIXI_DEBUG: all @@ -234,14 +232,19 @@ jobs: if: ${{ matrix.test_type == 'regular' || matrix.test_type == 'coverage' }} run: | cd libtrixi-julia - ../build/examples/trixi_controller_simple_c . libelixir_tree1d_dgsem_advection_basic.jl - ../build/examples/trixi_controller_simple_f . libelixir_tree1d_dgsem_advection_basic.jl - ../build/examples/trixi_controller_simple_c . libelixir_p4est2d_dgsem_euler_sedov.jl - ../build/examples/trixi_controller_simple_f . libelixir_p4est2d_dgsem_euler_sedov.jl - ../build/examples/trixi_controller_data_c . libelixir_t8code_2d_dgsem_advection_amr.jl - ../build/examples/trixi_controller_data_f . libelixir_t8code_2d_dgsem_advection_amr.jl - ../build/examples/trixi_controller_t8code_c . libelixir_t8code_2d_dgsem_advection_amr.jl - ../build/examples/trixi_controller_t8code_f . libelixir_t8code_2d_dgsem_advection_amr.jl + # all controllers + ../build/examples/trixi_controller_simple_c . libelixir_tree1d_advection_basic.jl + ../build/examples/trixi_controller_simple_f . libelixir_tree1d_advection_basic.jl + ../build/examples/trixi_controller_data_c . libelixir_t8code2d_advection_amr.jl + ../build/examples/trixi_controller_data_f . libelixir_t8code2d_advection_amr.jl + ../build/examples/trixi_controller_t8code_c . libelixir_t8code2d_advection_amr.jl + ../build/examples/trixi_controller_t8code_f . libelixir_t8code2d_advection_amr.jl + ../build/examples/trixi_controller_baroclinic_c . libelixir_t8code3d_euler_baroclinic_instability.jl + ../build/examples/trixi_controller_baroclinic_f . libelixir_t8code3d_euler_baroclinic_instability.jl + mpirun -n 2 ../build/examples/trixi_controller_mpi_c . libelixir_p4est2d_euler_sedov.jl + mpirun -n 2 ../build/examples/trixi_controller_mpi_f . libelixir_p4est2d_euler_sedov.jl + # remaining libelixirs + ../build/examples/trixi_controller_simple_c . libelixir_t8code3d_euler_tracer.jl env: LIBTRIXI_DEBUG: all @@ -251,7 +254,7 @@ jobs: cd build/examples mpirun -n 2 trixi_controller_simple_c \ ../../libtrixi-julia \ - ../../LibTrixi.jl/examples/libelixir_p4est2d_dgsem_euler_sedov.jl + ../../LibTrixi.jl/examples/libelixir_p4est2d_euler_sedov.jl env: LIBTRIXI_DEBUG: all diff --git a/LibTrixi.jl/README.md b/LibTrixi.jl/README.md index 0f631f9e..ee2ace1b 100644 --- a/LibTrixi.jl/README.md +++ b/LibTrixi.jl/README.md @@ -18,8 +18,8 @@ run, and finalize a simulation by running the following code: ```julia julia> using LibTrixi -julia> libelixir = pkgdir(LibTrixi, "examples", "libelixir_tree1d_dgsem_advection_basic.jl") -"/path/to/libtrixi/LibTrixi.jl/examples/libelixir_tree1d_dgsem_advection_basic.jl" +julia> libelixir = pkgdir(LibTrixi, "examples", "libelixir_tree1d_advection_basic.jl") +"/path/to/libtrixi/LibTrixi.jl/examples/libelixir_tree1d_advection_basic.jl" julia> handle = trixi_initialize_simulation(libelixir); # initialize a new simulation setup diff --git a/LibTrixi.jl/examples/libelixir_p4est2d_dgsem_euler_sedov.jl b/LibTrixi.jl/examples/libelixir_p4est2d_euler_sedov.jl similarity index 100% rename from LibTrixi.jl/examples/libelixir_p4est2d_dgsem_euler_sedov.jl rename to LibTrixi.jl/examples/libelixir_p4est2d_euler_sedov.jl diff --git a/LibTrixi.jl/examples/libelixir_t8code_2d_dgsem_advection_amr.jl b/LibTrixi.jl/examples/libelixir_t8code2d_advection_amr.jl similarity index 100% rename from LibTrixi.jl/examples/libelixir_t8code_2d_dgsem_advection_amr.jl rename to LibTrixi.jl/examples/libelixir_t8code2d_advection_amr.jl diff --git a/LibTrixi.jl/examples/libelixir_tree1d_dgsem_advection_basic.jl b/LibTrixi.jl/examples/libelixir_tree1d_advection_basic.jl similarity index 100% rename from LibTrixi.jl/examples/libelixir_tree1d_dgsem_advection_basic.jl rename to LibTrixi.jl/examples/libelixir_tree1d_advection_basic.jl diff --git a/LibTrixi.jl/test/test_interface.jl b/LibTrixi.jl/test/test_interface.jl index 3b03efd1..f35449ba 100644 --- a/LibTrixi.jl/test/test_interface.jl +++ b/LibTrixi.jl/test/test_interface.jl @@ -24,7 +24,7 @@ end libelixir = joinpath(dirname(pathof(LibTrixi)), - "../examples/libelixir_tree1d_dgsem_advection_basic.jl") + "../examples/libelixir_tree1d_advection_basic.jl") # initialize a simulation via API, receive a handle handle = trixi_initialize_simulation(libelixir) diff --git a/LibTrixi.jl/test/test_t8code.jl b/LibTrixi.jl/test/test_t8code.jl index 6d6a3200..2f581595 100644 --- a/LibTrixi.jl/test/test_t8code.jl +++ b/LibTrixi.jl/test/test_t8code.jl @@ -6,7 +6,7 @@ using Trixi libelixir = joinpath(dirname(pathof(LibTrixi)), - "../examples/libelixir_t8code_2d_dgsem_advection_amr.jl") + "../examples/libelixir_t8code2d_advection_amr.jl") # initialize a simulation via API, receive a handle handle = trixi_initialize_simulation(libelixir) diff --git a/README.md b/README.md index 744ba918..fc523ccb 100644 --- a/README.md +++ b/README.md @@ -112,7 +112,7 @@ Go to some directory from where you want to run a Trixi simulation. LIBTRIXI_DEBUG=all \ /bin/trixi_controller_simple_c \ \ - /share/libtrixi/LibTrixi.jl/examples/libelixir_tree1d_dgsem_advection_basic.jl + /share/libtrixi/LibTrixi.jl/examples/libelixir_tree1d_advection_basic.jl ``` which should give you an output similar to this: ``` @@ -224,7 +224,7 @@ JULIA_DEPOT_PATH= \ LIBTRIXI_DEBUG=all \ julia --project= /share/libtrixi/examples/trixi_controller_simple.jl - /share/libtrixi/LibTrixi.jl/examples/libelixir_tree1d_dgsem_advection_basic.jl + /share/libtrixi/LibTrixi.jl/examples/libelixir_tree1d_advection_basic.jl ``` Note: Most auxiliary output is hidden unless the environment variable `LIBTRIXI_DEBUG` is @@ -310,7 +310,7 @@ To try this out, perform the following steps: ```shell mpirun -n 2 trixi_controller_simple_c \ ../libtrixi-julia \ - ../LibTrixi.jl/examples/libelixir_p4est2d_dgsem_euler_sedov.jl + ../LibTrixi.jl/examples/libelixir_p4est2d_euler_sedov.jl ``` Optionally, you can set `LIBTRIXI_DEBUG=all` to get some debug output along the way. diff --git a/test/c/simulation.cpp b/test/c/simulation.cpp index 2deb9bf9..62be8029 100644 --- a/test/c/simulation.cpp +++ b/test/c/simulation.cpp @@ -10,7 +10,7 @@ const char * julia_project_path = JULIA_PROJECT_PATH; // Example libexlixir const char * libelixir_path = - "../../../LibTrixi.jl/examples/libelixir_p4est2d_dgsem_euler_sedov.jl"; + "../../../LibTrixi.jl/examples/libelixir_p4est2d_dgsem_sedov.jl"; TEST(CInterfaceTest, SimulationRun) { diff --git a/test/c/t8code.cpp b/test/c/t8code.cpp index dd99a555..9339b9b1 100644 --- a/test/c/t8code.cpp +++ b/test/c/t8code.cpp @@ -9,7 +9,7 @@ const char * julia_project_path = JULIA_PROJECT_PATH; // Example libexlixir const char * libelixir_path = - "../../../LibTrixi.jl/examples/libelixir_t8code_2d_dgsem_advection_amr.jl"; + "../../../LibTrixi.jl/examples/libelixir_t8code2d_advection_amr.jl"; TEST(CInterfaceTest, T8code) { diff --git a/test/fortran/simulationRun_suite.f90 b/test/fortran/simulationRun_suite.f90 index 7459a3a7..5f9efc8f 100644 --- a/test/fortran/simulationRun_suite.f90 +++ b/test/fortran/simulationRun_suite.f90 @@ -8,7 +8,7 @@ module simulationRun_suite character(len=*), parameter, public :: julia_project_path = JULIA_PROJECT_PATH character(len=*), parameter, public :: libelixir_path = & - "../../../LibTrixi.jl/examples/libelixir_p4est2d_dgsem_euler_sedov.jl" + "../../../LibTrixi.jl/examples/libelixir_p4est2d_dgsem_sedov.jl" contains diff --git a/test/fortran/t8code_suite.f90 b/test/fortran/t8code_suite.f90 index b3ae99cf..24d71545 100644 --- a/test/fortran/t8code_suite.f90 +++ b/test/fortran/t8code_suite.f90 @@ -10,7 +10,7 @@ module t8code_suite character(len=*), parameter, public :: julia_project_path = JULIA_PROJECT_PATH character(len=*), parameter, public :: libelixir_path = & - "../../../LibTrixi.jl/examples/libelixir_t8code_2d_dgsem_advection_amr.jl" + "../../../LibTrixi.jl/examples/libelixir_t8code2d_advection_amr.jl" contains From c6ec30a5867290cfb1ff3c6a18102144529056c2 Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Wed, 20 Nov 2024 15:17:23 +0100 Subject: [PATCH 58/89] fixes --- examples/trixi_controller_baroclinic.f90 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/trixi_controller_baroclinic.f90 b/examples/trixi_controller_baroclinic.f90 index 136ef0fe..98e33abe 100644 --- a/examples/trixi_controller_baroclinic.f90 +++ b/examples/trixi_controller_baroclinic.f90 @@ -1,6 +1,6 @@ subroutine source_terms_baroclinic( nnodes, nodes, forest, ndofs, & u1, u2, u3, u4, du2, du3, du4, du5 ) - use t8_mo_fortran_interface + use t8_fortran_interface_mod use, intrinsic :: iso_c_binding, only: c_ptr, c_int, c_double implicit none @@ -45,7 +45,7 @@ subroutine source_terms_baroclinic( nnodes, nodes, forest, ndofs, & ele = sqrt( global_coords(1)*global_coords(1) + & global_coords(2)*global_coords(2) + & global_coords(3)*global_coords(3) ) - ele_corrected = max( ele - radius_earth, 0.0) + radius_earth + ele_corrected = max( ele - radius_earth, 0.0_dp ) + radius_earth ! Gravity term temp = g_r2 / (ele_corrected*ele_corrected*ele_corrected) From b866b8b16bf1fc4da5e9f7d5ab6b43f0fad4e2e2 Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Wed, 20 Nov 2024 15:17:36 +0100 Subject: [PATCH 59/89] adapt index.md to README.md --- docs/src/index.md | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/docs/src/index.md b/docs/src/index.md index ea3cf45c..4df3c33c 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -2,7 +2,7 @@ [![Docs-stable](https://img.shields.io/badge/docs-stable-blue.svg)](https://trixi-framework.github.io/libtrixi/stable) [![Docs-dev](https://img.shields.io/badge/docs-dev-blue.svg)](https://trixi-framework.github.io/libtrixi/dev) -[![Build Status](https://github.com/trixi-framework/libtrixi/workflows/CI/badge.svg)](https://github.com/trixi-framework/libtrixi/actions?query=workflow%3ACI) +[![Build Status](https://github.com/trixi-framework/libtrixi/actions/workflows/ci.yml/badge.svg)](https://github.com/trixi-framework/libtrixi/actions?query=workflow%3ACI) [![Coveralls](https://coveralls.io/repos/github/trixi-framework/libtrixi/badge.svg)](https://coveralls.io/github/trixi-framework/libtrixi) [![Codecov](https://codecov.io/gh/trixi-framework/libtrixi/branch/main/graph/badge.svg)](https://codecov.io/gh/trixi-framework/libtrixi) [![License: MIT](https://img.shields.io/badge/License-MIT-success.svg)](https://opensource.org/licenses/MIT) @@ -24,7 +24,7 @@ software packages need to be made available locally before installing libtrixi: * [CMake](https://cmake.org/) * MPI (e.g., [OpenMPI](https://www.open-mpi.org/) or [MPICH](https://www.mpich.org/)) * [HDF5](https://www.hdfgroup.org/solutions/hdf5/) -* [t8code](https://github.com/DLR-AMR/t8code) +* [t8code](https://github.com/DLR-AMR/t8code) v3.0.0 ### Get the sources @@ -57,7 +57,7 @@ For building, `cmake` and its typical workflow is used. - Optional specification of build type sets some default compiler options for optimized or debug code. - Building with t8code support is optional. It requires to pass - `-DT8CODE_PREFIX=`. + `-DT8CODE_ROOT=`. 3. Call make @@ -100,7 +100,7 @@ In your code, pass the path to the `libtrixi-julia` directory to `trixi_initiali see the code of the examples. If you did not modify the default value for the Julia depot when calling `libtrixi-init-julia`, libtrixi will find it automatically. Otherwise, when running a program that uses libtrixi, you need to make sure to set the -`JULIA_DEPOT_PATH` environment variable to point to the `` folder reported. +`JULIA_DEPOT_PATH` environment variable to point to the `` folder reported. If you intend to use additional Julia packages, besides `Trixi` and `OrdinaryDiffEq`, you will have to add them to your Julia project (i.e. use @@ -114,7 +114,7 @@ Go to some directory from where you want to run a Trixi simulation. LIBTRIXI_DEBUG=all \ /bin/trixi_controller_simple_c \ \ - /share/libtrixi/LibTrixi.jl/examples/libelixir_tree1d_dgsem_advection_basic.jl + /share/libtrixi/LibTrixi.jl/examples/libelixir_tree1d_advection_basic.jl ``` which should give you an output similar to this: ``` @@ -217,8 +217,7 @@ examples demonstrate different aspects on how to use the C and Fortran APIs of l - `trixi_controller_simple.(c|f90)`: basic usage - `trixi_controller_mpi.(c|f90)`: usage in the presence of MPI - `trixi_controller_data.(c|f90)`: simulation data access -- `trixi_controller_t8code.c`: interacting with t8code - (there is no Fortran example yet as the Fortran interface of t8code is still under development) +- `trixi_controller_t8code.(c|f90)`: interacting with t8code If you just want to test the Julia part of libtrixi, i.e., LibTrixi.jl, you can also run `trixi_controller_simple.jl` from Julia. @@ -228,7 +227,7 @@ JULIA_DEPOT_PATH= \ LIBTRIXI_DEBUG=all \ julia --project= /share/libtrixi/examples/trixi_controller_simple.jl - /share/libtrixi/LibTrixi.jl/examples/libelixir_tree1d_dgsem_advection_basic.jl + /share/libtrixi/LibTrixi.jl/examples/libelixir_tree1d_advection_basic.jl ``` Note: Most auxiliary output is hidden unless the environment variable `LIBTRIXI_DEBUG` is @@ -269,7 +268,7 @@ please refer to #### Note on thread-local storage (TLS) -Note: On Linux and FreeBSD systems (i.e., *not* on macOS or Windows), Julia may internally +On Linux and FreeBSD systems (i.e., *not* on macOS or Windows), Julia may internally use a faster implementation for thread-local storage (TLS), which is used whenever Julia functions such task management, garbage collection etc. are used in a multithreaded context, or when they are themselves multithreaded. To activate the fast TLS in your @@ -284,8 +283,8 @@ library with a C interface. This is possible with the use of the Julia package [PackageCompiler.jl](https://github.com/JuliaLang/PackageCompiler.jl). To try this out, perform the following steps: -1. Initialize the project directory `libtrixi-julia` using `libtrixi-init-julia` as - described above. +1. Initialize the project directory `libtrixi-julia` using `libtrixi-init-julia` as + described above. 2. Build *using make* @@ -315,7 +314,7 @@ To try this out, perform the following steps: ```shell mpirun -n 2 trixi_controller_simple_c \ ../libtrixi-julia \ - ../LibTrixi.jl/examples/libelixir_p4est2d_dgsem_euler_sedov.jl + ../LibTrixi.jl/examples/libelixir_p4est2d_euler_sedov.jl ``` Optionally, you can set `LIBTRIXI_DEBUG=all` to get some debug output along the way. From ac1b65369940120d73611793fae183f65b4359e2 Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Wed, 20 Nov 2024 16:29:36 +0100 Subject: [PATCH 60/89] change to non-adaptive time integrator --- ...r_t8code3d_euler_baroclinic_instability.jl | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/LibTrixi.jl/examples/libelixir_t8code3d_euler_baroclinic_instability.jl b/LibTrixi.jl/examples/libelixir_t8code3d_euler_baroclinic_instability.jl index 7c358a3c..22d94197 100644 --- a/LibTrixi.jl/examples/libelixir_t8code3d_euler_baroclinic_instability.jl +++ b/LibTrixi.jl/examples/libelixir_t8code3d_euler_baroclinic_instability.jl @@ -244,14 +244,14 @@ function init_simstate() # estimate for the speed of sound surface_flux = FluxLMARS(340) volume_flux = flux_kennedy_gruber - solver = DGSEM(polydeg = 3, surface_flux = surface_flux, + solver = DGSEM(polydeg = 5, surface_flux = surface_flux, volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) # for nice results, use 4 and 8 here lat_lon_levels = 3 layers = 4 mesh = Trixi.T8codeMeshCubedSphere(lat_lon_levels, layers, 6.371229e6, 30000.0, - polydeg = 3, initial_refinement_level = 0) + polydeg = 5, initial_refinement_level = 0) # create the database and three vectors for the source terms database = LibTrixiDataBaseType(undef, 4) @@ -271,7 +271,7 @@ function init_simstate() source_terms = source_term_database, boundary_conditions = boundary_conditions) - # for nice results use 10 day + # for nice results, use 10 days days = 0.1 tspan = (0.0, days * 24 * 60 * 60.0) @@ -284,21 +284,24 @@ function init_simstate() alive_callback = AliveCallback(analysis_interval = analysis_interval) + stepsize_callback = StepsizeCallback(cfl=1.6) + save_solution = SaveSolutionCallback(interval = 50, save_initial_solution = true, save_final_solution = true, solution_variables = cons2prim, - output_directory = "out_baroclinic",) + output_directory = "out_baroclinic") callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, + stepsize_callback, save_solution) - # use a Runge-Kutta method with automatic (error based) time step size control - integrator = init(ode, RDPK3SpFSAL49(thread = OrdinaryDiffEq.False()); - abstol = 1.0e-6, reltol = 1.0e-6, - ode_default_options()..., callback = callbacks, maxiters=1e7); + # OrdinaryDiffEq's integrator + integrator = init(ode, CarpenterKennedy2N54(williamson_condition=false), + dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep=false, callback=callbacks, maxiters=1e7); # create simulation state simstate = SimulationState(semi, integrator, database) From 58444f3e4199ed5db1cbd8af9e62e34498014bd4 Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Wed, 20 Nov 2024 16:51:19 +0100 Subject: [PATCH 61/89] missing controlers in ci checks --- .github/workflows/ci.yml | 10 +++++++++- .../examples/libelixir_t8code3d_euler_tracer.jl | 2 +- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e88bc704..74266fdb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -274,7 +274,15 @@ jobs: "../build/examples/trixi_controller_t8code_c" \ "../build/examples/trixi_controller_t8code_c ." \ "../build/examples/trixi_controller_t8code_f" \ - "../build/examples/trixi_controller_t8code_f ." + "../build/examples/trixi_controller_t8code_f ." \ + "../build/examples/trixi_controller_baroclinic_c" \ + "../build/examples/trixi_controller_baroclinic_c ." \ + "../build/examples/trixi_controller_baroclinic_f" \ + "../build/examples/trixi_controller_baroclinic_f ." \ + "../build/examples/trixi_controller_mpi_c" \ + "../build/examples/trixi_controller_mpi_c ." \ + "../build/examples/trixi_controller_mpi_f" \ + "../build/examples/trixi_controller_mpi_f ." do $command if [ $? -ne 2 ]; then diff --git a/LibTrixi.jl/examples/libelixir_t8code3d_euler_tracer.jl b/LibTrixi.jl/examples/libelixir_t8code3d_euler_tracer.jl index 1c7df858..276710e2 100644 --- a/LibTrixi.jl/examples/libelixir_t8code3d_euler_tracer.jl +++ b/LibTrixi.jl/examples/libelixir_t8code3d_euler_tracer.jl @@ -67,7 +67,7 @@ function init_simstate() surface_flux = FluxLMARS(374) solver = DGSEM(polydeg = 3, surface_flux = surface_flux) - # increase trees_per_cube_face or initial_refinement_level to get nicer results + # increase trees_per_cube_face to 4 to get nicer results lat_lon_levels = 2 layers = 1 mesh = Trixi.T8codeMeshCubedSphere(lat_lon_levels, layers, 6.371229e6, 30000.0, From 218cd91f8d2db49b711f882c3a9d5c254b955789 Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Wed, 27 Nov 2024 08:52:45 +0100 Subject: [PATCH 62/89] use zeros in initial data --- .../libelixir_t8code3d_euler_baroclinic_instability.jl | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/LibTrixi.jl/examples/libelixir_t8code3d_euler_baroclinic_instability.jl b/LibTrixi.jl/examples/libelixir_t8code3d_euler_baroclinic_instability.jl index 22d94197..75cc00e8 100644 --- a/LibTrixi.jl/examples/libelixir_t8code3d_euler_baroclinic_instability.jl +++ b/LibTrixi.jl/examples/libelixir_t8code3d_euler_baroclinic_instability.jl @@ -260,10 +260,12 @@ function init_simstate() nnodes = nnodesdim^3 nelements = Trixi.ncells(mesh) - database[1] = Ref(Vector{Float64}(undef, nelements*nnodes)) - database[2] = Ref(Vector{Float64}(undef, nelements*nnodes)) - database[3] = Ref(Vector{Float64}(undef, nelements*nnodes)) - database[4] = Ref(Vector{Float64}(undef, nelements*nnodes)) + # provide some data because calc_sources! will already be called during initialization + zero_data = Vector{Float64}(0.0, nelements*nnodes) + database[1] = zero_data + database[2] = zero_data + database[3] = zero_data + database[4] = zero_data source_term_database = SourceTerm(nnodesdim, database) From 47a2e4cbb80e2434c32952b920eae7186d9ebd6c Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Wed, 27 Nov 2024 09:22:41 +0100 Subject: [PATCH 63/89] missing renamings --- examples/trixi_controller_baroclinic.c | 8 ++++---- examples/trixi_controller_baroclinic.f90 | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/examples/trixi_controller_baroclinic.c b/examples/trixi_controller_baroclinic.c index 49217605..368a6044 100644 --- a/examples/trixi_controller_baroclinic.c +++ b/examples/trixi_controller_baroclinic.c @@ -102,10 +102,10 @@ int main ( int argc, char *argv[] ) { double * du5 = calloc( ndofs, sizeof(double) ); // Store source term vectors in Trixi - trixi_store_in_database( handle, 1, ndofs, du2 ); - trixi_store_in_database( handle, 2, ndofs, du3 ); - trixi_store_in_database( handle, 3, ndofs, du4 ); - trixi_store_in_database( handle, 4, ndofs, du5 ); + trixi_register_data( handle, 1, ndofs, du2 ); + trixi_register_data( handle, 2, ndofs, du3 ); + trixi_register_data( handle, 3, ndofs, du4 ); + trixi_register_data( handle, 4, ndofs, du5 ); // Get number of quadrature nodes int nnodes = trixi_nnodes( handle ); diff --git a/examples/trixi_controller_baroclinic.f90 b/examples/trixi_controller_baroclinic.f90 index 98e33abe..e9c3928c 100644 --- a/examples/trixi_controller_baroclinic.f90 +++ b/examples/trixi_controller_baroclinic.f90 @@ -126,10 +126,10 @@ program trixi_controller_baroclinic_f allocate( du5(ndofs) ) ! Store source term vectors in Trixi - call trixi_store_in_database( handle, 1, ndofs, du2 ) - call trixi_store_in_database( handle, 2, ndofs, du3 ) - call trixi_store_in_database( handle, 3, ndofs, du4 ) - call trixi_store_in_database( handle, 4, ndofs, du5 ) + call trixi_register_data( handle, 1, ndofs, du2 ) + call trixi_register_data( handle, 2, ndofs, du3 ) + call trixi_register_data( handle, 3, ndofs, du4 ) + call trixi_register_data( handle, 4, ndofs, du5 ) ! Get number of quadrature nodes nnodes = trixi_nnodes( handle ) From 8bd1b2309d0d113989adc0836196ae22d2344b59 Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Wed, 27 Nov 2024 09:24:08 +0100 Subject: [PATCH 64/89] time not needed anymore --- examples/trixi_controller_baroclinic.f90 | 4 ---- 1 file changed, 4 deletions(-) diff --git a/examples/trixi_controller_baroclinic.f90 b/examples/trixi_controller_baroclinic.f90 index e9c3928c..15afdf84 100644 --- a/examples/trixi_controller_baroclinic.f90 +++ b/examples/trixi_controller_baroclinic.f90 @@ -79,7 +79,6 @@ program trixi_controller_baroclinic_f character(len=256) :: argument type(c_ptr) :: forest integer, parameter :: dp = selected_real_kind(12) - real(c_double) :: t real(dp), dimension(:), pointer :: u1, u2, u3, u4, du2, du3, du4, du5, nodes => null() @@ -155,9 +154,6 @@ program trixi_controller_baroclinic_f ! Exit loop once simulation is completed if ( trixi_is_finished(handle) ) exit - ! Get current time - t = trixi_get_time( handle ); - ! Get current state call trixi_load_primitive_vars( handle, 1, u1 ) call trixi_load_primitive_vars( handle, 2, u2 ) From 85f882c4fa7c3e1355b57d06c7ac9e23cf797d25 Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Wed, 27 Nov 2024 10:05:29 +0100 Subject: [PATCH 65/89] tuned simulation parameters --- ...r_t8code3d_euler_baroclinic_instability.jl | 46 +++++++++---------- 1 file changed, 21 insertions(+), 25 deletions(-) diff --git a/LibTrixi.jl/examples/libelixir_t8code3d_euler_baroclinic_instability.jl b/LibTrixi.jl/examples/libelixir_t8code3d_euler_baroclinic_instability.jl index 75cc00e8..f1fa4fd9 100644 --- a/LibTrixi.jl/examples/libelixir_t8code3d_euler_baroclinic_instability.jl +++ b/LibTrixi.jl/examples/libelixir_t8code3d_euler_baroclinic_instability.jl @@ -18,7 +18,7 @@ using LibTrixi # Callable struct holding vectors with source terms struct SourceTerm nnodesdim::Int - database::Vector{Ref{Vector{Float64}}} + registry::LibTrixiDataRegistry end # We overwrite Trixi.jl's internal method here such that it calls source_terms with indices @@ -43,11 +43,10 @@ end equations::CompressibleEulerEquations3D) @unpack nnodesdim = source index_global = (element-1) * nnodesdim^3 + (k-1) * nnodesdim^2 + (j-1) * nnodesdim + i - # massive allocations occur when directly accessing source.database[1][][1] - du2::Vector{Float64} = source.database[1][] - du3::Vector{Float64} = source.database[2][] - du4::Vector{Float64} = source.database[3][] - du5::Vector{Float64} = source.database[4][] + du2::Vector{Float64} = source.registry[1] + du3::Vector{Float64} = source.registry[2] + du4::Vector{Float64} = source.registry[3] + du5::Vector{Float64} = source.registry[4] return SVector(zero(eltype(u)), du2[index_global], du3[index_global], du4[index_global], du5[index_global]) end @@ -248,33 +247,33 @@ function init_simstate() volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) # for nice results, use 4 and 8 here - lat_lon_levels = 3 + lat_lon_levels = 2 layers = 4 mesh = Trixi.T8codeMeshCubedSphere(lat_lon_levels, layers, 6.371229e6, 30000.0, polydeg = 5, initial_refinement_level = 0) - # create the database and three vectors for the source terms - database = LibTrixiDataBaseType(undef, 4) + # create the data registry and three vectors for the source terms + registry = LibTrixiDataRegistry(undef, 4) nnodesdim = Trixi.nnodes(solver) nnodes = nnodesdim^3 nelements = Trixi.ncells(mesh) # provide some data because calc_sources! will already be called during initialization - zero_data = Vector{Float64}(0.0, nelements*nnodes) - database[1] = zero_data - database[2] = zero_data - database[3] = zero_data - database[4] = zero_data + zero_data = zeros(Float64, nelements*nnodes) + registry[1] = zero_data + registry[2] = zero_data + registry[3] = zero_data + registry[4] = zero_data - source_term_database = SourceTerm(nnodesdim, database) + source_term_data_registry = SourceTerm(nnodesdim, registry) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms = source_term_database, + source_terms = source_term_data_registry, boundary_conditions = boundary_conditions) # for nice results, use 10 days - days = 0.1 + days = 0.02 tspan = (0.0, days * 24 * 60 * 60.0) ode = semidiscretize(semi, tspan) @@ -286,8 +285,6 @@ function init_simstate() alive_callback = AliveCallback(analysis_interval = analysis_interval) - stepsize_callback = StepsizeCallback(cfl=1.6) - save_solution = SaveSolutionCallback(interval = 50, save_initial_solution = true, save_final_solution = true, @@ -297,16 +294,15 @@ function init_simstate() callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, - stepsize_callback, save_solution) - # OrdinaryDiffEq's integrator - integrator = init(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks, maxiters=1e7); + # use a Runge-Kutta method with automatic (error based) time step size control + integrator = init(ode, RDPK3SpFSAL49(thread = OrdinaryDiffEq.False()); + abstol = 1.0e-6, reltol = 1.0e-6, + ode_default_options()..., callback = callbacks, maxiters=1e7); # create simulation state - simstate = SimulationState(semi, integrator, database) + simstate = SimulationState(semi, integrator, registry) return simstate end From 49fa81538075ce08433a8d82d1d4f716c6178288 Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Wed, 27 Nov 2024 13:40:23 +0100 Subject: [PATCH 66/89] itree and ielement need to be 0-based --- examples/trixi_controller_baroclinic.f90 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/trixi_controller_baroclinic.f90 b/examples/trixi_controller_baroclinic.f90 index 15afdf84..7679e45d 100644 --- a/examples/trixi_controller_baroclinic.f90 +++ b/examples/trixi_controller_baroclinic.f90 @@ -24,11 +24,11 @@ subroutine source_terms_baroclinic( nnodes, nodes, forest, ndofs, & num_local_trees = t8_forest_get_num_local_trees (forest) ! Iterate through all local trees index = 1 - do itree = 1,num_local_trees + do itree = 0,num_local_trees-1 ! Get number of elements of this tree num_elements_in_tree = t8_forest_get_tree_num_elements (forest, itree) ! Iterate through all the local elements - do ielement = 1,num_elements_in_tree + do ielement = 0,num_elements_in_tree-1 ! Get a pointer to the current element element = t8_forest_get_element_in_tree (forest, itree, ielement) do k = 1,nnodes From 5cf1aec6c7c8c5aa6adeb6e8a312ae3f30f1bbc2 Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Thu, 28 Nov 2024 14:06:34 +0100 Subject: [PATCH 67/89] one more to free --- examples/trixi_controller_baroclinic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/trixi_controller_baroclinic.c b/examples/trixi_controller_baroclinic.c index 368a6044..cec6cc0e 100644 --- a/examples/trixi_controller_baroclinic.c +++ b/examples/trixi_controller_baroclinic.c @@ -28,7 +28,6 @@ void source_terms_baroclinic(int nnodes, double * nodes, t8_forest_t forest, // Get number of elements of this tree t8_locidx_t num_elements_in_tree = t8_forest_get_tree_num_elements (forest, itree); // Iterate through all the local elements - // TODO: What happens in parallel computations with MPI? for (t8_locidx_t ielement = 0; ielement < num_elements_in_tree; ++ielement) { // Get a pointer to the current element const t8_element_t *element = t8_forest_get_element_in_tree (forest, itree, ielement); @@ -158,6 +157,7 @@ int main ( int argc, char *argv[] ) { free(du3); free(du4); free(du5); + free(nodes); return 0; } From 8ccad7b4bd8a9610ace4405f8044439a12bc368a Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Thu, 28 Nov 2024 14:06:52 +0100 Subject: [PATCH 68/89] ouch... --- examples/trixi_controller_baroclinic.f90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/trixi_controller_baroclinic.f90 b/examples/trixi_controller_baroclinic.f90 index 7679e45d..d0b551b3 100644 --- a/examples/trixi_controller_baroclinic.f90 +++ b/examples/trixi_controller_baroclinic.f90 @@ -58,7 +58,7 @@ subroutine source_terms_baroclinic( nnodes, nodes, forest, ndofs, & ! Coriolis term du2(index) = du2(index) + 2.0 * angular_velocity * u3(index) * u1(index) - du3(index) = du2(index) - 2.0 * angular_velocity * u2(index) * u1(index) + du3(index) = du3(index) - 2.0 * angular_velocity * u2(index) * u1(index) index = index + 1 end do From 5599568cd6cf343462e4823462376237cd406602 Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Thu, 28 Nov 2024 14:27:22 +0100 Subject: [PATCH 69/89] less output --- .../libelixir_t8code3d_euler_baroclinic_instability.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/LibTrixi.jl/examples/libelixir_t8code3d_euler_baroclinic_instability.jl b/LibTrixi.jl/examples/libelixir_t8code3d_euler_baroclinic_instability.jl index f1fa4fd9..e912bcbc 100644 --- a/LibTrixi.jl/examples/libelixir_t8code3d_euler_baroclinic_instability.jl +++ b/LibTrixi.jl/examples/libelixir_t8code3d_euler_baroclinic_instability.jl @@ -28,9 +28,9 @@ function Trixi.calc_sources!(du, u, t, source_terms::SourceTerm, Trixi.@threaded for element in eachelement(dg, cache) for k in eachnode(dg), j in eachnode(dg), i in eachnode(dg) u_local = Trixi.get_node_vars(u, equations, dg, i, j, k, element) - x_local = Trixi.get_node_coords(node_coordinates, equations, dg, - i, j, k, element) du_local = source_terms(u_local, i, j, k, element, t, equations) + #x_local = Trixi.get_node_coords(node_coordinates, equations, dg, + # i, j, k, element) #du_local_ref = source_terms_baroclinic_instability(u_local, x_local, t, # equations) Trixi.add_to_node_vars!(du, du_local, equations, dg, i, j, k, element) @@ -285,7 +285,7 @@ function init_simstate() alive_callback = AliveCallback(analysis_interval = analysis_interval) - save_solution = SaveSolutionCallback(interval = 50, + save_solution = SaveSolutionCallback(interval = 500, save_initial_solution = true, save_final_solution = true, solution_variables = cons2prim, From a90d9838d90d66c99e7a921ba78d0cb8f0942eac Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Mon, 2 Dec 2024 14:51:50 +0100 Subject: [PATCH 70/89] add trixi_get_data_pointer --- LibTrixi.jl/src/LibTrixi.jl | 3 +++ LibTrixi.jl/src/api_c.jl | 21 +++++++++++++++++++++ LibTrixi.jl/src/api_jl.jl | 5 +++++ src/api.c | 25 +++++++++++++++++++++++++ src/api.f90 | 18 ++++++++++++++++++ src/trixi.h | 1 + 6 files changed, 73 insertions(+) diff --git a/LibTrixi.jl/src/LibTrixi.jl b/LibTrixi.jl/src/LibTrixi.jl index f2f9bcde..bc30b312 100644 --- a/LibTrixi.jl/src/LibTrixi.jl +++ b/LibTrixi.jl/src/LibTrixi.jl @@ -61,6 +61,9 @@ export trixi_load_element_averaged_primitive_vars, export trixi_register_data, trixi_register_data_cfptr, trixi_register_data_jl +export trixi_get_data_pointer, + trixi_get_data_pointer_cfptr, + trixi_get_data_pointer_jl export trixi_version_library, trixi_version_library_cfptr, trixi_version_library_jl diff --git a/LibTrixi.jl/src/api_c.jl b/LibTrixi.jl/src/api_c.jl index 6b729d82..b7635a16 100644 --- a/LibTrixi.jl/src/api_c.jl +++ b/LibTrixi.jl/src/api_c.jl @@ -538,6 +538,25 @@ trixi_load_element_averaged_primitive_vars_cfptr() = @cfunction(trixi_load_element_averaged_primitive_vars, Cvoid, (Cint, Cint, Ptr{Cdouble})) +""" + trixi_get_data_pointer(simstate_handle::Cint)::Ptr{Cdouble} + +Return pointer to internal data vector. +""" +function trixi_get_data_pointer end + +Base.@ccallable function trixi_get_data_pointer(simstate_handle::Cint)::Ptr{Cdouble} + simstate = load_simstate(simstate_handle) + return trixi_get_data_pointer_jl(simstate) +end + +trixi_get_data_pointer_cfptr() = @cfunction(trixi_get_data_pointer, Ptr{Cdouble}, (Cint,)) + + + +############################################################################################ +# t8code +############################################################################################ """ trixi_get_t8code_forest(simstate_handle::Cint)::::Ptr{Trixi.t8_forest} @@ -557,6 +576,8 @@ end trixi_get_t8code_forest_cfptr() = @cfunction(trixi_get_t8code_forest, Ptr{Trixi.t8_forest}, (Cint,)) + + ############################################################################################ # Auxiliary ############################################################################################ diff --git a/LibTrixi.jl/src/api_jl.jl b/LibTrixi.jl/src/api_jl.jl index 5d728425..324fd4b0 100644 --- a/LibTrixi.jl/src/api_jl.jl +++ b/LibTrixi.jl/src/api_jl.jl @@ -208,6 +208,11 @@ function trixi_register_data_jl(simstate, index, data) end +function trixi_get_data_pointer_jl(simstate) + return pointer(simstate.integrator.u) +end + + function trixi_get_simulation_time_jl(simstate) return simstate.integrator.t end diff --git a/src/api.c b/src/api.c index da2b17d2..4eddae8c 100644 --- a/src/api.c +++ b/src/api.c @@ -25,6 +25,7 @@ enum { TRIXI_FTPR_LOAD_PRIMITIVE_VARS, TRIXI_FTPR_LOAD_ELEMENT_AVERAGED_PRIMITIVE_VARS, TRIXI_FTPR_REGISTER_DATA, + TRIXI_FPTR_GET_DATA_POINTER, TRIXI_FTPR_VERSION_LIBRARY, TRIXI_FTPR_VERSION_LIBRARY_MAJOR, TRIXI_FTPR_VERSION_LIBRARY_MINOR, @@ -63,6 +64,7 @@ static const char* trixi_function_pointer_names[] = { [TRIXI_FTPR_LOAD_PRIMITIVE_VARS] = "trixi_load_primitive_vars_cfptr", [TRIXI_FTPR_LOAD_ELEMENT_AVERAGED_PRIMITIVE_VARS] = "trixi_load_element_averaged_primitive_vars_cfptr", [TRIXI_FTPR_REGISTER_DATA] = "trixi_register_data_cfptr", + [TRIXI_FPTR_GET_DATA_POINTER] = "trixi_get_data_pointer_cfptr", [TRIXI_FTPR_VERSION_LIBRARY] = "trixi_version_library_cfptr", [TRIXI_FTPR_VERSION_LIBRARY_MAJOR] = "trixi_version_library_major_cfptr", [TRIXI_FTPR_VERSION_LIBRARY_MINOR] = "trixi_version_library_minor_cfptr", @@ -726,6 +728,29 @@ void trixi_register_data(int handle, int index, int size, const double * data) { } +/** + * @anchor trixi_get_data_pointer_api_c + * + * @brief Return pointer to internal data vector. + * + * The returned pointer points to the beginning of the internal data array used in Trixi.jl. + * This array contains the conservative variables, i.e. density, momentum density in the + * three Cartesian coordinates, and energy density, in this sequence. The pointer can be + * used to read, but also to write these variables. The latter should be done with care. + * Writing while a time step in being performed will lead to undefined behavior. + * + * @param[in] handle simulation handle + */ +double * trixi_get_data_pointer(int handle) { + + // Get function pointer + double * (*get_data_pointer)(int) = trixi_function_pointers[TRIXI_FPTR_GET_DATA_POINTER]; + + // Call function + return get_data_pointer(handle); +} + + /** * @anchor trixi_get_simulation_time_api_c * diff --git a/src/api.f90 b/src/api.f90 index 385f7ca6..3d45f83f 100644 --- a/src/api.f90 +++ b/src/api.f90 @@ -442,6 +442,24 @@ subroutine trixi_register_data(handle, index, size, data) bind(c) real(c_double), dimension(*), intent(in) :: data end subroutine + !> + !! @anchor trixi_get_data_pointer_api_c + !! + !! @brief Return pointer to internal data vector. + !! + !! The returned pointer points to the beginning of the internal data array used in + !! Trixi.jl. This array contains the conservative variables, i.e. density, momentum + !! density in the three Cartesian coordinates, and energy density, in this sequence. + !! The pointer can be used to read, but also to write these variables. The latter + !! should be done with care. Writing while a time step in being performed will lead to + !! undefined behavior. + !! + !! @param[in] handle simulation handle + type (c_ptr) function trixi_get_data_pointer(handle) bind(c) + use, intrinsic :: iso_c_binding, only: c_int, c_ptr + integer(c_int), value, intent(in) :: handle + end function + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! diff --git a/src/trixi.h b/src/trixi.h index b8d3f433..f2584189 100644 --- a/src/trixi.h +++ b/src/trixi.h @@ -40,6 +40,7 @@ void trixi_load_node_weights(int handle, double* node_weights); void trixi_load_primitive_vars(int handle, int variable_id, double * data); void trixi_load_element_averaged_primitive_vars(int handle, int variable_id, double * data); void trixi_register_data(int handle, int index, int size, const double * data); +double * trixi_get_data_pointer(int handle); // T8code #if !defined(T8_H) && !defined(T8_FOREST_GENERAL_H) From 449149f10d03bf89e88afd6b7a85b261ce0f4a40 Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Mon, 2 Dec 2024 14:52:25 +0100 Subject: [PATCH 71/89] add examples working with data pointer --- .github/workflows/ci.yml | 3 + ...libelixir_t8code_2d_dgsem_advection_amr.jl | 9 ++- examples/CMakeLists.txt | 1 + examples/trixi_controller_raw_data.c | 63 +++++++++++++++++++ 4 files changed, 74 insertions(+), 2 deletions(-) create mode 100644 examples/trixi_controller_raw_data.c diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9d8a19b4..ed47a4b8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -246,6 +246,7 @@ jobs: ../build/examples/trixi_controller_simple_f . libelixir_p4est2d_dgsem_euler_sedov.jl ../build/examples/trixi_controller_data_c . libelixir_t8code_2d_dgsem_advection_amr.jl ../build/examples/trixi_controller_data_f . libelixir_t8code_2d_dgsem_advection_amr.jl + ../build/examples/trixi_controller_raw_data_c . libelixir_t8code_2d_dgsem_advection_amr.jl ../build/examples/trixi_controller_t8code_c . libelixir_t8code_2d_dgsem_advection_amr.jl ../build/examples/trixi_controller_t8code_f . libelixir_t8code_2d_dgsem_advection_amr.jl env: @@ -274,6 +275,8 @@ jobs: "../build/examples/trixi_controller_data_c ." \ "../build/examples/trixi_controller_data_f" \ "../build/examples/trixi_controller_data_f ." \ + "../build/examples/trixi_controller_raw_data_c" \ + "../build/examples/trixi_controller_raw_data_c ." \ "../build/examples/trixi_controller_t8code_c" \ "../build/examples/trixi_controller_t8code_c ." \ "../build/examples/trixi_controller_t8code_f" \ diff --git a/LibTrixi.jl/examples/libelixir_t8code_2d_dgsem_advection_amr.jl b/LibTrixi.jl/examples/libelixir_t8code_2d_dgsem_advection_amr.jl index a30080b7..3964f6bc 100644 --- a/LibTrixi.jl/examples/libelixir_t8code_2d_dgsem_advection_amr.jl +++ b/LibTrixi.jl/examples/libelixir_t8code_2d_dgsem_advection_amr.jl @@ -51,18 +51,23 @@ function init_simstate() # The AMRCallback triggers adaptive mesh refinement amr_controller = ControllerThreeLevel(semi, IndicatorMax(semi, variable=first), base_level=2, - med_level=3, med_threshold=0.1, - max_level=4, max_threshold=0.6) + med_level=3, med_threshold=0.8, + max_level=4, max_threshold=1.2) amr_callback = AMRCallback(semi, amr_controller, interval=10, adapt_initial_condition=true, adapt_initial_condition_only_refine=true) + save_solution = SaveSolutionCallback(interval=10, + save_initial_solution=true, + save_final_solution=true) + # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, amr_callback, + save_solution, stepsize_callback) diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 361eb198..41cd778c 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -5,6 +5,7 @@ set ( EXAMPLES trixi_controller_mpi.f90 trixi_controller_data.c trixi_controller_data.f90 + trixi_controller_raw_data.c trixi_controller_t8code.c trixi_controller_t8code.f90 ) diff --git a/examples/trixi_controller_raw_data.c b/examples/trixi_controller_raw_data.c new file mode 100644 index 00000000..9d502a61 --- /dev/null +++ b/examples/trixi_controller_raw_data.c @@ -0,0 +1,63 @@ +#include +#include + +#include + +int main ( int argc, char *argv[] ) { + + if ( argc < 2 ) { + fprintf(stderr, "ERROR: missing arguments: PROJECT_DIR LIBELIXIR_PATH\n\n"); + fprintf(stderr, "usage: %s PROJECT_DIR LIBELIXIR_PATH\n", argv[0]); + return 2; + } else if ( argc < 3 ) { + fprintf(stderr, "ERROR: missing argument: LIBELIXIR_PATH\n\n"); + fprintf(stderr, "usage: %s PROJECT_DIR LIBELIXIR_PATH\n", argv[0]); + return 2; + } + + // Initialize Trixi + printf("\n*** Trixi controller *** Initialize Trixi\n"); + trixi_initialize( argv[1], NULL ); + + // Set up the Trixi simulation + // We get a handle to use subsequently + printf("\n*** Trixi controller *** Set up Trixi simulation\n"); + int handle = trixi_initialize_simulation( argv[2] ); + + // Main loop + int steps = 0; + + printf("\n*** Trixi controller *** Entering main loop\n"); + while ( !trixi_is_finished( handle ) ) { + + trixi_step( handle ); + steps++; + + if (steps % 10 == 0) { + + // Get number of degrees of freedom + int ndofs = trixi_ndofsglobal( handle ); + + // Get a pointer to Trixi's internal simulation data + double * raw_data = trixi_get_data_pointer(handle); + + for (int i = 0; i < ndofs; ++i) { + // Compute local deviation from density 1 + const double dev = raw_data[i] - 1.0; + + // Apply 20% damping + raw_data[i] = 1.0 + 0.8 * dev; + } + } + } + + // Finalize Trixi simulation + printf("\n*** Trixi controller *** Finalize Trixi simulation\n"); + trixi_finalize_simulation( handle ); + + // Finalize Trixi + printf("\n*** Trixi controller *** Finalize Trixi\n"); + trixi_finalize(); + + return 0; +} From 9dec2dfce1d03db006e06f4eb91c33761f5a34a5 Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Thu, 16 Jan 2025 16:11:02 +0100 Subject: [PATCH 72/89] changed file name --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c1521c86..c3ccea5c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -243,7 +243,7 @@ jobs: ../build/examples/trixi_controller_simple_f . libelixir_tree1d_advection_basic.jl ../build/examples/trixi_controller_data_c . libelixir_t8code2d_advection_amr.jl ../build/examples/trixi_controller_data_f . libelixir_t8code2d_advection_amr.jl - ../build/examples/trixi_controller_raw_data_c . libelixir_t8code_2d_dgsem_advection_amr.jl + ../build/examples/trixi_controller_raw_data_c . libelixir_t8code2d_advection_amr.jl ../build/examples/trixi_controller_t8code_c . libelixir_t8code2d_advection_amr.jl ../build/examples/trixi_controller_t8code_f . libelixir_t8code2d_advection_amr.jl ../build/examples/trixi_controller_baroclinic_c . libelixir_t8code3d_euler_baroclinic_instability.jl From c8cae4c72cb3054760b12a5c610edff64232fbfd Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Thu, 31 Jul 2025 16:05:28 +0200 Subject: [PATCH 73/89] improve example using new passive tracer equations --- .github/workflows/ci.yml | 10 +- LibTrixi.jl/Project.toml | 2 +- .../libelixir_t8code2d_advection_amr.jl | 88 -------------- .../libelixir_t8code2d_euler_tracer_amr.jl | 109 ++++++++++++++++++ LibTrixi.jl/test/test_t8code.jl | 2 +- examples/trixi_controller_raw_data.c | 12 +- test/c/t8code.cpp | 2 +- test/fortran/t8code_suite.f90 | 2 +- 8 files changed, 126 insertions(+), 101 deletions(-) delete mode 100644 LibTrixi.jl/examples/libelixir_t8code2d_advection_amr.jl create mode 100644 LibTrixi.jl/examples/libelixir_t8code2d_euler_tracer_amr.jl diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c3ccea5c..b37cb5a2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -241,11 +241,11 @@ jobs: # all controllers ../build/examples/trixi_controller_simple_c . libelixir_tree1d_advection_basic.jl ../build/examples/trixi_controller_simple_f . libelixir_tree1d_advection_basic.jl - ../build/examples/trixi_controller_data_c . libelixir_t8code2d_advection_amr.jl - ../build/examples/trixi_controller_data_f . libelixir_t8code2d_advection_amr.jl - ../build/examples/trixi_controller_raw_data_c . libelixir_t8code2d_advection_amr.jl - ../build/examples/trixi_controller_t8code_c . libelixir_t8code2d_advection_amr.jl - ../build/examples/trixi_controller_t8code_f . libelixir_t8code2d_advection_amr.jl + ../build/examples/trixi_controller_data_c . libelixir_t8code2d_euler_tracer_amr.jl + ../build/examples/trixi_controller_data_f . libelixir_t8code2d_euler_tracer_amr.jl + ../build/examples/trixi_controller_raw_data_c . libelixir_t8code2d_euler_tracer_amr.jl + ../build/examples/trixi_controller_t8code_c . libelixir_t8code2d_euler_tracer_amr.jl + ../build/examples/trixi_controller_t8code_f . libelixir_t8code2d_euler_tracer_amr.jl ../build/examples/trixi_controller_baroclinic_c . libelixir_t8code3d_euler_baroclinic_instability.jl ../build/examples/trixi_controller_baroclinic_f . libelixir_t8code3d_euler_baroclinic_instability.jl mpirun -n 2 ../build/examples/trixi_controller_mpi_c . libelixir_p4est2d_euler_sedov.jl diff --git a/LibTrixi.jl/Project.toml b/LibTrixi.jl/Project.toml index e784b53b..89693b47 100644 --- a/LibTrixi.jl/Project.toml +++ b/LibTrixi.jl/Project.toml @@ -13,7 +13,7 @@ Trixi = "a7f1ee26-1774-49b1-8366-f1abc58fbfcb" MPI = "0.20.13" OrdinaryDiffEq = "6.53.2" Pkg = "1.8" -Trixi = "0.9.12" +Trixi = "0.11.12" julia = "1.8" [preferences.OrdinaryDiffEq] diff --git a/LibTrixi.jl/examples/libelixir_t8code2d_advection_amr.jl b/LibTrixi.jl/examples/libelixir_t8code2d_advection_amr.jl deleted file mode 100644 index 3964f6bc..00000000 --- a/LibTrixi.jl/examples/libelixir_t8code2d_advection_amr.jl +++ /dev/null @@ -1,88 +0,0 @@ -using LibTrixi -using OrdinaryDiffEq -using Trixi - -# The function to create the simulation state needs to be named `init_simstate` -function init_simstate() - - ############################################################################### - # semidiscretization of the linear advection equation - - advection_velocity = (0.2, -0.7) - equations = LinearScalarAdvectionEquation2D(advection_velocity) - - # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux - solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) - - coordinates_min = (-1.0, -1.0) # minimum coordinates (min(x), min(y)) - coordinates_max = ( 1.0, 1.0) # maximum coordinates (max(x), max(y)) - - mapping = Trixi.coordinates2mapping(coordinates_min, coordinates_max) - - trees_per_dimension = (2, 2) - - mesh = T8codeMesh(trees_per_dimension, polydeg=3, - mapping=mapping, - initial_refinement_level=1) - - # A semidiscretization collects data structures and functions for the spatial discretization - semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_convergence_test, solver) - - - ############################################################################### - # ODE solvers, callbacks etc. - - # Create ODE problem with time span from 0.0 to 0.2 - ode = semidiscretize(semi, (0.0, 0.2)); - - # At the beginning of the main loop, the SummaryCallback prints a summary of the simulation setup - # and resets the timers - summary_callback = SummaryCallback() - - # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results - analysis_interval = 100 - analysis_callback = AnalysisCallback(semi, interval=analysis_interval) - - alive_callback = AliveCallback(analysis_interval=analysis_interval) - - # The StepsizeCallback handles the re-calculation of the maximum Δt after each time step - stepsize_callback = StepsizeCallback(cfl=0.5) - - # The AMRCallback triggers adaptive mesh refinement - amr_controller = ControllerThreeLevel(semi, IndicatorMax(semi, variable=first), - base_level=2, - med_level=3, med_threshold=0.8, - max_level=4, max_threshold=1.2) - amr_callback = AMRCallback(semi, amr_controller, - interval=10, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) - - save_solution = SaveSolutionCallback(interval=10, - save_initial_solution=true, - save_final_solution=true) - - # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver - callbacks = CallbackSet(summary_callback, - analysis_callback, - alive_callback, - amr_callback, - save_solution, - stepsize_callback) - - - ############################################################################### - # create the time integrator - - # OrdinaryDiffEq's `integrator` - integrator = init(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); - - ############################################################################### - # Create simulation state - - simstate = SimulationState(semi, integrator) - - return simstate -end diff --git a/LibTrixi.jl/examples/libelixir_t8code2d_euler_tracer_amr.jl b/LibTrixi.jl/examples/libelixir_t8code2d_euler_tracer_amr.jl new file mode 100644 index 00000000..17bc3ba3 --- /dev/null +++ b/LibTrixi.jl/examples/libelixir_t8code2d_euler_tracer_amr.jl @@ -0,0 +1,109 @@ +using LibTrixi +using OrdinaryDiffEq +using Trixi + +# The function to create the simulation state needs to be named `init_simstate` +function init_simstate() + + ############################################################################### + # initial condition: density wave + tracer blob + + function initial_condition_wave_blob(x, t, + equations::PassiveTracerEquations) + # Initial condition for flow equations: density wave + v1 = 0.1 + v2 = 0.2 + rho = 1 + 0.5 * sinpi(2 * (x[1] + x[2] - t * (v1 + v2))) + rho_v1 = rho * v1 + rho_v2 = rho * v2 + p = 20 + rho_e = p / (equations.flow_equations.gamma - 1) + 0.5 * rho * (v1^2 + v2^2) + + # Initial condition for tracers: blob in fraction of density + tracer = 0.2 * exp(-20 * (x[1] + 0.45)^2 - 10 * (x[2] - 0.15)^2) + + return SVector(rho, rho_v1, rho_v2, rho_e, rho * tracer) + end + + ############################################################################### + # semidiscretization of the compressible Euler equations + + gamma = 1.4 + flow_equations = CompressibleEulerEquations2D(gamma) + equations = PassiveTracerEquations(flow_equations, n_tracers = 1) + + # Create DG solver with polynomial degree = 5, Ranocha flux, and derived tracer flux + solver = DGSEM(polydeg = 5, surface_flux = FluxTracerEquationsCentral(flux_ranocha)) + + coordinates_min = (-1.0, -1.0) # minimum coordinates (min(x), min(y)) + coordinates_max = ( 1.0, 1.0) # maximum coordinates (max(x), max(y)) + trees_per_dimension = (4, 4) # initial resolution (without refinement) + mesh = T8codeMesh(trees_per_dimension, polydeg = 1, + coordinates_min = coordinates_min, coordinates_max = coordinates_max, + initial_refinement_level = 1) + + # Create spatial discretization + semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_wave_blob, + solver) + + ############################################################################### + # ODE solvers, callbacks etc. + + # Create ODE problem with time span from 0.0 to 2.0 + ode = semidiscretize(semi, (0.0, 2.0)); + + # SummaryCallback prints a summary of the simulation setup and recorded performance data + summary_callback = SummaryCallback() + + # AnalysisCallback analyses the solution at regular intervals and prints the results + analysis_interval = 100 + analysis_callback = AnalysisCallback(semi, interval=analysis_interval) + + # AliveCallback prints a one line summary at regular intervals + alive_callback = AliveCallback(analysis_interval=analysis_interval) + + # StepsizeCallback handles the re-calculation of the maximum Δt after each time step + stepsize_callback = StepsizeCallback(cfl=0.5) + + # AMRCallback triggers adaptive mesh refinement + @inline function first_tracer(u, equations::PassiveTracerEquations) + return Trixi.tracers(u, equations)[1] + end + amr_controller = ControllerThreeLevel(semi, IndicatorMax(semi, variable=first_tracer), + base_level=1, + med_level=2, med_threshold=0.1, + max_level=2, max_threshold=0.1) + amr_callback = AMRCallback(semi, amr_controller, + interval=10, + adapt_initial_condition=true, + adapt_initial_condition_only_refine=true) + + # SaveSolutionCallback writes the solution at regular intervals + save_solution = SaveSolutionCallback(interval=100, + save_initial_solution=true, + save_final_solution=true, + solution_variables = cons2prim) + + # CallbackSet collects all callbacks + callbacks = CallbackSet(summary_callback, + analysis_callback, + alive_callback, + amr_callback, + save_solution, + stepsize_callback) + + ############################################################################### + # create the time integrator + + # OrdinaryDiffEq's `integrator` + integrator = init(ode, CarpenterKennedy2N54(williamson_condition=false), + dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep=false, callback=callbacks); + + ############################################################################### + # Create simulation state + + simstate = SimulationState(semi, integrator) + + return simstate +end diff --git a/LibTrixi.jl/test/test_t8code.jl b/LibTrixi.jl/test/test_t8code.jl index 2f581595..dc69b8e1 100644 --- a/LibTrixi.jl/test/test_t8code.jl +++ b/LibTrixi.jl/test/test_t8code.jl @@ -6,7 +6,7 @@ using Trixi libelixir = joinpath(dirname(pathof(LibTrixi)), - "../examples/libelixir_t8code2d_advection_amr.jl") + "../examples/libelixir_t8code2d_euler_tracer_amr.jl") # initialize a simulation via API, receive a handle handle = trixi_initialize_simulation(libelixir) diff --git a/examples/trixi_controller_raw_data.c b/examples/trixi_controller_raw_data.c index 9d502a61..c2a83024 100644 --- a/examples/trixi_controller_raw_data.c +++ b/examples/trixi_controller_raw_data.c @@ -42,11 +42,15 @@ int main ( int argc, char *argv[] ) { double * raw_data = trixi_get_data_pointer(handle); for (int i = 0; i < ndofs; ++i) { - // Compute local deviation from density 1 - const double dev = raw_data[i] - 1.0; + // Density comes first + const double rho = raw_data[i]; - // Apply 20% damping - raw_data[i] = 1.0 + 0.8 * dev; + // Tracer comes last + const double rho_tracer = raw_data[4*ndofs + i]; + + // Apply 20% damping to tracer (fraction of density) + const double tracer = 0.8 * (rho_tracer / rho); + raw_data[4*ndofs + i] = tracer * rho; } } } diff --git a/test/c/t8code.cpp b/test/c/t8code.cpp index 9339b9b1..18bf50e4 100644 --- a/test/c/t8code.cpp +++ b/test/c/t8code.cpp @@ -9,7 +9,7 @@ const char * julia_project_path = JULIA_PROJECT_PATH; // Example libexlixir const char * libelixir_path = - "../../../LibTrixi.jl/examples/libelixir_t8code2d_advection_amr.jl"; + "../../../LibTrixi.jl/examples/libelixir_t8code2d_euler_tracer_amr.jl"; TEST(CInterfaceTest, T8code) { diff --git a/test/fortran/t8code_suite.f90 b/test/fortran/t8code_suite.f90 index 24d71545..e95afd84 100644 --- a/test/fortran/t8code_suite.f90 +++ b/test/fortran/t8code_suite.f90 @@ -10,7 +10,7 @@ module t8code_suite character(len=*), parameter, public :: julia_project_path = JULIA_PROJECT_PATH character(len=*), parameter, public :: libelixir_path = & - "../../../LibTrixi.jl/examples/libelixir_t8code2d_advection_amr.jl" + "../../../LibTrixi.jl/examples/libelixir_t8code2d_euler_tracer_amr.jl" contains From e5b53a7973ab2453d1867dd47208adecca523cd8 Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Thu, 31 Jul 2025 16:21:26 +0200 Subject: [PATCH 74/89] new Trixi compat --- LibTrixi.jl/test/Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LibTrixi.jl/test/Project.toml b/LibTrixi.jl/test/Project.toml index 19feeb5d..3174d971 100644 --- a/LibTrixi.jl/test/Project.toml +++ b/LibTrixi.jl/test/Project.toml @@ -5,7 +5,7 @@ Trixi = "a7f1ee26-1774-49b1-8366-f1abc58fbfcb" [compat] OrdinaryDiffEq = "6.53.2" -Trixi = "0.9.12, 0.10, 0.11, 0.12, 0.13" +Trixi = "0.11.12, 0.12, 0.13" [preferences.OrdinaryDiffEq] PrecompileAutoSpecialize = false From 7c5f20bc419c7c827d8ecffe0eaecb17e3acb41d Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Thu, 31 Jul 2025 16:51:10 +0200 Subject: [PATCH 75/89] adjust time steps --- LibTrixi.jl/examples/libelixir_t8code2d_euler_tracer_amr.jl | 2 +- examples/trixi_controller_raw_data.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/LibTrixi.jl/examples/libelixir_t8code2d_euler_tracer_amr.jl b/LibTrixi.jl/examples/libelixir_t8code2d_euler_tracer_amr.jl index 17bc3ba3..7485256b 100644 --- a/LibTrixi.jl/examples/libelixir_t8code2d_euler_tracer_amr.jl +++ b/LibTrixi.jl/examples/libelixir_t8code2d_euler_tracer_amr.jl @@ -63,7 +63,7 @@ function init_simstate() alive_callback = AliveCallback(analysis_interval=analysis_interval) # StepsizeCallback handles the re-calculation of the maximum Δt after each time step - stepsize_callback = StepsizeCallback(cfl=0.5) + stepsize_callback = StepsizeCallback(cfl = 1.0) # AMRCallback triggers adaptive mesh refinement @inline function first_tracer(u, equations::PassiveTracerEquations) diff --git a/examples/trixi_controller_raw_data.c b/examples/trixi_controller_raw_data.c index c2a83024..058c21a9 100644 --- a/examples/trixi_controller_raw_data.c +++ b/examples/trixi_controller_raw_data.c @@ -33,7 +33,7 @@ int main ( int argc, char *argv[] ) { trixi_step( handle ); steps++; - if (steps % 10 == 0) { + if (steps % 100 == 0) { // Get number of degrees of freedom int ndofs = trixi_ndofsglobal( handle ); From a15a65e8027978c0e641bbf10821b2032875044d Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Thu, 31 Jul 2025 17:55:23 +0200 Subject: [PATCH 76/89] fix access pattern --- .../examples/libelixir_t8code2d_euler_tracer_amr.jl | 8 ++++---- examples/trixi_controller_raw_data.c | 10 +++++----- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/LibTrixi.jl/examples/libelixir_t8code2d_euler_tracer_amr.jl b/LibTrixi.jl/examples/libelixir_t8code2d_euler_tracer_amr.jl index 7485256b..2d927d05 100644 --- a/LibTrixi.jl/examples/libelixir_t8code2d_euler_tracer_amr.jl +++ b/LibTrixi.jl/examples/libelixir_t8code2d_euler_tracer_amr.jl @@ -71,15 +71,15 @@ function init_simstate() end amr_controller = ControllerThreeLevel(semi, IndicatorMax(semi, variable=first_tracer), base_level=1, - med_level=2, med_threshold=0.1, - max_level=2, max_threshold=0.1) + med_level=2, med_threshold=0.05, + max_level=2, max_threshold=0.05) amr_callback = AMRCallback(semi, amr_controller, - interval=10, + interval=50, adapt_initial_condition=true, adapt_initial_condition_only_refine=true) # SaveSolutionCallback writes the solution at regular intervals - save_solution = SaveSolutionCallback(interval=100, + save_solution = SaveSolutionCallback(interval=50, save_initial_solution=true, save_final_solution=true, solution_variables = cons2prim) diff --git a/examples/trixi_controller_raw_data.c b/examples/trixi_controller_raw_data.c index 058c21a9..5e64ae38 100644 --- a/examples/trixi_controller_raw_data.c +++ b/examples/trixi_controller_raw_data.c @@ -43,14 +43,14 @@ int main ( int argc, char *argv[] ) { for (int i = 0; i < ndofs; ++i) { // Density comes first - const double rho = raw_data[i]; + const double rho = raw_data[5*i]; // Tracer comes last - const double rho_tracer = raw_data[4*ndofs + i]; + const double rho_tracer = raw_data[5*i + 4]; - // Apply 20% damping to tracer (fraction of density) - const double tracer = 0.8 * (rho_tracer / rho); - raw_data[4*ndofs + i] = tracer * rho; + // Apply 10% damping to tracer (fraction of density) + const double tracer = 0.9 * (rho_tracer / rho); + raw_data[5*i + 4] = tracer * rho; } } } From f3927d592298925893413c1ab9b3834b082f372d Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Fri, 1 Aug 2025 00:07:30 +0200 Subject: [PATCH 77/89] add trixi_(load|store)_conservative_vars --- .github/workflows/ci.yml | 21 ++-- LibTrixi.jl/src/LibTrixi.jl | 6 + LibTrixi.jl/src/api_c.jl | 48 ++++++++ LibTrixi.jl/src/api_jl.jl | 49 ++++++++ LibTrixi.jl/test/test_interface.jl | 21 ++++ README.md | 2 +- docs/src/index.md | 2 +- examples/.gitignore | 12 +- examples/CMakeLists.txt | 7 +- ...er_data.c => trixi_controller_data_load.c} | 0 ...ata.f90 => trixi_controller_data_load.f90} | 2 +- ...w_data.c => trixi_controller_data_store.c} | 28 +++++ examples/trixi_controller_data_store.f90 | 115 ++++++++++++++++++ src/api.c | 55 +++++++++ src/api.f90 | 42 +++++++ src/trixi.h | 2 + 16 files changed, 393 insertions(+), 19 deletions(-) rename examples/{trixi_controller_data.c => trixi_controller_data_load.c} (100%) rename examples/{trixi_controller_data.f90 => trixi_controller_data_load.f90} (98%) rename examples/{trixi_controller_raw_data.c => trixi_controller_data_store.c} (68%) create mode 100644 examples/trixi_controller_data_store.f90 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5c1adf20..76ae3bd9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -243,9 +243,10 @@ jobs: # all controllers ../build/examples/trixi_controller_simple_c . libelixir_tree1d_advection_basic.jl ../build/examples/trixi_controller_simple_f . libelixir_tree1d_advection_basic.jl - ../build/examples/trixi_controller_data_c . libelixir_t8code2d_euler_tracer_amr.jl - ../build/examples/trixi_controller_data_f . libelixir_t8code2d_euler_tracer_amr.jl - ../build/examples/trixi_controller_raw_data_c . libelixir_t8code2d_euler_tracer_amr.jl + ../build/examples/trixi_controller_data_load_c . libelixir_t8code2d_euler_tracer_amr.jl + ../build/examples/trixi_controller_data_load_f . libelixir_t8code2d_euler_tracer_amr.jl + ../build/examples/trixi_controller_data_store_c . libelixir_t8code2d_euler_tracer_amr.jl + ../build/examples/trixi_controller_data_store_f . libelixir_t8code2d_euler_tracer_amr.jl ../build/examples/trixi_controller_t8code_c . libelixir_t8code2d_euler_tracer_amr.jl ../build/examples/trixi_controller_t8code_f . libelixir_t8code2d_euler_tracer_amr.jl ../build/examples/trixi_controller_baroclinic_c . libelixir_t8code3d_euler_baroclinic_instability.jl @@ -276,12 +277,14 @@ jobs: "../build/examples/trixi_controller_simple_c ." \ "../build/examples/trixi_controller_simple_f" \ "../build/examples/trixi_controller_simple_f ." \ - "../build/examples/trixi_controller_data_c" \ - "../build/examples/trixi_controller_data_c ." \ - "../build/examples/trixi_controller_data_f" \ - "../build/examples/trixi_controller_data_f ." \ - "../build/examples/trixi_controller_raw_data_c" \ - "../build/examples/trixi_controller_raw_data_c ." \ + "../build/examples/trixi_controller_data_load_c" \ + "../build/examples/trixi_controller_data_load_c ." \ + "../build/examples/trixi_controller_data_load_f" \ + "../build/examples/trixi_controller_data_load_f ." \ + "../build/examples/trixi_controller_data_store_c" \ + "../build/examples/trixi_controller_data_store_c ." \ + "../build/examples/trixi_controller_data_store_f" \ + "../build/examples/trixi_controller_data_store_f ." \ "../build/examples/trixi_controller_t8code_c" \ "../build/examples/trixi_controller_t8code_c ." \ "../build/examples/trixi_controller_t8code_f" \ diff --git a/LibTrixi.jl/src/LibTrixi.jl b/LibTrixi.jl/src/LibTrixi.jl index 385b5b04..89f0e50c 100644 --- a/LibTrixi.jl/src/LibTrixi.jl +++ b/LibTrixi.jl/src/LibTrixi.jl @@ -52,12 +52,18 @@ export trixi_load_node_reference_coordinates, export trixi_load_node_weights, trixi_load_node_weights_cfptr, trixi_load_node_weights_jl +export trixi_load_conservative_vars, + trixi_load_conservative_vars_cfptr, + trixi_load_conservative_vars_jl export trixi_load_primitive_vars, trixi_load_primitive_vars_cfptr, trixi_load_primitive_vars_jl export trixi_load_element_averaged_primitive_vars, trixi_load_element_averaged_primitive_vars_cfptr, trixi_load_element_averaged_primitive_vars_jl +export trixi_store_conservative_vars, + trixi_store_conservative_vars_cfptr, + trixi_store_conservative_vars_jl export trixi_register_data, trixi_register_data_cfptr, trixi_register_data_jl diff --git a/LibTrixi.jl/src/api_c.jl b/LibTrixi.jl/src/api_c.jl index 7ebc5655..7893a41d 100644 --- a/LibTrixi.jl/src/api_c.jl +++ b/LibTrixi.jl/src/api_c.jl @@ -432,6 +432,30 @@ trixi_load_node_weights_cfptr() = @cfunction(trixi_load_node_weights, Cvoid, (Cint, Ptr{Cdouble})) +""" + trixi_load_conservative_vars(simstate_handle::Cint, variable_id::Cint, + data::Ptr{Cdouble})::Cvoid + +Load conservative variable. +""" +function trixi_load_conservative_vars end + +Base.@ccallable function trixi_load_conservative_vars(simstate_handle::Cint, + variable_id::Cint, + data::Ptr{Cdouble})::Cvoid + simstate = load_simstate(simstate_handle) + + # convert C to Julia array + size = trixi_ndofs_jl(simstate) + data_jl = unsafe_wrap(Array, data, size) + + trixi_load_conservative_vars_jl(simstate, variable_id, data_jl) +end + +trixi_load_conservative_vars_cfptr() = + @cfunction(trixi_load_conservative_vars, Cvoid, (Cint, Cint, Ptr{Cdouble})) + + """ trixi_load_primitive_vars(simstate_handle::Cint, variable_id::Cint, data::Ptr{Cdouble})::Cvoid @@ -461,6 +485,30 @@ trixi_load_primitive_vars_cfptr() = @cfunction(trixi_load_primitive_vars, Cvoid, (Cint, Cint, Ptr{Cdouble})) +""" + trixi_store_conservative_vars(simstate_handle::Cint, variable_id::Cint, + data::Ptr{Cdouble})::Cvoid + +Store conservative variable. +""" +function trixi_store_conservative_vars end + +Base.@ccallable function trixi_store_conservative_vars(simstate_handle::Cint, + variable_id::Cint, + data::Ptr{Cdouble})::Cvoid + simstate = load_simstate(simstate_handle) + + # convert C to Julia array + size = trixi_ndofs_jl(simstate) + data_jl = unsafe_wrap(Array, data, size) + + trixi_store_conservative_vars_jl(simstate, variable_id, data_jl) +end + +trixi_store_conservative_vars_cfptr() = + @cfunction(trixi_store_conservative_vars, Cvoid, (Cint, Cint, Ptr{Cdouble})) + + """ trixi_register_data(data::Ptr{Cdouble}, size::Cint, index::Cint, simstate_handle::Cint)::Cvoid diff --git a/LibTrixi.jl/src/api_jl.jl b/LibTrixi.jl/src/api_jl.jl index d43cfe28..8031d2bd 100644 --- a/LibTrixi.jl/src/api_jl.jl +++ b/LibTrixi.jl/src/api_jl.jl @@ -140,6 +140,31 @@ function trixi_load_node_weights_jl(simstate, data) end +function trixi_load_conservative_vars_jl(simstate, variable_id, data) + mesh, equations, solver, cache = mesh_equations_solver_cache(simstate.semi) + n_nodes_per_dim = nnodes(solver) + n_dims = ndims(mesh) + n_nodes = n_nodes_per_dim^n_dims + + u_ode = simstate.integrator.u + u = wrap_array(u_ode, mesh, equations, solver, cache) + + # all permutations of nodes indices for arbitrary dimension + node_cis = CartesianIndices(ntuple(i -> n_nodes_per_dim, n_dims)) + node_lis = LinearIndices(node_cis) + + for element in eachelement(solver, cache) + for node_ci in node_cis + node_vars = get_node_vars(u, equations, solver, node_ci, element) + node_index = (element-1) * n_nodes + node_lis[node_ci] + data[node_index] = node_vars[variable_id] + end + end + + return nothing +end + + function trixi_load_primitive_vars_jl(simstate, variable_id, data) mesh, equations, solver, cache = mesh_equations_solver_cache(simstate.semi) n_nodes_per_dim = nnodes(solver) @@ -201,6 +226,30 @@ function trixi_load_element_averaged_primitive_vars_jl(simstate, variable_id, da end +function trixi_store_conservative_vars_jl(simstate, variable_id, data) + mesh, equations, solver, cache = mesh_equations_solver_cache(simstate.semi) + n_nodes_per_dim = nnodes(solver) + n_dims = ndims(mesh) + n_nodes = n_nodes_per_dim^n_dims + + u_ode = simstate.integrator.u + u = wrap_array(u_ode, mesh, equations, solver, cache) + + # all permutations of nodes indices for arbitrary dimension + node_cis = CartesianIndices(ntuple(i -> n_nodes_per_dim, n_dims)) + node_lis = LinearIndices(node_cis) + + for element in eachelement(solver, cache) + for node_ci in node_cis + node_index = (element-1) * n_nodes + node_lis[node_ci] + u[variable_id, node_ci, element] = data[node_index] + end + end + + return nothing +end + + function trixi_register_data_jl(simstate, index, data) simstate.registry[index] = data if show_debug_output() diff --git a/LibTrixi.jl/test/test_interface.jl b/LibTrixi.jl/test/test_interface.jl index 7278cbf0..28698580 100644 --- a/LibTrixi.jl/test/test_interface.jl +++ b/LibTrixi.jl/test/test_interface.jl @@ -141,12 +141,33 @@ end trixi_load_element_averaged_primitive_vars_jl(simstate_jl, 1, data_jl) @test data_c == data_jl + # compare conservative variable values on all dofs + data_c = zeros(ndofs_c) + trixi_load_conservative_vars(handle, Int32(1), pointer(data_c)) + data_jl = zeros(ndofs_jl) + trixi_load_conservative_vars_jl(simstate_jl, 1, data_jl) + @test data_c == data_jl + # compare primitive variable values on all dofs data_c = zeros(ndofs_c) trixi_load_primitive_vars(handle, Int32(1), pointer(data_c)) data_jl = zeros(ndofs_jl) trixi_load_primitive_vars_jl(simstate_jl, 1, data_jl) @test data_c == data_jl + + # write 1.0 to first variable and compare via raw access + data_c = fill(1.0, ndofs_c) + trixi_store_primitive_vars(handle, Int32(1), pointer(data_c)) + data_ptr_c = trixi_get_data_pointer(handle) + data_jl = unsafe_wrap(Array, data_ptr_c, ndofs_c) + @test data_jl .== 1.0 + + # write 2.0 to first variable and compare via raw access + data_jl = fill(2.0, ndofs_jl) + trixi_store_primitive_vars_jl(simstate_jl, 1, data_jl) + data_ptr_jl = trixi_get_data_pointer_jl(simstate_jl) + data_jl = unsafe_wrap(Array, data_ptr_jl, ndofs_jl) + @test data_jl .== 2.0 end diff --git a/README.md b/README.md index 47735339..c9c74b20 100644 --- a/README.md +++ b/README.md @@ -213,7 +213,7 @@ aspects on how to use the C and Fortran APIs of libtrixi: - `trixi_controller_simple.(c|f90)`: basic usage - `trixi_controller_mpi.(c|f90)`: usage in the presence of MPI -- `trixi_controller_data.(c|f90)`: simulation data access +- `trixi_controller_data_load.(c|f90)`: simulation data access - `trixi_controller_t8code.(c|f90)`: interacting with t8code If you just want to test the Julia part of libtrixi, i.e., LibTrixi.jl, you can also run diff --git a/docs/src/index.md b/docs/src/index.md index 3c19903d..4640c277 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -216,7 +216,7 @@ examples demonstrate different aspects on how to use the C and Fortran APIs of l - `trixi_controller_simple.(c|f90)`: basic usage - `trixi_controller_mpi.(c|f90)`: usage in the presence of MPI -- `trixi_controller_data.(c|f90)`: simulation data access +- `trixi_controller_data_load.(c|f90)`: simulation data access - `trixi_controller_t8code.(c|f90)`: interacting with t8code If you just want to test the Julia part of libtrixi, i.e., LibTrixi.jl, you can also run diff --git a/examples/.gitignore b/examples/.gitignore index 70e92df7..f95b5fed 100644 --- a/examples/.gitignore +++ b/examples/.gitignore @@ -1,8 +1,12 @@ -trixi_controller_simple_c -trixi_controller_simple_f +trixi_controller_baroclinic_c +trixi_controller_baroclinic_f +trixi_controller_data_load_c +trixi_controller_data_load_f +trixi_controller_data_store_c +trixi_controller_data_store_f trixi_controller_mpi_c trixi_controller_mpi_f -trixi_controller_data_c -trixi_controller_data_f +trixi_controller_simple_c +trixi_controller_simple_f trixi_controller_t8code_c trixi_controller_t8code_f diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 3d4a5cce..508fb4bf 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -3,9 +3,10 @@ set ( EXAMPLES trixi_controller_simple.f90 trixi_controller_mpi.c trixi_controller_mpi.f90 - trixi_controller_data.c - trixi_controller_data.f90 - trixi_controller_raw_data.c + trixi_controller_data_load.c + trixi_controller_data_load.f90 + trixi_controller_data_store.c + trixi_controller_data_store.f90 trixi_controller_t8code.c trixi_controller_t8code.f90 trixi_controller_baroclinic.c diff --git a/examples/trixi_controller_data.c b/examples/trixi_controller_data_load.c similarity index 100% rename from examples/trixi_controller_data.c rename to examples/trixi_controller_data_load.c diff --git a/examples/trixi_controller_data.f90 b/examples/trixi_controller_data_load.f90 similarity index 98% rename from examples/trixi_controller_data.f90 rename to examples/trixi_controller_data_load.f90 index d5d09667..7c7f9e59 100644 --- a/examples/trixi_controller_data.f90 +++ b/examples/trixi_controller_data_load.f90 @@ -1,4 +1,4 @@ -program trixi_controller_data_f +program trixi_controller_data_load_f use LibTrixi use, intrinsic :: iso_fortran_env, only: error_unit use, intrinsic :: iso_c_binding, only: c_int, c_double diff --git a/examples/trixi_controller_raw_data.c b/examples/trixi_controller_data_store.c similarity index 68% rename from examples/trixi_controller_raw_data.c rename to examples/trixi_controller_data_store.c index 5e64ae38..6b5c27d1 100644 --- a/examples/trixi_controller_raw_data.c +++ b/examples/trixi_controller_data_store.c @@ -26,6 +26,8 @@ int main ( int argc, char *argv[] ) { // Main loop int steps = 0; + double* rho = NULL; + double* rho_tracer = NULL; printf("\n*** Trixi controller *** Entering main loop\n"); while ( !trixi_is_finished( handle ) ) { @@ -53,6 +55,29 @@ int main ( int argc, char *argv[] ) { raw_data[5*i + 4] = tracer * rho; } } + + if (steps % 100 == 50) { + + // Get number of degrees of freedom + int ndofs = trixi_ndofsglobal( handle ); + + // Allocate memory + rho = realloc( rho, sizeof(double) * ndofs ); + rho_tracer = realloc( rho_tracer, sizeof(double) * ndofs ); + + // Get density and tracer + trixi_load_conservative_vars(handle, 1, rho); + trixi_load_conservative_vars(handle, 5, rho_tracer); + + for (int i = 0; i < ndofs; ++i) { + // Apply 5% amplification to tracer (fraction of density) + const double tracer = 1.05 * (rho_tracer[i] / rho[i]); + rho_tracer[i] = tracer * rho[i]; + } + + // Write back tracer + trixi_store_conservative_vars(handle, 5, rho_tracer); + } } // Finalize Trixi simulation @@ -63,5 +88,8 @@ int main ( int argc, char *argv[] ) { printf("\n*** Trixi controller *** Finalize Trixi\n"); trixi_finalize(); + free(rho); + free(rho_tracer); + return 0; } diff --git a/examples/trixi_controller_data_store.f90 b/examples/trixi_controller_data_store.f90 new file mode 100644 index 00000000..f11f1744 --- /dev/null +++ b/examples/trixi_controller_data_store.f90 @@ -0,0 +1,115 @@ +program trixi_controller_data_store_f + use LibTrixi + use, intrinsic :: iso_fortran_env, only: error_unit + use, intrinsic :: iso_c_binding, only: c_int, c_double, c_f_pointer, c_ptr + + implicit none + + integer(c_int) :: handle, ndofs, steps, i + character(len=256) :: argument + integer, parameter :: dp = selected_real_kind(12) + real(dp) :: tracer, rho_val, rho_tracer_val + real(dp), dimension(:), pointer :: rho => null(), rho_tracer => null() + type(c_ptr) :: raw_data_c + real(c_double), dimension(:), pointer :: raw_data + + + if (command_argument_count() < 1) then + call get_command_argument(0, argument) + write(error_unit, '(a)') "ERROR: missing arguments: PROJECT_DIR LIBELIXIR_PATH" + write(error_unit, '(a)') "" + write(error_unit, '(3a)') "usage: ", trim(argument), " PROJECT_DIR LIBELIXIR_PATH" + call exit(2) + else if (command_argument_count() < 2) then + call get_command_argument(0, argument) + write(error_unit, '(a)') "ERROR: missing argument: LIBELIXIR_PATH" + write(error_unit, '(a)') "" + write(error_unit, '(3a)') "usage: ", trim(argument), " PROJECT_DIR LIBELIXIR_PATH" + call exit(2) + end if + + + ! Initialize Trixi + write(*, '(a)') "" + write(*, '(a)') "*** Trixi controller *** Initialize Trixi" + call get_command_argument(1, argument) + call trixi_initialize(argument) + + ! Set up the Trixi simulation + ! We get a handle to use subsequently + write(*, '(a)') "*** Trixi controller *** Set up Trixi simulation" + call get_command_argument(2, argument) + handle = trixi_initialize_simulation(argument) + + ! Main loop + steps = 0 + write(*, '(a)') "*** Trixi controller *** Entering main loop" + + do + ! Exit loop once simulation is completed + if ( trixi_is_finished(handle) ) exit + + call trixi_step(handle) + steps = steps + 1 + + if (modulo(steps, 100) == 0) then + ! get number of degrees of freedom + ndofs = trixi_ndofsglobal(handle) + + ! Get a pointer to Trixi's internal simulation data + raw_data_c = trixi_get_data_pointer(handle) + call c_f_pointer(raw_data_c, raw_data, [ndofs]) + + do i = 1,ndofs + ! density comes first + rho_val = raw_data(5*(i-1) + 1 ) + + ! tracer comes last + rho_tracer_val = raw_data(5*i) + + ! Apply 10% damping to tracer (fraction of density) + tracer = 0.9 * (rho_tracer_val / rho_val) + raw_data(5*i) = tracer * rho_val + end do + end if + + if (modulo(steps, 100) == 50) then + ! get number of degrees of freedom + ndofs = trixi_ndofsglobal(handle) + + ! allocate memory + if ( associated(rho) ) deallocate(rho) + allocate( rho(ndofs) ) + if ( associated(rho_tracer) ) deallocate(rho_tracer) + allocate( rho_tracer(ndofs) ) + + ! get density and tracer + call trixi_load_conservative_vars(handle, 1, rho) + call trixi_load_conservative_vars(handle, 5, rho_tracer) + + do i = 1,ndofs + ! apply 5% amplification to tracer (fraction of density) + tracer = 1.05 * (rho_tracer(i) / rho(i)) + rho_tracer(i) = tracer * rho(i) + end do + + ! wite back tracer + call trixi_store_conservative_vars(handle, 5, rho_tracer) + end if + end do + + ! Finalize Trixi simulation + write(*, '(a)') "" + write(*, '(a)') "*** Trixi controller *** Finalize Trixi simulation" + call trixi_finalize_simulation(handle) + + ! Finalize Trixi + write(*, '(a)') "" + write(*, '(a)') "*** Trixi controller *** Finalize Trixi" + call trixi_finalize() + + deallocate(rho) + nullify(rho) + deallocate(rho_tracer) + nullify(rho_tracer) +end program diff --git a/src/api.c b/src/api.c index 4eddae8c..3c5e013b 100644 --- a/src/api.c +++ b/src/api.c @@ -22,8 +22,10 @@ enum { TRIXI_FPTR_NNODES, TRIXI_FPTR_LOAD_NODE_REFERENCE_COORDINATES, TRIXI_FPTR_LOAD_NODE_WEIGHTS, + TRIXI_FPTR_LOAD_CONSERVATIVE_VARS, TRIXI_FTPR_LOAD_PRIMITIVE_VARS, TRIXI_FTPR_LOAD_ELEMENT_AVERAGED_PRIMITIVE_VARS, + TRIXI_FPTR_STORE_CONSERVATIVE_VARS, TRIXI_FTPR_REGISTER_DATA, TRIXI_FPTR_GET_DATA_POINTER, TRIXI_FTPR_VERSION_LIBRARY, @@ -61,8 +63,10 @@ static const char* trixi_function_pointer_names[] = { [TRIXI_FPTR_NNODES] = "trixi_nnodes_cfptr", [TRIXI_FPTR_LOAD_NODE_REFERENCE_COORDINATES] = "trixi_load_node_reference_coordinates_cfptr", [TRIXI_FPTR_LOAD_NODE_WEIGHTS] = "trixi_load_node_weights_cfptr", + [TRIXI_FPTR_LOAD_CONSERVATIVE_VARS] = "trixi_load_conservative_vars_cfptr", [TRIXI_FTPR_LOAD_PRIMITIVE_VARS] = "trixi_load_primitive_vars_cfptr", [TRIXI_FTPR_LOAD_ELEMENT_AVERAGED_PRIMITIVE_VARS] = "trixi_load_element_averaged_primitive_vars_cfptr", + [TRIXI_FPTR_STORE_CONSERVATIVE_VARS] = "trixi_store_conservative_vars_cfptr", [TRIXI_FTPR_REGISTER_DATA] = "trixi_register_data_cfptr", [TRIXI_FPTR_GET_DATA_POINTER] = "trixi_get_data_pointer_cfptr", [TRIXI_FTPR_VERSION_LIBRARY] = "trixi_version_library_cfptr", @@ -645,6 +649,32 @@ void trixi_load_node_weights(int handle, double* node_weights) { } +/** + * @anchor trixi_load_conservative_vars_api_c + * + * @brief Load conservative variable. + * + * The values for the conservative variable at position `variable_id` at every degree of + * freedom are stored in the given array `data`. + * + * The given array has to be of correct size (ndofs) and memory has to be allocated + * beforehand. + * + * @param[in] handle simulation handle + * @param[in] variable_id index of variable + * @param[out] data values for all degrees of freedom + */ +void trixi_load_conservative_vars(int handle, int variable_id, double * data) { + + // Get function pointer + void (*load_conservative_vars)(int, int, double *) = + trixi_function_pointers[TRIXI_FPTR_LOAD_CONSERVATIVE_VARS]; + + // Call function + return load_conservative_vars(handle, variable_id, data); +} + + /** * @anchor trixi_load_primitive_vars_api_c * @@ -697,6 +727,31 @@ void trixi_load_element_averaged_primitive_vars(int handle, int variable_id, dou } +/** + * @anchor trixi_store_conservative_vars_api_c + * + * @brief Store conservative variable. + * + * The values for the conservative variable at position `variable_id` at every degree of + * freedom are read from the given array `data` and written to Trixi.jl's internal storage. * + * + * The given array has to be of correct size (ndofs). + * + * @param[in] handle simulation handle + * @param[in] variable_id index of variable + * @param[in] data values for all degrees of freedom + */ +void trixi_store_conservative_vars(int handle, int variable_id, double * data) { + + // Get function pointer + void (*store_conservative_vars)(int, int, double *) = + trixi_function_pointers[TRIXI_FPTR_STORE_CONSERVATIVE_VARS]; + + // Call function + return store_conservative_vars(handle, variable_id, data); +} + + /** * @anchor trixi_register_data_api_c * diff --git a/src/api.f90 b/src/api.f90 index 0dec1e47..a0743b63 100644 --- a/src/api.f90 +++ b/src/api.f90 @@ -374,6 +374,27 @@ subroutine trixi_load_node_weights(handle, node_weights) bind(c) real(c_double), dimension(*), intent(out) :: node_weights end subroutine + !> + !! @anchor trixi_load_conservative_vars_api_c + !! + !! @brief Load conservative variable. + !! + !! The values for the conservative variable at position `variable_id` at every degree of + !! freedom are stored in the given array `data`. + !! + !! The given array has to be of correct size (ndofs) and memory has to be allocated + !! beforehand. + !! + !! @param[in] handle simulation handle + !! @param[in] variable_id index of variable + !! @param[out] data values for all degrees of freedom + subroutine trixi_load_conservative_vars(handle, variable_id, data) bind(c) + use, intrinsic :: iso_c_binding, only: c_int, c_double + integer(c_int), value, intent(in) :: handle + integer(c_int), value, intent(in) :: variable_id + real(c_double), dimension(*), intent(out) :: data + end subroutine + !> !! @fn LibTrixi::trixi_load_primitive_vars::trixi_load_primitive_vars(handle, variable_id, data) !! @@ -423,6 +444,27 @@ subroutine trixi_load_element_averaged_primitive_vars(handle, variable_id, data) real(c_double), dimension(*), intent(out) :: data end subroutine + !> + !! @anchor trixi_store_conservative_vars_api_c + !! + !! @brief Store conservative variable. + !! + !! The values for the conservative variable at position `variable_id` at every degree of + !! freedom are read from the given array `data` and written to Trixi.jl's internal + !! storage. + !! + !! The given array has to be of correct size (ndofs). + !! + !! @param[in] handle simulation handle + !! @param[in] variable_id index of variable + !! @param[in] data values for all degrees of freedom + subroutine trixi_store_conservative_vars(handle, variable_id, data) bind(c) + use, intrinsic :: iso_c_binding, only: c_int, c_double + integer(c_int), value, intent(in) :: handle + integer(c_int), value, intent(in) :: variable_id + real(c_double), dimension(*), intent(in) :: data + end subroutine + !> !! @fn LibTrixi::trixi_register_data::trixi_register_data(handle, variable_id, data) !! diff --git a/src/trixi.h b/src/trixi.h index f2584189..4a975dce 100644 --- a/src/trixi.h +++ b/src/trixi.h @@ -37,8 +37,10 @@ double trixi_calculate_dt(int handle); double trixi_get_simulation_time(int handle); void trixi_load_node_reference_coordinates(int handle, double* node_coords); void trixi_load_node_weights(int handle, double* node_weights); +void trixi_load_conservative_vars(int handle, int variable_id, double * data); void trixi_load_primitive_vars(int handle, int variable_id, double * data); void trixi_load_element_averaged_primitive_vars(int handle, int variable_id, double * data); +void trixi_store_conservative_vars(int handle, int variable_id, double * data); void trixi_register_data(int handle, int index, int size, const double * data); double * trixi_get_data_pointer(int handle); From bd0670e7b241135bb308b10d6303e95edd5133e3 Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Fri, 1 Aug 2025 00:19:51 +0200 Subject: [PATCH 78/89] tests --- LibTrixi.jl/test/test_interface.jl | 4 ++-- test/c/simulation.cpp | 21 ++++++++++++++++++++- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/LibTrixi.jl/test/test_interface.jl b/LibTrixi.jl/test/test_interface.jl index 28698580..21b4f99a 100644 --- a/LibTrixi.jl/test/test_interface.jl +++ b/LibTrixi.jl/test/test_interface.jl @@ -157,14 +157,14 @@ end # write 1.0 to first variable and compare via raw access data_c = fill(1.0, ndofs_c) - trixi_store_primitive_vars(handle, Int32(1), pointer(data_c)) + trixi_store_conservative_vars(handle, Int32(1), pointer(data_c)) data_ptr_c = trixi_get_data_pointer(handle) data_jl = unsafe_wrap(Array, data_ptr_c, ndofs_c) @test data_jl .== 1.0 # write 2.0 to first variable and compare via raw access data_jl = fill(2.0, ndofs_jl) - trixi_store_primitive_vars_jl(simstate_jl, 1, data_jl) + trixi_store_conservative_vars_jl(simstate_jl, 1, data_jl) data_ptr_jl = trixi_get_data_pointer_jl(simstate_jl) data_jl = unsafe_wrap(Array, data_ptr_jl, ndofs_jl) @test data_jl .== 2.0 diff --git a/test/c/simulation.cpp b/test/c/simulation.cpp index 36fbccbb..ea07ce80 100644 --- a/test/c/simulation.cpp +++ b/test/c/simulation.cpp @@ -100,8 +100,18 @@ TEST(CInterfaceTest, SimulationRun) { } EXPECT_NEAR(integral, 0.4, 1e-17); - // Check primitive variable values on all dofs + // Check conservative variable values std::vector rho(ndofs); + std::vector rho_energy(ndofs); + trixi_load_conservative_vars(handle, 1, rho.data()); + trixi_load_conservative_vars(handle, 4, rho_energy.data()); + // check memory borders + EXPECT_DOUBLE_EQ(rho[0], 1.0); + EXPECT_DOUBLE_EQ(rho[ndofs-1], 1.0); + EXPECT_DOUBLE_EQ(rho_energy[0], 1.0e-5); + EXPECT_DOUBLE_EQ(rho_energy[ndofs-1], 1.0e-5); + + // Check primitive variable values std::vector energy(ndofs); trixi_load_primitive_vars(handle, 1, rho.data()); trixi_load_primitive_vars(handle, 4, energy.data()); @@ -166,6 +176,15 @@ TEST(CInterfaceTest, SimulationRun) { FAIL() << "Test cannot be run with " << nranks << " ranks."; } + // Check storing of conservative variables + rho[0] = 42.0 + rho[ndofs-1] = 23.0 + trixi_store_conservative_vars(handle, 1, rho.data()); + + double * raw_data = trixi_get_data_pointer(handle); + EXPECT_DOUBLE_EQ(rho[0], raw_data[0]); + EXPECT_DOUBLE_EQ(rho[ndofs-1], raw_data[5*(ndofs-1)]); + // Finalize Trixi simulation trixi_finalize_simulation(handle); From aa098d9690d1ef23fcedfa382415e620d4e49e0e Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Fri, 1 Aug 2025 00:27:27 +0200 Subject: [PATCH 79/89] !fixup --- examples/trixi_controller_data_store.f90 | 2 +- test/c/simulation.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/trixi_controller_data_store.f90 b/examples/trixi_controller_data_store.f90 index f11f1744..ab2960ff 100644 --- a/examples/trixi_controller_data_store.f90 +++ b/examples/trixi_controller_data_store.f90 @@ -93,7 +93,7 @@ program trixi_controller_data_store_f rho_tracer(i) = tracer * rho(i) end do - ! wite back tracer + ! write back tracer call trixi_store_conservative_vars(handle, 5, rho_tracer) end if end do diff --git a/test/c/simulation.cpp b/test/c/simulation.cpp index ea07ce80..f7d266ea 100644 --- a/test/c/simulation.cpp +++ b/test/c/simulation.cpp @@ -177,8 +177,8 @@ TEST(CInterfaceTest, SimulationRun) { } // Check storing of conservative variables - rho[0] = 42.0 - rho[ndofs-1] = 23.0 + rho[0] = 42.0; + rho[ndofs-1] = 23.0; trixi_store_conservative_vars(handle, 1, rho.data()); double * raw_data = trixi_get_data_pointer(handle); From b29b880be4da59780b81460fe67fc151bdff7252 Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Fri, 1 Aug 2025 00:33:52 +0200 Subject: [PATCH 80/89] !fixup --- LibTrixi.jl/test/test_interface.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/LibTrixi.jl/test/test_interface.jl b/LibTrixi.jl/test/test_interface.jl index 21b4f99a..51e5a537 100644 --- a/LibTrixi.jl/test/test_interface.jl +++ b/LibTrixi.jl/test/test_interface.jl @@ -160,14 +160,14 @@ end trixi_store_conservative_vars(handle, Int32(1), pointer(data_c)) data_ptr_c = trixi_get_data_pointer(handle) data_jl = unsafe_wrap(Array, data_ptr_c, ndofs_c) - @test data_jl .== 1.0 + @test all(data_jl .== 1.0) # write 2.0 to first variable and compare via raw access data_jl = fill(2.0, ndofs_jl) trixi_store_conservative_vars_jl(simstate_jl, 1, data_jl) data_ptr_jl = trixi_get_data_pointer_jl(simstate_jl) data_jl = unsafe_wrap(Array, data_ptr_jl, ndofs_jl) - @test data_jl .== 2.0 + @test all(data_jl .== 2.0) end From 4ee71ba91dd409424b884e85c17316b7a2db6e25 Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Fri, 1 Aug 2025 01:06:37 +0200 Subject: [PATCH 81/89] fortran test --- test/c/simulation.cpp | 6 +++--- test/fortran/simulationRun_suite.f90 | 24 +++++++++++++++++++++++- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/test/c/simulation.cpp b/test/c/simulation.cpp index f7d266ea..f67d9be5 100644 --- a/test/c/simulation.cpp +++ b/test/c/simulation.cpp @@ -108,8 +108,8 @@ TEST(CInterfaceTest, SimulationRun) { // check memory borders EXPECT_DOUBLE_EQ(rho[0], 1.0); EXPECT_DOUBLE_EQ(rho[ndofs-1], 1.0); - EXPECT_DOUBLE_EQ(rho_energy[0], 1.0e-5); - EXPECT_DOUBLE_EQ(rho_energy[ndofs-1], 1.0e-5); + EXPECT_DOUBLE_EQ(rho_energy[0], 2.5e-5); + EXPECT_DOUBLE_EQ(rho_energy[ndofs-1], 2.5e-5); // Check primitive variable values std::vector energy(ndofs); @@ -183,7 +183,7 @@ TEST(CInterfaceTest, SimulationRun) { double * raw_data = trixi_get_data_pointer(handle); EXPECT_DOUBLE_EQ(rho[0], raw_data[0]); - EXPECT_DOUBLE_EQ(rho[ndofs-1], raw_data[5*(ndofs-1)]); + EXPECT_DOUBLE_EQ(rho[ndofs-1], raw_data[4*(ndofs-1)]); // Finalize Trixi simulation trixi_finalize_simulation(handle); diff --git a/test/fortran/simulationRun_suite.f90 b/test/fortran/simulationRun_suite.f90 index c9261f02..3d9c1157 100644 --- a/test/fortran/simulationRun_suite.f90 +++ b/test/fortran/simulationRun_suite.f90 @@ -1,6 +1,7 @@ module simulationRun_suite use LibTrixi use testdrive, only : new_unittest, unittest_type, error_type, check + use, intrinsic :: iso_c_binding, only: c_double, c_f_pointer, c_ptr implicit none private @@ -29,6 +30,8 @@ subroutine test_simulationRun(error) integer, parameter :: dp = selected_real_kind(15) real(dp) :: dt, time, integral real(dp), dimension(:), allocatable :: data, weights + type(c_ptr) :: raw_data_c + real(c_double), dimension(:), pointer :: raw_data ! Initialize Trixi call trixi_initialize(julia_project_path) @@ -99,9 +102,17 @@ subroutine test_simulationRun(error) call check(error, integral, 0.4_dp) deallocate(data) - ! Check primitive variable values + ! Check conservative variable values size = ndofs allocate(data(size)) + call trixi_load_conservative_vars(handle, 1, data) + call check(error, data(1), 1.0_dp) + call check(error, data(3200), 1.0_dp) + call check(error, data(size), 2.5e-5_dp) + deallocate(data) + + ! Check primitive variable values + allocate(data(size)) call trixi_load_primitive_vars(handle, 1, data) call check(error, data(1), 1.0_dp) call check(error, data(3200), 1.0_dp) @@ -115,6 +126,17 @@ subroutine test_simulationRun(error) call check(error, data(1), 1.0_dp) call check(error, data(94), 0.99833232379996562_dp) call check(error, data(size), 1.0_dp) + + ! Check storing of conservative variables + data(1) = 42.0 + data(ndofs) = 23.0 + call trixi_store_conservative_vars(handle, 1, data) + + raw_data_c = trixi_get_data_pointer(handle) + call c_f_pointer(raw_data_c, raw_data, [ndofs]) + call check(error, data(1), raw_data(1)) + call check(error, data(ndofs), raw_data(4*ndofs - 3)) + deallocate(data) ! Finalize Trixi simulation From bbf2a600ed2c2be849947900d04ead8a041fe589 Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Fri, 1 Aug 2025 01:37:22 +0200 Subject: [PATCH 82/89] reference --- test/fortran/simulationRun_suite.f90 | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/test/fortran/simulationRun_suite.f90 b/test/fortran/simulationRun_suite.f90 index 3d9c1157..2ee4bca8 100644 --- a/test/fortran/simulationRun_suite.f90 +++ b/test/fortran/simulationRun_suite.f90 @@ -108,11 +108,9 @@ subroutine test_simulationRun(error) call trixi_load_conservative_vars(handle, 1, data) call check(error, data(1), 1.0_dp) call check(error, data(3200), 1.0_dp) - call check(error, data(size), 2.5e-5_dp) - deallocate(data) + call check(error, data(size), 1.0_dp) ! Check primitive variable values - allocate(data(size)) call trixi_load_primitive_vars(handle, 1, data) call check(error, data(1), 1.0_dp) call check(error, data(3200), 1.0_dp) From 5b2d2cc7dd60eb35ae8544e02396cdeecdd8b4a2 Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Fri, 1 Aug 2025 02:22:23 +0200 Subject: [PATCH 83/89] mention new examples --- README.md | 2 +- docs/src/index.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index c9c74b20..771d1ae0 100644 --- a/README.md +++ b/README.md @@ -213,7 +213,7 @@ aspects on how to use the C and Fortran APIs of libtrixi: - `trixi_controller_simple.(c|f90)`: basic usage - `trixi_controller_mpi.(c|f90)`: usage in the presence of MPI -- `trixi_controller_data_load.(c|f90)`: simulation data access +- `trixi_controller_data_(load|store).(c|f90)`: simulation data access - `trixi_controller_t8code.(c|f90)`: interacting with t8code If you just want to test the Julia part of libtrixi, i.e., LibTrixi.jl, you can also run diff --git a/docs/src/index.md b/docs/src/index.md index 4640c277..62f1714c 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -216,7 +216,7 @@ examples demonstrate different aspects on how to use the C and Fortran APIs of l - `trixi_controller_simple.(c|f90)`: basic usage - `trixi_controller_mpi.(c|f90)`: usage in the presence of MPI -- `trixi_controller_data_load.(c|f90)`: simulation data access +- `trixi_controller_data_(load|store).(c|f90)`: simulation data access - `trixi_controller_t8code.(c|f90)`: interacting with t8code If you just want to test the Julia part of libtrixi, i.e., LibTrixi.jl, you can also run From 4372c57d071e6349c5dffb7066ad1184b2821ca4 Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Wed, 8 Oct 2025 16:32:36 +0200 Subject: [PATCH 84/89] rename (load|store)*vars to var --- LibTrixi.jl/src/LibTrixi.jl | 30 ++++----- LibTrixi.jl/src/api_c.jl | 77 ++++++++++++------------ LibTrixi.jl/src/api_jl.jl | 10 +-- LibTrixi.jl/test/test_interface.jl | 20 +++--- examples/trixi_controller_baroclinic.c | 8 +-- examples/trixi_controller_baroclinic.f90 | 8 +-- examples/trixi_controller_data_load.c | 2 +- examples/trixi_controller_data_load.f90 | 2 +- examples/trixi_controller_data_store.c | 8 +-- examples/trixi_controller_data_store.f90 | 8 +-- src/api.c | 69 ++++++++++----------- src/api.f90 | 24 ++++---- src/trixi.h | 10 +-- test/c/simulation.cpp | 20 +++--- test/fortran/simulationRun_suite.f90 | 10 +-- 15 files changed, 154 insertions(+), 152 deletions(-) diff --git a/LibTrixi.jl/src/LibTrixi.jl b/LibTrixi.jl/src/LibTrixi.jl index 89f0e50c..0c1ae24d 100644 --- a/LibTrixi.jl/src/LibTrixi.jl +++ b/LibTrixi.jl/src/LibTrixi.jl @@ -52,24 +52,24 @@ export trixi_load_node_reference_coordinates, export trixi_load_node_weights, trixi_load_node_weights_cfptr, trixi_load_node_weights_jl -export trixi_load_conservative_vars, - trixi_load_conservative_vars_cfptr, - trixi_load_conservative_vars_jl -export trixi_load_primitive_vars, - trixi_load_primitive_vars_cfptr, - trixi_load_primitive_vars_jl -export trixi_load_element_averaged_primitive_vars, - trixi_load_element_averaged_primitive_vars_cfptr, - trixi_load_element_averaged_primitive_vars_jl -export trixi_store_conservative_vars, - trixi_store_conservative_vars_cfptr, - trixi_store_conservative_vars_jl +export trixi_load_conservative_var, + trixi_load_conservative_var_cfptr, + trixi_load_conservative_var_jl +export trixi_load_primitive_var, + trixi_load_primitive_var_cfptr, + trixi_load_primitive_var_jl +export trixi_load_element_averaged_primitive_var, + trixi_load_element_averaged_primitive_var_cfptr, + trixi_load_element_averaged_primitive_var_jl +export trixi_store_conservative_var, + trixi_store_conservative_var_cfptr, + trixi_store_conservative_var_jl export trixi_register_data, trixi_register_data_cfptr, trixi_register_data_jl -export trixi_get_data_pointer, - trixi_get_data_pointer_cfptr, - trixi_get_data_pointer_jl +export trixi_get_conservative_vars_pointer, + trixi_get_conservative_vars_pointer_cfptr, + trixi_get_conservative_vars_pointer_jl export trixi_version_library, trixi_version_library_cfptr, trixi_version_library_jl diff --git a/LibTrixi.jl/src/api_c.jl b/LibTrixi.jl/src/api_c.jl index 7893a41d..d5629197 100644 --- a/LibTrixi.jl/src/api_c.jl +++ b/LibTrixi.jl/src/api_c.jl @@ -433,32 +433,32 @@ trixi_load_node_weights_cfptr() = """ - trixi_load_conservative_vars(simstate_handle::Cint, variable_id::Cint, - data::Ptr{Cdouble})::Cvoid + trixi_load_conservative_var(simstate_handle::Cint, variable_id::Cint, + data::Ptr{Cdouble})::Cvoid Load conservative variable. """ -function trixi_load_conservative_vars end +function trixi_load_conservative_var end -Base.@ccallable function trixi_load_conservative_vars(simstate_handle::Cint, - variable_id::Cint, - data::Ptr{Cdouble})::Cvoid +Base.@ccallable function trixi_load_conservative_var(simstate_handle::Cint, + variable_id::Cint, + data::Ptr{Cdouble})::Cvoid simstate = load_simstate(simstate_handle) # convert C to Julia array size = trixi_ndofs_jl(simstate) data_jl = unsafe_wrap(Array, data, size) - trixi_load_conservative_vars_jl(simstate, variable_id, data_jl) + trixi_load_conservative_var_jl(simstate, variable_id, data_jl) end -trixi_load_conservative_vars_cfptr() = - @cfunction(trixi_load_conservative_vars, Cvoid, (Cint, Cint, Ptr{Cdouble})) +trixi_load_conservative_var_cfptr() = + @cfunction(trixi_load_conservative_var, Cvoid, (Cint, Cint, Ptr{Cdouble})) """ - trixi_load_primitive_vars(simstate_handle::Cint, variable_id::Cint, - data::Ptr{Cdouble})::Cvoid + trixi_load_primitive_var(simstate_handle::Cint, variable_id::Cint, + data::Ptr{Cdouble})::Cvoid Load primitive variable. @@ -467,46 +467,46 @@ are stored in the given array `data`. The given array has to be of correct size (ndofs) and memory has to be allocated beforehand. """ -function trixi_load_primitive_vars end +function trixi_load_primitive_var end -Base.@ccallable function trixi_load_primitive_vars(simstate_handle::Cint, variable_id::Cint, - data::Ptr{Cdouble})::Cvoid +Base.@ccallable function trixi_load_primitive_var(simstate_handle::Cint, variable_id::Cint, + data::Ptr{Cdouble})::Cvoid simstate = load_simstate(simstate_handle) # convert C to Julia array size = trixi_ndofs_jl(simstate) data_jl = unsafe_wrap(Array, data, size) - trixi_load_primitive_vars_jl(simstate, variable_id, data_jl) + trixi_load_primitive_var_jl(simstate, variable_id, data_jl) return nothing end -trixi_load_primitive_vars_cfptr() = - @cfunction(trixi_load_primitive_vars, Cvoid, (Cint, Cint, Ptr{Cdouble})) +trixi_load_primitive_var_cfptr() = + @cfunction(trixi_load_primitive_var, Cvoid, (Cint, Cint, Ptr{Cdouble})) """ - trixi_store_conservative_vars(simstate_handle::Cint, variable_id::Cint, - data::Ptr{Cdouble})::Cvoid + trixi_store_conservative_var(simstate_handle::Cint, variable_id::Cint, + data::Ptr{Cdouble})::Cvoid Store conservative variable. """ -function trixi_store_conservative_vars end +function trixi_store_conservative_var end -Base.@ccallable function trixi_store_conservative_vars(simstate_handle::Cint, - variable_id::Cint, - data::Ptr{Cdouble})::Cvoid +Base.@ccallable function trixi_store_conservative_var(simstate_handle::Cint, + variable_id::Cint, + data::Ptr{Cdouble})::Cvoid simstate = load_simstate(simstate_handle) # convert C to Julia array size = trixi_ndofs_jl(simstate) data_jl = unsafe_wrap(Array, data, size) - trixi_store_conservative_vars_jl(simstate, variable_id, data_jl) + trixi_store_conservative_var_jl(simstate, variable_id, data_jl) end -trixi_store_conservative_vars_cfptr() = - @cfunction(trixi_store_conservative_vars, Cvoid, (Cint, Cint, Ptr{Cdouble})) +trixi_store_conservative_var_cfptr() = + @cfunction(trixi_store_conservative_var, Cvoid, (Cint, Cint, Ptr{Cdouble})) """ @@ -557,8 +557,8 @@ trixi_get_simulation_time_cfptr() = @cfunction(trixi_get_simulation_time, Cdoubl """ - trixi_load_element_averaged_primitive_vars(simstate_handle::Cint, variable_id::Cint, - data::Ptr{Cdouble})::Cvoid + trixi_load_element_averaged_primitive_var(simstate_handle::Cint, variable_id::Cint, + data::Ptr{Cdouble})::Cvoid Load element averages for primitive variable. @@ -568,9 +568,9 @@ element are stored in the given array `data`. The given array has to be of correct size (nelements) and memory has to be allocated beforehand. """ -function trixi_load_element_averaged_primitive_vars end +function trixi_load_element_averaged_primitive_var end -Base.@ccallable function trixi_load_element_averaged_primitive_vars(simstate_handle::Cint, +Base.@ccallable function trixi_load_element_averaged_primitive_var(simstate_handle::Cint, variable_id::Cint, data::Ptr{Cdouble})::Cvoid simstate = load_simstate(simstate_handle) @@ -578,27 +578,28 @@ Base.@ccallable function trixi_load_element_averaged_primitive_vars(simstate_han size = trixi_nelements_jl(simstate) data_jl = unsafe_wrap(Array, data, size) - trixi_load_element_averaged_primitive_vars_jl(simstate, variable_id, data_jl) + trixi_load_element_averaged_primitive_var_jl(simstate, variable_id, data_jl) return nothing end -trixi_load_element_averaged_primitive_vars_cfptr() = - @cfunction(trixi_load_element_averaged_primitive_vars, Cvoid, (Cint, Cint, Ptr{Cdouble})) +trixi_load_element_averaged_primitive_var_cfptr() = + @cfunction(trixi_load_element_averaged_primitive_var, Cvoid, (Cint, Cint, Ptr{Cdouble})) """ - trixi_get_data_pointer(simstate_handle::Cint)::Ptr{Cdouble} + trixi_get_conservative_vars_pointer(simstate_handle::Cint)::Ptr{Cdouble} Return pointer to internal data vector. """ -function trixi_get_data_pointer end +function trixi_get_conservative_vars_pointer end -Base.@ccallable function trixi_get_data_pointer(simstate_handle::Cint)::Ptr{Cdouble} +Base.@ccallable function trixi_get_conservative_vars_pointer(simstate_handle::Cint)::Ptr{Cdouble} simstate = load_simstate(simstate_handle) - return trixi_get_data_pointer_jl(simstate) + return trixi_get_conservative_vars_pointer_jl(simstate) end -trixi_get_data_pointer_cfptr() = @cfunction(trixi_get_data_pointer, Ptr{Cdouble}, (Cint,)) +trixi_get_conservative_vars_pointer_cfptr() = + @cfunction(trixi_get_conservative_vars_pointer, Ptr{Cdouble}, (Cint,)) diff --git a/LibTrixi.jl/src/api_jl.jl b/LibTrixi.jl/src/api_jl.jl index 8031d2bd..f60968ee 100644 --- a/LibTrixi.jl/src/api_jl.jl +++ b/LibTrixi.jl/src/api_jl.jl @@ -140,7 +140,7 @@ function trixi_load_node_weights_jl(simstate, data) end -function trixi_load_conservative_vars_jl(simstate, variable_id, data) +function trixi_load_conservative_var_jl(simstate, variable_id, data) mesh, equations, solver, cache = mesh_equations_solver_cache(simstate.semi) n_nodes_per_dim = nnodes(solver) n_dims = ndims(mesh) @@ -165,7 +165,7 @@ function trixi_load_conservative_vars_jl(simstate, variable_id, data) end -function trixi_load_primitive_vars_jl(simstate, variable_id, data) +function trixi_load_primitive_var_jl(simstate, variable_id, data) mesh, equations, solver, cache = mesh_equations_solver_cache(simstate.semi) n_nodes_per_dim = nnodes(solver) n_dims = ndims(mesh) @@ -190,7 +190,7 @@ function trixi_load_primitive_vars_jl(simstate, variable_id, data) end -function trixi_load_element_averaged_primitive_vars_jl(simstate, variable_id, data) +function trixi_load_element_averaged_primitive_var_jl(simstate, variable_id, data) mesh, equations, solver, cache = mesh_equations_solver_cache(simstate.semi) n_nodes = nnodes(solver) n_dims = ndims(mesh) @@ -226,7 +226,7 @@ function trixi_load_element_averaged_primitive_vars_jl(simstate, variable_id, da end -function trixi_store_conservative_vars_jl(simstate, variable_id, data) +function trixi_store_conservative_var_jl(simstate, variable_id, data) mesh, equations, solver, cache = mesh_equations_solver_cache(simstate.semi) n_nodes_per_dim = nnodes(solver) n_dims = ndims(mesh) @@ -259,7 +259,7 @@ function trixi_register_data_jl(simstate, index, data) end -function trixi_get_data_pointer_jl(simstate) +function trixi_get_conservative_vars_pointer_jl(simstate) return pointer(simstate.integrator.u) end diff --git a/LibTrixi.jl/test/test_interface.jl b/LibTrixi.jl/test/test_interface.jl index 51e5a537..97dc6bd3 100644 --- a/LibTrixi.jl/test/test_interface.jl +++ b/LibTrixi.jl/test/test_interface.jl @@ -136,36 +136,36 @@ end # compare element averaged values data_c = zeros(nelements_c) - trixi_load_element_averaged_primitive_vars(handle, Int32(1), pointer(data_c)) + trixi_load_element_averaged_primitive_var(handle, Int32(1), pointer(data_c)) data_jl = zeros(nelements_jl) - trixi_load_element_averaged_primitive_vars_jl(simstate_jl, 1, data_jl) + trixi_load_element_averaged_primitive_var_jl(simstate_jl, 1, data_jl) @test data_c == data_jl # compare conservative variable values on all dofs data_c = zeros(ndofs_c) - trixi_load_conservative_vars(handle, Int32(1), pointer(data_c)) + trixi_load_conservative_var(handle, Int32(1), pointer(data_c)) data_jl = zeros(ndofs_jl) - trixi_load_conservative_vars_jl(simstate_jl, 1, data_jl) + trixi_load_conservative_var_jl(simstate_jl, 1, data_jl) @test data_c == data_jl # compare primitive variable values on all dofs data_c = zeros(ndofs_c) - trixi_load_primitive_vars(handle, Int32(1), pointer(data_c)) + trixi_load_primitive_var(handle, Int32(1), pointer(data_c)) data_jl = zeros(ndofs_jl) - trixi_load_primitive_vars_jl(simstate_jl, 1, data_jl) + trixi_load_primitive_var_jl(simstate_jl, 1, data_jl) @test data_c == data_jl # write 1.0 to first variable and compare via raw access data_c = fill(1.0, ndofs_c) - trixi_store_conservative_vars(handle, Int32(1), pointer(data_c)) - data_ptr_c = trixi_get_data_pointer(handle) + trixi_store_conservative_var(handle, Int32(1), pointer(data_c)) + data_ptr_c = trixi_get_conservative_vars_pointer(handle) data_jl = unsafe_wrap(Array, data_ptr_c, ndofs_c) @test all(data_jl .== 1.0) # write 2.0 to first variable and compare via raw access data_jl = fill(2.0, ndofs_jl) - trixi_store_conservative_vars_jl(simstate_jl, 1, data_jl) - data_ptr_jl = trixi_get_data_pointer_jl(simstate_jl) + trixi_store_conservative_var_jl(simstate_jl, 1, data_jl) + data_ptr_jl = trixi_get_conservative_vars_pointer_jl(simstate_jl) data_jl = unsafe_wrap(Array, data_ptr_jl, ndofs_jl) @test all(data_jl .== 2.0) end diff --git a/examples/trixi_controller_baroclinic.c b/examples/trixi_controller_baroclinic.c index cec6cc0e..22cdefe3 100644 --- a/examples/trixi_controller_baroclinic.c +++ b/examples/trixi_controller_baroclinic.c @@ -128,10 +128,10 @@ int main ( int argc, char *argv[] ) { while ( !trixi_is_finished( handle ) ) { // Get current state - trixi_load_primitive_vars( handle, 1, u1 ); - trixi_load_primitive_vars( handle, 2, u2 ); - trixi_load_primitive_vars( handle, 3, u3 ); - trixi_load_primitive_vars( handle, 4, u4 ); + trixi_load_primitive_var( handle, 1, u1 ); + trixi_load_primitive_var( handle, 2, u2 ); + trixi_load_primitive_var( handle, 3, u3 ); + trixi_load_primitive_var( handle, 4, u4 ); // Compute source terms source_terms_baroclinic( nnodes, nodes, forest, diff --git a/examples/trixi_controller_baroclinic.f90 b/examples/trixi_controller_baroclinic.f90 index d0b551b3..f0a95ff0 100644 --- a/examples/trixi_controller_baroclinic.f90 +++ b/examples/trixi_controller_baroclinic.f90 @@ -155,10 +155,10 @@ program trixi_controller_baroclinic_f if ( trixi_is_finished(handle) ) exit ! Get current state - call trixi_load_primitive_vars( handle, 1, u1 ) - call trixi_load_primitive_vars( handle, 2, u2 ) - call trixi_load_primitive_vars( handle, 3, u3 ) - call trixi_load_primitive_vars( handle, 4, u4 ) + call trixi_load_primitive_var( handle, 1, u1 ) + call trixi_load_primitive_var( handle, 2, u2 ) + call trixi_load_primitive_var( handle, 3, u3 ) + call trixi_load_primitive_var( handle, 4, u4 ) ! Compute source terms call source_terms_baroclinic( nnodes, nodes, forest, ndofs, & diff --git a/examples/trixi_controller_data_load.c b/examples/trixi_controller_data_load.c index 35e88cdd..9ed41f3d 100644 --- a/examples/trixi_controller_data_load.c +++ b/examples/trixi_controller_data_load.c @@ -49,7 +49,7 @@ int main ( int argc, char *argv[] ) { data = realloc( data, sizeof(double) * nelements ); // Get element averaged values for first variable - trixi_load_element_averaged_primitive_vars(handle, 1, data); + trixi_load_element_averaged_primitive_var(handle, 1, data); } } diff --git a/examples/trixi_controller_data_load.f90 b/examples/trixi_controller_data_load.f90 index 7c7f9e59..b041d502 100644 --- a/examples/trixi_controller_data_load.f90 +++ b/examples/trixi_controller_data_load.f90 @@ -66,7 +66,7 @@ program trixi_controller_data_load_f allocate( data(nelements) ) ! get element averaged values for first variable - call trixi_load_element_averaged_primitive_vars(handle, 1, data) + call trixi_load_element_averaged_primitive_var(handle, 1, data) end if end do diff --git a/examples/trixi_controller_data_store.c b/examples/trixi_controller_data_store.c index 6b5c27d1..7b28e515 100644 --- a/examples/trixi_controller_data_store.c +++ b/examples/trixi_controller_data_store.c @@ -41,7 +41,7 @@ int main ( int argc, char *argv[] ) { int ndofs = trixi_ndofsglobal( handle ); // Get a pointer to Trixi's internal simulation data - double * raw_data = trixi_get_data_pointer(handle); + double * raw_data = trixi_get_conservative_vars_pointer(handle); for (int i = 0; i < ndofs; ++i) { // Density comes first @@ -66,8 +66,8 @@ int main ( int argc, char *argv[] ) { rho_tracer = realloc( rho_tracer, sizeof(double) * ndofs ); // Get density and tracer - trixi_load_conservative_vars(handle, 1, rho); - trixi_load_conservative_vars(handle, 5, rho_tracer); + trixi_load_conservative_var(handle, 1, rho); + trixi_load_conservative_var(handle, 5, rho_tracer); for (int i = 0; i < ndofs; ++i) { // Apply 5% amplification to tracer (fraction of density) @@ -76,7 +76,7 @@ int main ( int argc, char *argv[] ) { } // Write back tracer - trixi_store_conservative_vars(handle, 5, rho_tracer); + trixi_store_conservative_var(handle, 5, rho_tracer); } } diff --git a/examples/trixi_controller_data_store.f90 b/examples/trixi_controller_data_store.f90 index ab2960ff..f18b2a7c 100644 --- a/examples/trixi_controller_data_store.f90 +++ b/examples/trixi_controller_data_store.f90 @@ -57,7 +57,7 @@ program trixi_controller_data_store_f ndofs = trixi_ndofsglobal(handle) ! Get a pointer to Trixi's internal simulation data - raw_data_c = trixi_get_data_pointer(handle) + raw_data_c = trixi_get_conservative_vars_pointer(handle) call c_f_pointer(raw_data_c, raw_data, [ndofs]) do i = 1,ndofs @@ -84,8 +84,8 @@ program trixi_controller_data_store_f allocate( rho_tracer(ndofs) ) ! get density and tracer - call trixi_load_conservative_vars(handle, 1, rho) - call trixi_load_conservative_vars(handle, 5, rho_tracer) + call trixi_load_conservative_var(handle, 1, rho) + call trixi_load_conservative_var(handle, 5, rho_tracer) do i = 1,ndofs ! apply 5% amplification to tracer (fraction of density) @@ -94,7 +94,7 @@ program trixi_controller_data_store_f end do ! write back tracer - call trixi_store_conservative_vars(handle, 5, rho_tracer) + call trixi_store_conservative_var(handle, 5, rho_tracer) end if end do diff --git a/src/api.c b/src/api.c index 3c5e013b..74f0d5f8 100644 --- a/src/api.c +++ b/src/api.c @@ -22,12 +22,12 @@ enum { TRIXI_FPTR_NNODES, TRIXI_FPTR_LOAD_NODE_REFERENCE_COORDINATES, TRIXI_FPTR_LOAD_NODE_WEIGHTS, - TRIXI_FPTR_LOAD_CONSERVATIVE_VARS, - TRIXI_FTPR_LOAD_PRIMITIVE_VARS, - TRIXI_FTPR_LOAD_ELEMENT_AVERAGED_PRIMITIVE_VARS, - TRIXI_FPTR_STORE_CONSERVATIVE_VARS, + TRIXI_FPTR_LOAD_CONSERVATIVE_VAR, + TRIXI_FTPR_LOAD_PRIMITIVE_VAR, + TRIXI_FTPR_LOAD_ELEMENT_AVERAGED_PRIMITIVE_VAR, + TRIXI_FPTR_STORE_CONSERVATIVE_VAR, TRIXI_FTPR_REGISTER_DATA, - TRIXI_FPTR_GET_DATA_POINTER, + TRIXI_FPTR_GET_CONSERVATIVE_VARS_POINTER, TRIXI_FTPR_VERSION_LIBRARY, TRIXI_FTPR_VERSION_LIBRARY_MAJOR, TRIXI_FTPR_VERSION_LIBRARY_MINOR, @@ -63,12 +63,12 @@ static const char* trixi_function_pointer_names[] = { [TRIXI_FPTR_NNODES] = "trixi_nnodes_cfptr", [TRIXI_FPTR_LOAD_NODE_REFERENCE_COORDINATES] = "trixi_load_node_reference_coordinates_cfptr", [TRIXI_FPTR_LOAD_NODE_WEIGHTS] = "trixi_load_node_weights_cfptr", - [TRIXI_FPTR_LOAD_CONSERVATIVE_VARS] = "trixi_load_conservative_vars_cfptr", - [TRIXI_FTPR_LOAD_PRIMITIVE_VARS] = "trixi_load_primitive_vars_cfptr", - [TRIXI_FTPR_LOAD_ELEMENT_AVERAGED_PRIMITIVE_VARS] = "trixi_load_element_averaged_primitive_vars_cfptr", - [TRIXI_FPTR_STORE_CONSERVATIVE_VARS] = "trixi_store_conservative_vars_cfptr", + [TRIXI_FPTR_LOAD_CONSERVATIVE_VAR] = "trixi_load_conservative_var_cfptr", + [TRIXI_FTPR_LOAD_PRIMITIVE_VAR] = "trixi_load_primitive_var_cfptr", + [TRIXI_FTPR_LOAD_ELEMENT_AVERAGED_PRIMITIVE_VAR] = "trixi_load_element_averaged_primitive_var_cfptr", + [TRIXI_FPTR_STORE_CONSERVATIVE_VAR] = "trixi_store_conservative_var_cfptr", [TRIXI_FTPR_REGISTER_DATA] = "trixi_register_data_cfptr", - [TRIXI_FPTR_GET_DATA_POINTER] = "trixi_get_data_pointer_cfptr", + [TRIXI_FPTR_GET_CONSERVATIVE_VARS_POINTER] = "trixi_get_conservative_vars_pointer_cfptr", [TRIXI_FTPR_VERSION_LIBRARY] = "trixi_version_library_cfptr", [TRIXI_FTPR_VERSION_LIBRARY_MAJOR] = "trixi_version_library_major_cfptr", [TRIXI_FTPR_VERSION_LIBRARY_MINOR] = "trixi_version_library_minor_cfptr", @@ -650,7 +650,7 @@ void trixi_load_node_weights(int handle, double* node_weights) { /** - * @anchor trixi_load_conservative_vars_api_c + * @anchor trixi_load_conservative_var_api_c * * @brief Load conservative variable. * @@ -664,19 +664,19 @@ void trixi_load_node_weights(int handle, double* node_weights) { * @param[in] variable_id index of variable * @param[out] data values for all degrees of freedom */ -void trixi_load_conservative_vars(int handle, int variable_id, double * data) { +void trixi_load_conservative_var(int handle, int variable_id, double * data) { // Get function pointer - void (*load_conservative_vars)(int, int, double *) = - trixi_function_pointers[TRIXI_FPTR_LOAD_CONSERVATIVE_VARS]; + void (*load_conservative_var)(int, int, double *) = + trixi_function_pointers[TRIXI_FPTR_LOAD_CONSERVATIVE_VAR]; // Call function - return load_conservative_vars(handle, variable_id, data); + return load_conservative_var(handle, variable_id, data); } /** - * @anchor trixi_load_primitive_vars_api_c + * @anchor trixi_load_primitive_var_api_c * * @brief Load primitive variable * @@ -690,19 +690,19 @@ void trixi_load_conservative_vars(int handle, int variable_id, double * data) { * @param[in] variable_id index of variable * @param[out] data values for all degrees of freedom */ -void trixi_load_primitive_vars(int handle, int variable_id, double * data) { +void trixi_load_primitive_var(int handle, int variable_id, double * data) { // Get function pointer - void (*load_primitive_vars)(int, int, double *) = - trixi_function_pointers[TRIXI_FTPR_LOAD_PRIMITIVE_VARS]; + void (*load_primitive_var)(int, int, double *) = + trixi_function_pointers[TRIXI_FTPR_LOAD_PRIMITIVE_VAR]; // Call function - load_primitive_vars(handle, variable_id, data); + load_primitive_var(handle, variable_id, data); } /** - * @anchor trixi_load_element_averaged_primitive_vars_api_c + * @anchor trixi_load_element_averaged_primitive_var_api_c * * @brief Load element averages for primitive variable * @@ -716,19 +716,19 @@ void trixi_load_primitive_vars(int handle, int variable_id, double * data) { * @param[in] variable_id index of variable * @param[out] data element averaged values for all elements */ -void trixi_load_element_averaged_primitive_vars(int handle, int variable_id, double * data) { +void trixi_load_element_averaged_primitive_var(int handle, int variable_id, double * data) { // Get function pointer - void (*load_element_averaged_primitive_vars)(int, int, double *) = - trixi_function_pointers[TRIXI_FTPR_LOAD_ELEMENT_AVERAGED_PRIMITIVE_VARS]; + void (*load_element_averaged_primitive_var)(int, int, double *) = + trixi_function_pointers[TRIXI_FTPR_LOAD_ELEMENT_AVERAGED_PRIMITIVE_VAR]; // Call function - load_element_averaged_primitive_vars(handle, variable_id, data); + load_element_averaged_primitive_var(handle, variable_id, data); } /** - * @anchor trixi_store_conservative_vars_api_c + * @anchor trixi_store_conservative_var_api_c * * @brief Store conservative variable. * @@ -741,14 +741,14 @@ void trixi_load_element_averaged_primitive_vars(int handle, int variable_id, dou * @param[in] variable_id index of variable * @param[in] data values for all degrees of freedom */ -void trixi_store_conservative_vars(int handle, int variable_id, double * data) { +void trixi_store_conservative_var(int handle, int variable_id, double * data) { // Get function pointer - void (*store_conservative_vars)(int, int, double *) = - trixi_function_pointers[TRIXI_FPTR_STORE_CONSERVATIVE_VARS]; + void (*store_conservative_var)(int, int, double *) = + trixi_function_pointers[TRIXI_FPTR_STORE_CONSERVATIVE_VAR]; // Call function - return store_conservative_vars(handle, variable_id, data); + return store_conservative_var(handle, variable_id, data); } @@ -784,7 +784,7 @@ void trixi_register_data(int handle, int index, int size, const double * data) { /** - * @anchor trixi_get_data_pointer_api_c + * @anchor trixi_get_conservative_vars_pointer_api_c * * @brief Return pointer to internal data vector. * @@ -796,13 +796,14 @@ void trixi_register_data(int handle, int index, int size, const double * data) { * * @param[in] handle simulation handle */ -double * trixi_get_data_pointer(int handle) { +double * trixi_get_conservative_vars_pointer(int handle) { // Get function pointer - double * (*get_data_pointer)(int) = trixi_function_pointers[TRIXI_FPTR_GET_DATA_POINTER]; + double * (*get_conservative_vars_pointer)(int) = + trixi_function_pointers[TRIXI_FPTR_GET_CONSERVATIVE_VARS_POINTER]; // Call function - return get_data_pointer(handle); + return get_conservative_vars_pointer(handle); } diff --git a/src/api.f90 b/src/api.f90 index a0743b63..1b7b2933 100644 --- a/src/api.f90 +++ b/src/api.f90 @@ -375,7 +375,7 @@ subroutine trixi_load_node_weights(handle, node_weights) bind(c) end subroutine !> - !! @anchor trixi_load_conservative_vars_api_c + !! @anchor trixi_load_conservative_var_api_c !! !! @brief Load conservative variable. !! @@ -388,7 +388,7 @@ subroutine trixi_load_node_weights(handle, node_weights) bind(c) !! @param[in] handle simulation handle !! @param[in] variable_id index of variable !! @param[out] data values for all degrees of freedom - subroutine trixi_load_conservative_vars(handle, variable_id, data) bind(c) + subroutine trixi_load_conservative_var(handle, variable_id, data) bind(c) use, intrinsic :: iso_c_binding, only: c_int, c_double integer(c_int), value, intent(in) :: handle integer(c_int), value, intent(in) :: variable_id @@ -396,7 +396,7 @@ subroutine trixi_load_conservative_vars(handle, variable_id, data) bind(c) end subroutine !> - !! @fn LibTrixi::trixi_load_primitive_vars::trixi_load_primitive_vars(handle, variable_id, data) + !! @fn LibTrixi::trixi_load_primitive_var::trixi_load_primitive_var(handle, variable_id, data) !! !! @brief Load primitive variable !! @@ -404,8 +404,8 @@ subroutine trixi_load_conservative_vars(handle, variable_id, data) bind(c) !! @param[in] variable_id index of variable !! @param[out] data primitive variable values for all degrees of freedom !! - !! @see @ref trixi_load_primitive_vars_api_c "trixi_load_primitive_vars (C API)" - subroutine trixi_load_primitive_vars(handle, variable_id, data) bind(c) + !! @see @ref trixi_load_primitive_var_api_c "trixi_load_primitive_var (C API)" + subroutine trixi_load_primitive_var(handle, variable_id, data) bind(c) use, intrinsic :: iso_c_binding, only: c_int, c_double integer(c_int), value, intent(in) :: handle integer(c_int), value, intent(in) :: variable_id @@ -428,7 +428,7 @@ real(c_double) function trixi_get_simulation_time(handle) bind(c) end function !> - !! @fn LibTrixi::trixi_load_element_averaged_primitive_vars::trixi_load_element_averaged_primitive_vars(handle, variable_id, data) + !! @fn LibTrixi::trixi_load_element_averaged_primitive_var::trixi_load_element_averaged_primitive_var(handle, variable_id, data) !! !! @brief Load element averages for primitive variable !! @@ -436,8 +436,8 @@ real(c_double) function trixi_get_simulation_time(handle) bind(c) !! @param[in] variable_id index of variable !! @param[out] data averaged values for all elements !! - !! @see @ref trixi_load_element_averaged_primitive_vars_api_c "trixi_load_element_averaged_primitive_vars (C API)" - subroutine trixi_load_element_averaged_primitive_vars(handle, variable_id, data) bind(c) + !! @see @ref trixi_load_element_averaged_primitive_var_api_c "trixi_load_element_averaged_primitive_var (C API)" + subroutine trixi_load_element_averaged_primitive_var(handle, variable_id, data) bind(c) use, intrinsic :: iso_c_binding, only: c_int, c_double integer(c_int), value, intent(in) :: handle integer(c_int), value, intent(in) :: variable_id @@ -445,7 +445,7 @@ subroutine trixi_load_element_averaged_primitive_vars(handle, variable_id, data) end subroutine !> - !! @anchor trixi_store_conservative_vars_api_c + !! @anchor trixi_store_conservative_var_api_c !! !! @brief Store conservative variable. !! @@ -458,7 +458,7 @@ subroutine trixi_load_element_averaged_primitive_vars(handle, variable_id, data) !! @param[in] handle simulation handle !! @param[in] variable_id index of variable !! @param[in] data values for all degrees of freedom - subroutine trixi_store_conservative_vars(handle, variable_id, data) bind(c) + subroutine trixi_store_conservative_var(handle, variable_id, data) bind(c) use, intrinsic :: iso_c_binding, only: c_int, c_double integer(c_int), value, intent(in) :: handle integer(c_int), value, intent(in) :: variable_id @@ -485,7 +485,7 @@ subroutine trixi_register_data(handle, index, size, data) bind(c) end subroutine !> - !! @anchor trixi_get_data_pointer_api_c + !! @anchor trixi_get_conservative_vars_pointer_api_c !! !! @brief Return pointer to internal data vector. !! @@ -497,7 +497,7 @@ subroutine trixi_register_data(handle, index, size, data) bind(c) !! undefined behavior. !! !! @param[in] handle simulation handle - type (c_ptr) function trixi_get_data_pointer(handle) bind(c) + type (c_ptr) function trixi_get_conservative_vars_pointer(handle) bind(c) use, intrinsic :: iso_c_binding, only: c_int, c_ptr integer(c_int), value, intent(in) :: handle end function diff --git a/src/trixi.h b/src/trixi.h index 4a975dce..7abeacc1 100644 --- a/src/trixi.h +++ b/src/trixi.h @@ -37,12 +37,12 @@ double trixi_calculate_dt(int handle); double trixi_get_simulation_time(int handle); void trixi_load_node_reference_coordinates(int handle, double* node_coords); void trixi_load_node_weights(int handle, double* node_weights); -void trixi_load_conservative_vars(int handle, int variable_id, double * data); -void trixi_load_primitive_vars(int handle, int variable_id, double * data); -void trixi_load_element_averaged_primitive_vars(int handle, int variable_id, double * data); -void trixi_store_conservative_vars(int handle, int variable_id, double * data); +void trixi_load_conservative_var(int handle, int variable_id, double * data); +void trixi_load_primitive_var(int handle, int variable_id, double * data); +void trixi_load_element_averaged_primitive_var(int handle, int variable_id, double * data); +void trixi_store_conservative_var(int handle, int variable_id, double * data); void trixi_register_data(int handle, int index, int size, const double * data); -double * trixi_get_data_pointer(int handle); +double * trixi_get_conservative_vars_pointer(int handle); // T8code #if !defined(T8_H) && !defined(T8_FOREST_GENERAL_H) diff --git a/test/c/simulation.cpp b/test/c/simulation.cpp index f67d9be5..56320f85 100644 --- a/test/c/simulation.cpp +++ b/test/c/simulation.cpp @@ -103,8 +103,8 @@ TEST(CInterfaceTest, SimulationRun) { // Check conservative variable values std::vector rho(ndofs); std::vector rho_energy(ndofs); - trixi_load_conservative_vars(handle, 1, rho.data()); - trixi_load_conservative_vars(handle, 4, rho_energy.data()); + trixi_load_conservative_var(handle, 1, rho.data()); + trixi_load_conservative_var(handle, 4, rho_energy.data()); // check memory borders EXPECT_DOUBLE_EQ(rho[0], 1.0); EXPECT_DOUBLE_EQ(rho[ndofs-1], 1.0); @@ -113,8 +113,8 @@ TEST(CInterfaceTest, SimulationRun) { // Check primitive variable values std::vector energy(ndofs); - trixi_load_primitive_vars(handle, 1, rho.data()); - trixi_load_primitive_vars(handle, 4, energy.data()); + trixi_load_primitive_var(handle, 1, rho.data()); + trixi_load_primitive_var(handle, 4, energy.data()); // check memory borders EXPECT_DOUBLE_EQ(rho[0], 1.0); EXPECT_DOUBLE_EQ(rho[ndofs-1], 1.0); @@ -126,10 +126,10 @@ TEST(CInterfaceTest, SimulationRun) { std::vector v1_averages(nelements); std::vector v2_averages(nelements); std::vector e_averages(nelements); - trixi_load_element_averaged_primitive_vars(handle, 1, rho_averages.data()); - trixi_load_element_averaged_primitive_vars(handle, 2, v1_averages.data()); - trixi_load_element_averaged_primitive_vars(handle, 3, v2_averages.data()); - trixi_load_element_averaged_primitive_vars(handle, 4, e_averages.data()); + trixi_load_element_averaged_primitive_var(handle, 1, rho_averages.data()); + trixi_load_element_averaged_primitive_var(handle, 2, v1_averages.data()); + trixi_load_element_averaged_primitive_var(handle, 3, v2_averages.data()); + trixi_load_element_averaged_primitive_var(handle, 4, e_averages.data()); if (nranks == 1) { // check memory borders (densities at the beginning, energies at the end) EXPECT_DOUBLE_EQ(rho_averages[0], 1.0); @@ -179,9 +179,9 @@ TEST(CInterfaceTest, SimulationRun) { // Check storing of conservative variables rho[0] = 42.0; rho[ndofs-1] = 23.0; - trixi_store_conservative_vars(handle, 1, rho.data()); + trixi_store_conservative_var(handle, 1, rho.data()); - double * raw_data = trixi_get_data_pointer(handle); + double * raw_data = trixi_get_conservative_vars_pointer(handle); EXPECT_DOUBLE_EQ(rho[0], raw_data[0]); EXPECT_DOUBLE_EQ(rho[ndofs-1], raw_data[4*(ndofs-1)]); diff --git a/test/fortran/simulationRun_suite.f90 b/test/fortran/simulationRun_suite.f90 index 2ee4bca8..ed40707c 100644 --- a/test/fortran/simulationRun_suite.f90 +++ b/test/fortran/simulationRun_suite.f90 @@ -105,13 +105,13 @@ subroutine test_simulationRun(error) ! Check conservative variable values size = ndofs allocate(data(size)) - call trixi_load_conservative_vars(handle, 1, data) + call trixi_load_conservative_var(handle, 1, data) call check(error, data(1), 1.0_dp) call check(error, data(3200), 1.0_dp) call check(error, data(size), 1.0_dp) ! Check primitive variable values - call trixi_load_primitive_vars(handle, 1, data) + call trixi_load_primitive_var(handle, 1, data) call check(error, data(1), 1.0_dp) call check(error, data(3200), 1.0_dp) call check(error, data(size), 1.0_dp) @@ -120,7 +120,7 @@ subroutine test_simulationRun(error) ! Check element averaged values size = nelements allocate(data(size)) - call trixi_load_element_averaged_primitive_vars(handle, 1, data) + call trixi_load_element_averaged_primitive_var(handle, 1, data) call check(error, data(1), 1.0_dp) call check(error, data(94), 0.99833232379996562_dp) call check(error, data(size), 1.0_dp) @@ -128,9 +128,9 @@ subroutine test_simulationRun(error) ! Check storing of conservative variables data(1) = 42.0 data(ndofs) = 23.0 - call trixi_store_conservative_vars(handle, 1, data) + call trixi_store_conservative_var(handle, 1, data) - raw_data_c = trixi_get_data_pointer(handle) + raw_data_c = trixi_get_conservative_vars_pointer(handle) call c_f_pointer(raw_data_c, raw_data, [ndofs]) call check(error, data(1), raw_data(1)) call check(error, data(ndofs), raw_data(4*ndofs - 3)) From 2d1bb72cbb7526f152cac42d698f30b935e07512 Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Wed, 8 Oct 2025 17:01:39 +0200 Subject: [PATCH 85/89] niceify --- .github/workflows/ci.yml | 1 + ...ixir_structured2d_source_terms_callback.jl | 35 ++++++++++++------- examples/CMakeLists.txt | 2 +- 3 files changed, 24 insertions(+), 14 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 76ae3bd9..a69a8d2a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -243,6 +243,7 @@ jobs: # all controllers ../build/examples/trixi_controller_simple_c . libelixir_tree1d_advection_basic.jl ../build/examples/trixi_controller_simple_f . libelixir_tree1d_advection_basic.jl + ../build/examples/trixi_controller_simple_c . libelixir_structured2d_source_terms_callback.jl ../build/examples/trixi_controller_data_load_c . libelixir_t8code2d_euler_tracer_amr.jl ../build/examples/trixi_controller_data_load_f . libelixir_t8code2d_euler_tracer_amr.jl ../build/examples/trixi_controller_data_store_c . libelixir_t8code2d_euler_tracer_amr.jl diff --git a/LibTrixi.jl/examples/libelixir_structured2d_source_terms_callback.jl b/LibTrixi.jl/examples/libelixir_structured2d_source_terms_callback.jl index 80dbe7ca..3472d7f5 100644 --- a/LibTrixi.jl/examples/libelixir_structured2d_source_terms_callback.jl +++ b/LibTrixi.jl/examples/libelixir_structured2d_source_terms_callback.jl @@ -3,20 +3,25 @@ using Trixi using OrdinaryDiffEq using Libdl -# TODO: hard-coded path for SO -so_handle = dlopen("./lib/libsource_terms.so") -println("Opened library ", dlpath(so_handle)) -source_term_fptr = dlsym(so_handle, "source_term_wave") -println("Obtained function pointer ", source_term_fptr) - -# TODO: global buffer to avoid allocation of temporary storage in source_term_callback -sources_tmp::Vector{Cdouble} = Vector{Cdouble}(undef, 4) +struct SourceTermsCallback + source_term_fptr::Ptr{Nothing} + buffer::Vector{Cdouble} + + function SourceTermsCallback(; n_vars, so_path) + so_handle = dlopen(so_path) + @info "Opened library ", dlpath(so_handle) + source_term_fptr = dlsym(so_handle, "source_term_wave") + @info "Obtained function pointer ", source_term_fptr + + new(source_term_fptr, Vector{Cdouble}(undef, n_vars)) + end +end -function source_term_callback(u, x, t, equations::CompressibleEulerEquations2D) +function (callback::SourceTermsCallback)(u, x, t, equations::CompressibleEulerEquations2D) + @unpack source_term_fptr, buffer = callback @ccall $source_term_fptr(u::Ptr{Cdouble}, x::Ptr{Cdouble}, t::Cdouble, - equations.gamma::Cdouble, - sources_tmp::Ptr{Cdouble})::Cvoid - return SVector(sources_tmp[1], sources_tmp[2], sources_tmp[3], sources_tmp[4]) + equations.gamma::Cdouble, buffer::Ptr{Cdouble})::Cvoid + return SVector(buffer[1], buffer[2], buffer[3], buffer[4]) end # The function to create the simulation state needs to be named `init_simstate` @@ -25,6 +30,10 @@ function init_simstate() ############################################################################### # semidiscretization of the compressible Euler equations + # use external function in locally compiled shared object + source_terms_callback = SourceTermsCallback(n_vars = 4, + so_path = "./lib/libsource_terms.so") + equations = CompressibleEulerEquations2D(1.4) initial_condition = initial_condition_convergence_test @@ -39,7 +48,7 @@ function init_simstate() mesh = StructuredMesh(cells_per_dimension, coordinates_min, coordinates_max) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms = source_term_callback) + source_terms = source_terms_callback) ############################################################################### # ODE solvers, callbacks etc. diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 27d95648..a0b7b24c 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -17,7 +17,7 @@ if ( NOT T8CODE_FOUND ) list( FILTER EXAMPLES EXCLUDE REGEX "trixi_controller_baroclinic.*" ) endif() -# example standalone library with callback +# examplary external library providing function used to compute source terms add_library ( source_terms SHARED source_terms.h source_terms.c From 482ee631fffceb064ce3e858f0b7241257dc78aa Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Wed, 8 Oct 2025 17:05:10 +0200 Subject: [PATCH 86/89] typo --- examples/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index a0b7b24c..6910f2ec 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -17,7 +17,7 @@ if ( NOT T8CODE_FOUND ) list( FILTER EXAMPLES EXCLUDE REGEX "trixi_controller_baroclinic.*" ) endif() -# examplary external library providing function used to compute source terms +# exemplary external library providing function used to compute source terms add_library ( source_terms SHARED source_terms.h source_terms.c From 33b49036eb9ae6832ede540c5ec6688d55590a17 Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Wed, 8 Oct 2025 21:54:01 +0200 Subject: [PATCH 87/89] move so next to libelixir --- .github/workflows/ci.yml | 1 + .../examples/libelixir_structured2d_source_terms_callback.jl | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 540ff992..948d194b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -165,6 +165,7 @@ jobs: mkdir libtrixi-julia cd libtrixi-julia cp ../install/share/libtrixi/LibTrixi.jl/examples/libelixir_* . + cp ../install/lib/libsource_terms.so . mkdir julia-depot ../install/bin/libtrixi-init-julia .. \ --hdf5-library /usr/lib/x86_64-linux-gnu/hdf5/openmpi/libhdf5.so \ diff --git a/LibTrixi.jl/examples/libelixir_structured2d_source_terms_callback.jl b/LibTrixi.jl/examples/libelixir_structured2d_source_terms_callback.jl index 3472d7f5..69836bfb 100644 --- a/LibTrixi.jl/examples/libelixir_structured2d_source_terms_callback.jl +++ b/LibTrixi.jl/examples/libelixir_structured2d_source_terms_callback.jl @@ -32,7 +32,8 @@ function init_simstate() # use external function in locally compiled shared object source_terms_callback = SourceTermsCallback(n_vars = 4, - so_path = "./lib/libsource_terms.so") + so_path = joinpath(@__DIR__, + "libsource_terms.so")) equations = CompressibleEulerEquations2D(1.4) From d4db650d254795a05858b10e907c220e8545959d Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Thu, 9 Oct 2025 20:57:18 +0200 Subject: [PATCH 88/89] use Base.RefValue{NTuple} --- .../libelixir_structured2d_source_terms_callback.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/LibTrixi.jl/examples/libelixir_structured2d_source_terms_callback.jl b/LibTrixi.jl/examples/libelixir_structured2d_source_terms_callback.jl index 69836bfb..c3528683 100644 --- a/LibTrixi.jl/examples/libelixir_structured2d_source_terms_callback.jl +++ b/LibTrixi.jl/examples/libelixir_structured2d_source_terms_callback.jl @@ -3,9 +3,9 @@ using Trixi using OrdinaryDiffEq using Libdl -struct SourceTermsCallback +struct SourceTermsCallback{NVARS} source_term_fptr::Ptr{Nothing} - buffer::Vector{Cdouble} + buffer::Base.RefValue{NTuple{NVARS, Float64}} function SourceTermsCallback(; n_vars, so_path) so_handle = dlopen(so_path) @@ -13,7 +13,7 @@ struct SourceTermsCallback source_term_fptr = dlsym(so_handle, "source_term_wave") @info "Obtained function pointer ", source_term_fptr - new(source_term_fptr, Vector{Cdouble}(undef, n_vars)) + new{n_vars}(source_term_fptr, Base.RefValue(ntuple(i -> 0.0, n_vars))) end end @@ -21,7 +21,7 @@ function (callback::SourceTermsCallback)(u, x, t, equations::CompressibleEulerEq @unpack source_term_fptr, buffer = callback @ccall $source_term_fptr(u::Ptr{Cdouble}, x::Ptr{Cdouble}, t::Cdouble, equations.gamma::Cdouble, buffer::Ptr{Cdouble})::Cvoid - return SVector(buffer[1], buffer[2], buffer[3], buffer[4]) + return SVector(buffer[]) end # The function to create the simulation state needs to be named `init_simstate` From 1ad3ff603d67cd58f3e4c768339d1a44434acde5 Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Thu, 9 Oct 2025 21:03:50 +0200 Subject: [PATCH 89/89] easier to write --- .../examples/libelixir_structured2d_source_terms_callback.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LibTrixi.jl/examples/libelixir_structured2d_source_terms_callback.jl b/LibTrixi.jl/examples/libelixir_structured2d_source_terms_callback.jl index c3528683..05437e7b 100644 --- a/LibTrixi.jl/examples/libelixir_structured2d_source_terms_callback.jl +++ b/LibTrixi.jl/examples/libelixir_structured2d_source_terms_callback.jl @@ -13,7 +13,7 @@ struct SourceTermsCallback{NVARS} source_term_fptr = dlsym(so_handle, "source_term_wave") @info "Obtained function pointer ", source_term_fptr - new{n_vars}(source_term_fptr, Base.RefValue(ntuple(i -> 0.0, n_vars))) + new{n_vars}(source_term_fptr, Ref(ntuple(i -> 0.0, n_vars))) end end