Skip to content

Commit

Permalink
initial draft for C API
Browse files Browse the repository at this point in the history
  • Loading branch information
benegee committed Aug 16, 2023
1 parent 8a5c877 commit bcd63ac
Show file tree
Hide file tree
Showing 12 changed files with 618 additions and 590 deletions.
11 changes: 9 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,15 @@ find_package( MPI REQUIRED )

# Library target
add_library ( ${PROJECT_NAME} SHARED
src/trixi.c
src/trixi.h
src/function_pointers.h
src/function_pointers.c
src/auxiliary.h
src/auxiliary.c
src/control.c
src/data.c
src/setup.c
src/version.c
src/trixi.f90
)

Expand Down Expand Up @@ -79,7 +86,7 @@ target_compile_options( ${PROJECT_NAME} PRIVATE -Wall -Wextra -Werror)

# Add auxiliary *object* library to support fast thread-local storage (TLS)
add_library ( ${PROJECT_NAME}_tls OBJECT
src/trixi_tls.c
src/tls.c
)
target_include_directories( ${PROJECT_NAME}_tls PRIVATE ${JULIA_INCLUDE_DIRS} )

Expand Down
62 changes: 62 additions & 0 deletions src/auxiliary.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#include "auxiliary.h"
#include "trixi.h"


// Run Julia command and check for errors
// Source: https://github.com/JuliaLang/julia/blob/c0dd6ff8363f948237304821941b06d67014fa6a/test/embedding/embedding.c#L17-L31
jl_value_t* checked_eval_string(const char* code, const char* func, const char* file, int lineno) {

jl_value_t *result = jl_eval_string(code);

if (jl_exception_occurred()) {

// none of these allocate, so a gc-root (JL_GC_PUSH) is not necessary
jl_printf(jl_stderr_stream(), "ERROR in %s:%d (%s):\n", file, lineno, func);
jl_printf(jl_stderr_stream(),
"The following Julia code could not be evaluated: %s\n", code);
jl_call2(jl_get_function(jl_base_module, "showerror"), jl_stderr_obj(),
jl_exception_occurred());
jl_printf(jl_stderr_stream(), "\n");
jl_atexit_hook(1);
exit(1);
}

assert(result && "Missing return value but no exception occurred!");

return result;
}


void print_and_die(const char* message, const char* func, const char* file, int lineno) {
fprintf(stderr, "ERROR in %s:%d (%s): %s\n", file, lineno, func, message);
exit(1);
}


int show_debug_output() {
const char * env = getenv("LIBTRIXI_DEBUG");
if (env == NULL) {
return 0;
}

if (strcmp(env, "all") == 0 || strcmp(env, "c") == 0) {
return 1;
} else {
return 0;
}
}


/**
* @anchor julia_eval_string_api_c
*
* @brief Execute Julia code
*
* Execute the provided code in the current Julia runtime environment.
*
* @warning Only for development. Code is not checked prior to execution.
*/
void julia_eval_string(const char * code) {

checked_eval_string(code, LOC);
}
20 changes: 20 additions & 0 deletions src/auxiliary.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#ifndef AUXILIARY_H_
#define AUXILIARY_H_

#include <julia.h>

// Function for more helpful error messages
void print_and_die(const char* message, const char* func, const char* file, int lineno);
#define LOC __func__, __FILE__, __LINE__

// Function to determine debug level
int show_debug_output();

// Function to evaluate julia REPL string with exception handling
jl_value_t* checked_eval_string(const char* code, const char* func, const char* file,
int lineno);

// Execute the provided code in the current Julia runtime environment
void julia_eval_string(const char * code);

#endif // ifndef AUXILIARY_H_
88 changes: 88 additions & 0 deletions src/control.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
#include "trixi.h"
#include "function_pointers.h"


/**
* @anchor trixi_initialize_simulation_api_c
*
* @brief Set up Trixi simulation
*
* Set up a Trixi simulation by reading the provided libelixir file. It resembles Trixi's
* typical elixir files with the following differences:
* - Everything (except `using ...`) has to be inside a `function init_simstate()`
* - OrdinaryDiffEq's integrator has to be created by calling `init` (instead of `solve`)
* - A `SimulationState` has to be created from the semidiscretization and the integrator
* See the examples in the `LibTrixi.jl/examples` folder
*
* @param[in] libelixir Path to libelexir file.
*
* @return handle (integer) to Trixi simulation instance
*/
int trixi_initialize_simulation(const char * libelixir) {

// Get function pointer
int (*initialize_simulation)(const char *) = trixi_function_pointers[TRIXI_FTPR_INITIALIZE_SIMULATION];

// Call function
return initialize_simulation( libelixir );
}


/**
* @anchor trixi_is_finished_api_c
*
* @brief Check if simulation is finished
*
* Checks if the simulation identified by handle has reached its final time.
*
* @param[in] handle simulation handle
*
* @return 1 if finished, 0 if not
*/
int trixi_is_finished(int handle) {

// Get function pointer
int (*is_finished)(int) = trixi_function_pointers[TRIXI_FTPR_IS_FINISHED];

// Call function
return is_finished( handle );
}


