From d5ecc49df72ee10e475c81842cc1f9d1a66b9e22 Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Thu, 22 Feb 2024 17:49:17 +0100 Subject: [PATCH 01/73] 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/73] 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/73] 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/73] 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/73] 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/73] 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/73] 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/73] 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/73] 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/73] 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/73] 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/73] 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/73] 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/73] 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/73] 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 b8648508d08f87ccd56f9a331c95e6d5de826180 Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Thu, 29 Feb 2024 16:36:32 +0100 Subject: [PATCH 16/73] 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 17/73] 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 18/73] 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 19/73] 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 20/73] 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 21/73] 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 22/73] 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 23/73] 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 24/73] 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 25/73] 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 26/73] 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 27/73] 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 28/73] 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 29/73] 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 30/73] 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 31/73] 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 32/73] 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 33/73] 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 34/73] 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 35/73] 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 36/73] 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 37/73] 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 38/73] 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 39/73] 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 40/73] 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 41/73] 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 42/73] 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 7b654a451179049adfe2b7be6996c8bf59d4926b Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Tue, 19 Nov 2024 12:14:55 +0100 Subject: [PATCH 43/73] 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 44/73] 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 45/73] 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 46/73] 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 47/73] 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 48/73] 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 49/73] 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 50/73] 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 51/73] 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 52/73] 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 53/73] 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 54/73] 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 55/73] 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 56/73] 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 57/73] 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 58/73] 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 59/73] 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 60/73] 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 61/73] 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 62/73] 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 63/73] 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 64/73] 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 65/73] 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 142e6a2f463b666c5acc4b0a42f36eafa57a9cff Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Thu, 28 Nov 2024 14:43:59 +0100 Subject: [PATCH 66/73] typo in docstring --- LibTrixi.jl/src/api_c.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LibTrixi.jl/src/api_c.jl b/LibTrixi.jl/src/api_c.jl index 6b729d82..68bb408d 100644 --- a/LibTrixi.jl/src/api_c.jl +++ b/LibTrixi.jl/src/api_c.jl @@ -539,7 +539,7 @@ trixi_load_element_averaged_primitive_vars_cfptr() = """ - trixi_get_t8code_forest(simstate_handle::Cint)::::Ptr{Trixi.t8_forest} + trixi_get_t8code_forest(simstate_handle::Cint)::Ptr{Trixi.t8_forest} Return t8code forest of the current T8codeMesh. From 8794de77ae392acb1fc8fe3ba472c7de4f685096 Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Tue, 17 Dec 2024 09:20:45 +0100 Subject: [PATCH 67/73] adopt new t8code ForestWrapper --- LibTrixi.jl/src/api_jl.jl | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/LibTrixi.jl/src/api_jl.jl b/LibTrixi.jl/src/api_jl.jl index 5d728425..ee9c354f 100644 --- a/LibTrixi.jl/src/api_jl.jl +++ b/LibTrixi.jl/src/api_jl.jl @@ -46,13 +46,15 @@ function trixi_finalize_simulation_jl(simstate) end end - # In course of garbage collection, MPI might get finalized before t8code related objects. - # This can lead to crashes because t8code allocates MPI related objects, e.g. shared - # memory arrays. The workaround is to finalize T8codeMesh explicitly in advance. + # In course of garbage collection, MPI might get finalized before t8code related + # objects. This can lead to crashes because t8code allocates MPI related objects, e.g. + # shared memory arrays. + # T8code.jl implements manual ref counting to deal with this issue. + # For p4est the workaround is to finalize P4estMeshes explicitly in advance. # x-ref: https://github.com/DLR-AMR/t8code/issues/1295 # x-ref: https://github.com/trixi-framework/libtrixi/pull/215#discussion_r1843676330 mesh, _, _, _ = mesh_equations_solver_cache(simstate.semi) - if mesh isa Trixi.T8codeMesh || mesh isa Trixi.P4estMesh + if mesh isa Trixi.P4estMesh finalize(mesh) end @@ -215,7 +217,7 @@ end function trixi_get_t8code_forest_jl(simstate) mesh, _, _, _ = mesh_equations_solver_cache(simstate.semi) - return mesh.forest + return mesh.forest.pointer end ############################################################################################ From 5f5fe48dfca1e28ae5a5bc77c1a6f80a6b801a95 Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Tue, 17 Dec 2024 09:25:33 +0100 Subject: [PATCH 68/73] switch to newest t8code release --- .github/workflows/ci.yml | 4 ++-- README.md | 2 +- docs/src/index.md | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b0a32f10..d89cc3f6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,13 +38,13 @@ jobs: - '1.10' - '1.11' t8code_version: - - '3.0.0' + - '3.0.1' include: - os: ubuntu-latest test_type: coverage arch: x64 julia_version: '1.11' - t8code_version: '3.0.0' + t8code_version: '3.0.1' env: # Necessary for HDF5 to play nice with Julia LD_PRELOAD: /lib/x86_64-linux-gnu/libcurl.so.4 diff --git a/README.md b/README.md index fc523ccb..47735339 100644 --- a/README.md +++ b/README.md @@ -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) v3.0.0 +* [t8code](https://github.com/DLR-AMR/t8code) v3.0.1 ### Get the sources diff --git a/docs/src/index.md b/docs/src/index.md index 4df3c33c..3c19903d 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -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) v3.0.0 +* [t8code](https://github.com/DLR-AMR/t8code) v3.0.1 ### Get the sources From f341561440039a3d081db67a0cf7e84ae58c7946 Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Fri, 20 Dec 2024 08:43:17 +0100 Subject: [PATCH 69/73] cubed sphere stuff only works with latest Trixi release --- LibTrixi.jl/Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LibTrixi.jl/Project.toml b/LibTrixi.jl/Project.toml index a92ba70d..e784b53b 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.7.16, 0.8, 0.9" +Trixi = "0.9.12" julia = "1.8" [preferences.OrdinaryDiffEq] From 889f9902e60ec11c5197b3f42080f43f3138c7d8 Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Fri, 20 Dec 2024 09:46:38 +0100 Subject: [PATCH 70/73] missed renaming --- test/c/simulation.cpp | 2 +- test/fortran/simulationRun_suite.f90 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/c/simulation.cpp b/test/c/simulation.cpp index beacbe82..36fbccbb 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_sedov.jl"; + "../../../LibTrixi.jl/examples/libelixir_p4est2d_euler_sedov.jl"; TEST(CInterfaceTest, SimulationRun) { diff --git a/test/fortran/simulationRun_suite.f90 b/test/fortran/simulationRun_suite.f90 index 65c1f98b..c9261f02 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_sedov.jl" + "../../../LibTrixi.jl/examples/libelixir_p4est2d_euler_sedov.jl" contains From 63ece7a915e3405761e0fcf2de22b9bcc4fb413b Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Fri, 20 Dec 2024 09:46:57 +0100 Subject: [PATCH 71/73] enable t8code for package compiler as well --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d89cc3f6..e8a9bdbe 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -196,6 +196,7 @@ jobs: cd build cmake .. -DCMAKE_INSTALL_PREFIX=../install \ -DCMAKE_BUILD_TYPE=Debug \ + -DT8CODE_ROOT=$PWD/../t8code-local/prefix \ -DUSE_PACKAGE_COMPILER=ON \ -DJULIA_PROJECT_PATH=$PWD/../libtrixi-julia From 90312a1641f8cc62f86d6b6e081f62e050e91cc1 Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Tue, 7 Jan 2025 12:27:19 +0100 Subject: [PATCH 72/73] review --- .github/workflows/ci.yml | 1 - ...ibelixir_t8code3d_euler_baroclinic_instability.jl | 12 ++++++------ 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e8a9bdbe..d89cc3f6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -196,7 +196,6 @@ jobs: cd build cmake .. -DCMAKE_INSTALL_PREFIX=../install \ -DCMAKE_BUILD_TYPE=Debug \ - -DT8CODE_ROOT=$PWD/../t8code-local/prefix \ -DUSE_PACKAGE_COMPILER=ON \ -DJULIA_PROJECT_PATH=$PWD/../libtrixi-julia diff --git a/LibTrixi.jl/examples/libelixir_t8code3d_euler_baroclinic_instability.jl b/LibTrixi.jl/examples/libelixir_t8code3d_euler_baroclinic_instability.jl index e912bcbc..557ce772 100644 --- a/LibTrixi.jl/examples/libelixir_t8code3d_euler_baroclinic_instability.jl +++ b/LibTrixi.jl/examples/libelixir_t8code3d_euler_baroclinic_instability.jl @@ -252,7 +252,7 @@ function init_simstate() mesh = Trixi.T8codeMeshCubedSphere(lat_lon_levels, layers, 6.371229e6, 30000.0, polydeg = 5, initial_refinement_level = 0) - # create the data registry and three vectors for the source terms + # create the data registry and four vectors for the source terms registry = LibTrixiDataRegistry(undef, 4) nnodesdim = Trixi.nnodes(solver) @@ -260,11 +260,11 @@ function init_simstate() nelements = Trixi.ncells(mesh) # provide some data because calc_sources! will already be called during initialization - zero_data = zeros(Float64, nelements*nnodes) - registry[1] = zero_data - registry[2] = zero_data - registry[3] = zero_data - registry[4] = zero_data + # Note: the data pointers in the registry will be overwritten before the first real use + registry[1] = zeros(Float64, nelements*nnodes) + registry[2] = zeros(Float64, nelements*nnodes) + registry[3] = zeros(Float64, nelements*nnodes) + registry[4] = zeros(Float64, nelements*nnodes) source_term_data_registry = SourceTerm(nnodesdim, registry) From b379e50670e2519637b2d575dedd774d6b4049b1 Mon Sep 17 00:00:00 2001 From: Benedict Geihe Date: Tue, 7 Jan 2025 16:16:49 +0100 Subject: [PATCH 73/73] filter out baroclinic example --- examples/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 6684be7c..1cdf293b 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -12,6 +12,7 @@ set ( EXAMPLES if ( NOT T8CODE_FOUND ) list( FILTER EXAMPLES EXCLUDE REGEX ".*(t|T)8(c|C)(o|O)(d|D)(e|E).*" ) + list( FILTER EXAMPLES EXCLUDE REGEX "trixi_controller_baroclinic.*" ) endif() foreach ( EXAMPLE ${EXAMPLES} )