Skip to content

Commit ae0ac67

Browse files
benegeesloede
andauthored
RFC: source terms via global vector storage (#173)
* add getter for number of dofs * change trixi_load_cell_average add parameter index and only get averaged of the variable at position index * fix: ensure Int32 * adapt reference value * add getter for all dofs values * adapt next value * add trixi_store_in_database proof of concept for creating data vectors in libelixirs which can be filled later by external applications * add trixi_ndofs_element * add tests * add missing parts in tests * fix tests * deallocate first * add trixi_load_prim to Fortran API * reference value * get doxygen right * add trixi_get_time, trixi_load_node_coordinates required in this PR, subject to change * implement source terms controller demonstrates source terms via database * libelixir with source terms via database * change Array to Vector * spelling * make everything more consistent! * use const double * * missed merge conflict * transpose calloc args * add functions to get quadrature information * update CI badge URL * remove load_node_coordinates * add get_t8code_forest to Fortran interface * format * add trixi_store_in_database to Fortran interface * adapt min version according to main CMakeLists.txt * missed while merging * change default argument for DataBase parameter * remove deprecated export * test for get_time * add tests for trixi_store_in_database * need Int32 * cannot compare Refs * check based on address * relax error tolerance * remove deprecated example * rename get_time to get_simulation_time * rename database to registry * spurious Ref access --------- Co-authored-by: Michael Schlottke-Lakemper <michael@sloede.com> Co-authored-by: Benedict <135045760+bgeihe@users.noreply.github.com>
1 parent 714203f commit ae0ac67

File tree

13 files changed

+218
-16
lines changed

13 files changed

+218
-16
lines changed

LibTrixi.jl/examples/libelixir_p4est2d_dgsem_euler_sedov.jl

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,9 @@ function init_simstate()
106106
###############################################################################
107107
# Create simulation state
108108

109-
simstate = SimulationState(semi, integrator)
109+
# registry only used for tests
110+
registry = LibTrixiDataRegistry(undef, 1)
111+
simstate = SimulationState(semi, integrator, registry)
110112

111113
return simstate
112114
end

LibTrixi.jl/src/LibTrixi.jl

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@ export trixi_load_primitive_vars,
5858
export trixi_load_element_averaged_primitive_vars,
5959
trixi_load_element_averaged_primitive_vars_cfptr,
6060
trixi_load_element_averaged_primitive_vars_jl
61+
export trixi_register_data,
62+
trixi_register_data_cfptr,
63+
trixi_register_data_jl
6164
export trixi_version_library,
6265
trixi_version_library_cfptr,
6366
trixi_version_library_jl
@@ -82,8 +85,13 @@ export trixi_get_t8code_forest,
8285
export trixi_eval_julia,
8386
trixi_eval_julia_cfptr,
8487
trixi_eval_julia_jl
88+
export trixi_get_simulation_time,
89+
trixi_get_simulation_time_cfptr,
90+
trixi_get_simulation_time_jl
91+
8592

8693
export SimulationState, store_simstate, load_simstate, delete_simstate!
94+
export LibTrixiDataRegistry
8795

8896

8997
# global storage of name and version information of loaded packages

LibTrixi.jl/src/api_c.jl

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -461,6 +461,53 @@ trixi_load_primitive_vars_cfptr() =
461461
@cfunction(trixi_load_primitive_vars, Cvoid, (Cint, Cint, Ptr{Cdouble}))
462462

463463

464+
"""
465+
trixi_register_data(data::Ptr{Cdouble}, size::Cint, index::Cint,
466+
simstate_handle::Cint)::Cvoid
467+
468+
Store data vector in current simulation's registry.
469+
470+
A reference to the passed data array `data` will be stored in the registry of the simulation
471+
given by `simstate_handle` at given `index`. The registry object has to be created in
472+
`init_simstate()` of the running libelixir and can be used throughout the simulation.
473+
474+
The registry object has to exist, has to be of type `LibTrixiDataRegistry`, and has to hold
475+
enough data references such that access at `index` is valid.
476+
Memory storage remains on the user side. It must not be deallocated as long as it might be
477+
accessed via the registry. The size of `data` has to match `size`.
478+
"""
479+
function trixi_register_data end
480+
481+
Base.@ccallable function trixi_register_data(simstate_handle::Cint, index::Cint,
482+
size::Cint, data::Ptr{Cdouble})::Cvoid
483+
simstate = load_simstate(simstate_handle)
484+
485+
# convert C to Julia array
486+
data_jl = unsafe_wrap(Array, data, size)
487+
488+
trixi_register_data_jl(simstate, index, data_jl)
489+
return nothing
490+
end
491+
492+
trixi_register_data_cfptr() =
493+
@cfunction(trixi_register_data, Cvoid, (Cint, Cint, Cint, Ptr{Cdouble},))
494+
495+
496+
"""
497+
trixi_get_simulation_time(simstate_handle::Cint)::Cdouble
498+
499+
Return current physical time.
500+
"""
501+
function trixi_get_simulation_time end
502+
503+
Base.@ccallable function trixi_get_simulation_time(simstate_handle::Cint)::Cdouble
504+
simstate = load_simstate(simstate_handle)
505+
return trixi_get_simulation_time_jl(simstate)
506+
end
507+
508+
trixi_get_simulation_time_cfptr() = @cfunction(trixi_get_simulation_time, Cdouble, (Cint,))
509+
510+
464511
"""
465512
trixi_load_element_averaged_primitive_vars(simstate_handle::Cint, variable_id::Cint,
466513
data::Ptr{Cdouble})::Cvoid

LibTrixi.jl/src/api_jl.jl

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,20 @@ function trixi_load_element_averaged_primitive_vars_jl(simstate, variable_id, da
199199
end
200200

201201

202+
function trixi_register_data_jl(simstate, index, data)
203+
simstate.registry[index] = data
204+
if show_debug_output()
205+
println("New data vector registered at index ", index)
206+
end
207+
return nothing
208+
end
209+
210+
211+
function trixi_get_simulation_time_jl(simstate)
212+
return simstate.integrator.t
213+
end
214+
215+
202216
function trixi_get_t8code_forest_jl(simstate)
203217
mesh, _, _, _ = mesh_equations_solver_cache(simstate.semi)
204218
return mesh.forest

LibTrixi.jl/src/simulationstate.jl

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,21 @@
1+
const LibTrixiDataRegistry = Vector{Vector{Float64}}
2+
13
"""
24
SimulationState
35
4-
Data structure to store a simulation state that consists of a semidiscretization
5-
plus the time integrator.
6+
Data structure to store a simulation state consisting of
7+
- a semidiscretization
8+
- the time integrator
9+
- an optional array of data vectors
610
"""
711
mutable struct SimulationState{SemiType, IntegratorType}
812
semi::SemiType
913
integrator::IntegratorType
14+
registry::LibTrixiDataRegistry
15+
16+
function SimulationState(semi, integrator, registry = LibTrixiDataRegistry())
17+
return new{typeof(semi), typeof(integrator)}(semi, integrator, registry)
18+
end
1019
end
1120

1221
# Global variables to store different simulation states

LibTrixi.jl/test/test_interface.jl

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,25 @@ end
5959
dt_jl = trixi_calculate_dt_jl(simstate_jl)
6060
@test dt_c == dt_jl
6161

62+
# compare time
63+
time_c = trixi_get_simulation_time(handle)
64+
time_jl = trixi_get_simulation_time_jl(simstate_jl)
65+
@test time_c == time_jl
66+
6267
# compare finished status
6368
@test trixi_is_finished(handle) == 0
6469
@test !trixi_is_finished_jl(simstate_jl)
70+
71+
# manually increase registries (for testing only!)
72+
push!(simstate_jl.registry, Vector{Float64}())
73+
push!(LibTrixi.simstates[handle].registry, Vector{Float64}())
74+
# store a vector
75+
test_data = [1.0, 2.0, 3.0]
76+
trixi_register_data(handle, Int32(1), Int32(3), pointer(test_data))
77+
trixi_register_data_jl(simstate_jl, 1, test_data)
78+
# check that the same memory is referenced
79+
@test pointer(simstate_jl.registry[1]) ==
80+
pointer(LibTrixi.simstates[handle].registry[1])
6581
end
6682

6783

examples/external/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Specify the minimum version
2-
cmake_minimum_required ( VERSION 3.9 )
2+
cmake_minimum_required ( VERSION 3.12 )
33

44
# Specify a project name
55
project(ExternalLibTrixi)

src/api.c

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ enum {
2424
TRIXI_FPTR_LOAD_NODE_WEIGHTS,
2525
TRIXI_FTPR_LOAD_PRIMITIVE_VARS,
2626
TRIXI_FTPR_LOAD_ELEMENT_AVERAGED_PRIMITIVE_VARS,
27+
TRIXI_FTPR_REGISTER_DATA,
2728
TRIXI_FTPR_VERSION_LIBRARY,
2829
TRIXI_FTPR_VERSION_LIBRARY_MAJOR,
2930
TRIXI_FTPR_VERSION_LIBRARY_MINOR,
@@ -32,6 +33,7 @@ enum {
3233
TRIXI_FTPR_VERSION_JULIA_EXTENDED,
3334
TRIXI_FTPR_EVAL_JULIA,
3435
TRIXI_FTPR_GET_T8CODE_FOREST,
36+
TRIXI_FPTR_GET_SIMULATION_TIME,
3537

3638
// The last one is for the array size
3739
TRIXI_NUM_FPTRS
@@ -60,14 +62,16 @@ static const char* trixi_function_pointer_names[] = {
6062
[TRIXI_FPTR_LOAD_NODE_WEIGHTS] = "trixi_load_node_weights_cfptr",
6163
[TRIXI_FTPR_LOAD_PRIMITIVE_VARS] = "trixi_load_primitive_vars_cfptr",
6264
[TRIXI_FTPR_LOAD_ELEMENT_AVERAGED_PRIMITIVE_VARS] = "trixi_load_element_averaged_primitive_vars_cfptr",
65+
[TRIXI_FTPR_REGISTER_DATA] = "trixi_register_data_cfptr",
6366
[TRIXI_FTPR_VERSION_LIBRARY] = "trixi_version_library_cfptr",
6467
[TRIXI_FTPR_VERSION_LIBRARY_MAJOR] = "trixi_version_library_major_cfptr",
6568
[TRIXI_FTPR_VERSION_LIBRARY_MINOR] = "trixi_version_library_minor_cfptr",
6669
[TRIXI_FTPR_VERSION_LIBRARY_PATCH] = "trixi_version_library_patch_cfptr",
6770
[TRIXI_FTPR_VERSION_JULIA] = "trixi_version_julia_cfptr",
6871
[TRIXI_FTPR_VERSION_JULIA_EXTENDED] = "trixi_version_julia_extended_cfptr",
6972
[TRIXI_FTPR_EVAL_JULIA] = "trixi_eval_julia_cfptr",
70-
[TRIXI_FTPR_GET_T8CODE_FOREST] = "trixi_get_t8code_forest_cfptr"
73+
[TRIXI_FTPR_GET_T8CODE_FOREST] = "trixi_get_t8code_forest_cfptr",
74+
[TRIXI_FPTR_GET_SIMULATION_TIME] = "trixi_get_simulation_time_cfptr"
7175
};
7276

7377
// Track initialization/finalization status to prevent unhelpful errors
@@ -691,6 +695,58 @@ void trixi_load_element_averaged_primitive_vars(int handle, int variable_id, dou
691695
}
692696

693697

698+
/**
699+
* @anchor trixi_register_data_api_c
700+
*
701+
* @brief Store data vector in current simulation's registry
702+
*
703+
* A reference to the passed data array `data` will be stored in the registry of the
704+
* simulation given by `simstate_handle` at given `index`. The registry object has to be
705+
* created in `init_simstate()` of the running libelixir and can be used throughout the
706+
* simulation.
707+
*
708+
* The registry object has to exist, has to be of type `LibTrixiDataRegistry`, and has to
709+
* hold enough data references such that access at `index` is valid.
710+
* Memory storage remains on the user side. It must not be deallocated as long as it might
711+
* be accessed via the registry. The size of `data` has to match `size`.
712+
*
713+
* @param[in] handle simulation handle
714+
* @param[in] index index in registry where data vector will be stored
715+
* @param[in] size size of given data vector
716+
* @param[in] data data vector to store
717+
*/
718+
void trixi_register_data(int handle, int index, int size, const double * data) {
719+
720+
// Get function pointer
721+
void (*register_data)(int, int, int, const double *) =
722+
trixi_function_pointers[TRIXI_FTPR_REGISTER_DATA];
723+
724+
// Call function
725+
register_data(handle, index, size, data);
726+
}
727+
728+
729+
/**
730+
* @anchor trixi_get_simulation_time_api_c
731+
*
732+
* @brief Return current physical time.
733+
*
734+
* @param[in] handle simulation handle
735+
*
736+
* @return physical time
737+
*/
738+
double trixi_get_simulation_time(int handle) {
739+
740+
// Get function pointer
741+
double (*get_simulation_time)(int) =
742+
trixi_function_pointers[TRIXI_FPTR_GET_SIMULATION_TIME];
743+
744+
// Call function
745+
return get_simulation_time(handle);
746+
}
747+
748+
749+
694750
/******************************************************************************************/
695751
/* T8code */
696752
/******************************************************************************************/

src/api.f90

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -388,9 +388,24 @@ subroutine trixi_load_primitive_vars(handle, variable_id, data) bind(c)
388388
use, intrinsic :: iso_c_binding, only: c_int, c_double
389389
integer(c_int), value, intent(in) :: handle
390390
integer(c_int), value, intent(in) :: variable_id
391-
real(c_double), dimension(*), intent(in) :: data
391+
real(c_double), dimension(*), intent(out) :: data
392392
end subroutine
393393

394+
!>
395+
!! @fn LibTrixi::trixi_get_simulation_time::trixi_get_simulation_time(handle)
396+
!!
397+
!! @brief Return current physical time.
398+
!!
399+
!! @param[in] handle simulation handle
400+
!!
401+
!! @return physical time
402+
!!
403+
!! @see @ref trixi_get_simulation_time_api_c "trixi_get_simulation_time (C API)"
404+
real(c_double) function trixi_get_simulation_time(handle) bind(c)
405+
use, intrinsic :: iso_c_binding, only: c_int, c_double
406+
integer(c_int), value, intent(in) :: handle
407+
end function
408+
394409
!>
395410
!! @fn LibTrixi::trixi_load_element_averaged_primitive_vars::trixi_load_element_averaged_primitive_vars(handle, variable_id, data)
396411
!!
@@ -405,6 +420,25 @@ subroutine trixi_load_element_averaged_primitive_vars(handle, variable_id, data)
405420
use, intrinsic :: iso_c_binding, only: c_int, c_double
406421
integer(c_int), value, intent(in) :: handle
407422
integer(c_int), value, intent(in) :: variable_id
423+
real(c_double), dimension(*), intent(out) :: data
424+
end subroutine
425+
426+
!>
427+
!! @fn LibTrixi::trixi_register_data::trixi_register_data(handle, variable_id, data)
428+
!!
429+
!! @brief Store data vector in current simulation's registry
430+
!!
431+
!! @param[in] handle simulation handle
432+
!! @param[in] index index in registry where data vector will be stored
433+
!! @param[in] size size of given data vector
434+
!! @param[in] data data vector to store
435+
!!
436+
!! @see @ref trixi_register_data_api_c "trixi_register_data (C API)"
437+
subroutine trixi_register_data(handle, index, size, data) bind(c)
438+
use, intrinsic :: iso_c_binding, only: c_int, c_double
439+
integer(c_int), value, intent(in) :: handle
440+
integer(c_int), value, intent(in) :: index
441+
integer(c_int), value, intent(in) :: size
408442
real(c_double), dimension(*), intent(in) :: data
409443
end subroutine
410444

src/trixi.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,12 @@ int trixi_ndofselement(int handle);
3434
int trixi_nvariables(int handle);
3535
int trixi_nnodes(int handle);
3636
double trixi_calculate_dt(int handle);
37+
double trixi_get_simulation_time(int handle);
3738
void trixi_load_node_reference_coordinates(int handle, double* node_coords);
3839
void trixi_load_node_weights(int handle, double* node_weights);
3940
void trixi_load_primitive_vars(int handle, int variable_id, double * data);
4041
void trixi_load_element_averaged_primitive_vars(int handle, int variable_id, double * data);
42+
void trixi_register_data(int handle, int index, int size, const double * data);
4143

4244
// T8code
4345
#if !defined(T8_H) && !defined(T8_FOREST_GENERAL_H)

0 commit comments

Comments
 (0)