/**
* @anchor trixi_step_api_c
*
* @brief Perform next simulation step
*
* Let the simulation identified by handle advance by one step.
*
* @param[in] handle simulation handle
*/
void trixi_step(int handle) {

// Get function pointer
int (*step)(int) = trixi_function_pointers[TRIXI_FTPR_STEP];

// Call function
step( handle );
}


/**
* @anchor trixi_finalize_simulation_api_c
*
* @brief Finalize simulation
*
* Finalize the simulation identified by handle. This will also release the handle.
*
* @param[in] handle simulation handle
*/
void trixi_finalize_simulation(int handle) {

// Get function pointer
void (*finalize_simulation)(int) = trixi_function_pointers[TRIXI_FTPR_FINALIZE_SIMULATION];

// Call function
finalize_simulation(handle);
}

98 changes: 98 additions & 0 deletions src/data.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
#include "trixi.h"
#include "function_pointers.h"


/**
* @anchor trixi_calculate_dt_api_c
*
* @brief Get time step length
*
* Get the current time step length of the simulation identified by handle.
*
* @param[in] handle simulation handle
*
* @return Time step length
*/
double trixi_calculate_dt(int handle) {

// Get function pointer
double (*calculate_dt)(int) = trixi_function_pointers[TRIXI_FTPR_CALCULATE_DT];;

// Call function
return calculate_dt( handle );
}


/**
* @anchor trixi_ndims_api_c
*
* @brief Return number of spatial dimensions
*
* @param[in] handle simulation handle
*/
int trixi_ndims(int handle) {

// Get function pointer
int (*ndims)(int) = trixi_function_pointers[TRIXI_FTPR_NDIMS];

// Call function
return ndims(handle);
}


/**
* @anchor trixi_nelements_api_c
*
* @brief Return number of elements (cells)
*
* @param[in] handle simulation handle
*/
int trixi_nelements(int handle) {

// Get function pointer
int (*nelements)(int) = trixi_function_pointers[TRIXI_FTPR_NELEMENTS];

// Call function
return nelements(handle);
}


/**
* @anchor trixi_nvariables_api_c
*
* @brief Return number of (conservative) variables
*
* @param[in] handle simulation handle
*/
int trixi_nvariables(int handle) {

// Get function pointer
int (*nvariables)(int) = trixi_function_pointers[TRIXI_FTPR_NVARIABLES];

// Call function
return nvariables(handle);
}


/**
* @anchor trixi_load_cell_averages_api_c
*
* @brief Return cell averaged values
*
* 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).
*
* The given array has to be of correct size and memory has to be allocated beforehand.
*
* @param[in] handle simulation handle
* @param[out] data cell averaged values for all cells and all primitive variables
*/
void trixi_load_cell_averages(double * data, int handle) {

// Get function pointer
void (*load_cell_averages)(double *, int) = trixi_function_pointers[TRIXI_FTPR_LOAD_CELL_AVERAGES];

// Call function
load_cell_averages(data, handle);
}
21 changes: 21 additions & 0 deletions src/function_pointers.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#include "function_pointers.h"

void* trixi_function_pointers[TRIXI_NUM_FPTRS];

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_FTPR_NELEMENTS] = "trixi_nelements_cfptr",
[TRIXI_FTPR_NVARIABLES] = "trixi_nvariables_cfptr",
[TRIXI_FTPR_LOAD_CELL_AVERAGES] = "trixi_load_cell_averages_cfptr",
[TRIXI_FTPR_VERSION] = "trixi_version_cfptr",
[TRIXI_FTPR_VERSION_MAJOR] = "trixi_version_major_cfptr",
[TRIXI_FTPR_VERSION_MINOR] = "trixi_version_minor_cfptr",
[TRIXI_FTPR_VERSION_PATCH] = "trixi_version_patch_cfptr",
[TRIXI_FTPR_VERSION_JULIA] = "trixi_version_julia_cfptr",
[TRIXI_FTPR_VERSION_JULIA_EXTENDED] = "trixi_version_julia_extended_cfptr"
};
33 changes: 33 additions & 0 deletions src/function_pointers.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#ifndef FUNCTION_POINTERS_H_
#define FUNCTION_POINTERS_H_

// Enum to index function pointer array
enum {
TRIXI_FTPR_INITIALIZE_SIMULATION,
TRIXI_FTPR_CALCULATE_DT,
TRIXI_FTPR_IS_FINISHED,
TRIXI_FTPR_STEP,
TRIXI_FTPR_FINALIZE_SIMULATION,
TRIXI_FTPR_NDIMS,
TRIXI_FTPR_NELEMENTS,
TRIXI_FTPR_NVARIABLES,
TRIXI_FTPR_LOAD_CELL_AVERAGES,
TRIXI_FTPR_VERSION,
TRIXI_FTPR_VERSION_MAJOR,
TRIXI_FTPR_VERSION_MINOR,
TRIXI_FTPR_VERSION_PATCH,
TRIXI_FTPR_VERSION_JULIA,
TRIXI_FTPR_VERSION_JULIA_EXTENDED,

// The last one is for the array size
TRIXI_NUM_FPTRS
};

// Function pointer array
extern 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
extern const char* trixi_function_pointer_names[TRIXI_NUM_FPTRS];

#endif // ifndef FUNCTION_POINTERS_H_
Loading

0 comments on commit bcd63ac

Please sign in to comment.