From 2ce8eb5c5536b49be1fb950fca7a414a2c8c9843 Mon Sep 17 00:00:00 2001 From: Fedor Baart Date: Wed, 6 Dec 2017 20:42:27 +0100 Subject: [PATCH 1/3] fix broken log levels, align set_var/set_value with csdms --- models/c/model.c | 80 +++++++++++++++++---------- models/cpp/model.cpp | 129 ++++++++++++++++++++++--------------------- models/include/bmi.h | 25 +++++++-- 3 files changed, 136 insertions(+), 98 deletions(-) diff --git a/models/c/model.c b/models/c/model.c index 8810366..bb11047 100644 --- a/models/c/model.c +++ b/models/c/model.c @@ -42,21 +42,21 @@ BMI_API int initialize(const char *config_file) { current = 0; sprintf(msg, "initializing with %s", config_file); - _log(INFO, msg); + _log(LEVEL_INFO, msg); return 0; } BMI_API int update(double dt){ sprintf(msg, "updating from %f with %f", current, (dt != -1 ? dt : timestep)); - _log(DEBUG, msg); + _log(LEVEL_DEBUG, msg); current = current + (dt != -1 ? dt : timestep); return 0; } BMI_API int finalize() { - _log(INFO, "finalizing c model"); + _log(LEVEL_INFO, "finalizing c model"); return 0; } @@ -101,7 +101,7 @@ BMI_API void get_var_name(int n, char *name) strncpy(name, "", MAXSTRINGLEN); } sprintf(msg, "getting variable %d -> %s", n, name); - _log(DEBUG, msg); + _log(LEVEL_DEBUG, msg); } @@ -111,27 +111,27 @@ BMI_API void get_var_rank(const char *name, int *rank) if (strcmp(name, "arr1") == 0) { *rank = 1; - } + } else if (strcmp(name, "arr2") == 0) { *rank = 2; - } + } else if (strcmp(name, "arr3") == 0) { *rank = 3; - } - else + } + else { *rank = 0; } sprintf(msg, "variable %s has rank %d", name, *rank); - _log(DEBUG, msg); + _log(LEVEL_DEBUG, msg); } BMI_API void get_var_shape(const char *name, int shape[MAXDIMS]) { - + int rank = 0; int i; for (i = 0; i < MAXDIMS; i++) { @@ -143,25 +143,25 @@ BMI_API void get_var_shape(const char *name, int shape[MAXDIMS]) if (strcmp(name, "arr1") == 0) { shape[0] = 3; - } + } else if (strcmp(name, "arr2") == 0) { shape[0] = 2; shape[1] = 3; - } + } else if (strcmp(name, "arr3") == 0) { shape[0] = 2; shape[1] = 2; shape[2] = 3; - } - else + } + else { - + } sprintf(msg, "variable %s has shape %d", name, *shape); - _log(DEBUG, msg); + _log(LEVEL_DEBUG, msg); } BMI_API void get_var_type(const char *name, char *type) @@ -170,47 +170,49 @@ BMI_API void get_var_type(const char *name, char *type) if (strcmp(name, "arr1") == 0) { strncpy(type, "double", MAXSTRINGLEN); - } + } else if (strcmp(name, "arr2") == 0) { strncpy(type, "int", MAXSTRINGLEN); - } + } else if (strcmp(name, "arr3") == 0) { strncpy(type, "bool", MAXSTRINGLEN); - } - else + } + else { strncpy(type, "", MAXSTRINGLEN); } sprintf(msg, "variable %s has type %s", name, type); - _log(DEBUG, msg); + _log(LEVEL_DEBUG, msg); } -BMI_API void get_var(const char *name, void **ptr) +BMI_API int get_value_ptr(const char *name, void **ptr) { /* The value referenced to by ptr is the memory address of arr1 */ if (strcmp(name, "arr1") == 0) { *ptr = &arr1; - } + } else if (strcmp(name, "arr2") == 0) { *ptr = &arr2; - } + } else if (strcmp(name, "arr3") == 0) { *ptr = &arr3; - } - else + } + else { *ptr = NULL; + return 1; } sprintf(msg, "variable %s is at location %p", name, *ptr); - _log(DEBUG, msg); + _log(LEVEL_DEBUG, msg); + return 0; } -BMI_API void set_var(const char *name, const void *ptr) +BMI_API int set_value(const char *name, const void *ptr) { if (strcmp(name, "arr1") == 0) { @@ -224,6 +226,10 @@ BMI_API void set_var(const char *name, const void *ptr) { memcpy(arr3, ptr, sizeof(arr3)); } + else { + return 1; + } + return 0; } BMI_API void set_var_slice(const char *name, const int *start, const int *count, const void *ptr) @@ -241,11 +247,27 @@ BMI_API void set_var_slice(const char *name, const int *start, const int *count, } } +BMI_API void set_var_at_indices(const char *name, const int *start, const int *count, const void *ptr) +{ + int i; + int j; + if (strcmp(name, "arr2") == 0) { + for(i = 0; i < count[0]; ++i) + { + for (j = 0; j < count[1]; ++j) + { + arr2[start[0] + i][start[1] + j] = ((int*) ptr)[i * 3 + j]; + } + } + } +} + + BMI_API void set_logger(Logger callback) { char *msg = "Logger attached to c model."; logger = callback; - _log(INFO, msg); + _log(LEVEL_INFO, msg); } /* private log function, which logs to the logging callback */ diff --git a/models/cpp/model.cpp b/models/cpp/model.cpp index f00dad8..bdcbdaf 100644 --- a/models/cpp/model.cpp +++ b/models/cpp/model.cpp @@ -11,21 +11,21 @@ double timestep = 1; // define some arrays for exchange double arr1[3] = { 3, 2, 1}; int arr2[2][3] = - { +{ { 3, 2, 1}, { 6, 4, 2} - }; +}; bool arr3[2][2][3] = - { +{ { - { true, false, false}, - { false, true, false} + { true, false, false}, + { false, true, false} }, { - { false, false, false}, - { false, true, false} + { false, false, false}, + { false, true, false} } - }; +}; /* Store callback */ Logger logger = NULL; @@ -35,67 +35,68 @@ void _log(Level level, std::string msg); extern "C" { - BMI_API int initialize(const char *config_file) - { + BMI_API int initialize(const char *config_file) + { std::ostringstream msg; msg << "initializing with " << config_file; - _log(INFO, msg.str()); - return 0; - } - - BMI_API int update(double dt) - { - std::ostringstream msg; - msg << "updating from " << current << " with dt: " << (dt != -1 ? dt : timestep); - _log(DEBUG, msg.str()); - current += (dt != -1 ? dt : timestep); - return 0; - } - - BMI_API int finalize() - { - return 0; - } - - BMI_API void get_start_time(double *t) - { - *t = 0; - } - - BMI_API void get_end_time(double *t) - { - *t = 10; - } - - BMI_API void get_current_time(double *t) - { - *t = current; - } - - BMI_API void get_time_step(double *dt) - { - *dt = timestep; - } - - BMI_API void get_var(const char *name, void **ptr) - { - /* The value referenced to by ptr is the memory address of arr1 */ - *ptr = &arr1; - } - - BMI_API void set_logger(Logger callback) - { - Level level = INFO; - std::string msg = "Logging attached to cxx model"; - logger = callback; - logger(level, msg.c_str()); - } + _log(LEVEL_INFO, msg.str()); + return 0; + } + + BMI_API int update(double dt) + { + std::ostringstream msg; + msg << "updating from " << current << " with dt: " << (dt != -1 ? dt : timestep); + _log(LEVEL_DEBUG, msg.str()); + current += (dt != -1 ? dt : timestep); + return 0; + } + + BMI_API int finalize() + { + return 0; + } + + BMI_API void get_start_time(double *t) + { + *t = 0; + } + + BMI_API void get_end_time(double *t) + { + *t = 10; + } + + BMI_API void get_current_time(double *t) + { + *t = current; + } + + BMI_API void get_time_step(double *dt) + { + *dt = timestep; + } + + BMI_API int get_value_ptr(const char *name, void **ptr) + { + /* The value referenced to by ptr is the memory address of arr1 */ + *ptr = &arr1; + return 0; + } + + BMI_API void set_logger(Logger callback) + { + Level level = LEVEL_INFO; + std::string msg = "Logging attached to cxx model"; + logger = callback; + logger(level, msg.c_str()); + } } void _log(Level level, std::string msg) { - if (logger != NULL) { - logger(level, msg.c_str()); - } + if (logger != NULL) { + logger(level, msg.c_str()); + } } // placeholder function, all dll's need a main.. in windows only diff --git a/models/include/bmi.h b/models/include/bmi.h index 5a560aa..a94ae71 100644 --- a/models/include/bmi.h +++ b/models/include/bmi.h @@ -6,7 +6,7 @@ #define BMI_API_H #define BMI_API_VERSION_MAJOR 1 -#define BMI_API_VERSION_MINOR 0 +#define BMI_API_VERSION_MINOR 1 #if defined _WIN32 #define BMI_API __declspec(dllexport) @@ -63,11 +63,27 @@ extern "C" { BMI_API void get_var_name(int index, char *name); - /* get a pointer pointer - a reference to a multidimensional array */ - BMI_API void get_var(const char *name, void **ptr); + /* compatible with csdms BMI api */ + BMI_API int get_value(const char *name, const void *ptr); + BMI_API int get_value_ptr(const char *name, void **ptr); + /* please note these are not ordered the same as set_value_at_indices */ + BMI_API int get_value_at_indices(const char *name, void **ptr, int *inds); + + /* get a pointer pointer - a reference to a multidimensional array */ + BMI_API void get_var(const char *name, void **ptr) { + get_value_ptr(name, ptr); + return; + } + + /* compatible with csdms BMI api */ + BMI_API int set_value(const char *name, const void *ptr); + BMI_API int set_value_at_indices(const char *name, int *inds, void *ptr); /* Set the variable from contiguous memory referenced to by ptr */ - BMI_API void set_var(const char *name, const void *ptr); + BMI_API void set_var(const char *name, const void *ptr) { + set_value(name, ptr); + return; + }; /* Set a slice of the variable from contiguous memory using start / count multi-dimensional indices */ BMI_API void set_var_slice(const char *name, const int *start, const int *count, const void *ptr); @@ -83,4 +99,3 @@ extern "C" { #endif #endif - From cf3d1b91de6b0995ef32da95a8ba587da0cd7400 Mon Sep 17 00:00:00 2001 From: Fedor Baart Date: Wed, 6 Dec 2017 20:50:37 +0100 Subject: [PATCH 2/3] c example --- models/c/model.c | 17 ++++++++--------- models/include/bmi.h | 3 ++- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/models/c/model.c b/models/c/model.c index bb11047..ead40ef 100644 --- a/models/c/model.c +++ b/models/c/model.c @@ -247,19 +247,18 @@ BMI_API void set_var_slice(const char *name, const int *start, const int *count, } } -BMI_API void set_var_at_indices(const char *name, const int *start, const int *count, const void *ptr) +BMI_API int set_value_at_indices(const char *name, int *inds, int len, void *ptr) { - int i; - int j; - if (strcmp(name, "arr2") == 0) { - for(i = 0; i < count[0]; ++i) + if (strcmp(name, "arr1") == 0) { + for(int i = 0; i < len; ++i) { - for (j = 0; j < count[1]; ++j) - { - arr2[start[0] + i][start[1] + j] = ((int*) ptr)[i * 3 + j]; - } + /* unravel index here... */ + int idx = inds[i]; + arr1[idx] = ((int*) ptr)[i]; } + return 0; } + return 1; } diff --git a/models/include/bmi.h b/models/include/bmi.h index a94ae71..dadbf1e 100644 --- a/models/include/bmi.h +++ b/models/include/bmi.h @@ -78,7 +78,8 @@ extern "C" { /* compatible with csdms BMI api */ BMI_API int set_value(const char *name, const void *ptr); - BMI_API int set_value_at_indices(const char *name, int *inds, void *ptr); + /* There is an inconsistency in the csdms api here. The len is missing in the spec. */ + BMI_API int set_value_at_indices(const char *name, int *inds, int len, void *ptr); /* Set the variable from contiguous memory referenced to by ptr */ BMI_API void set_var(const char *name, const void *ptr) { set_value(name, ptr); From d9ce29286ba4e33229ec02ead9084fa8f88c8b4d Mon Sep 17 00:00:00 2001 From: Fedor Baart Date: Sun, 2 Feb 2020 21:16:20 +0100 Subject: [PATCH 3/3] add get_var_slice --- models/fortran/model.f90 | 57 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/models/fortran/model.f90 b/models/fortran/model.f90 index 67050a2..6972b19 100644 --- a/models/fortran/model.f90 +++ b/models/fortran/model.f90 @@ -204,6 +204,55 @@ subroutine set_var(c_var_name, xptr) bind(C, name="set_var") end select end subroutine set_var + + subroutine set_var_slice(c_var_name, c_start, count, xptr) bind(C, name="set_var_slice") + + !DEC$ ATTRIBUTES DLLEXPORT :: set_var_slice + ! Return a pointer to the variable + use iso_c_binding, only: c_double, c_char, c_loc, c_f_pointer + + integer(c_int) :: c_start(MAXDIMS) + integer(c_int) :: start(MAXDIMS) + integer(c_int) :: count(MAXDIMS) + character(kind=c_char), intent(in) :: c_var_name(*) + type(c_ptr), value, intent(in) :: xptr + + + real(c_double), pointer :: x_1d_double_ptr(:) + real(c_double), pointer :: x_2d_double_ptr(:,:) + real(c_double), pointer :: x_3d_double_ptr(:,:,:) + integer(c_int), pointer :: x_1d_int_ptr(:) + integer(c_int), pointer :: x_2d_int_ptr(:,:) + integer(c_int), pointer :: x_3d_int_ptr(:,:,:) + real(c_float), pointer :: x_1d_float_ptr(:) + real(c_float), pointer :: x_2d_float_ptr(:,:) + real(c_float), pointer :: x_3d_float_ptr(:,:,:) + logical(c_bool), pointer :: x_1d_bool_ptr(:) + logical(c_bool), pointer :: x_2d_bool_ptr(:,:) + logical(c_bool), pointer :: x_3d_bool_ptr(:,:,:) + + ! The fortran name of the attribute name + character(len=strlen(c_var_name)) :: var_name + ! Store the name + var_name = char_array_to_string(c_var_name) + + start = c_start + 1 + + select case(var_name) + case("arr1") + call c_f_pointer(xptr, x_1d_double_ptr, (/count(1)/)) + arr1(start(1):(start(1)+count(1)-1)) = (/ x_1d_double_ptr /) + case("arr2") + call c_f_pointer(xptr, x_2d_int_ptr, (/count(1), count(2)/)) + arr2(start(1):(start(1)+count(1)), start(2):(start(2)+count(2))) = x_2d_int_ptr + case("arr3") + call c_f_pointer(xptr, x_3d_int_ptr, (/count(1), count(2), count(3)/)) + arr3(start(1):(start(1)+count(1)), start(2):(start(2)+count(2)), start(3):(start(3)+count(3))) = x_3d_bool_ptr + end select + + end subroutine set_var_slice + + subroutine get_current_time(time) bind(C, name="get_current_time") !DEC$ ATTRIBUTES DLLEXPORT :: get_current_time @@ -220,6 +269,14 @@ subroutine get_start_time(time) bind(C, name="get_start_time") end subroutine get_start_time + subroutine get_time_step(time_step) bind(C, name="get_time_step") + !DEC$ ATTRIBUTES DLLEXPORT :: get_time_step + + real(c_double) :: time_step + time_step = 1.0 + + end subroutine get_time_step + subroutine get_end_time(time) bind(C, name="get_end_time") !DEC$ ATTRIBUTES DLLEXPORT :: get_end_time