diff --git a/bindings/C/CMakeLists.txt b/bindings/C/CMakeLists.txt index a7d3bddfdd0f1a6f04b738d53bbaa4b941a50905..75f35a43a93c6ff2a1e013e4ff5328b2bdf3e4d4 100644 --- a/bindings/C/CMakeLists.txt +++ b/bindings/C/CMakeLists.txt @@ -9,6 +9,7 @@ ${CMAKE_CURRENT_SOURCE_DIR}/adios2/adios2_c_adios.cpp ${CMAKE_CURRENT_SOURCE_DIR}/adios2/adios2_c_glue.cpp ${CMAKE_CURRENT_SOURCE_DIR}/adios2/adios2_c_io.cpp ${CMAKE_CURRENT_SOURCE_DIR}/adios2/adios2_c_engine.cpp +${CMAKE_CURRENT_SOURCE_DIR}/adios2/adios2_c_variable.cpp ) target_include_directories(adios2 @@ -26,6 +27,7 @@ install( adios2/adios2_c_adios.h adios2/adios2_c_glue.h adios2/adios2_c_io.h + adios2/adios2_c_variable.h adios2/adios2_c_engine.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/adios2 ) diff --git a/bindings/C/adios2/adios2_c_engine.cpp b/bindings/C/adios2/adios2_c_engine.cpp index d2d0880834b4201288021e4aa8b34529d7df8e44..cbdd0ab0846e4cda143dbdb116850e22b6505aa0 100644 --- a/bindings/C/adios2/adios2_c_engine.cpp +++ b/bindings/C/adios2/adios2_c_engine.cpp @@ -156,6 +156,142 @@ void adios2_perform_puts(adios2_Engine *engine) engineCpp.PerformPuts(); } +void adios2_get_sync(adios2_Engine *engine, adios2_Variable *variable, + void *values) +{ + adios2::VariableBase *variableBase = + reinterpret_cast<adios2::VariableBase *>(variable); + const std::string type(variableBase->m_Type); + + adios2::Engine &engineCpp = *reinterpret_cast<adios2::Engine *>(engine); + + if (type == "compound") + { + // not supported + } +#define declare_template_instantiation(T) \ + else if (type == adios2::GetType<T>()) \ + { \ + engineCpp.GetSync(*dynamic_cast<adios2::Variable<T> *>(variableBase), \ + reinterpret_cast<T *>(values)); \ + } + ADIOS2_FOREACH_TYPE_1ARG(declare_template_instantiation) +#undef declare_template_instantiation +} + +void adios2_get_sync_self(adios2_Engine *engine, adios2_Variable *variable) +{ + adios2::VariableBase *variableBase = + reinterpret_cast<adios2::VariableBase *>(variable); + const std::string type(variableBase->m_Type); + + adios2::Engine &engineCpp = *reinterpret_cast<adios2::Engine *>(engine); + + if (type == "compound") + { + // not supported + } +#define declare_template_instantiation(T) \ + else if (type == adios2::GetType<T>()) \ + { \ + engineCpp.GetSync(*dynamic_cast<adios2::Variable<T> *>(variableBase)); \ + } + ADIOS2_FOREACH_TYPE_1ARG(declare_template_instantiation) +#undef declare_template_instantiation +} + +void adios2_get_sync_by_name(adios2_Engine *engine, const char *variable_name, + void *values) +{ + auto &engineCpp = *reinterpret_cast<adios2::Engine *>(engine); + const std::string type( + engineCpp.GetIO().InquireVariableType(variable_name)); + + if (type == "compound") + { + // not supported + } +#define declare_template_instantiation(T) \ + else if (type == adios2::GetType<T>()) \ + { \ + engineCpp.GetSync(variable_name, reinterpret_cast<T *>(values)); \ + } + ADIOS2_FOREACH_TYPE_1ARG(declare_template_instantiation) +#undef declare_template_instantiation +} + +void adios2_get_deferred(adios2_Engine *engine, adios2_Variable *variable, + void *values) +{ + adios2::VariableBase *variableBase = + reinterpret_cast<adios2::VariableBase *>(variable); + const std::string type(variableBase->m_Type); + + adios2::Engine &engineCpp = *reinterpret_cast<adios2::Engine *>(engine); + + if (type == "compound") + { + // not supported + } +#define declare_template_instantiation(T) \ + else if (type == adios2::GetType<T>()) \ + { \ + engineCpp.GetDeferred( \ + *dynamic_cast<adios2::Variable<T> *>(variableBase), \ + reinterpret_cast<T *>(values)); \ + } + ADIOS2_FOREACH_TYPE_1ARG(declare_template_instantiation) +#undef declare_template_instantiation +} + +void adios2_get_deferred_self(adios2_Engine *engine, adios2_Variable *variable) +{ + adios2::VariableBase *variableBase = + reinterpret_cast<adios2::VariableBase *>(variable); + const std::string type(variableBase->m_Type); + + adios2::Engine &engineCpp = *reinterpret_cast<adios2::Engine *>(engine); + + if (type == "compound") + { + // not supported + } +#define declare_template_instantiation(T) \ + else if (type == adios2::GetType<T>()) \ + { \ + engineCpp.GetDeferred( \ + *dynamic_cast<adios2::Variable<T> *>(variableBase)); \ + } + ADIOS2_FOREACH_TYPE_1ARG(declare_template_instantiation) +#undef declare_template_instantiation +} + +void adios2_get_deferred_by_name(adios2_Engine *engine, + const char *variable_name, void *values) +{ + auto &engineCpp = *reinterpret_cast<adios2::Engine *>(engine); + const std::string type( + engineCpp.GetIO().InquireVariableType(variable_name)); + + if (type == "compound") + { + // not supported + } +#define declare_template_instantiation(T) \ + else if (type == adios2::GetType<T>()) \ + { \ + engineCpp.GetDeferred(variable_name, reinterpret_cast<T *>(values)); \ + } + ADIOS2_FOREACH_TYPE_1ARG(declare_template_instantiation) +#undef declare_template_instantiation +} + +void adios2_perform_gets(adios2_Engine *engine) +{ + auto &engineCpp = *reinterpret_cast<adios2::Engine *>(engine); + engineCpp.PerformGets(); +} + void adios2_end_step(adios2_Engine *engine) { auto &engineCpp = *reinterpret_cast<adios2::Engine *>(engine); diff --git a/bindings/C/adios2/adios2_c_engine.h b/bindings/C/adios2/adios2_c_engine.h index 178905524681968a70ede719b4dbf2bfd7f2adae..7cb9af4d891dd0b9354ba9d2d0689765228bb04e 100644 --- a/bindings/C/adios2/adios2_c_engine.h +++ b/bindings/C/adios2/adios2_c_engine.h @@ -22,6 +22,8 @@ extern "C" { */ void adios2_begin_step(adios2_Engine *engine); +//***************** PUT ***************** + /** * Put a variable in IO using a adios2_Variable handler * @param engine handler for engine executing the write @@ -33,7 +35,7 @@ void adios2_put_sync(adios2_Engine *engine, adios2_Variable *variable, void adios2_put_sync_self(adios2_Engine *engine, adios2_Variable *variable); -void adios2_put_sync_by_name(adios2_Engine *engine, const char *variableName, +void adios2_put_sync_by_name(adios2_Engine *engine, const char *variable_name, const void *values); /** @@ -48,10 +50,29 @@ void adios2_put_deferred(adios2_Engine *engine, adios2_Variable *variable, void adios2_put_deferred_self(adios2_Engine *engine, adios2_Variable *variable); void adios2_put_deferred_by_name(adios2_Engine *engine, - const char *variableName, const void *values); + const char *variable_name, const void *values); void adios2_perform_puts(adios2_Engine *engine); +//***************** GET ***************** +void adios2_get_sync(adios2_Engine *engine, adios2_Variable *variable, + void *values); + +void adios2_get_sync_self(adios2_Engine *engine, adios2_Variable *variable); + +void adios2_get_sync_by_name(adios2_Engine *engine, const char *variable_name, + void *values); + +void adios2_get_deferred(adios2_Engine *engine, adios2_Variable *variable, + void *values); + +void adios2_get_deferred_self(adios2_Engine *engine, adios2_Variable *variable); + +void adios2_get_deferred_by_name(adios2_Engine *engine, + const char *variable_name, void *values); + +void adios2_perform_gets(adios2_Engine *engine); + /** * terminates interaction with current step * @param engine handler executing IO tasks diff --git a/bindings/C/adios2/adios2_c_glue.h b/bindings/C/adios2/adios2_c_glue.h index 3b1ffd65cdd4b6d33bf9f10d78e67410a7be140e..07058f294de04a4956eed554896dc251080caadf 100644 --- a/bindings/C/adios2/adios2_c_glue.h +++ b/bindings/C/adios2/adios2_c_glue.h @@ -3,7 +3,7 @@ * accompanying file Copyright.txt for details. * * adios2_c_glue.h : used by languages other than C, using the C-bindings API - * (e.g. Fortran), not meant to be for applications + * (e.g. Fortran), not meant to be used by applications * * Created on: Nov 3, 2017 * Author: William F Godoy godoywf@ornl.gov diff --git a/bindings/C/adios2/adios2_c_types.h b/bindings/C/adios2/adios2_c_types.h index b567579aab61ac7231f141bc69580535316c390a..f20e03d901aa322f20fc567ae272354c41d1f67a 100644 --- a/bindings/C/adios2/adios2_c_types.h +++ b/bindings/C/adios2/adios2_c_types.h @@ -31,6 +31,7 @@ typedef enum { } adios2_constant_dims; typedef enum { + adios2_type_unknown = -1, adios2_type_char = 0, adios2_type_int = 1, @@ -44,7 +45,9 @@ typedef enum { adios2_type_int32_t = 8, adios2_type_int64_t = 9, - adios2_type_string, + adios2_type_string = 10, + adios2_type_string_array = 11, + adios2_type_signed_char, adios2_type_short, diff --git a/bindings/C/adios2/adios2_c_variable.cpp b/bindings/C/adios2/adios2_c_variable.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0f4690a85d626605fa5fc70a20d6a0c6af0b713b --- /dev/null +++ b/bindings/C/adios2/adios2_c_variable.cpp @@ -0,0 +1,204 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * adios2_c_variable.cpp + * + * Created on: Nov 10, 2017 + * Author: William F Godoy godoywf@ornl.gov + */ + +#include "adios2_c_variable.h" + +#include "adios2/core/Variable.h" +#include "adios2/helper/adiosFunctions.h" + +const std::map<std::string, std::vector<adios2_type>> adios2_types_map = { + {"char", {adios2_type_char}}, + {"int", {adios2_type_int, adios2_type_int32_t}}, + {"float", {adios2_type_float}}, + {"double", {adios2_type_double}}, + {"float complex", {adios2_type_float_complex}}, + {"double complex", {adios2_type_double_complex}}, + {"signed char", {adios2_type_int8_t, adios2_type_signed_char}}, + {"short", {adios2_type_int16_t, adios2_type_short}}, + {"long int", {adios2_type_int64_t, adios2_type_long_int}}, + {"long long int", {adios2_type_int64_t, adios2_type_long_long_int}}, + {"string", {adios2_type_string}}, + {"string array", {adios2_type_string_array}}, + {"unsigned char", {adios2_type_unsigned_char, adios2_type_uint8_t}}, + {"unsigned short", {adios2_type_unsigned_short, adios2_type_uint16_t}}, + {"unsigned int", {adios2_type_unsigned_int, adios2_type_uint32_t}}, + {"unsigned long int", + {adios2_type_unsigned_long_int, adios2_type_uint64_t}}, + {"unsigned long long int", + {adios2_type_unsigned_long_long_int, adios2_type_uint64_t}}, +}; + +const char *adios2_variable_name(const adios2_Variable *variable, + size_t *length) +{ + const adios2::VariableBase *variableBase = + reinterpret_cast<const adios2::VariableBase *>(variable); + if (length != nullptr) + { + *length = variableBase->m_Name.size(); + } + return variableBase->m_Name.c_str(); +} + +adios2_type adios2_variable_type(const adios2_Variable *variable) +{ + const adios2::VariableBase *variableBase = + reinterpret_cast<const adios2::VariableBase *>(variable); + + auto itType = adios2_types_map.find(variableBase->m_Type); + + if (itType == adios2_types_map.end()) + { + return adios2_type_unknown; + } + + return itType->second.front(); +} + +int adios2_variable_is_constant_dims(const adios2_Variable *variable) +{ + const adios2::VariableBase *variableBase = + reinterpret_cast<const adios2::VariableBase *>(variable); + const int isConstantDims = (variableBase->m_ConstantDims) ? 1 : 0; + return isConstantDims; +} + +const size_t adios2_variable_ndims(const adios2_Variable *variable) +{ + const adios2::VariableBase *variableBase = + reinterpret_cast<const adios2::VariableBase *>(variable); + return variableBase->m_Shape.size(); +} + +const size_t *adios2_variable_shape(const adios2_Variable *variable) +{ + const adios2::VariableBase *variableBase = + reinterpret_cast<const adios2::VariableBase *>(variable); + return variableBase->m_Shape.data(); +} + +const size_t *adios2_variable_start(const adios2_Variable *variable) +{ + const adios2::VariableBase *variableBase = + reinterpret_cast<const adios2::VariableBase *>(variable); + return variableBase->m_Start.data(); +} + +const size_t *adios2_variable_count(const adios2_Variable *variable) +{ + const adios2::VariableBase *variableBase = + reinterpret_cast<const adios2::VariableBase *>(variable); + return variableBase->m_Count.data(); +} + +const size_t +adios2_variable_available_steps_start(const adios2_Variable *variable) +{ + const adios2::VariableBase *variableBase = + reinterpret_cast<const adios2::VariableBase *>(variable); + return variableBase->m_AvailableStepsStart; +} + +const size_t +adios2_variable_available_steps_count(const adios2_Variable *variable) +{ + const adios2::VariableBase *variableBase = + reinterpret_cast<const adios2::VariableBase *>(variable); + return variableBase->m_AvailableStepsCount; +} + +void adios2_set_dimensions(adios2_Variable *variable, const size_t ndims, + const size_t *shape, const size_t *start, + const size_t *count) +{ + auto lf_Assign = [](const size_t ndims, const size_t *input, + adios2::Dims &dims) { + + if (input != nullptr) + { + dims.clear(); + dims.assign(input, input + ndims); + } + }; + + adios2::VariableBase *variableBase = + reinterpret_cast<adios2::VariableBase *>(variable); + + lf_Assign(ndims, shape, variableBase->m_Shape); + lf_Assign(ndims, start, variableBase->m_Start); + lf_Assign(ndims, count, variableBase->m_Count); + variableBase->CheckDimensions("in call to adios2_set_selection"); +} + +void adios2_set_selection(adios2_Variable *variable, const size_t ndims, + const size_t *start, const size_t *count) +{ + adios2::VariableBase *variableBase = + reinterpret_cast<adios2::VariableBase *>(variable); + + const adios2::Dims startV(start, start + ndims); + const adios2::Dims countV(count, count + ndims); + variableBase->SetSelection({startV, countV}); + variableBase->CheckDimensions("in call to adios2_set_selection"); +} + +void adios2_set_step_selection(adios2_Variable *variable, + const size_t step_start, const size_t step_count) +{ + adios2::VariableBase *variableBase = + reinterpret_cast<adios2::VariableBase *>(variable); + variableBase->SetStepSelection(adios2::Box<size_t>{step_start, step_count}); +} + +void *adios2_get_data(const adios2_Variable *variable) +{ + const adios2::VariableBase *variableBase = + reinterpret_cast<const adios2::VariableBase *>(variable); + const std::string type(variableBase->m_Type); + + void *data = nullptr; + if (type == "compound") + { + // not supported + } +#define declare_template_instantiation(T) \ + else if (type == adios2::GetType<T>()) \ + { \ + const adios2::Variable<T> *variableCpp = \ + reinterpret_cast<const adios2::Variable<T> *>(variable); \ + data = variableCpp->GetData(); \ + } + ADIOS2_FOREACH_TYPE_1ARG(declare_template_instantiation) +#undef declare_template_instantiation + + return data; +} + +void adios2_set_data(adios2_Variable *variable, const void *data) +{ + adios2::VariableBase *variableBase = + reinterpret_cast<adios2::VariableBase *>(variable); + + const std::string type(variableBase->m_Type); + + if (type == "compound") + { + // not supported + } +#define declare_template_instantiation(T) \ + else if (type == adios2::GetType<T>()) \ + { \ + adios2::Variable<T> *variableCpp = \ + reinterpret_cast<adios2::Variable<T> *>(variable); \ + variableCpp->SetData(reinterpret_cast<const T *>(data)); \ + } + ADIOS2_FOREACH_TYPE_1ARG(declare_template_instantiation) +#undef declare_template_instantiation +} diff --git a/bindings/C/adios2/adios2_c_variable.h b/bindings/C/adios2/adios2_c_variable.h new file mode 100644 index 0000000000000000000000000000000000000000..2f214a7913f65bd30d8d463fa68cab1ae25c24d6 --- /dev/null +++ b/bindings/C/adios2/adios2_c_variable.h @@ -0,0 +1,130 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * adios2_c_variable.h : exposes some members of the Variable handler + * + * Created on: Nov 10, 2017 + * Author: William F Godoy godoywf@ornl.gov + */ + +#ifndef BINDINGS_C_ADIOS2_ADIOS2_C_VARIABLE_H_ +#define BINDINGS_C_ADIOS2_ADIOS2_C_VARIABLE_H_ + +#include "adios2_c_types.h" + +#include <stddef.h> //size_t + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Retrieve variable name (read-only) + * @param variable handler + * @return name + */ +const char *adios2_variable_name(const adios2_Variable *variable, + size_t *length); + +/** + * Retrieve variable type (read-only) + * @param variable handler + * @return type + */ +adios2_type adios2_variable_type(const adios2_Variable *variable); + +/** + * Check if dimensions are constant + * @param variable + * @return 0: false (dimensions are not constant), 1: true dimensions are + * declared constant + */ +int adios2_variable_is_constant_dims(const adios2_Variable *variable); + +const size_t adios2_variable_ndims(const adios2_Variable *variable); + +/** + * Retrieve current variable shape (read-only) + * @param variable handler + * @return shape + */ +const size_t *adios2_variable_shape(const adios2_Variable *variable); + +/** + * Retrieve current variable start (read-only) + * @param variable handler + * @return + */ +const size_t *adios2_variable_start(const adios2_Variable *variable); + +/** + * Retrieve current variable shape (read-only) + * @param variable + * @return type + */ +const size_t *adios2_variable_count(const adios2_Variable *variable); + +const size_t +adios2_variable_available_steps_start(const adios2_Variable *variable); + +const size_t +adios2_variable_available_steps_count(const adios2_Variable *variable); + +/** + * Set new dimensions + * @param variable + * @param shape + * @param start + * @param count + */ +void adios2_set_dimensions(adios2_Variable *variable, const size_t ndims, + const size_t *shape, const size_t *start, + const size_t *count); + +/** + * Set new selection using start and count + * @param variable + * @param start + * @param count + */ +void adios2_set_selection(adios2_Variable *variable, const size_t ndims, + const size_t *start, const size_t *count); + +/** + * Set new step selection using step_start and step_count + * @param variable + * @param step_start + * @param step_count + */ +void adios2_set_step_selection(adios2_Variable *variable, + const size_t step_start, + const size_t step_count); + +/** + * Returns the minimum required allocation (in number of elements of a certain + * type, not bytes) + * for the current selection + * @param variable + * @return memory size to be allocated by a pointer/vector to read this + */ +size_t adios2_selection_size(const adios2_Variable *variable); + +/** + * Get current data pointer, types must match + * @param variable + */ +void *adios2_get_data(const adios2_Variable *variable); + +/** + * Sets current data pointer, types must match + * @param variable + * @param data + */ +void adios2_set_data(adios2_Variable *variable, const void *data); + +#ifdef __cplusplus +} // end extern C +#endif + +#endif /* BINDINGS_C_ADIOS2_ADIOS2_C_VARIABLE_H_ */ diff --git a/bindings/C/adios2_c.h b/bindings/C/adios2_c.h index 64cc07d32995449ecfb294ed3743c08b10dbec6e..2813ff6d0ec275278e51b88c234fa2a8ff9ada62 100644 --- a/bindings/C/adios2_c.h +++ b/bindings/C/adios2_c.h @@ -16,5 +16,6 @@ #include "adios2/adios2_c_engine.h" #include "adios2/adios2_c_glue.h" #include "adios2/adios2_c_io.h" +#include "adios2/adios2_c_variable.h" #endif /* ADIOS2_BINDINGS_C_ADIOS2_C_H_ */ diff --git a/bindings/fortran/CMakeLists.txt b/bindings/fortran/CMakeLists.txt index d60df4ad5fbd54b46e5b3807bcfdfe4c796c1475..58a4191a4e6f7002cd119c32037cf516e8ad9914 100644 --- a/bindings/fortran/CMakeLists.txt +++ b/bindings/fortran/CMakeLists.txt @@ -11,6 +11,7 @@ FortranCInterface_VERIFY(CXX QUIET) set(F2C f2c/adios2_f2c_adios.cpp f2c/adios2_f2c_io.cpp + f2c/adios2_f2c_variable.cpp f2c/adios2_f2c_engine.cpp ) @@ -20,9 +21,12 @@ set(MODULES modules/adios2_parameters_mod.f90 modules/adios2_adios_mod.f90 modules/adios2_io_mod.f90 + modules/adios2_variable_mod.f90 modules/adios2_engine_mod.f90 modules/adios2_engine_write_mod.f90 modules/adios2_engine_iwrite_mod.f90 + modules/adios2_engine_read_mod.f90 + modules/adios2_engine_iread_mod.f90 ) add_library(adios2_f ${MODULES} ${F2C}) diff --git a/bindings/fortran/adios2_mod.f90 b/bindings/fortran/adios2_mod.f90 index 12b55387e5c289b3b1f1b003a8d6968d0edb253e..294222b4ade37136de4c1cdd46fe3d942ce83cd8 100644 --- a/bindings/fortran/adios2_mod.f90 +++ b/bindings/fortran/adios2_mod.f90 @@ -13,7 +13,7 @@ module adios2 use adios2_parameters use adios2_adios use adios2_io -! TODO use adios2_variable + use adios2_variable use adios2_engine end module diff --git a/bindings/fortran/f2c/adios2_f2c_engine.cpp b/bindings/fortran/f2c/adios2_f2c_engine.cpp index 9a45a011be430f2e11f2d45456de87bcb138f168..3a9c8108b9547309e490f0be3ac23bac2783663a 100644 --- a/bindings/fortran/f2c/adios2_f2c_engine.cpp +++ b/bindings/fortran/f2c/adios2_f2c_engine.cpp @@ -26,6 +26,7 @@ void FC_GLOBAL(adios2_begin_step_f2c, } } +// ******** PUTS */ void FC_GLOBAL(adios2_put_sync_f2c, ADIOS2_PUT_SYNC_F2C)(adios2_Engine **engine, adios2_Variable **variable, @@ -50,7 +51,68 @@ void FC_GLOBAL(adios2_put_deferred_f2c, *ierr = 0; try { - adios2_put_sync(*engine, *variable, values); + adios2_put_deferred(*engine, *variable, values); + } + catch (std::exception &e) + { + *ierr = 1; + } +} + +void FC_GLOBAL(adios2_perform_puts_f2c, + ADIOS2_PERFORM_PUTS_F2C)(adios2_Engine **engine, int *ierr) +{ + *ierr = 0; + try + { + adios2_perform_puts(*engine); + } + catch (std::exception &e) + { + *ierr = 1; + } +} + +// ******** GETS */ +void FC_GLOBAL(adios2_get_sync_f2c, + ADIOS2_get_SYNC_F2C)(adios2_Engine **engine, + adios2_Variable **variable, void *values, + int *ierr) +{ + *ierr = 0; + try + { + adios2_get_sync(*engine, *variable, values); + } + catch (std::exception &e) + { + *ierr = 1; + } +} + +void FC_GLOBAL(adios2_get_deferred_f2c, + ADIOS2_get_DEFERRED_F2C)(adios2_Engine **engine, + adios2_Variable **variable, + void *values, int *ierr) +{ + *ierr = 0; + try + { + adios2_get_deferred(*engine, *variable, values); + } + catch (std::exception &e) + { + *ierr = 1; + } +} + +void FC_GLOBAL(adios2_perform_gets_f2c, + ADIOS2_PERFORM_GETS_F2C)(adios2_Engine **engine, int *ierr) +{ + *ierr = 0; + try + { + adios2_perform_gets(*engine); } catch (std::exception &e) { diff --git a/bindings/fortran/f2c/adios2_f2c_engine.h b/bindings/fortran/f2c/adios2_f2c_engine.h index 76b8551bf71544491696a38363f788b5b1a0ca36..bc3ee6250f2bd94f77bd66e1199a7155e9708cf1 100644 --- a/bindings/fortran/f2c/adios2_f2c_engine.h +++ b/bindings/fortran/f2c/adios2_f2c_engine.h @@ -22,6 +22,7 @@ extern "C" { void FC_GLOBAL(adios2_begin_step_f2c, ADIOS2_BEGIN_STEP_F2C)(adios2_Engine **engine, int *ierr); +// ************** PUT void FC_GLOBAL(adios2_put_sync_f2c, ADIOS2_PUT_SYNC_F2C)(adios2_Engine **engine, adios2_Variable **variable, @@ -32,15 +33,29 @@ void FC_GLOBAL(adios2_put_deferred_f2c, adios2_Variable **variable, const void *values, int *ierr); +void FC_GLOBAL(adios2_perform_puts_f2c, + ADIOS2_PERFORM_PUTS_F2C)(adios2_Engine **engine, int *ierr); + +// ************** GET +void FC_GLOBAL(adios2_get_sync_f2c, + ADIOS2_get_SYNC_F2C)(adios2_Engine **engine, + adios2_Variable **variable, void *values, + int *ierr); + +void FC_GLOBAL(adios2_get_deferred_f2c, + ADIOS2_get_DEFERRED_F2C)(adios2_Engine **engine, + adios2_Variable **variable, + void *values, int *ierr); + +void FC_GLOBAL(adios2_perform_gets_f2c, + ADIOS2_PERFORM_GETS_F2C)(adios2_Engine **engine, int *ierr); + void FC_GLOBAL(adios2_end_step_f2c, ADIOS2_END_STEP_F2C)(adios2_Engine **engine, int *ierr); void FC_GLOBAL(adios2_close_f2c, ADIOS2_CLOSE_F2C)(adios2_Engine **engine, int *ierr); -void FC_GLOBAL(adios2_finalize_f2c, ADIOS2_FINALIZE_F2C)(adios2_ADIOS **adios, - int *ierr); - #ifdef __cplusplus } #endif diff --git a/bindings/fortran/f2c/adios2_f2c_io.cpp b/bindings/fortran/f2c/adios2_f2c_io.cpp index 615f2e2a4fb2b1884e6aa2232d2a9d4ff617cbc9..99113da382f5979ec52c035ede19b1248ca03221 100644 --- a/bindings/fortran/f2c/adios2_f2c_io.cpp +++ b/bindings/fortran/f2c/adios2_f2c_io.cpp @@ -78,7 +78,8 @@ void FC_GLOBAL(adios2_define_variable_f2c, ADIOS2_DEFINE_VARIABLE_F2C)( const int *count, const int *constant_dims, int *ierr) { auto lf_IntToSizeT = [](const int *dimensions, const int size, - std::vector<std::size_t> &output) { + std::vector<std::size_t> &output, + const bool offset) { if (dimensions == nullptr) { @@ -86,18 +87,29 @@ void FC_GLOBAL(adios2_define_variable_f2c, ADIOS2_DEFINE_VARIABLE_F2C)( } output.resize(size); - for (unsigned int d = 0; d < size; ++d) + + if (offset) + { + for (unsigned int d = 0; d < size; ++d) + { + output[d] = dimensions[d] - 1; + } + } + else { - output[d] = dimensions[d]; + for (unsigned int d = 0; d < size; ++d) + { + output[d] = dimensions[d]; + } } }; *ierr = 0; std::vector<std::size_t> shapeV, startV, countV; - lf_IntToSizeT(shape, *ndims, shapeV); - lf_IntToSizeT(start, *ndims, startV); - lf_IntToSizeT(count, *ndims, countV); + lf_IntToSizeT(shape, *ndims, shapeV, false); + lf_IntToSizeT(start, *ndims, startV, true); + lf_IntToSizeT(count, *ndims, countV, false); try { @@ -112,6 +124,27 @@ void FC_GLOBAL(adios2_define_variable_f2c, ADIOS2_DEFINE_VARIABLE_F2C)( } } +void FC_GLOBAL(adios2_inquire_variable_f2c, + ADIOS2_INQUIRE_VARIABLE_F2C)(adios2_Variable **variable, + adios2_IO **io, + const char *variable_name, + int *ierr) +{ + *ierr = 0; + try + { + *variable = adios2_inquire_variable(*io, variable_name); + if (*variable == nullptr) + { + *ierr = 2; + } + } + catch (std::exception &e) + { + *ierr = 1; + } +} + void FC_GLOBAL(adios2_open_f2c, ADIOS2_OPEN_F2C)(adios2_Engine **engine, adios2_IO **io, const char *name, const int *open_mode, diff --git a/bindings/fortran/f2c/adios2_f2c_io.h b/bindings/fortran/f2c/adios2_f2c_io.h index 0e73994df8b3b387e18fd73e994f26dd47bf6ed1..b5aa9b364549c0536fbf49721b5921f3c2c5a2ab 100644 --- a/bindings/fortran/f2c/adios2_f2c_io.h +++ b/bindings/fortran/f2c/adios2_f2c_io.h @@ -39,6 +39,12 @@ void FC_GLOBAL(adios2_define_variable_f2c, ADIOS2_DEFINE_VARIABLE_F2C)( const int *type, const int *ndims, const int *shape, const int *start, const int *count, const int *constant_dims, int *ierr); +void FC_GLOBAL(adios2_inquire_variable_f2c, + ADIOS2_INQUIRE_VARIABLE_F2C)(adios2_Variable **variable, + adios2_IO **io, + const char *variable_name, + int *ierr); + void FC_GLOBAL(adios2_open_f2c, ADIOS2_OPEN_F2C)(adios2_Engine **engine, adios2_IO **io, const char *name, const int *open_mode, diff --git a/bindings/fortran/f2c/adios2_f2c_variable.cpp b/bindings/fortran/f2c/adios2_f2c_variable.cpp new file mode 100644 index 0000000000000000000000000000000000000000..799f6626ad5ada4d86bdbe452d0505e969192e69 --- /dev/null +++ b/bindings/fortran/f2c/adios2_f2c_variable.cpp @@ -0,0 +1,113 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * adios2_f2c_variable.cpp + * + * Created on: Nov 12, 2017 + * Author: William F Godoy godoywf@ornl.gov + */ + +#include "adios2_f2c_variable.h" + +#include <cstddef> +#include <stdexcept> +#include <string.h> //strcpy +#include <vector> + +void FC_GLOBAL(adios2_variable_name_f2c, + ADIOS2_VARIABLE_NAME_F2C)(const adios2_Variable **variable, + char name[1024], int *length, + int *ierr) +{ + *ierr = 0; + try + { + size_t lengthC = 0; + const char *nameC = adios2_variable_name(*variable, &lengthC); + + if (nameC == nullptr) + { + throw std::runtime_error("ERROR: null pointer\n"); + } + + for (size_t i = 0; i < lengthC; ++i) + { + name[i] = nameC[i]; + } + + *length = static_cast<int>(lengthC); + } + catch (std::exception &e) + { + *ierr = 1; + } +} + +void FC_GLOBAL(adios2_variable_type_f2c, + ADIOS2_VARIABLE_TYPE_F2C)(const adios2_Variable **variable, + int *type, int *ierr) +{ + *ierr = 0; + try + { + *type = static_cast<int>(adios2_variable_type(*variable)); + } + catch (std::exception &e) + { + *ierr = 1; + } +} + +void FC_GLOBAL(adios2_set_selection_f2c, + ADIOS2_SET_SELECTION_F2C)(adios2_Variable **variable, + const int *ndims, const int *start, + const int *count, int *ierr) +{ + auto lf_IntToSizeT = [](const int *dimensions, const int size, + std::vector<std::size_t> &output, + const bool offset) { + + if (dimensions == nullptr) + { + return; + } + + output.resize(size); + + if (offset) + { + for (unsigned int d = 0; d < size; ++d) + { + output[d] = dimensions[d] - 1; + } + } + else + { + for (unsigned int d = 0; d < size; ++d) + { + output[d] = dimensions[d]; + } + } + }; + + *ierr = 0; + if (start == nullptr || count == nullptr) + { + *ierr = 1; + return; + } + + std::vector<std::size_t> startV, countV; + lf_IntToSizeT(start, *ndims, startV, true); + lf_IntToSizeT(count, *ndims, countV, false); + + try + { + adios2_set_selection(*variable, *ndims, startV.data(), countV.data()); + } + catch (std::exception &e) + { + *ierr = 1; + } +} diff --git a/bindings/fortran/f2c/adios2_f2c_variable.h b/bindings/fortran/f2c/adios2_f2c_variable.h new file mode 100644 index 0000000000000000000000000000000000000000..704bcf4869b903bae3709d6a637c20ba6e838ebb --- /dev/null +++ b/bindings/fortran/f2c/adios2_f2c_variable.h @@ -0,0 +1,39 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * adios2_f2c_variable.h : variable handle functions + * + * Created on: Nov 12, 2017 + * Author: William F Godoy godoywf@ornl.gov + */ +#ifndef BINDINGS_FORTRAN_F2C_ADIOS2_F2C_VARIABLE_H_ +#define BINDINGS_FORTRAN_F2C_ADIOS2_F2C_VARIABLE_H_ + +#include "adios2/ADIOSConfig.h" +#include <FC.h> +#include <adios2_c.h> + +#ifdef __cplusplus +extern "C" { +#endif + +void FC_GLOBAL(adios2_variable_name_f2c, + ADIOS2_VARIABLE_NAME_F2C)(const adios2_Variable **variable, + char name[1024], int *length, + int *ierr); + +void FC_GLOBAL(adios2_variable_type_f2c, + ADIOS2_VARIABLE_TYPE_F2C)(const adios2_Variable **variable, + int *c_type, int *ierr); + +void FC_GLOBAL(adios2_set_selection_f2c, + ADIOS2_SET_SELECTION_F2C)(adios2_Variable **variable, + const int *ndims, const int *start, + const int *count, int *ierr); + +#ifdef __cplusplus +} +#endif + +#endif /* BINDINGS_FORTRAN_F2C_ADIOS2_F2C_VARIABLE_H_ */ diff --git a/bindings/fortran/modules/adios2_engine_iread_mod.f90 b/bindings/fortran/modules/adios2_engine_iread_mod.f90 new file mode 100644 index 0000000000000000000000000000000000000000..44ac5b5039e961df44e5b146655cdf4f916d458a --- /dev/null +++ b/bindings/fortran/modules/adios2_engine_iread_mod.f90 @@ -0,0 +1,660 @@ +! +! Distributed under the OSI-approved Apache License, Version 2.0. See +! accompanying file Copyright.txt for details. +! +! adios2_engine_iread_mod.f90 : ADIOS2 Fortran bindings for Engine generic +! deferred READ (iread) functions +! +! Created on: Aug 22, 2017 +! Author: William F Godoy godoywf@ornl.gov +! +module adios2_engine_iread + + interface adios2_iread + + ! Single Value + module procedure adios2_iread_integer + module procedure adios2_iread_real + module procedure adios2_iread_dp + module procedure adios2_iread_complex + module procedure adios2_iread_complex_dp + module procedure adios2_iread_integer1 + module procedure adios2_iread_integer2 + module procedure adios2_iread_integer8 + + ! 1D Array + module procedure adios2_iread_integer_1d + module procedure adios2_iread_real_1d + module procedure adios2_iread_dp_1d + module procedure adios2_iread_complex_1d + module procedure adios2_iread_complex_dp_1d + module procedure adios2_iread_integer1_1d + module procedure adios2_iread_integer2_1d + module procedure adios2_iread_integer8_1d + + ! 2D Array + module procedure adios2_iread_integer_2d + module procedure adios2_iread_real_2d + module procedure adios2_iread_dp_2d + module procedure adios2_iread_complex_2d + module procedure adios2_iread_complex_dp_2d + module procedure adios2_iread_integer1_2d + module procedure adios2_iread_integer2_2d + module procedure adios2_iread_integer8_2d + + ! 3D Array + module procedure adios2_iread_integer_3d + module procedure adios2_iread_real_3d + module procedure adios2_iread_dp_3d + module procedure adios2_iread_complex_3d + module procedure adios2_iread_complex_dp_3d + module procedure adios2_iread_integer1_3d + module procedure adios2_iread_integer2_3d + module procedure adios2_iread_integer8_3d + + ! 4D Array + module procedure adios2_iread_integer_4d + module procedure adios2_iread_real_4d + module procedure adios2_iread_dp_4d + module procedure adios2_iread_complex_4d + module procedure adios2_iread_complex_dp_4d + module procedure adios2_iread_integer1_4d + module procedure adios2_iread_integer2_4d + module procedure adios2_iread_integer8_4d + + ! 5D Array + module procedure adios2_iread_integer_5d + module procedure adios2_iread_real_5d + module procedure adios2_iread_dp_5d + module procedure adios2_iread_complex_5d + module procedure adios2_iread_complex_dp_5d + module procedure adios2_iread_integer1_5d + module procedure adios2_iread_integer2_5d + module procedure adios2_iread_integer8_5d + + ! 6D Array + module procedure adios2_iread_integer_6d + module procedure adios2_iread_real_6d + module procedure adios2_iread_dp_6d + module procedure adios2_iread_complex_6d + module procedure adios2_iread_complex_dp_6d + module procedure adios2_iread_integer1_6d + module procedure adios2_iread_integer2_6d + module procedure adios2_iread_integer8_6d + + end interface + +contains + + ! Single Value + subroutine adios2_iread_integer( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + integer, intent(out):: values + integer, intent(out):: ierr + + call adios2_get_deferred_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_iread_real( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + real, intent(out):: values + integer, intent(out):: ierr + + call adios2_get_deferred_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_iread_dp( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + real(kind=8), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_deferred_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_iread_complex( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + complex, intent(out):: values + integer, intent(out):: ierr + + call adios2_get_deferred_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_iread_complex_dp( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + complex(kind=8), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_deferred_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_iread_integer1( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + integer(kind=1), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_deferred_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_iread_integer2( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + integer(kind=2), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_deferred_f2c(engine, variable, values, ierr) + + end subroutine + + + subroutine adios2_iread_integer8( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + integer(kind=8), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_deferred_f2c(engine, variable, values, ierr) + + end subroutine + + ! 1D Array + subroutine adios2_iread_integer_1d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + integer, dimension(:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_deferred_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_iread_real_1d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + real, dimension(:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_deferred_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_iread_dp_1d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + real(kind=8), dimension(:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_deferred_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_iread_complex_1d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + complex, dimension(:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_deferred_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_iread_complex_dp_1d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + complex(kind=8), dimension(:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_deferred_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_iread_integer1_1d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + integer(kind=1), dimension(:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_deferred_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_iread_integer2_1d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + integer(kind=2), dimension(:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_deferred_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_iread_integer8_1d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + integer(kind=8), dimension(:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_deferred_f2c(engine, variable, values, ierr) + + end subroutine + + ! 2D Array + subroutine adios2_iread_integer_2d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + integer, dimension(:,:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_deferred_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_iread_real_2d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + real, dimension(:,:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_deferred_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_iread_dp_2d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + real(kind=8), dimension(:,:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_deferred_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_iread_complex_2d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + complex, dimension(:,:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_deferred_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_iread_complex_dp_2d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + complex(kind=8), dimension(:,:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_deferred_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_iread_integer1_2d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + integer(kind=1), dimension(:,:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_deferred_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_iread_integer2_2d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + integer(kind=2), dimension(:,:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_deferred_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_iread_integer8_2d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + integer(kind=8), dimension(:,:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_deferred_f2c(engine, variable, values, ierr) + + end subroutine + + ! 3D Array + subroutine adios2_iread_integer_3d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + integer, dimension(:,:,:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_deferred_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_iread_real_3d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + real, dimension(:,:,:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_deferred_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_iread_dp_3d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + real(kind=8), dimension(:,:,:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_deferred_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_iread_complex_3d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + complex, dimension(:,:,:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_deferred_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_iread_complex_dp_3d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + complex(kind=8), dimension(:,:,:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_deferred_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_iread_integer1_3d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + integer(kind=1), dimension(:,:,:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_deferred_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_iread_integer2_3d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + integer(kind=2), dimension(:,:,:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_deferred_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_iread_integer8_3d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + integer(kind=8), dimension(:,:,:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_deferred_f2c(engine, variable, values, ierr) + + end subroutine + + + ! 4D Array + subroutine adios2_iread_integer_4d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + integer, dimension(:,:,:,:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_deferred_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_iread_real_4d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + real, dimension(:,:,:,:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_deferred_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_iread_dp_4d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + real(kind=8), dimension(:,:,:,:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_deferred_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_iread_complex_4d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + complex, dimension(:,:,:,:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_deferred_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_iread_complex_dp_4d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + complex(kind=8), dimension(:,:,:,:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_deferred_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_iread_integer1_4d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + integer(kind=1), dimension(:,:,:,:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_deferred_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_iread_integer2_4d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + integer(kind=2), dimension(:,:,:,:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_deferred_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_iread_integer8_4d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + integer(kind=8), dimension(:,:,:,:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_deferred_f2c(engine, variable, values, ierr) + + end subroutine + + + ! 5D Array + subroutine adios2_iread_integer_5d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + integer, dimension(:,:,:,:,:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_deferred_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_iread_real_5d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + real, dimension(:,:,:,:,:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_deferred_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_iread_dp_5d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + real(kind=8), dimension(:,:,:,:,:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_deferred_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_iread_complex_5d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + complex, dimension(:,:,:,:,:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_deferred_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_iread_complex_dp_5d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + complex(kind=8), dimension(:,:,:,:,:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_deferred_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_iread_integer1_5d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + integer(kind=1), dimension(:,:,:,:,:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_deferred_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_iread_integer2_5d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + integer(kind=2), dimension(:,:,:,:,:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_deferred_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_iread_integer8_5d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + integer(kind=8), dimension(:,:,:,:,:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_deferred_f2c(engine, variable, values, ierr) + + end subroutine + + + ! 6D Array + subroutine adios2_iread_integer_6d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + integer, dimension(:,:,:,:,:,:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_deferred_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_iread_real_6d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + real, dimension(:,:,:,:,:,:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_deferred_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_iread_dp_6d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + real(kind=8), dimension(:,:,:,:,:,:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_deferred_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_iread_complex_6d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + complex, dimension(:,:,:,:,:,:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_deferred_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_iread_complex_dp_6d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + complex(kind=8), dimension(:,:,:,:,:,:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_deferred_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_iread_integer1_6d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + integer(kind=1), dimension(:,:,:,:,:,:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_deferred_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_iread_integer2_6d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + integer(kind=2), dimension(:,:,:,:,:,:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_deferred_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_iread_integer8_6d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + integer(kind=8), dimension(:,:,:,:,:,:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_deferred_f2c(engine, variable, values, ierr) + + end subroutine + +end module diff --git a/bindings/fortran/modules/adios2_engine_mod.f90 b/bindings/fortran/modules/adios2_engine_mod.f90 index 3bda71211d135e5f9722c221ac480d7fe077e0d4..9ff921673598c7718859518270b0b5f4c550c282 100644 --- a/bindings/fortran/modules/adios2_engine_mod.f90 +++ b/bindings/fortran/modules/adios2_engine_mod.f90 @@ -10,10 +10,39 @@ module adios2_engine use adios2_engine_write use adios2_engine_iwrite + use adios2_engine_read + use adios2_engine_iread implicit none contains + subroutine adios2_begin_step(engine, ierr) + integer(kind=8), intent(in) :: engine + integer, intent(out) :: ierr + + call adios2_begin_step_f2c(engine, ierr) + + end subroutine + + + subroutine adios2_perform_puts(engine, ierr) + integer(kind=8), intent(in) :: engine + integer, intent(out) :: ierr + + call adios2_perform_puts_f2c(engine, ierr) + + end subroutine + + + subroutine adios2_perform_gets(engine, ierr) + integer(kind=8), intent(in) :: engine + integer, intent(out) :: ierr + + call adios2_perform_gets_f2c(engine, ierr) + + end subroutine + + subroutine adios2_end_step(engine, ierr) integer(kind=8), intent(in) :: engine integer, intent(out) :: ierr diff --git a/bindings/fortran/modules/adios2_engine_read_mod.f90 b/bindings/fortran/modules/adios2_engine_read_mod.f90 new file mode 100644 index 0000000000000000000000000000000000000000..220937e4fd9e4a39da59bd7c9331e67ff2a83a0c --- /dev/null +++ b/bindings/fortran/modules/adios2_engine_read_mod.f90 @@ -0,0 +1,660 @@ +! +! Distributed under the OSI-approved Apache License, Version 2.0. See +! accompanying file Copyright.txt for details. +! +! adios2_engine_read_mod.f90 : ADIOS2 Fortran bindings for Engine generic +! Read functions +! +! Created on: Aug 22, 2017 +! Author: William F Godoy godoywf@ornl.gov +! +module adios2_engine_read + + interface adios2_read + + ! Single Value + module procedure adios2_read_integer + module procedure adios2_read_real + module procedure adios2_read_dp + module procedure adios2_read_complex + module procedure adios2_read_complex_dp + module procedure adios2_read_integer1 + module procedure adios2_read_integer2 + module procedure adios2_read_integer8 + + ! 1D Array + module procedure adios2_read_integer_1d + module procedure adios2_read_real_1d + module procedure adios2_read_dp_1d + module procedure adios2_read_complex_1d + module procedure adios2_read_complex_dp_1d + module procedure adios2_read_integer1_1d + module procedure adios2_read_integer2_1d + module procedure adios2_read_integer8_1d + + ! 2D Array + module procedure adios2_read_integer_2d + module procedure adios2_read_real_2d + module procedure adios2_read_dp_2d + module procedure adios2_read_complex_2d + module procedure adios2_read_complex_dp_2d + module procedure adios2_read_integer1_2d + module procedure adios2_read_integer2_2d + module procedure adios2_read_integer8_2d + + ! 3D Array + module procedure adios2_read_integer_3d + module procedure adios2_read_real_3d + module procedure adios2_read_dp_3d + module procedure adios2_read_complex_3d + module procedure adios2_read_complex_dp_3d + module procedure adios2_read_integer1_3d + module procedure adios2_read_integer2_3d + module procedure adios2_read_integer8_3d + + ! 4D Array + module procedure adios2_read_integer_4d + module procedure adios2_read_real_4d + module procedure adios2_read_dp_4d + module procedure adios2_read_complex_4d + module procedure adios2_read_complex_dp_4d + module procedure adios2_read_integer1_4d + module procedure adios2_read_integer2_4d + module procedure adios2_read_integer8_4d + + ! 5D Array + module procedure adios2_read_integer_5d + module procedure adios2_read_real_5d + module procedure adios2_read_dp_5d + module procedure adios2_read_complex_5d + module procedure adios2_read_complex_dp_5d + module procedure adios2_read_integer1_5d + module procedure adios2_read_integer2_5d + module procedure adios2_read_integer8_5d + + ! 6D Array + module procedure adios2_read_integer_6d + module procedure adios2_read_real_6d + module procedure adios2_read_dp_6d + module procedure adios2_read_complex_6d + module procedure adios2_read_complex_dp_6d + module procedure adios2_read_integer1_6d + module procedure adios2_read_integer2_6d + module procedure adios2_read_integer8_6d + + end interface + +contains + + ! Single Value + subroutine adios2_read_integer( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + integer, intent(out):: values + integer, intent(out):: ierr + + call adios2_get_sync_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_read_real( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + real, intent(out):: values + integer, intent(out):: ierr + + call adios2_get_sync_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_read_dp( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + real(kind=8), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_sync_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_read_complex( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + complex, intent(out):: values + integer, intent(out):: ierr + + call adios2_get_sync_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_read_complex_dp( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + complex(kind=8), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_sync_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_read_integer1( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + integer(kind=1), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_sync_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_read_integer2( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + integer(kind=2), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_sync_f2c(engine, variable, values, ierr) + + end subroutine + + + subroutine adios2_read_integer8( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + integer(kind=8), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_sync_f2c(engine, variable, values, ierr) + + end subroutine + + ! 1D Array + subroutine adios2_read_integer_1d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + integer, dimension(:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_sync_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_read_real_1d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + real, dimension(:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_sync_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_read_dp_1d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + real(kind=8), dimension(:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_sync_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_read_complex_1d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + complex, dimension(:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_sync_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_read_complex_dp_1d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + complex(kind=8), dimension(:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_sync_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_read_integer1_1d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + integer(kind=1), dimension(:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_sync_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_read_integer2_1d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + integer(kind=2), dimension(:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_sync_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_read_integer8_1d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + integer(kind=8), dimension(:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_sync_f2c(engine, variable, values, ierr) + + end subroutine + + ! 2D Array + subroutine adios2_read_integer_2d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + integer, dimension(:,:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_sync_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_read_real_2d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + real, dimension(:,:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_sync_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_read_dp_2d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + real(kind=8), dimension(:,:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_sync_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_read_complex_2d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + complex, dimension(:,:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_sync_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_read_complex_dp_2d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + complex(kind=8), dimension(:,:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_sync_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_read_integer1_2d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + integer(kind=1), dimension(:,:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_sync_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_read_integer2_2d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + integer(kind=2), dimension(:,:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_sync_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_read_integer8_2d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + integer(kind=8), dimension(:,:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_sync_f2c(engine, variable, values, ierr) + + end subroutine + + ! 3D Array + subroutine adios2_read_integer_3d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + integer, dimension(:,:,:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_sync_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_read_real_3d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + real, dimension(:,:,:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_sync_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_read_dp_3d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + real(kind=8), dimension(:,:,:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_sync_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_read_complex_3d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + complex, dimension(:,:,:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_sync_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_read_complex_dp_3d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + complex(kind=8), dimension(:,:,:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_sync_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_read_integer1_3d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + integer(kind=1), dimension(:,:,:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_sync_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_read_integer2_3d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + integer(kind=2), dimension(:,:,:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_sync_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_read_integer8_3d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + integer(kind=8), dimension(:,:,:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_sync_f2c(engine, variable, values, ierr) + + end subroutine + + + ! 4D Array + subroutine adios2_read_integer_4d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + integer, dimension(:,:,:,:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_sync_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_read_real_4d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + real, dimension(:,:,:,:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_sync_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_read_dp_4d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + real(kind=8), dimension(:,:,:,:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_sync_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_read_complex_4d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + complex, dimension(:,:,:,:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_sync_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_read_complex_dp_4d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + complex(kind=8), dimension(:,:,:,:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_sync_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_read_integer1_4d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + integer(kind=1), dimension(:,:,:,:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_sync_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_read_integer2_4d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + integer(kind=2), dimension(:,:,:,:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_sync_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_read_integer8_4d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + integer(kind=8), dimension(:,:,:,:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_sync_f2c(engine, variable, values, ierr) + + end subroutine + + + ! 5D Array + subroutine adios2_read_integer_5d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + integer, dimension(:,:,:,:,:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_sync_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_read_real_5d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + real, dimension(:,:,:,:,:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_sync_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_read_dp_5d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + real(kind=8), dimension(:,:,:,:,:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_sync_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_read_complex_5d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + complex, dimension(:,:,:,:,:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_sync_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_read_complex_dp_5d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + complex(kind=8), dimension(:,:,:,:,:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_sync_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_read_integer1_5d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + integer(kind=1), dimension(:,:,:,:,:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_sync_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_read_integer2_5d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + integer(kind=2), dimension(:,:,:,:,:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_sync_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_read_integer8_5d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + integer(kind=8), dimension(:,:,:,:,:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_sync_f2c(engine, variable, values, ierr) + + end subroutine + + + ! 6D Array + subroutine adios2_read_integer_6d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + integer, dimension(:,:,:,:,:,:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_sync_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_read_real_6d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + real, dimension(:,:,:,:,:,:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_sync_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_read_dp_6d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + real(kind=8), dimension(:,:,:,:,:,:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_sync_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_read_complex_6d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + complex, dimension(:,:,:,:,:,:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_sync_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_read_complex_dp_6d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + complex(kind=8), dimension(:,:,:,:,:,:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_sync_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_read_integer1_6d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + integer(kind=1), dimension(:,:,:,:,:,:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_sync_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_read_integer2_6d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + integer(kind=2), dimension(:,:,:,:,:,:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_sync_f2c(engine, variable, values, ierr) + + end subroutine + + subroutine adios2_read_integer8_6d( engine, variable, values, ierr ) + integer(kind=8), intent(in):: engine + integer(kind=8), intent(in):: variable + integer(kind=8), dimension(:,:,:,:,:,:), intent(out):: values + integer, intent(out):: ierr + + call adios2_get_sync_f2c(engine, variable, values, ierr) + + end subroutine + +end module diff --git a/bindings/fortran/modules/adios2_functions_mod.f90 b/bindings/fortran/modules/adios2_functions_mod.f90 index 82ccbd60880687cba8e7c2b65e455e700bd1f5ba..0c516468f0518711695001a9eb1284d37c9c25e2 100644 --- a/bindings/fortran/modules/adios2_functions_mod.f90 +++ b/bindings/fortran/modules/adios2_functions_mod.f90 @@ -1,4 +1,5 @@ module adios2_functions + use adios2_parameters implicit none contains @@ -13,4 +14,36 @@ contains end function + + subroutine adios2_StringC2F( c_string, length, f_string ) + character*(*), intent(in) :: c_string + integer, intent(in) :: length + character(len=:), allocatable, intent(out) :: f_string + + if( allocated(f_string) ) deallocate(f_string) + if( length > 0 ) then + allocate( character(length) :: f_string ) + f_string = c_string(1:length) + end if + + end subroutine + + + subroutine adios2_TypeC2F( c_type, f_type ) + integer, intent(in) :: c_type + integer, intent(out) :: f_type + + integer :: i + + f_type = adios2_type_unknown + + do i=-1,11 + if( c_type == i ) then + f_type = c_type + exit + end if + end do + + end subroutine + end module diff --git a/bindings/fortran/modules/adios2_io_mod.f90 b/bindings/fortran/modules/adios2_io_mod.f90 index 9b349f82ca22bdbea889de4b5f45d67f6c42ae81..a70f69231ef150db74367a26d4e3b2637036c41a 100644 --- a/bindings/fortran/modules/adios2_io_mod.f90 +++ b/bindings/fortran/modules/adios2_io_mod.f90 @@ -2,7 +2,7 @@ ! Distributed under the OSI-approved Apache License, Version 2.0. See ! accompanying file Copyright.txt for details. ! -! adios2_io.f90 : ADIOS2 Fortran bindings for IO class +! adios2_io_mod.f90 : ADIOS2 Fortran bindings for IO class ! ! Created on: Mar 13, 2017 ! Author: William F Godoy godoywf@ornl.gov @@ -80,4 +80,16 @@ contains end subroutine + subroutine adios2_inquire_variable(variable, io, variable_name, ierr) + integer(kind=8), intent(out) :: variable + integer(kind=8), intent(in) :: io + character*(*), intent(in) :: variable_name + integer, intent(out) :: ierr + + call adios2_inquire_variable_f2c(variable, io, & + & TRIM(ADJUSTL(variable_name))//char(0), ierr) + + end subroutine + + end module diff --git a/bindings/fortran/modules/adios2_parameters_mod.f90 b/bindings/fortran/modules/adios2_parameters_mod.f90 index 7c78942f396489f6d38b08190b7d31bf4085e505..997ba65b56fb84c9e6a864bb654151eda0ab833b 100644 --- a/bindings/fortran/modules/adios2_parameters_mod.f90 +++ b/bindings/fortran/modules/adios2_parameters_mod.f90 @@ -14,7 +14,8 @@ module adios2_parameters logical, parameter :: adios2_debug_mode_on = .true. logical, parameter :: adios2_debug_mode_off = .false. - ! Type + ! Types + integer, parameter :: adios2_type_unknown = -1 integer, parameter :: adios2_type_character = 0 integer, parameter :: adios2_type_integer = 1 integer, parameter :: adios2_type_real = 2 @@ -27,10 +28,17 @@ module adios2_parameters integer, parameter :: adios2_type_integer4 = 8 integer, parameter :: adios2_type_integer8 = 9 + integer, parameter :: adios2_type_string = 10 + integer, parameter :: adios2_type_string_array = 11 + ! Constant dims logical, parameter :: adios2_constant_dims_true = .true. logical, parameter :: adios2_constant_dims_false = .false. + ! Found or not found, ierr value + integer, parameter :: adios2_found = 0 + integer, parameter :: adios2_not_found = 2 + ! Mode integer, parameter :: adios2_mode_undefined = 0 integer, parameter :: adios2_mode_write = 1 diff --git a/bindings/fortran/modules/adios2_variable_mod.f90 b/bindings/fortran/modules/adios2_variable_mod.f90 new file mode 100644 index 0000000000000000000000000000000000000000..c6cbe1df6befc1cae578713a1ffec861073dd94f --- /dev/null +++ b/bindings/fortran/modules/adios2_variable_mod.f90 @@ -0,0 +1,57 @@ +! +! Distributed under the OSI-approved Apache License, Version 2.0. See +! accompanying file Copyright.txt for details. +! +! adios2_variable_mod.f90 : ADIOS2 Fortran bindings for Variable class +! +! Created on: Mar 13, 2017 +! Author: William F Godoy godoywf@ornl.gov +! + +module adios2_variable + use adios2_functions + implicit none + +contains + + subroutine adios2_variable_name(variable, name, ierr) + integer(kind=8), intent(out) :: variable + character(len = :), allocatable, intent(out) :: name + integer, intent(out) :: ierr + + character(len = 1024) :: c_name + integer :: length, i + + call adios2_variable_name_f2c( variable, c_name, length, ierr ) + call adios2_StringC2F(c_name, length, name) + + end subroutine + + + subroutine adios2_variable_type(variable, type, ierr) + integer(kind=8), intent(out) :: variable + integer, intent(out) :: type + integer, intent(out) :: ierr + + integer :: c_type + + call adios2_variable_type_f2c( variable, c_type, ierr ) + call adios2_TypeC2F( c_type, type ) + + end subroutine + + + subroutine adios2_set_selection(variable, ndims, start_dims, count_dims, & + & ierr) + integer(kind=8), intent(out) :: variable + integer, intent(in) :: ndims + integer, dimension(:), intent(in) :: start_dims + integer, dimension(:), intent(in) :: count_dims + integer, intent(out) :: ierr + + call adios2_set_selection_f2c(variable, ndims, start_dims, & + & count_dims, ierr) + + end subroutine + +end module diff --git a/bindings/python/EnginePy.cpp b/bindings/python/EnginePy.cpp index a3e7b11800e13497b14894064af80282e033a6b8..3120be8a4f2445a43aa5112106494056bdc23340 100644 --- a/bindings/python/EnginePy.cpp +++ b/bindings/python/EnginePy.cpp @@ -5,7 +5,7 @@ * EnginePy.cpp * * Created on: Mar 15, 2017 - * Author: wgodoy + * Author: William F Godoy godoywf@ornl.gov */ #include "EnginePy.h" @@ -25,35 +25,12 @@ EnginePy::EnginePy(IO &io, const std::string &name, const Mode openMode, { } +void EnginePy::BeginStep() { m_Engine.BeginStep(); } + void EnginePy::PutSync(VariableBase *variable, const pybind11::array &array) { - if (variable->m_Type.empty()) // Define in IO - { - auto &io = m_Engine.GetIO(); + DefineInIO(variable, array); - if (array.is(pybind11::array())) - { - if (m_DebugMode) - { - throw std::invalid_argument( - "ERROR: passing an empty numpy array for variable " + - variable->m_Name + ", in call to PutSync"); - } - } -#define declare_type(T) \ - else if (pybind11::isinstance< \ - pybind11::array_t<T, pybind11::array::c_style>>(array)) \ - { \ - variable = &io.DefineVariable<T>(variable->m_Name, variable->m_Shape, \ - variable->m_Start, variable->m_Count, \ - variable->m_ConstantDims); \ - m_VariablesPlaceholder.erase(variable->m_Name); \ - } - ADIOS2_FOREACH_NUMPY_TYPE_1ARG(declare_type) -#undef declare_type - } - - // PutSync if (variable->m_Type == "compound") { // not supported @@ -80,10 +57,143 @@ void EnginePy::PutSync(VariableBase *variable, const pybind11::array &array) void EnginePy::PutSync(VariableBase *variable, const std::string &string) { + DefineInIO(variable, string); m_Engine.PutSync(*dynamic_cast<adios2::Variable<std::string> *>(variable), string); } +void EnginePy::PutDeferred(VariableBase *variable, const pybind11::array &array) +{ + DefineInIO(variable, array); + + if (variable->m_Type == "compound") + { + // not supported + } +#define declare_type(T) \ + else if (variable->m_Type == GetType<T>()) \ + { \ + m_Engine.PutDeferred(*dynamic_cast<adios2::Variable<T> *>(variable), \ + reinterpret_cast<const T *>(array.data())); \ + } + ADIOS2_FOREACH_NUMPY_TYPE_1ARG(declare_type) +#undef declare_type + else + { + if (m_DebugMode) + { + throw std::invalid_argument("ERROR: variable " + variable->m_Name + + " numpy array type is not supported or " + "is not memory contiguous " + ", in call to PutDeferred\n"); + } + } +} + +void EnginePy::PutDeferred(VariableBase *variable, const std::string &string) +{ + DefineInIO(variable, string); + m_Engine.PutDeferred( + *dynamic_cast<adios2::Variable<std::string> *>(variable), string); +} + +void EnginePy::PerformPuts() { m_Engine.PerformPuts(); } + +void EnginePy::GetSync(VariableBase *variable, pybind11::array &array) +{ + if (variable->m_Type == "compound") + { + // not supported + } +#define declare_type(T) \ + else if (variable->m_Type == GetType<T>()) \ + { \ + m_Engine.GetSync( \ + *dynamic_cast<adios2::Variable<T> *>(variable), \ + reinterpret_cast<T *>(const_cast<void *>(array.data()))); \ + } + ADIOS2_FOREACH_NUMPY_TYPE_1ARG(declare_type) +#undef declare_type + else + { + if (m_DebugMode) + { + throw std::invalid_argument( + "ERROR: in variable " + variable->m_Name + " of type " + + variable->m_Type + + ", numpy array type is 1) not supported, 2) a type mismatch or" + "3) is not memory contiguous " + ", in call to GetSync\n"); + } + } +} + +void EnginePy::GetSync(VariableBase *variable, std::string &string) +{ + if (variable->m_Type == GetType<std::string>()) + { + m_Engine.GetSync( + *dynamic_cast<adios2::Variable<std::string> *>(variable), string); + } + else + { + if (m_DebugMode) + { + throw std::invalid_argument("ERROR: variable " + variable->m_Name + + " of type " + variable->m_Type + + " is not string, in call to GetSync"); + } + } +} + +void EnginePy::GetDeferred(VariableBase *variable, pybind11::array &array) +{ + if (variable->m_Type == "compound") + { + // not supported + } +#define declare_type(T) \ + else if (variable->m_Type == GetType<T>()) \ + { \ + m_Engine.GetDeferred( \ + *dynamic_cast<adios2::Variable<T> *>(variable), \ + reinterpret_cast<T *>(const_cast<void *>(array.data()))); \ + } + ADIOS2_FOREACH_NUMPY_TYPE_1ARG(declare_type) +#undef declare_type + else + { + if (m_DebugMode) + { + throw std::invalid_argument( + "ERROR: in variable " + variable->m_Name + " of type " + + variable->m_Type + + ", numpy array type is 1) not supported, 2) a type mismatch or" + "3) is not memory contiguous " + ", in call to GetSync\n"); + } + } +} + +void EnginePy::GetDeferred(VariableBase *variable, std::string &string) +{ + if (variable->m_Type == GetType<std::string>()) + { + m_Engine.GetDeferred( + *dynamic_cast<adios2::Variable<std::string> *>(variable), string); + } + else + { + if (m_DebugMode) + { + throw std::invalid_argument( + "ERROR: variable " + variable->m_Name + " of type " + + variable->m_Type + " is not string, in call to GetDeferred"); + } + } +} +void EnginePy::PerformGets() { m_Engine.PerformGets(); } + void EnginePy::EndStep() { m_Engine.EndStep(); } void EnginePy::Close(const int transportIndex) @@ -91,4 +201,46 @@ void EnginePy::Close(const int transportIndex) m_Engine.Close(transportIndex); } +// PRIVATE +void EnginePy::DefineInIO(VariableBase *variable, const pybind11::array &array) +{ + if (variable->m_Type.empty()) // Define in IO + { + auto &io = m_Engine.GetIO(); + + if (array.is(pybind11::array())) + { + if (m_DebugMode) + { + throw std::invalid_argument( + "ERROR: passing an empty numpy array for variable " + + variable->m_Name + ", in call to Put/Get"); + } + } +#define declare_type(T) \ + else if (pybind11::isinstance< \ + pybind11::array_t<T, pybind11::array::c_style>>(array)) \ + { \ + variable = &io.DefineVariable<T>(variable->m_Name, variable->m_Shape, \ + variable->m_Start, variable->m_Count, \ + variable->m_ConstantDims); \ + m_VariablesPlaceholder.erase(variable->m_Name); \ + } + ADIOS2_FOREACH_NUMPY_TYPE_1ARG(declare_type) +#undef declare_type + } +} + +void EnginePy::DefineInIO(VariableBase *variable, const std::string &string) +{ + if (variable->m_Type.empty()) // Define in IO + { + auto &io = m_Engine.GetIO(); + variable = &io.DefineVariable<std::string>( + variable->m_Name, variable->m_Shape, variable->m_Start, + variable->m_Count, variable->m_ConstantDims); + m_VariablesPlaceholder.erase(variable->m_Name); + } +} + } // end namespace adios2 diff --git a/bindings/python/EnginePy.h b/bindings/python/EnginePy.h index e4b426345c488a559113ed1991178138999c836c..7ef45d27fdcaa1867dd651abdcba9fa4039e4ddf 100644 --- a/bindings/python/EnginePy.h +++ b/bindings/python/EnginePy.h @@ -32,9 +32,24 @@ public: ~EnginePy() = default; + void BeginStep(); + void PutSync(VariableBase *variable, const pybind11::array &array); void PutSync(VariableBase *variable, const std::string &string); + void PutDeferred(VariableBase *variable, const pybind11::array &array); + void PutDeferred(VariableBase *variable, const std::string &string); + + void PerformPuts(); + + void GetSync(VariableBase *variable, pybind11::array &array); + void GetSync(VariableBase *variable, std::string &string); + + void GetDeferred(VariableBase *variable, pybind11::array &array); + void GetDeferred(VariableBase *variable, std::string &string); + + void PerformGets(); + void EndStep(); void Close(const int transportIndex = -1); @@ -43,6 +58,9 @@ private: Engine &m_Engine; std::map<std::string, VariableBase> &m_VariablesPlaceholder; const bool m_DebugMode; + + void DefineInIO(VariableBase *variable, const pybind11::array &array); + void DefineInIO(VariableBase *variable, const std::string &string); }; } // end namespace adios2 diff --git a/bindings/python/gluePyBind11.cpp b/bindings/python/gluePyBind11.cpp index ec8b28731a4f1ed5d13c291b8fccbbe423a08ef7..374b72a11313a8289d6215a0943a4164186b28cc 100644 --- a/bindings/python/gluePyBind11.cpp +++ b/bindings/python/gluePyBind11.cpp @@ -134,7 +134,8 @@ PYBIND11_MODULE(adios2, m) .def("DeclareIO", &adios2::ADIOSPy::DeclareIO); pybind11::class_<adios2::VariableBase>(m, "Variable") - .def("SetSelection", &adios2::VariableBase::SetSelection); + .def("SetSelection", &adios2::VariableBase::SetSelection) + .def("SelectionSize", &adios2::VariableBase::SelectionSize); pybind11::class_<adios2::IOPy>(m, "IOPy") .def("SetEngine", &adios2::IOPy::SetEngine) @@ -158,12 +159,34 @@ PYBIND11_MODULE(adios2, m) adios2::IOPy::Open); pybind11::class_<adios2::EnginePy>(m, "EnginePy") + .def("BeginStep", &adios2::EnginePy::BeginStep) .def("PutSync", (void (adios2::EnginePy::*)(adios2::VariableBase *, const pybind11::array &)) & adios2::EnginePy::PutSync) .def("PutSync", (void (adios2::EnginePy::*)(adios2::VariableBase *, const std::string &)) & adios2::EnginePy::PutSync) + .def("PutDeferred", + (void (adios2::EnginePy::*)(adios2::VariableBase *, + const pybind11::array &)) & + adios2::EnginePy::PutDeferred) + .def("PutDeferred", (void (adios2::EnginePy::*)(adios2::VariableBase *, + const std::string &)) & + adios2::EnginePy::PutDeferred) + .def("PerformPuts", &adios2::EnginePy::PerformPuts) + .def("GetSync", (void (adios2::EnginePy::*)(adios2::VariableBase *, + pybind11::array &)) & + adios2::EnginePy::GetSync) + .def("GetSync", (void (adios2::EnginePy::*)(adios2::VariableBase *, + std::string &)) & + adios2::EnginePy::GetSync) + .def("GetDeferred", (void (adios2::EnginePy::*)(adios2::VariableBase *, + pybind11::array &)) & + adios2::EnginePy::GetDeferred) + .def("GetDeferred", (void (adios2::EnginePy::*)(adios2::VariableBase *, + std::string &)) & + adios2::EnginePy::GetDeferred) + .def("PerformGets", &adios2::EnginePy::PerformGets) .def("EndStep", &adios2::EnginePy::EndStep) .def("Close", &adios2::EnginePy::Close, pybind11::arg("transportIndex") = -1); diff --git a/examples/hello/bpReader/CMakeLists.txt b/examples/hello/bpReader/CMakeLists.txt index 74235567d498bbcd972927c7f390ffb485151a2f..fd7a77a894968b341f704c2964e8e92c13125943 100644 --- a/examples/hello/bpReader/CMakeLists.txt +++ b/examples/hello/bpReader/CMakeLists.txt @@ -18,20 +18,17 @@ if(ADIOS2_HAVE_MPI) target_link_libraries(hello_bpReaderHeatMap3D ${MPI_C_LIBRARIES}) target_link_libraries(hello_bpReaderHeatMap3D adios2) + if(ADIOS2_HAVE_Fortran) + add_executable(hello_bpReaderHeatMap3D_f helloBPReaderHeatMap3D.f90) + target_link_libraries(hello_bpReaderHeatMap3D_f MPI::MPI_Fortran) + target_link_libraries(hello_bpReaderHeatMap3D_f adios2_f) + endif() + # add_executable(hello_bpReader_c helloBPReader.c) # target_include_directories(hello_bpReader_c PRIVATE ${MPI_C_INCLUDE_PATH}) # target_link_libraries(hello_bpReader_c ${MPI_C_LIBRARIES}) -# -# if(ADIOS2_HAVE_Fortran) -# add_executable(hello_bpReader_f helloBPReader.f90) -# target_include_directories(hello_bpReader_f -# PRIVATE ${MPI_Fortran_INCLUDE_PATH} -# ${MPI_C_INCLUDE_PATH}) -# -# target_link_libraries(hello_bpReader_f PRIVATE ${MPI_Fortran_LIBRARIES} -# ${MPI_C_LIBRARIES}) -# endif() + else() add_executable(hello_bpReader helloBPReader_nompi.cpp) diff --git a/examples/hello/bpReader/helloBPReaderHeatMap2D.cpp b/examples/hello/bpReader/helloBPReaderHeatMap2D.cpp index 86fc95ed6fb180be1752efe27b27191ec4d87aa9..3305d29f4e1486b42651699b03d7881f09269ad6 100644 --- a/examples/hello/bpReader/helloBPReaderHeatMap2D.cpp +++ b/examples/hello/bpReader/helloBPReaderHeatMap2D.cpp @@ -91,7 +91,7 @@ int main(int argc, char *argv[]) if (inTemperature != nullptr) { inTemperature->SetSelection({{2, 2}, {6, 1}}); - size_t elementsSize = inTemperature->GetElementsSize(); + size_t elementsSize = inTemperature->SelectionSize(); std::vector<unsigned int> inTemperatures(elementsSize); std::cout << "Pre-allocated " << elementsSize << " elements, " << elementsSize * sizeof(unsigned int) << " bytes\n"; diff --git a/examples/hello/bpReader/helloBPReaderHeatMap3D.cpp b/examples/hello/bpReader/helloBPReaderHeatMap3D.cpp index 71cb73f486ade9a744127fdbec5d56ebe0f837de..d41d039c1a49b42717022192ce3d46db0078c2bc 100644 --- a/examples/hello/bpReader/helloBPReaderHeatMap3D.cpp +++ b/examples/hello/bpReader/helloBPReaderHeatMap3D.cpp @@ -2,17 +2,21 @@ * Distributed under the OSI-approved Apache License, Version 2.0. See * accompanying file Copyright.txt for details. * - * helloBPReaderHeatMap.cpp : Writes a heat map in a regular 2D mesh, + * helloBPReaderHeatMap3D.cpp : Writes a heat map in a regular 3D mesh, * values grow from 0 in increments of 1 * - * temperature[gNx, Ny] + * temperature[gNx, Ny, Nz] * where: gNx = MPI_size_x * Nx * - * 0 1 2 ... Ny-1 - * Ny Ny+1 Ny+2 ... 2*Ny-1 + * k Map: + * k= Nz-1 . . . . + * k=1 . . . . + * k=0 . . . . + * 0 1 2 ... Nz-1 + * Nz Nz+1 Nz+2 ... 2*Nz-1 * ... * ... - * (gNx-1)*Ny ... gNx*Ny-1 + *(Ny-1)*Nz ... Ny*Nz-1 * * * Created on: Nov 1, 2017 @@ -73,13 +77,13 @@ int main(int argc, char *argv[]) // ************************** WRITE /*** IO class object: settings and factory of Settings: Variables, * Parameters, Transports, and Execution: Engines */ - adios2::IO &putHeatMap = adios.DeclareIO("HeatMapWriter"); + adios2::IO &putHeatMap = adios.DeclareIO("HeatMapWrite"); adios2::Variable<unsigned int> &outTemperature = putHeatMap.DefineVariable<unsigned int>( "temperature", shape, start, count, adios2::ConstantDims); - /** Will create HeatMap.bp */ + /** Will create HeatMap3D.bp */ adios2::Engine &bpWriter = putHeatMap.Open("HeatMap3D.bp", adios2::Mode::Write); @@ -89,7 +93,7 @@ int main(int argc, char *argv[]) // ************************** READ if (rank == 0) { - adios2::IO &getHeatMap = adios.DeclareIO("HeatMapReader"); + adios2::IO &getHeatMap = adios.DeclareIO("HeatMapRead"); adios2::Engine &bpReader = getHeatMap.Open("HeatMap3D.bp", adios2::Mode::Read); @@ -100,14 +104,15 @@ int main(int argc, char *argv[]) if (inTemperature != nullptr) { inTemperature->SetSelection({{2, 2, 2}, {4, 4, 4}}); - const size_t elementsSize = inTemperature->GetElementsSize(); + const size_t elementsSize = inTemperature->SelectionSize(); std::vector<unsigned int> inTemperatures(elementsSize); std::cout << "Pre-allocated " << elementsSize << " elements, " << elementsSize * sizeof(unsigned int) << " bytes\n"; bpReader.GetSync(*inTemperature, inTemperatures.data()); - std::cout << "Incoming temperature map:\n"; + std::cout << "Temperature map selection: "; + std::cout << "{ start = [2,2,2], count = [4,4,4] }\n"; for (auto i = 0; i < inTemperatures.size(); ++i) { diff --git a/examples/hello/bpReader/helloBPReaderHeatMap3D.f90 b/examples/hello/bpReader/helloBPReaderHeatMap3D.f90 new file mode 100644 index 0000000000000000000000000000000000000000..89805866bb9d83d6b2079890d07fa73aec7da020 --- /dev/null +++ b/examples/hello/bpReader/helloBPReaderHeatMap3D.f90 @@ -0,0 +1,104 @@ +program helloBPReaderHeatMap3D + use mpi + use adios2 + + implicit none + + integer(kind=8) :: adios + integer(kind=8) :: ioPut, var_temperatures, bpWriter + integer(kind=8) :: ioGet, var_temperaturesIn, bpReader + integer, dimension(:,:,:), allocatable :: temperatures, sel_temperatures + integer, dimension(3) :: ishape, istart, icount + integer, dimension(3) :: sel_start, sel_count + integer :: ierr, irank, isize, inx, iny, inz + integer :: i, j, k, iglobal, value, ilinear, icounter + + call MPI_INIT(ierr) + call MPI_COMM_RANK(MPI_COMM_WORLD, irank, ierr) + call MPI_COMM_SIZE(MPI_COMM_WORLD, isize, ierr) + + inx = 10 + iny = 10 + inz = 10 + + icount = (/ inx, iny, inz /) + istart = (/ irank * inx+1, 1, 1 /) + ishape = (/ isize * inx, iny, inz /) + + allocate( temperatures( inx, iny, inz ) ) + ! populate temperature + do k=1, icount(3) + do j=1, icount(2) + do i=1, icount(1) + iglobal = istart(1) + (i-1)-1 + value = (k-1) * ishape(1) * ishape(2) + (j-1) * ishape(1) + & + & iglobal + temperatures(i,j,k) = value + end do + end do + end do + + ! Start adios2 Writer + call adios2_init( adios, MPI_COMM_WORLD, adios2_debug_mode_on, ierr ) + call adios2_declare_io( ioPut, adios, 'HeatMapWrite', ierr ) + + call adios2_define_variable( var_temperatures, ioPut, 'temperatures', & + & adios2_type_integer, 3, ishape, istart, icount, & + & adios2_constant_dims_true, ierr ) + + call adios2_open( bpWriter, ioPut, 'HeatMap3D_f.bp', & + & adios2_mode_write, ierr ) + + call adios2_write( bpWriter, var_temperatures, temperatures, ierr ) + + call adios2_close( bpWriter, ierr ) + + + if( allocated(temperatures) ) deallocate(temperatures) + + ! Start adios2 Reader in rank 0 + if( irank == 0 ) then + + call adios2_declare_io( ioGet, adios, 'HeatMapRead', ierr ) + + call adios2_open( bpReader, ioGet, 'HeatMap3D_f.bp', & + & adios2_mode_read, ierr) + + call adios2_inquire_variable( var_temperaturesIn, ioGet, & + & 'temperatures', ierr ) + + if( ierr == adios2_found ) then + + sel_start = (/ 3, 3, 3 /) + sel_count = (/ 4, 4, 4 /) + allocate( sel_temperatures( sel_count(1), sel_count(2), & + & sel_count(3) ) ) + + call adios2_set_selection( var_temperaturesIn, 3, sel_start, & + & sel_count, ierr ) + + call adios2_read( bpReader, var_temperaturesIn, sel_temperatures, & + & ierr ) + + write(*,'(A,3(I1,A),A,3(I1,A),A)') 'Temperature map selection & + & [ start = (', (sel_start(i),',',i=1,3) , ') & + & count = (', (sel_count(i),',',i=1,3) , ') ]' + + + do k=1,sel_count(3) + do j=1,sel_count(2) + do i=1,sel_count(1) + write(6,'(I4) ', advance="no") sel_temperatures(i,j,k) + end do + write(*,*) + end do + end do + + + if( allocated(sel_temperatures) ) deallocate(sel_temperatures) + + end if + + end if + +end program helloBPReaderHeatMap3D diff --git a/examples/hello/bpTimeWriter/helloBPTimeWriter.cpp b/examples/hello/bpTimeWriter/helloBPTimeWriter.cpp index 6f485e1606291cec97678a19efa80c14c5c8f8ad..6ab37a388f24beb17266d3828f77a1df4a906028 100644 --- a/examples/hello/bpTimeWriter/helloBPTimeWriter.cpp +++ b/examples/hello/bpTimeWriter/helloBPTimeWriter.cpp @@ -36,69 +36,109 @@ int main(int argc, char *argv[]) * recommended */ adios2::ADIOS adios(MPI_COMM_WORLD, adios2::DebugON); - /*** IO class object: settings and factory of Settings: Variables, - * Parameters, Transports, and Execution: Engines */ - adios2::IO &bpIO = adios.DeclareIO("BPFile_N2N"); - bpIO.SetParameters({{"Threads", "2"}}); + /// WRITE + { + /*** IO class object: settings and factory of Settings: Variables, + * Parameters, Transports, and Execution: Engines */ + adios2::IO &bpIO = adios.DeclareIO("BPFile_N2N"); + bpIO.SetParameters({{"Threads", "2"}}); - /** global array: name, { shape (total dimensions) }, { start - * (local) }, - * { count (local) }, all are constant dimensions */ - const unsigned int variablesSize = 1; - std::vector<adios2::Variable<float> *> bpFloats(variablesSize); + /** global array: name, { shape (total dimensions) }, { start + * (local) }, + * { count (local) }, all are constant dimensions */ + const unsigned int variablesSize = 1; + std::vector<adios2::Variable<float> *> bpFloats(variablesSize); - adios2::Variable<std::string> &bpString = - bpIO.DefineVariable<std::string>("bpString"); + adios2::Variable<std::string> &bpString = + bpIO.DefineVariable<std::string>("bpString"); - for (unsigned int v = 0; v < variablesSize; ++v) - { - std::string namev("bpFloats"); - if (v < 10) + for (unsigned int v = 0; v < variablesSize; ++v) { - namev += "00"; + std::string namev("bpFloats"); + if (v < 10) + { + namev += "00"; + } + else if (v < 100) + { + namev += "0"; + } + namev += std::to_string(v); + + bpFloats[v] = + &bpIO.DefineVariable<float>(namev, {size * Nx}, {rank * Nx}, + {Nx}, adios2::ConstantDims); } - else if (v < 100) + + /** global single value variable: name */ + adios2::Variable<unsigned int> &bpTimeStep = + bpIO.DefineVariable<unsigned int>("timeStep"); + + /** Engine derived class, spawned to start IO operations */ + adios2::Engine &bpWriter = + bpIO.Open("myVector.bp", adios2::Mode::Write); + + for (unsigned int timeStep = 0; timeStep < 3; ++timeStep) { - namev += "0"; + // bpWriter.BeginStep(); + if (rank == 0) // global single value, only saved by rank 0 + { + bpWriter.PutSync<unsigned int>(bpTimeStep, timeStep); + } + + // template type is optional, but recommended + for (unsigned int v = 0; v < variablesSize; ++v) + { + myFloats[0] = static_cast<float>(v + timeStep); + bpWriter.PutSync(*bpFloats[v], myFloats.data()); + } + const std::string myString( + "Hello from rank: " + std::to_string(rank) + + " and timestep: " + std::to_string(timeStep)); + + bpWriter.PutSync(bpString, myString); + + bpWriter.EndStep(); } - namev += std::to_string(v); - bpFloats[v] = &bpIO.DefineVariable<float>( - namev, {size * Nx}, {rank * Nx}, {Nx}, adios2::ConstantDims); + bpWriter.Close(); } + MPI_Barrier(MPI_COMM_WORLD); - /** global single value variable: name */ - adios2::Variable<unsigned int> &bpTimeStep = - bpIO.DefineVariable<unsigned int>("timeStep"); + { /////////////////////READ + // if (rank == 0) + // { + adios2::IO &ioReader = adios.DeclareIO("bpReader"); - /** Engine derived class, spawned to start IO operations */ - adios2::Engine &bpWriter = - bpIO.Open("myVector.bp", adios2::Mode::Write); + adios2::Engine &bpReader = + ioReader.Open("myVector.bp", adios2::Mode::Read); - for (unsigned int timeStep = 0; timeStep < 3; ++timeStep) - { - // bpWriter.BeginStep(); - if (rank == 0) // global single value, only saved by rank 0 + adios2::Variable<float> *bpFloats000 = + ioReader.InquireVariable<float>("bpFloats000"); + + if (bpFloats000 != nullptr) { - bpWriter.PutSync<unsigned int>(bpTimeStep, timeStep); + bpFloats000->SetSelection({{rank * Nx}, {Nx}}); + bpFloats000->SetStepSelection({3, 1}); + + std::vector<float> data(bpFloats000->SelectionSize()); + bpReader.GetSync(*bpFloats000, data.data()); + + std::cout << "Data timestep " << bpFloats000->m_StepsStart + << " from rank " << rank << "\n"; + for (const auto datum : data) + { + std::cout << datum << " "; + } + std::cout << "\n"; } - - // template type is optional, but recommended - for (unsigned int v = 0; v < variablesSize; ++v) + else { - myFloats[0] = static_cast<float>(v + timeStep); - bpWriter.PutSync(*bpFloats[v], myFloats.data()); + std::cout << "Variable bpFloats000 not found\n"; } - const std::string myString( - "Hello from rank: " + std::to_string(rank) + " and timestep: " + - std::to_string(timeStep)); - - bpWriter.PutSync(bpString, myString); - - bpWriter.EndStep(); + bpReader.Close(); + //} } - - bpWriter.Close(); } catch (std::invalid_argument &e) { diff --git a/examples/hello/bpWriter/helloBPWriter.c b/examples/hello/bpWriter/helloBPWriter.c index a6f245d3d74e2c106c96f43f4290ddfe96e49771..268375e6999f0e306ffaa8e3d88e72720e5b3c99 100644 --- a/examples/hello/bpWriter/helloBPWriter.c +++ b/examples/hello/bpWriter/helloBPWriter.c @@ -46,6 +46,7 @@ int main(int argc, char *argv[]) adios2_Variable *variableH = adios2_define_variable(ioH, "bpFloats", adios2_type_float, 1, shape, start, count, adios2_constant_dims_true); + adios2_Engine *engineH = adios2_open(ioH, "myVector_c.bp", adios2_mode_write); diff --git a/examples/hello/bpWriter/helloBPWriter.f90 b/examples/hello/bpWriter/helloBPWriter.f90 index 3766bedbca4a35a796dc97ed72e9a946075a5a28..4b2b0b46e4b2587cabcb11ba8e2b449640612863 100644 --- a/examples/hello/bpWriter/helloBPWriter.f90 +++ b/examples/hello/bpWriter/helloBPWriter.f90 @@ -6,8 +6,10 @@ program helloBPWriter integer, dimension(1) :: shape_dims, start_dims, count_dims real, dimension(:), allocatable :: myArray - integer :: inx, irank, isize, ierr, i + integer :: inx, irank, isize, ierr, i, var1_type integer(kind=8) :: adios, io, var1, engine1 + character(len=:), allocatable :: var1_name + ! Launch MPI call MPI_Init(ierr) @@ -37,6 +39,11 @@ program helloBPWriter call adios2_define_variable(var1, io, "myArray", adios2_type_real, 1, & & shape_dims, start_dims, count_dims, adios2_constant_dims_true, ierr) + + call adios2_variable_name( var1, var1_name, ierr ) + call adios2_variable_type( var1, var1_type, ierr ) + write(*,*) 'Variable name: ', var1_name, ' type: ', var1_type + ! Open myVector_f.bp in write mode, this launches an engine call adios2_open(engine1, io, "myVector_f.bp", adios2_mode_write, ierr) @@ -49,7 +56,8 @@ program helloBPWriter ! Deallocates adios and calls its destructor call adios2_finalize(adios, ierr) - deallocate(myArray) + if( allocated(myArray) ) deallocate(myArray) + if( allocated(var1_name) ) deallocate(var1_name) call MPI_Finalize(ierr) diff --git a/source/adios2/ADIOSMacros.h b/source/adios2/ADIOSMacros.h index d95c2fab7c50a05c161641cd119e2e4435510fac..0d002d332d5702a107da96a6d8ef614193adf03c 100644 --- a/source/adios2/ADIOSMacros.h +++ b/source/adios2/ADIOSMacros.h @@ -70,6 +70,27 @@ MACRO(std::complex<double>) \ MACRO(std::complex<long double>) +#define ADIOS2_FOREACH_CHAR_TYPE_1ARG(MACRO) \ + MACRO(char) \ + MACRO(signed char) \ + MACRO(unsigned char) + +#define ADIOS2_FOREACH_NUMERIC_TYPE_1ARG(MACRO) \ + MACRO(short) \ + MACRO(unsigned short) \ + MACRO(int) \ + MACRO(unsigned int) \ + MACRO(long int) \ + MACRO(long long int) \ + MACRO(unsigned long int) \ + MACRO(unsigned long long int) \ + MACRO(float) \ + MACRO(double) \ + MACRO(long double) \ + MACRO(std::complex<float>) \ + MACRO(std::complex<double>) \ + MACRO(std::complex<long double>) + #define ADIOS2_FOREACH_ZFP_TYPE_1ARG(MACRO) \ MACRO(int32_t) \ MACRO(int64_t) \ diff --git a/source/adios2/core/ADIOS.h b/source/adios2/core/ADIOS.h index 0b00c1da889334b34e0557ee662465fcd81a1795..dc093d31f1696f68d35bfbcde6f239a4f589b59b 100644 --- a/source/adios2/core/ADIOS.h +++ b/source/adios2/core/ADIOS.h @@ -2,8 +2,7 @@ * Distributed under the OSI-approved Apache License, Version 2.0. See * accompanying file Copyright.txt for details. * - * ADIOS.h : ADIOS library starting point, factory class for IO and - * (polymorphic) Engines + * ADIOS.h : ADIOS library starting point, factory class for IO objects * Created on: Oct 3, 2016 * Author: William F Godoy godoywf@ornl.gov */ @@ -107,11 +106,18 @@ public: * @param name must be unique for each operator created with DefineOperator * @param type from derived class * @param parameters optional parameters - * @return + * @return reference to Operator object */ Operator &DefineOperator(const std::string name, const std::string type, const Params ¶meters = Params()); + /** + * Signature for passing Callback functions as operators + * @param name unique operator name + * @param function callable function + * @param parameters + * @return reference to Operator object + */ template <class R, class... Args> Operator &DefineOperator(const std::string name, const std::function<R(Args...)> &function, diff --git a/source/adios2/core/IO.cpp b/source/adios2/core/IO.cpp index f780868b54439aa4e510524fadab13ceb43ce985..b4b0abf4537989875dee1ecc43a1a09b8b79fb8f 100644 --- a/source/adios2/core/IO.cpp +++ b/source/adios2/core/IO.cpp @@ -173,6 +173,26 @@ std::map<std::string, Params> IO::GetAvailableVariables() noexcept if (type == "compound") { } +// TODO : enable string, add dimensions +#define declare_template_instantiation(C) \ + else if (type == GetType<C>()) \ + { \ + Variable<C> &variable = *InquireVariable<C>(name); \ + \ + const int min = static_cast<int>(variable.m_Min); \ + variablesInfo[name]["Min"] = std::to_string(min); \ + \ + const int max = static_cast<int>(variable.m_Max); \ + variablesInfo[name]["Max"] = std::to_string(max); \ + \ + variablesInfo[name]["StepsStart"] = \ + std::to_string(variable.m_AvailableStepsStart); \ + variablesInfo[name]["StepsCount"] = \ + std::to_string(variable.m_AvailableStepsCount); \ + } + ADIOS2_FOREACH_CHAR_TYPE_1ARG(declare_template_instantiation) +#undef declare_template_instantiation + #define declare_template_instantiation(T) \ else if (type == GetType<T>()) \ { \ @@ -188,10 +208,10 @@ std::map<std::string, Params> IO::GetAvailableVariables() noexcept variablesInfo[name]["StepsCount"] = \ std::to_string(variable.m_AvailableStepsCount); \ } - ADIOS2_FOREACH_TYPE_1ARG(declare_template_instantiation) + ADIOS2_FOREACH_NUMERIC_TYPE_1ARG(declare_template_instantiation) #undef declare_template_instantiation } - // TODO: add dimensions + return variablesInfo; } diff --git a/source/adios2/core/VariableBase.cpp b/source/adios2/core/VariableBase.cpp index 591e5ca5bde74066d61c163bf93d36638abdc887..aa3c8fa5fea15b8c1df66a54e306358892efed7c 100644 --- a/source/adios2/core/VariableBase.cpp +++ b/source/adios2/core/VariableBase.cpp @@ -134,7 +134,7 @@ size_t VariableBase::GetAvailableStepsCount() const return m_AvailableStepsCount; } -void VariableBase::SetStepSelection(const std::pair<size_t, size_t> &boxSteps) +void VariableBase::SetStepSelection(const Box<size_t> &boxSteps) { if (boxSteps.second == 0) { @@ -176,7 +176,7 @@ void VariableBase::ClearOperators() noexcept { m_OperatorsInfo.clear(); } void VariableBase::CheckDimensions(const std::string hint) const { - if (m_ShapeID == ShapeID::GlobalArray) + if (m_DebugMode && m_ShapeID == ShapeID::GlobalArray) { if (m_Start.empty() || m_Count.empty()) { @@ -192,7 +192,7 @@ void VariableBase::CheckDimensions(const std::string hint) const // TODO need to think more exceptions here } -size_t VariableBase::GetElementsSize() const +size_t VariableBase::SelectionSize() const { return GetTotalSize(m_Count) * m_StepsCount; } @@ -204,7 +204,7 @@ void VariableBase::InitShapeType() { if (std::count(m_Shape.begin(), m_Shape.end(), JoinedDim) == 1) { - if (!m_Start.empty() && + if (m_DebugMode && !m_Start.empty() && std::count(m_Start.begin(), m_Start.end(), 0) != m_Start.size()) { throw std::invalid_argument("ERROR: The Start array must be " @@ -224,17 +224,15 @@ void VariableBase::InitShapeType() } else { - if (m_DebugMode) + + if (m_DebugMode && m_ConstantDims) { - if (m_ConstantDims) - { - throw std::invalid_argument( - "ERROR: isConstantShape (true) argument is invalid " - "with empty start and count " - "arguments in call to " - "DefineVariable " + - m_Name + "\n"); - } + throw std::invalid_argument( + "ERROR: isConstantShape (true) argument is invalid " + "with empty start and count " + "arguments in call to " + "DefineVariable " + + m_Name + "\n"); } m_ShapeID = ShapeID::GlobalArray; @@ -299,11 +297,14 @@ void VariableBase::InitShapeType() } else { - throw std::invalid_argument( - "ERROR: if the " - "shape is empty, start must be empty as well, in call to " - "DefineVariable " + - m_Name + "\n"); + if (m_DebugMode) + { + throw std::invalid_argument( + "ERROR: if the " + "shape is empty, start must be empty as well, in call to " + "DefineVariable " + + m_Name + "\n"); + } } } @@ -317,6 +318,11 @@ void VariableBase::InitShapeType() void VariableBase::CheckDimensionsCommon(const std::string hint) const { + if (!m_DebugMode) + { + return; + } + if (m_Type == "string") { if (!(m_Shape.empty() && m_Start.empty() && m_Count.empty())) diff --git a/source/adios2/core/VariableBase.h b/source/adios2/core/VariableBase.h index 39d6410578db70a1d820725262e8be7e78a18edf..c57b716908a142a48e709eeb88dd41ba5304c124 100644 --- a/source/adios2/core/VariableBase.h +++ b/source/adios2/core/VariableBase.h @@ -148,7 +148,7 @@ public: * @return memory size to be allocated by a pointer/vector to read this * variable */ - size_t GetElementsSize() const; + size_t SelectionSize() const; protected: const bool m_DebugMode = false; diff --git a/source/adios2/engine/bp/BPFileReader.cpp b/source/adios2/engine/bp/BPFileReader.cpp index 207505d2932e2a10414e62e048c1c45a285cc94e..6900ccd06eda7f8a30d78db3da3b290c4d30401d 100644 --- a/source/adios2/engine/bp/BPFileReader.cpp +++ b/source/adios2/engine/bp/BPFileReader.cpp @@ -8,6 +8,8 @@ * Author: William F Godoy godoywf@ornl.gov */ +#include <iostream> //TODO will go away + #include "BPFileReader.h" #include "BPFileReader.tcc" @@ -27,8 +29,9 @@ BPFileReader::BPFileReader(IO &io, const std::string &name, const Mode mode, void BPFileReader::PerformGets() { - const auto variablesSubFileInfo = + const std::map<std::string, SubFileInfoMap> variablesSubfileInfo = m_BP3Deserializer.PerformGetsVariablesSubFileInfo(m_IO); + ReadVariables(m_IO, variablesSubfileInfo); } void BPFileReader::Close(const int transportIndex) @@ -89,8 +92,7 @@ void BPFileReader::InitBuffer() fileSize); } // broadcast buffer to all ranks from zero - m_BP3Deserializer.m_Metadata.m_Buffer = - BroadcastVector(m_BP3Deserializer.m_Metadata.m_Buffer, m_MPIComm); + BroadcastVector(m_BP3Deserializer.m_Metadata.m_Buffer, m_MPIComm); // fills IO with Variables and Attributes m_BP3Deserializer.ParseMetadata(m_IO); @@ -127,13 +129,14 @@ void BPFileReader::ReadVariables( for (const auto &subFileIndexPair : variableNamePair.second) { const size_t subFileIndex = subFileIndexPair.first; - const std::string subFile( - m_BP3Deserializer.GetBPSubFileName(m_Name, subFileIndex)); if (m_SubFileManager.m_Transports.count(subFileIndex) == 0) { - m_SubFileManager.OpenFiles({subFile}, adios2::Mode::Read, - {{{"transport", "File"}}}, profile); + const std::string subFile( + m_BP3Deserializer.GetBPSubFileName(m_Name, subFileIndex)); + + m_SubFileManager.OpenFileID(subFile, subFileIndex, Mode::Read, + {{"transport", "File"}}, profile); } for (const auto &stepPair : subFileIndexPair.second) // step diff --git a/source/adios2/helper/adiosMPIFunctions.h b/source/adios2/helper/adiosMPIFunctions.h index 0e4ebe68b7905707e190bcf33e82d5cd94f7b194..81a5562f6b42d6f050acdfdc0008056b838695b4 100644 --- a/source/adios2/helper/adiosMPIFunctions.h +++ b/source/adios2/helper/adiosMPIFunctions.h @@ -25,8 +25,8 @@ template <class T> T BroadcastValue(const T &input, MPI_Comm mpiComm, const int rankSource = 0); template <class T> -std::vector<T> BroadcastVector(const std::vector<T> &input, MPI_Comm mpiComm, - const int rankSource = 0); +void BroadcastVector(std::vector<T> &vector, MPI_Comm mpiComm, + const int rankSource = 0); template <class T> T ReduceValues(const T source, MPI_Comm mpiComm, MPI_Op operation = MPI_SUM, diff --git a/source/adios2/helper/adiosMPIFunctions.tcc b/source/adios2/helper/adiosMPIFunctions.tcc index a312d13335e80ec7267475bc5342e4eda9cc01ae..6bbf28df0886e482f01915d35d57fab9ea276a1a 100644 --- a/source/adios2/helper/adiosMPIFunctions.tcc +++ b/source/adios2/helper/adiosMPIFunctions.tcc @@ -105,56 +105,29 @@ unsigned long long int ReduceValues(const unsigned long long int source, // BroadcastVector specializations template <> -std::vector<char> BroadcastVector(const std::vector<char> &input, - MPI_Comm mpiComm, const int rankSource) +void BroadcastVector(std::vector<char> &vector, MPI_Comm mpiComm, + const int rankSource) { - // First Broadcast the size, then the contents - size_t inputSize = BroadcastValue(input.size(), mpiComm, rankSource); - int rank; - MPI_Comm_rank(mpiComm, &rank); - std::vector<char> output; + int size; + MPI_Comm_size(mpiComm, &size); - if (rank == rankSource) + if (size == 1) { - MPI_Bcast(const_cast<char *>(input.data()), static_cast<int>(inputSize), - MPI_CHAR, rankSource, mpiComm); - return input; // no copy - } - else - { - output.resize(inputSize); - MPI_Bcast(output.data(), static_cast<int>(inputSize), MPI_CHAR, - rankSource, mpiComm); + return; } - return output; -} - -template <> -std::vector<size_t> BroadcastVector(const std::vector<size_t> &input, - MPI_Comm mpiComm, const int rankSource) -{ // First Broadcast the size, then the contents - size_t inputSize = BroadcastValue(input.size(), mpiComm, rankSource); + size_t inputSize = BroadcastValue(vector.size(), mpiComm, rankSource); int rank; MPI_Comm_rank(mpiComm, &rank); - std::vector<size_t> output; - if (rank == rankSource) + if (rank != rankSource) { - MPI_Bcast(const_cast<size_t *>(input.data()), - static_cast<int>(inputSize), ADIOS2_MPI_SIZE_T, rankSource, - mpiComm); - return input; // no copy in rankSource - } - else - { - output.resize(inputSize); - MPI_Bcast(output.data(), static_cast<int>(inputSize), ADIOS2_MPI_SIZE_T, - rankSource, mpiComm); + vector.resize(inputSize); } - return output; + MPI_Bcast(vector.data(), static_cast<int>(inputSize), MPI_CHAR, rankSource, + mpiComm); } // GatherArrays specializations diff --git a/source/adios2/helper/adiosMath.cpp b/source/adios2/helper/adiosMath.cpp index 5ee06cd03ec323d8c26e2273faf260409e055e5e..79c3a2bdbc5b9e7aa84d008764c95dc0bca37aba 100644 --- a/source/adios2/helper/adiosMath.cpp +++ b/source/adios2/helper/adiosMath.cpp @@ -135,10 +135,10 @@ Box<Dims> IntersectionBox(const Box<Dims> &box1, const Box<Dims> &box2) noexcept } size_t LinearIndex(const Box<Dims> &localBox, const Dims &point, - const bool isRowMajor, const bool isZeroIndex) noexcept + const bool isRowMajor) noexcept { - auto lf_RowZero = [](const Dims &count, - const Dims &normalizedPoint) -> size_t { + auto lf_RowMajor = [](const Dims &count, + const Dims &normalizedPoint) -> size_t { const size_t countSize = count.size(); size_t linearIndex = 0; @@ -154,8 +154,8 @@ size_t LinearIndex(const Box<Dims> &localBox, const Dims &point, return linearIndex; }; - auto lf_ColumnOne = [](const Dims &count, - const Dims &normalizedPoint) -> size_t { + auto lf_ColumnMajor = [](const Dims &count, + const Dims &normalizedPoint) -> size_t { const size_t countSize = count.size(); size_t linearIndex = 0; @@ -164,10 +164,10 @@ size_t LinearIndex(const Box<Dims> &localBox, const Dims &point, for (size_t p = 1; p < countSize; ++p) { - linearIndex += (normalizedPoint[countSize - p] - 1) * product; + linearIndex += (normalizedPoint[countSize - p]) * product; product /= count[countSize - p]; } - linearIndex += (normalizedPoint[0] - 1); // fastest + linearIndex += normalizedPoint[0]; // fastest return linearIndex; }; @@ -190,13 +190,13 @@ size_t LinearIndex(const Box<Dims> &localBox, const Dims &point, size_t linearIndex = MaxSizeT - 1; - if (isRowMajor && isZeroIndex) + if (isRowMajor) { - linearIndex = lf_RowZero(count, normalizedPoint); + linearIndex = lf_RowMajor(count, normalizedPoint); } - else if (!isRowMajor && !isZeroIndex) + else { - linearIndex = lf_ColumnOne(count, normalizedPoint); + linearIndex = lf_ColumnMajor(count, normalizedPoint); } return linearIndex; diff --git a/source/adios2/helper/adiosMath.h b/source/adios2/helper/adiosMath.h index 4ca4140170db2a5211d98abe80eb8d019bada1f1..f5ab4bf9d2f2158606ac3a0e2123bbdcaa7d1d5d 100644 --- a/source/adios2/helper/adiosMath.h +++ b/source/adios2/helper/adiosMath.h @@ -120,7 +120,7 @@ Box<Dims> IntersectionBox(const Box<Dims> &box1, const Box<Dims> &box2) noexcept; /** - * Get a linear index for a point inside a localBox + * Get a linear index for a point inside a localBox depending on data layout * @param localBox start and count * @param point inside box * @param isRowMajor @@ -128,7 +128,7 @@ Box<Dims> IntersectionBox(const Box<Dims> &box1, * @return linear index for contiguous memory */ size_t LinearIndex(const Box<Dims> &localBox, const Dims &point, - const bool isRowMajor, const bool isZeroIndex) noexcept; + const bool isRowMajor) noexcept; } // end namespace adios2 diff --git a/source/adios2/helper/adiosSystem.cpp b/source/adios2/helper/adiosSystem.cpp index 233f2d096cffde6bb1b482c75bcdcbbc5a36ee72..cac0a33421628d3bbe0963968da800fe021eb6be 100644 --- a/source/adios2/helper/adiosSystem.cpp +++ b/source/adios2/helper/adiosSystem.cpp @@ -21,7 +21,7 @@ // remove ctime warning on Windows #ifdef _WIN32 -#pragma warning(disable : 4996) +#pragma warning(disable : 4996) // ctime warning #endif namespace adios2 @@ -46,4 +46,26 @@ std::string LocalTimeDate() noexcept return std::string(ctime(&now)); } -} // end namespace adios +bool IsRowMajor(const std::string hostLanguage) noexcept +{ + bool isRowMajor = true; + + if (hostLanguage == "Fortran" || hostLanguage == "R") + { + isRowMajor = false; + } + return isRowMajor; +} + +bool IsZeroIndexed(const std::string hostLanguage) noexcept +{ + bool isZeroIndexed = true; + + if (hostLanguage == "Fortran" || hostLanguage == "R") + { + isZeroIndexed = false; + } + return isZeroIndexed; +} + +} // end namespace adios2 diff --git a/source/adios2/helper/adiosSystem.h b/source/adios2/helper/adiosSystem.h index e241e65164a1ccf89cf805f9721dc5863ce0a5c7..0a8c2cfb78ff5903777fe1fc0ad3431af2c1fc25 100644 --- a/source/adios2/helper/adiosSystem.h +++ b/source/adios2/helper/adiosSystem.h @@ -40,6 +40,22 @@ bool IsLittleEndian() noexcept; */ std::string LocalTimeDate() noexcept; -} // end namespace adios +/** + * Support for language bindings, identify if data is row-major (C, C++) or not + * (Fortran, R) + * @param hostLanguage input host language + * @return true: row-major, false: column-major + */ +bool IsRowMajor(const std::string hostLanguage) noexcept; + +/** + * Support for language bindings, identify if data is zero-indexed (C, C++) or + * not (Fortran, R) + * @param hostLanguage input host language + * @return true: zero-indexed, false: one-indexed + */ +bool IsZeroIndexed(const std::string hostLanguage) noexcept; + +} // end namespace adios2 #endif /* ADIOS2_HELPER_ADIOSSYSTEM_H_ */ diff --git a/source/adios2/toolkit/format/bp3/BP3Base.h b/source/adios2/toolkit/format/bp3/BP3Base.h index 6f10ebdc7124afc67f17e6a48dfe4e6b13e47507..45bf3174e62fa95f2ce23eaf8e1052ce0fd1086a 100644 --- a/source/adios2/toolkit/format/bp3/BP3Base.h +++ b/source/adios2/toolkit/format/bp3/BP3Base.h @@ -207,10 +207,8 @@ protected: unsigned int m_Threads = 1; const bool m_DebugMode = false; - /** from host language */ - bool m_IsRowMajor = true; // C, C++ defaults - /** from host language */ - bool m_IsZeroIndex = true; // C, C++ + /** from host language in data information */ + bool m_IsRowMajor = true; /** method type for file I/O */ enum IO_METHOD diff --git a/source/adios2/toolkit/format/bp3/BP3Deserializer.cpp b/source/adios2/toolkit/format/bp3/BP3Deserializer.cpp index 1bfa4de39606f8cdcdfea9aa6df98ab9e19364dc..f614d90e320563be762f8e5714c5132fcb196fce 100644 --- a/source/adios2/toolkit/format/bp3/BP3Deserializer.cpp +++ b/source/adios2/toolkit/format/bp3/BP3Deserializer.cpp @@ -117,8 +117,15 @@ void BP3Deserializer::ParsePGIndex() position = m_Minifooter.PGIndexStart; m_MetadataSet.DataPGCount = ReadValue<uint64_t>(buffer, position); - const uint64_t pgLength = - ReadValue<uint64_t>(buffer, position); // not required + position += 10; // skipping lengths + const uint16_t nameLength = ReadValue<uint16_t>(buffer, position); + position += static_cast<size_t>(nameLength); // skipping name + const char isFortran = ReadValue<char>(buffer, position); + + if (isFortran == 'y') + { + m_IsRowMajor = false; + } } void BP3Deserializer::ParseVariablesIndex(IO &io) @@ -134,7 +141,7 @@ void BP3Deserializer::ParseVariablesIndex(IO &io) case (type_byte): { - DefineVariableInIO<char>(header, io, buffer, position); + DefineVariableInIO<signed char>(header, io, buffer, position); break; } @@ -152,7 +159,11 @@ void BP3Deserializer::ParseVariablesIndex(IO &io) case (type_long): { +#ifdef _WIN32 + DefineVariableInIO<long long int>(header, io, buffer, position); +#else DefineVariableInIO<long int>(header, io, buffer, position); +#endif break; } @@ -176,7 +187,12 @@ void BP3Deserializer::ParseVariablesIndex(IO &io) case (type_unsigned_long): { +#ifdef _WIN32 + DefineVariableInIO<unsigned long long int>(header, io, buffer, + position); +#else DefineVariableInIO<unsigned long int>(header, io, buffer, position); +#endif break; } diff --git a/source/adios2/toolkit/format/bp3/BP3Deserializer.h b/source/adios2/toolkit/format/bp3/BP3Deserializer.h index 4bf14e3f5b692ffc6ab99cf869059d9858b2ed9b..b81107c04ce05ef9b01775ce086b9d8c86511e5a 100644 --- a/source/adios2/toolkit/format/bp3/BP3Deserializer.h +++ b/source/adios2/toolkit/format/bp3/BP3Deserializer.h @@ -70,8 +70,8 @@ private: void ParseAttributesIndex(IO &io); /** - * This function reads a variable index element (serialized) and calls IO - * DefineVariable to deserialize the data + * Reads a variable index element (serialized) and calls IO.DefineVariable + * to deserialize the Variable metadata * @param header serialize * @param io * @param buffer @@ -91,8 +91,27 @@ private: const Box<Dims> &blockBox, const Box<Dims> &intersectionBox) const; + /** + * Row-major, zero-indexed data e.g. : C, C++ + * @param variable + * @param contiguousMemory + * @param blockBox + * @param intersectionBox + */ + template <class T> + void ClipContiguousMemoryCommonRow( + Variable<T> &variable, const std::vector<char> &contiguousMemory, + const Box<Dims> &blockBox, const Box<Dims> &intersectionBox) const; + + /** + * Column-major, one indexed data e.g. : Fortran, R + * @param variable + * @param contiguousMemory + * @param blockBox + * @param intersectionBox + */ template <class T> - void ClipContiguousMemoryCommonRowZero( + void ClipContiguousMemoryCommonColumn( Variable<T> &variable, const std::vector<char> &contiguousMemory, const Box<Dims> &blockBox, const Box<Dims> &intersectionBox) const; }; diff --git a/source/adios2/toolkit/format/bp3/BP3Deserializer.tcc b/source/adios2/toolkit/format/bp3/BP3Deserializer.tcc index c0c0933815e9ee7d1875916eaccbba11064b601a..31600629260a90b5c282f11364499d77d28b13cc 100644 --- a/source/adios2/toolkit/format/bp3/BP3Deserializer.tcc +++ b/source/adios2/toolkit/format/bp3/BP3Deserializer.tcc @@ -84,10 +84,7 @@ void BP3Deserializer::DefineVariableInIO(const ElementIndexHeader &header, position = initialPosition; - size_t currentStep = 1; - - std::vector<size_t> subsetPositions; // per step - subsetPositions.reserve(1); // expecting one subset per step + size_t currentStep = 0; // Starts at 1 in bp file while (position < endPosition) { @@ -100,14 +97,6 @@ void BP3Deserializer::DefineVariableInIO(const ElementIndexHeader &header, buffer, position, static_cast<DataTypes>(header.DataType), false); - if (subsetCharacteristics.Statistics.Step > currentStep) - { - currentStep = subsetCharacteristics.Statistics.Step; - variable->m_IndexStepBlockStarts[currentStep] = subsetPositions; - ++variable->m_AvailableStepsCount; - subsetPositions.clear(); - } - if (subsetCharacteristics.Statistics.Min < variable->m_Min) { variable->m_Min = subsetCharacteristics.Statistics.Min; @@ -118,14 +107,14 @@ void BP3Deserializer::DefineVariableInIO(const ElementIndexHeader &header, variable->m_Max = subsetCharacteristics.Statistics.Max; } - subsetPositions.push_back(subsetPosition); - position = subsetPosition + subsetCharacteristics.EntryLength + 5; - - if (position == endPosition) // check if last one + if (subsetCharacteristics.Statistics.Step > currentStep) { - variable->m_IndexStepBlockStarts[currentStep] = subsetPositions; - break; + currentStep = subsetCharacteristics.Statistics.Step; + variable->m_AvailableStepsCount = + subsetCharacteristics.Statistics.Step; } + variable->m_IndexStepBlockStarts[currentStep].push_back(subsetPosition); + position = subsetPosition + subsetCharacteristics.EntryLength + 5; } } @@ -178,13 +167,13 @@ BP3Deserializer::GetSubFileInfo(const Variable<T> &variable) const info.Seeks.first = blockCharacteristics.Statistics.PayloadOffset + LinearIndex(info.BlockBox, info.IntersectionBox.first, - m_IsRowMajor, m_IsZeroIndex) * + m_IsRowMajor) * sizeof(T); info.Seeks.second = blockCharacteristics.Statistics.PayloadOffset + (LinearIndex(info.BlockBox, info.IntersectionBox.second, - m_IsRowMajor, m_IsZeroIndex) + + m_IsRowMajor) + 1) * sizeof(T); @@ -217,15 +206,20 @@ void BP3Deserializer::ClipContiguousMemoryCommon( return; } - if (m_IsRowMajor && m_IsZeroIndex) + if (m_IsRowMajor) // stored with C, C++, Python + { + ClipContiguousMemoryCommonRow(variable, contiguousMemory, blockBox, + intersectionBox); + } + else // stored with Fortran, R { - ClipContiguousMemoryCommonRowZero(variable, contiguousMemory, blockBox, - intersectionBox); + ClipContiguousMemoryCommonColumn(variable, contiguousMemory, blockBox, + intersectionBox); } } template <class T> -void BP3Deserializer::ClipContiguousMemoryCommonRowZero( +void BP3Deserializer::ClipContiguousMemoryCommonRow( Variable<T> &variable, const std::vector<char> &contiguousMemory, const Box<Dims> &blockBox, const Box<Dims> &intersectionBox) const { @@ -242,17 +236,17 @@ void BP3Deserializer::ClipContiguousMemoryCommonRowZero( bool run = true; const size_t intersectionStart = - LinearIndex(blockBox, intersectionBox.first, true, true) * sizeof(T); + LinearIndex(blockBox, intersectionBox.first, true) * sizeof(T); while (run) { // here copy current linear memory between currentPoint and end const size_t contiguousStart = - LinearIndex(blockBox, currentPoint, true, true) * sizeof(T) - + LinearIndex(blockBox, currentPoint, true) * sizeof(T) - intersectionStart; const size_t variableStart = - LinearIndex(selectionBox, currentPoint, true, true) * sizeof(T); + LinearIndex(selectionBox, currentPoint, true) * sizeof(T); char *rawVariableData = reinterpret_cast<char *>(variable.GetData()); @@ -267,7 +261,7 @@ void BP3Deserializer::ClipContiguousMemoryCommonRowZero( while (true) { ++currentPoint[p]; - if (currentPoint[p] > end[p]) // TODO: check end condition + if (currentPoint[p] > end[p]) { if (p == 0) { @@ -288,6 +282,70 @@ void BP3Deserializer::ClipContiguousMemoryCommonRowZero( } // run } +template <class T> +void BP3Deserializer::ClipContiguousMemoryCommonColumn( + Variable<T> &variable, const std::vector<char> &contiguousMemory, + const Box<Dims> &blockBox, const Box<Dims> &intersectionBox) const +{ + const Dims &start = intersectionBox.first; + const Dims &end = intersectionBox.second; + const size_t stride = (end.front() - start.front() + 1) * sizeof(T); + + Dims currentPoint(start); // current point for memory copy + + const Box<Dims> selectionBox = + StartEndBox(variable.m_Start, variable.m_Count); + + const size_t dimensions = start.size(); + bool run = true; + + const size_t intersectionStart = + LinearIndex(blockBox, intersectionBox.first, false) * sizeof(T); + + while (run) + { + // here copy current linear memory between currentPoint and end + const size_t contiguousStart = + LinearIndex(blockBox, currentPoint, false) * sizeof(T) - + intersectionStart; + + const size_t variableStart = + LinearIndex(selectionBox, currentPoint, false) * sizeof(T); + + char *rawVariableData = reinterpret_cast<char *>(variable.GetData()); + + std::copy(&contiguousMemory[contiguousStart], + &contiguousMemory[contiguousStart + stride], + &rawVariableData[variableStart]); + + // here update each index recursively, always starting from the 2nd + // fastest changing index, since fastest changing index is the + // continuous part in the previous std::copy + size_t p = 1; + while (true) + { + ++currentPoint[p]; + if (currentPoint[p] > end[p]) + { + if (p == dimensions - 1) + { + run = false; // we are done + break; + } + else + { + currentPoint[p] = start[p]; + ++p; + } + } + else + { + break; // break inner p loop + } + } // dimension index update + } +} + } // end namespace format } // end namespace adios2 diff --git a/source/adios2/toolkit/transport/file/FileFStream.cpp b/source/adios2/toolkit/transport/file/FileFStream.cpp index e119c15967a873272dd5bda1c235ee006d20ab93..4f33cd22930067a7a57f39c67e501667f50fff90 100644 --- a/source/adios2/toolkit/transport/file/FileFStream.cpp +++ b/source/adios2/toolkit/transport/file/FileFStream.cpp @@ -34,7 +34,8 @@ void FileFStream::Open(const std::string &name, const Mode openMode) case (Mode::Write): ProfilerStart("open"); MkDir(m_Name); - m_FileStream.open(name, std::fstream::out | std::fstream::binary); + m_FileStream.open(name, std::fstream::out | std::fstream::binary | + std::fstream::trunc); ProfilerStop("open"); break; diff --git a/source/adios2/toolkit/transport/file/FilePOSIX.cpp b/source/adios2/toolkit/transport/file/FilePOSIX.cpp index 903c82992abb595fe8c6963826d43a33a076e3a1..c11b56824f89485aae66830b22912a10139f1230 100644 --- a/source/adios2/toolkit/transport/file/FilePOSIX.cpp +++ b/source/adios2/toolkit/transport/file/FilePOSIX.cpp @@ -49,7 +49,8 @@ void FilePOSIX::Open(const std::string &name, const Mode openMode) case (Mode::Write): ProfilerStart("open"); MkDir(m_Name); - m_FileDescriptor = open(m_Name.c_str(), O_WRONLY | O_CREAT, 0777); + m_FileDescriptor = + open(m_Name.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0777); ProfilerStop("open"); break; diff --git a/source/adios2/toolkit/transportman/TransportMan.cpp b/source/adios2/toolkit/transportman/TransportMan.cpp index 21ed6773e81bb507543011f4b4bc9db6bf807843..4505a3b28d73fee972b689d3a3750e53bdc62542 100644 --- a/source/adios2/toolkit/transportman/TransportMan.cpp +++ b/source/adios2/toolkit/transportman/TransportMan.cpp @@ -54,12 +54,12 @@ void TransportMan::OpenFiles(const std::vector<std::string> &fileNames, } } -void TransportMan::OpenFileID(const std::string &name, const unsigned int id, - const Mode openMode, const Params ¶meters, +void TransportMan::OpenFileID(const std::string &name, const size_t id, + const Mode mode, const Params ¶meters, const bool profile) { std::shared_ptr<Transport> file = - OpenFileTransport(name, openMode, parameters, profile); + OpenFileTransport(name, mode, parameters, profile); m_Transports.insert({id, file}); } diff --git a/source/adios2/toolkit/transportman/TransportMan.h b/source/adios2/toolkit/transportman/TransportMan.h index a305236a7191576159dc55904bd9edf26ef54173..2b7f51f7269a3f8db02581966a06ac266c7c2b91 100644 --- a/source/adios2/toolkit/transportman/TransportMan.h +++ b/source/adios2/toolkit/transportman/TransportMan.h @@ -61,9 +61,16 @@ public: const std::vector<Params> ¶metersVector, const bool profile); - void OpenFileID(const std::string &name, const unsigned int id, - const Mode openMode, const Params ¶meters, - const bool profile); + /** + * Used for sub-files defined by index + * @param name + * @param id + * @param openMode + * @param parameters + * @param profile + */ + void OpenFileID(const std::string &name, const size_t id, const Mode mode, + const Params ¶meters, const bool profile); /** * Gets each transport base name from either baseName at Open or name diff --git a/source/utils/bpls2/BPLS2.cpp b/source/utils/bpls2/BPLS2.cpp index 335444646db3a139ebd28f2018ad9e588fe8e732..3efc634435dbaea05c35eada09423f5ca00b0ea1 100644 --- a/source/utils/bpls2/BPLS2.cpp +++ b/source/utils/bpls2/BPLS2.cpp @@ -238,8 +238,8 @@ void BPLS2::ProcessTransport() const for (const auto &variablePair : variablesMap) { const std::string name(variablePair.first); - const Params ¶meters = variablePair.second; - const std::string type(parameters.at("Type")); + const Params &variableParameters = variablePair.second; + const std::string type(variableParameters.at("Type")); std::cout << " "; std::cout << std::left << std::setw(maxTypeSize) << type << " "; @@ -248,8 +248,8 @@ void BPLS2::ProcessTransport() const // print min max if (m_Parameters.count("long") == 1) { - std::cout << parameters.at("Min") << " / " - << parameters.at("Max"); + std::cout << variableParameters.at("Min") << " / " + << variableParameters.at("Max"); } std::cout << "\n"; } diff --git a/testing/adios2/engine/bp/CMakeLists.txt b/testing/adios2/engine/bp/CMakeLists.txt index b70bace799f079f933093208d248d8d9009f17a8..55e8f14ea28d71667e82b61b9d4a7409be11afed 100644 --- a/testing/adios2/engine/bp/CMakeLists.txt +++ b/testing/adios2/engine/bp/CMakeLists.txt @@ -3,8 +3,16 @@ # accompanying file Copyright.txt for details. #------------------------------------------------------------------------------# -# MPI versions of the test are not properly implemented at the moment +add_executable(TestBPWriteReadADIOS2 TestBPWriteReadADIOS2.cpp) +target_link_libraries(TestBPWriteReadADIOS2 adios2 gtest gtest_main) +if(ADIOS2_HAVE_MPI) + target_link_libraries(TestBPWriteReadADIOS2 MPI::MPI_C) + set(extra_test_args EXEC_WRAPPER ${MPIEXEC_COMMAND}) +endif() + +gtest_add_tests(TARGET TestBPWriteReadADIOS2 ${extra_test_args}) + if (ADIOS2_HAVE_ADIOS1) add_executable(TestBPWriteRead TestBPWriteRead.cpp) target_link_libraries(TestBPWriteRead adios2 gtest adios1::adios) @@ -29,8 +37,6 @@ if (ADIOS2_HAVE_ADIOS1) target_link_libraries(TestBPWriteReadstdio MPI::MPI_C) target_link_libraries(TestBPWriteReadfstream MPI::MPI_C) target_link_libraries(TestBPWriteProfilingJSON MPI::MPI_C) - - set(extra_test_args EXEC_WRAPPER ${MPIEXEC_COMMAND}) endif() gtest_add_tests(TARGET TestBPWriteRead ${extra_test_args}) diff --git a/testing/adios2/engine/bp/TestBPWriteReadADIOS2.cpp b/testing/adios2/engine/bp/TestBPWriteReadADIOS2.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e0d72e8078667aa3b5262cba35a22fbf8d0f6f14 --- /dev/null +++ b/testing/adios2/engine/bp/TestBPWriteReadADIOS2.cpp @@ -0,0 +1,912 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + */ +#include <cstdint> +#include <cstring> + +#include <iostream> +#include <stdexcept> + +#include <adios2.h> + +#include <gtest/gtest.h> + +#include "../SmallTestData.h" + +class BPWriteReadTestADIOS2 : public ::testing::Test +{ +public: + BPWriteReadTestADIOS2() = default; + + SmallTestData m_TestData; +}; + +//****************************************************************************** +// 1D 1x8 test data +//****************************************************************************** + +// ADIOS2 BP write, native ADIOS1 read +TEST_F(BPWriteReadTestADIOS2, ADIOS2BPWriteRead1D8) +{ + // Each process would write a 1x8 array and all processes would + // form a mpiSize * Nx 1D array + const std::string fname("ADIOS2BPWriteRead1D8.bp"); + + int mpiRank = 0, mpiSize = 1; + // Number of rows + const size_t Nx = 8; + + // Number of steps + const size_t NSteps = 3; + +#ifdef ADIOS2_HAVE_MPI + MPI_Comm_rank(MPI_COMM_WORLD, &mpiRank); + MPI_Comm_size(MPI_COMM_WORLD, &mpiSize); +#endif + +// Write test data using BP + +#ifdef ADIOS2_HAVE_MPI + adios2::ADIOS adios(MPI_COMM_WORLD, adios2::DebugON); +#else + adios2::ADIOS adios(true); +#endif + { + adios2::IO &io = adios.DeclareIO("TestIO"); + + // Declare 1D variables (NumOfProcesses * Nx) + // The local process' part (start, count) can be defined now or later + // before Write(). + { + const adios2::Dims shape{static_cast<size_t>(Nx * mpiSize)}; + const adios2::Dims start{static_cast<size_t>(Nx * mpiRank)}; + const adios2::Dims count{Nx}; + + auto &var_iString = io.DefineVariable<std::string>("iString"); + auto &var_i8 = io.DefineVariable<int8_t>("i8", shape, start, count); + auto &var_i16 = + io.DefineVariable<int16_t>("i16", shape, start, count); + auto &var_i32 = + io.DefineVariable<int32_t>("i32", shape, start, count); + auto &var_i64 = + io.DefineVariable<int64_t>("i64", shape, start, count); + auto &var_u8 = + io.DefineVariable<uint8_t>("u8", shape, start, count); + auto &var_u16 = + io.DefineVariable<uint16_t>("u16", shape, start, count); + auto &var_u32 = + io.DefineVariable<uint32_t>("u32", shape, start, count); + auto &var_u64 = + io.DefineVariable<uint64_t>("u64", shape, start, count); + auto &var_r32 = + io.DefineVariable<float>("r32", shape, start, count); + auto &var_r64 = + io.DefineVariable<double>("r64", shape, start, count); + } + + // Create the BP Engine + io.SetEngine("BPFileWriter"); + + io.AddTransport("file"); + + // QUESTION: It seems that BPFilterWriter cannot overwrite existing + // files + // Ex. if you tune Nx and NSteps, the test would fail. But if you clear + // the cache in + // ${adios2Build}/testing/adios2/engine/bp/ADIOS2BPWriteADIOS1Read1D8.bp.dir, + // then it works + adios2::Engine &bpWriter = io.Open(fname, adios2::Mode::Write); + + for (size_t step = 0; step < NSteps; ++step) + { + // Generate test data for each process uniquely + SmallTestData currentTestData = generateNewSmallTestData( + m_TestData, static_cast<int>(step), mpiRank, mpiSize); + + // Retrieve the variables that previously went out of scope + auto &var_iString = *io.InquireVariable<std::string>("iString"); + auto &var_i8 = *io.InquireVariable<int8_t>("i8"); + auto &var_i16 = *io.InquireVariable<int16_t>("i16"); + auto &var_i32 = *io.InquireVariable<int32_t>("i32"); + auto &var_i64 = *io.InquireVariable<int64_t>("i64"); + auto &var_u8 = *io.InquireVariable<uint8_t>("u8"); + auto &var_u16 = *io.InquireVariable<uint16_t>("u16"); + auto &var_u32 = *io.InquireVariable<uint32_t>("u32"); + auto &var_u64 = *io.InquireVariable<uint64_t>("u64"); + auto &var_r32 = *io.InquireVariable<float>("r32"); + auto &var_r64 = *io.InquireVariable<double>("r64"); + + // Make a 1D selection to describe the local dimensions of the + // variable we write and its offsets in the global spaces + adios2::Box<adios2::Dims> sel({mpiRank * Nx}, {Nx}); + + EXPECT_THROW(var_iString.SetSelection(sel), std::invalid_argument); + var_i8.SetSelection(sel); + var_i16.SetSelection(sel); + var_i32.SetSelection(sel); + var_i64.SetSelection(sel); + var_u8.SetSelection(sel); + var_u16.SetSelection(sel); + var_u32.SetSelection(sel); + var_u64.SetSelection(sel); + var_r32.SetSelection(sel); + var_r64.SetSelection(sel); + + // Write each one + // fill in the variable with values from starting index to + // starting index + count + bpWriter.BeginStep(); + bpWriter.PutSync(var_iString, currentTestData.S1); + bpWriter.PutSync(var_i8, currentTestData.I8.data()); + bpWriter.PutSync(var_i16, currentTestData.I16.data()); + bpWriter.PutSync(var_i32, currentTestData.I32.data()); + bpWriter.PutSync(var_i64, currentTestData.I64.data()); + bpWriter.PutSync(var_u8, currentTestData.U8.data()); + bpWriter.PutSync(var_u16, currentTestData.U16.data()); + bpWriter.PutSync(var_u32, currentTestData.U32.data()); + bpWriter.PutSync(var_u64, currentTestData.U64.data()); + bpWriter.PutSync(var_r32, currentTestData.R32.data()); + bpWriter.PutSync(var_r64, currentTestData.R64.data()); + bpWriter.EndStep(); + } + + // Close the file + bpWriter.Close(); + } + + { + adios2::IO &io = adios.DeclareIO("ReadIO"); + + adios2::Engine &bpReader = io.Open(fname, adios2::Mode::Read); + + // auto var_iString = io.InquireVariable<std::string>("iString"); + // ASSERT_NE(var_iString, nullptr); + // ASSERT_EQ(var_iString->m_Shape.size(), 0); + // ASSERT_EQ(var_iString->m_AvailableStepsCount, NSteps); + + auto var_i8 = io.InquireVariable<int8_t>("i8"); + ASSERT_NE(var_i8, nullptr); + ASSERT_EQ(var_i8->m_ShapeID, adios2::ShapeID::GlobalArray); + ASSERT_EQ(var_i8->m_AvailableStepsCount, NSteps); + ASSERT_EQ(var_i8->m_Shape[0], mpiSize * Nx); + + auto var_i16 = io.InquireVariable<int16_t>("i16"); + ASSERT_NE(var_i16, nullptr); + ASSERT_EQ(var_i16->m_ShapeID, adios2::ShapeID::GlobalArray); + ASSERT_EQ(var_i16->m_AvailableStepsCount, NSteps); + ASSERT_EQ(var_i16->m_Shape[0], mpiSize * Nx); + + auto var_i32 = io.InquireVariable<int32_t>("i32"); + ASSERT_NE(var_i32, nullptr); + ASSERT_EQ(var_i32->m_ShapeID, adios2::ShapeID::GlobalArray); + ASSERT_EQ(var_i32->m_AvailableStepsCount, NSteps); + ASSERT_EQ(var_i32->m_Shape[0], mpiSize * Nx); + + auto var_i64 = io.InquireVariable<int64_t>("i64"); + ASSERT_NE(var_i64, nullptr); + ASSERT_EQ(var_i64->m_ShapeID, adios2::ShapeID::GlobalArray); + ASSERT_EQ(var_i64->m_AvailableStepsCount, NSteps); + ASSERT_EQ(var_i64->m_Shape[0], mpiSize * Nx); + + auto var_u8 = io.InquireVariable<uint8_t>("u8"); + ASSERT_NE(var_u8, nullptr); + ASSERT_EQ(var_u8->m_ShapeID, adios2::ShapeID::GlobalArray); + ASSERT_EQ(var_u8->m_AvailableStepsCount, NSteps); + ASSERT_EQ(var_u8->m_Shape[0], mpiSize * Nx); + + auto var_u16 = io.InquireVariable<uint16_t>("u16"); + ASSERT_NE(var_u16, nullptr); + ASSERT_EQ(var_u16->m_ShapeID, adios2::ShapeID::GlobalArray); + ASSERT_EQ(var_u16->m_AvailableStepsCount, NSteps); + ASSERT_EQ(var_u16->m_Shape[0], mpiSize * Nx); + + auto var_u32 = io.InquireVariable<uint32_t>("u32"); + ASSERT_NE(var_u32, nullptr); + ASSERT_EQ(var_u32->m_ShapeID, adios2::ShapeID::GlobalArray); + ASSERT_EQ(var_u32->m_AvailableStepsCount, NSteps); + ASSERT_EQ(var_u32->m_Shape[0], mpiSize * Nx); + + auto var_u64 = io.InquireVariable<uint64_t>("u64"); + ASSERT_NE(var_u64, nullptr); + ASSERT_EQ(var_u64->m_ShapeID, adios2::ShapeID::GlobalArray); + ASSERT_EQ(var_u64->m_AvailableStepsCount, NSteps); + ASSERT_EQ(var_u64->m_Shape[0], mpiSize * Nx); + + auto var_r32 = io.InquireVariable<float>("r32"); + ASSERT_NE(var_r32, nullptr); + ASSERT_EQ(var_r32->m_ShapeID, adios2::ShapeID::GlobalArray); + ASSERT_EQ(var_r32->m_AvailableStepsCount, NSteps); + ASSERT_EQ(var_r32->m_Shape[0], mpiSize * Nx); + + auto var_r64 = io.InquireVariable<double>("r64"); + ASSERT_NE(var_r64, nullptr); + ASSERT_EQ(var_r64->m_ShapeID, adios2::ShapeID::GlobalArray); + ASSERT_EQ(var_r64->m_AvailableStepsCount, NSteps); + ASSERT_EQ(var_r64->m_Shape[0], mpiSize * Nx); + + // TODO: other types + + SmallTestData testData; + std::vector<char> IString(testData.S1.size()); + std::array<int8_t, Nx> I8; + std::array<int16_t, Nx> I16; + std::array<int32_t, Nx> I32; + std::array<int64_t, Nx> I64; + std::array<uint8_t, Nx> U8; + std::array<uint16_t, Nx> U16; + std::array<uint32_t, Nx> U32; + std::array<uint64_t, Nx> U64; + std::array<float, Nx> R32; + std::array<double, Nx> R64; + + const adios2::Dims start{mpiRank * Nx}; + const adios2::Dims count{Nx}; + + const adios2::Box<adios2::Dims> sel(start, count); + + var_i8->SetSelection(sel); + var_i16->SetSelection(sel); + var_i32->SetSelection(sel); + var_i64->SetSelection(sel); + + var_u8->SetSelection(sel); + var_u16->SetSelection(sel); + var_u32->SetSelection(sel); + var_u64->SetSelection(sel); + + var_r32->SetSelection(sel); + var_r64->SetSelection(sel); + + for (size_t t = 0; t < NSteps; ++t) + { + var_i8->SetStepSelection({t + 1, 1}); + var_i16->SetStepSelection({t + 1, 1}); + var_i32->SetStepSelection({t + 1, 1}); + var_i64->SetStepSelection({t + 1, 1}); + + var_u8->SetStepSelection({t + 1, 1}); + var_u16->SetStepSelection({t + 1, 1}); + var_u32->SetStepSelection({t + 1, 1}); + var_u64->SetStepSelection({t + 1, 1}); + + var_r32->SetStepSelection({t + 1, 1}); + var_r64->SetStepSelection({t + 1, 1}); + + // Generate test data for each rank uniquely + SmallTestData currentTestData = generateNewSmallTestData( + m_TestData, static_cast<int>(t), mpiRank, mpiSize); + + bpReader.GetDeferred(*var_i8, I8.data()); + bpReader.GetDeferred(*var_i16, I16.data()); + bpReader.GetDeferred(*var_i32, I32.data()); + bpReader.GetDeferred(*var_i64, I64.data()); + + bpReader.GetDeferred(*var_u8, U8.data()); + bpReader.GetDeferred(*var_u16, U16.data()); + bpReader.GetDeferred(*var_u32, U32.data()); + bpReader.GetDeferred(*var_u64, U64.data()); + + bpReader.GetDeferred(*var_r32, R32.data()); + bpReader.GetDeferred(*var_r64, R64.data()); + + bpReader.PerformGets(); + + for (size_t i = 0; i < Nx; ++i) + { + std::stringstream ss; + ss << "t=" << t << " i=" << i << " rank=" << mpiRank; + std::string msg = ss.str(); + + EXPECT_EQ(I8[i], currentTestData.I8[i]) << msg; + EXPECT_EQ(I16[i], currentTestData.I16[i]) << msg; + EXPECT_EQ(I32[i], currentTestData.I32[i]) << msg; + EXPECT_EQ(I64[i], currentTestData.I64[i]) << msg; + EXPECT_EQ(U8[i], currentTestData.U8[i]) << msg; + EXPECT_EQ(U16[i], currentTestData.U16[i]) << msg; + EXPECT_EQ(U32[i], currentTestData.U32[i]) << msg; + EXPECT_EQ(U64[i], currentTestData.U64[i]) << msg; + EXPECT_EQ(R32[i], currentTestData.R32[i]) << msg; + EXPECT_EQ(R64[i], currentTestData.R64[i]) << msg; + } + } + bpReader.Close(); + } +} + +//****************************************************************************** +// 2D 2x4 test data +//****************************************************************************** + +// ADIOS2 BP write, native ADIOS1 read +TEST_F(BPWriteReadTestADIOS2, ADIOS2BPWriteRead2D2x4) +{ + // Each process would write a 2x4 array and all processes would + // form a 2D 2 * (numberOfProcess*Nx) matrix where Nx is 4 here + const std::string fname("ADIOS2BPWriteRead2D2x4Test.bp"); + + int mpiRank = 0, mpiSize = 1; + // Number of rows + const std::size_t Nx = 4; + + // Number of rows + const std::size_t Ny = 2; + + // Number of steps + const std::size_t NSteps = 3; + +#ifdef ADIOS2_HAVE_MPI + MPI_Comm_rank(MPI_COMM_WORLD, &mpiRank); + MPI_Comm_size(MPI_COMM_WORLD, &mpiSize); +#endif + +// Write test data using ADIOS2 + +#ifdef ADIOS2_HAVE_MPI + adios2::ADIOS adios(MPI_COMM_WORLD, adios2::DebugON); +#else + adios2::ADIOS adios(true); +#endif + { + adios2::IO &io = adios.DeclareIO("TestIO"); + + // Declare 2D variables (Ny * (NumOfProcesses * Nx)) + // The local process' part (start, count) can be defined now or later + // before Write(). + { + const adios2::Dims shape{Ny, static_cast<size_t>(Nx * mpiSize)}; + const adios2::Dims start{0, static_cast<size_t>(mpiRank * Nx)}; + const adios2::Dims count{Ny, Nx}; + + auto &var_i8 = io.DefineVariable<int8_t>("i8", shape, start, count); + auto &var_i16 = + io.DefineVariable<int16_t>("i16", shape, start, count); + auto &var_i32 = + io.DefineVariable<int32_t>("i32", shape, start, count); + auto &var_i64 = + io.DefineVariable<int64_t>("i64", shape, start, count); + auto &var_u8 = + io.DefineVariable<uint8_t>("u8", shape, start, count); + auto &var_u16 = + io.DefineVariable<uint16_t>("u16", shape, start, count); + auto &var_u32 = + io.DefineVariable<uint32_t>("u32", shape, start, count); + auto &var_u64 = + io.DefineVariable<uint64_t>("u64", shape, start, count); + auto &var_r32 = + io.DefineVariable<float>("r32", shape, start, count); + auto &var_r64 = + io.DefineVariable<double>("r64", shape, start, count); + } + + // Create the BP Engine + io.SetEngine("BPFileWriter"); + io.AddTransport("file"); + + adios2::Engine &bpWriter = io.Open(fname, adios2::Mode::Write); + + for (size_t step = 0; step < NSteps; ++step) + { + // Generate test data for each process uniquely + SmallTestData currentTestData = generateNewSmallTestData( + m_TestData, static_cast<int>(step), mpiRank, mpiSize); + + // Retrieve the variables that previously went out of scope + auto &var_i8 = *io.InquireVariable<int8_t>("i8"); + auto &var_i16 = *io.InquireVariable<int16_t>("i16"); + auto &var_i32 = *io.InquireVariable<int32_t>("i32"); + auto &var_i64 = *io.InquireVariable<int64_t>("i64"); + auto &var_u8 = *io.InquireVariable<uint8_t>("u8"); + auto &var_u16 = *io.InquireVariable<uint16_t>("u16"); + auto &var_u32 = *io.InquireVariable<uint32_t>("u32"); + auto &var_u64 = *io.InquireVariable<uint64_t>("u64"); + auto &var_r32 = *io.InquireVariable<float>("r32"); + auto &var_r64 = *io.InquireVariable<double>("r64"); + + // Make a 2D selection to describe the local dimensions of the + // variable we write and its offsets in the global spaces + adios2::Box<adios2::Dims> sel( + {0, static_cast<size_t>(mpiRank * Nx)}, {Ny, Nx}); + var_i8.SetSelection(sel); + var_i16.SetSelection(sel); + var_i32.SetSelection(sel); + var_i64.SetSelection(sel); + var_u8.SetSelection(sel); + var_u16.SetSelection(sel); + var_u32.SetSelection(sel); + var_u64.SetSelection(sel); + var_r32.SetSelection(sel); + var_r64.SetSelection(sel); + + // Write each one + // fill in the variable with values from starting index to + // starting index + count + bpWriter.BeginStep(); + bpWriter.PutSync(var_i8, currentTestData.I8.data()); + bpWriter.PutSync(var_i16, currentTestData.I16.data()); + bpWriter.PutSync(var_i32, currentTestData.I32.data()); + bpWriter.PutSync(var_i64, currentTestData.I64.data()); + bpWriter.PutSync(var_u8, currentTestData.U8.data()); + bpWriter.PutSync(var_u16, currentTestData.U16.data()); + bpWriter.PutSync(var_u32, currentTestData.U32.data()); + bpWriter.PutSync(var_u64, currentTestData.U64.data()); + bpWriter.PutSync(var_r32, currentTestData.R32.data()); + bpWriter.PutSync(var_r64, currentTestData.R64.data()); + bpWriter.EndStep(); + } + + // Close the file + bpWriter.Close(); + } + + { + adios2::IO &io = adios.DeclareIO("ReadIO"); + + adios2::Engine &bpReader = io.Open(fname, adios2::Mode::Read); + + auto var_i8 = io.InquireVariable<int8_t>("i8"); + ASSERT_NE(var_i8, nullptr); + ASSERT_EQ(var_i8->m_ShapeID, adios2::ShapeID::GlobalArray); + ASSERT_EQ(var_i8->m_AvailableStepsCount, NSteps); + ASSERT_EQ(var_i8->m_Shape[0], Ny); + ASSERT_EQ(var_i8->m_Shape[1], static_cast<size_t>(mpiSize * Nx)); + + auto var_i16 = io.InquireVariable<int16_t>("i16"); + ASSERT_NE(var_i16, nullptr); + ASSERT_EQ(var_i16->m_ShapeID, adios2::ShapeID::GlobalArray); + ASSERT_EQ(var_i16->m_AvailableStepsCount, NSteps); + ASSERT_EQ(var_i16->m_Shape[0], Ny); + ASSERT_EQ(var_i16->m_Shape[1], static_cast<size_t>(mpiSize * Nx)); + + auto var_i32 = io.InquireVariable<int32_t>("i32"); + ASSERT_NE(var_i32, nullptr); + ASSERT_EQ(var_i32->m_ShapeID, adios2::ShapeID::GlobalArray); + ASSERT_EQ(var_i32->m_AvailableStepsCount, NSteps); + ASSERT_EQ(var_i32->m_Shape[0], Ny); + ASSERT_EQ(var_i32->m_Shape[1], static_cast<size_t>(mpiSize * Nx)); + + auto var_i64 = io.InquireVariable<int64_t>("i64"); + ASSERT_NE(var_i64, nullptr); + ASSERT_EQ(var_i64->m_ShapeID, adios2::ShapeID::GlobalArray); + ASSERT_EQ(var_i64->m_AvailableStepsCount, NSteps); + ASSERT_EQ(var_i64->m_Shape[0], Ny); + ASSERT_EQ(var_i64->m_Shape[1], static_cast<size_t>(mpiSize * Nx)); + + auto var_u8 = io.InquireVariable<uint8_t>("u8"); + ASSERT_NE(var_u8, nullptr); + ASSERT_EQ(var_u8->m_ShapeID, adios2::ShapeID::GlobalArray); + ASSERT_EQ(var_u8->m_AvailableStepsCount, NSteps); + ASSERT_EQ(var_u8->m_Shape[0], Ny); + ASSERT_EQ(var_u8->m_Shape[1], static_cast<size_t>(mpiSize * Nx)); + + auto var_u16 = io.InquireVariable<uint16_t>("u16"); + ASSERT_NE(var_u16, nullptr); + ASSERT_EQ(var_u16->m_ShapeID, adios2::ShapeID::GlobalArray); + ASSERT_EQ(var_u16->m_AvailableStepsCount, NSteps); + ASSERT_EQ(var_u16->m_Shape[0], Ny); + ASSERT_EQ(var_u16->m_Shape[1], static_cast<size_t>(mpiSize * Nx)); + + auto var_u32 = io.InquireVariable<uint32_t>("u32"); + ASSERT_NE(var_u32, nullptr); + ASSERT_EQ(var_u32->m_ShapeID, adios2::ShapeID::GlobalArray); + ASSERT_EQ(var_u32->m_AvailableStepsCount, NSteps); + ASSERT_EQ(var_u32->m_Shape[0], Ny); + ASSERT_EQ(var_u32->m_Shape[1], static_cast<size_t>(mpiSize * Nx)); + + auto var_u64 = io.InquireVariable<uint64_t>("u64"); + ASSERT_NE(var_u64, nullptr); + ASSERT_EQ(var_u64->m_ShapeID, adios2::ShapeID::GlobalArray); + ASSERT_EQ(var_u64->m_AvailableStepsCount, NSteps); + ASSERT_EQ(var_u64->m_Shape[0], Ny); + ASSERT_EQ(var_u64->m_Shape[1], static_cast<size_t>(mpiSize * Nx)); + + auto var_r32 = io.InquireVariable<float>("r32"); + ASSERT_NE(var_r32, nullptr); + ASSERT_EQ(var_r32->m_ShapeID, adios2::ShapeID::GlobalArray); + ASSERT_EQ(var_r32->m_AvailableStepsCount, NSteps); + ASSERT_EQ(var_r32->m_Shape[0], Ny); + ASSERT_EQ(var_r32->m_Shape[1], static_cast<size_t>(mpiSize * Nx)); + + auto var_r64 = io.InquireVariable<double>("r64"); + ASSERT_NE(var_r64, nullptr); + ASSERT_EQ(var_r64->m_ShapeID, adios2::ShapeID::GlobalArray); + ASSERT_EQ(var_r64->m_AvailableStepsCount, NSteps); + ASSERT_EQ(var_r64->m_Shape[0], Ny); + ASSERT_EQ(var_r64->m_Shape[1], static_cast<size_t>(mpiSize * Nx)); + + // If the size of the array is smaller than the data + // the result is weird... double and uint64_t would get + // completely garbage data + std::array<int8_t, Nx * Ny> I8; + std::array<int16_t, Nx * Ny> I16; + std::array<int32_t, Nx * Ny> I32; + std::array<int64_t, Nx * Ny> I64; + std::array<uint8_t, Nx * Ny> U8; + std::array<uint16_t, Nx * Ny> U16; + std::array<uint32_t, Nx * Ny> U32; + std::array<uint64_t, Nx * Ny> U64; + std::array<float, Nx * Ny> R32; + std::array<double, Nx * Ny> R64; + + const adios2::Dims start{0, static_cast<size_t>(mpiRank * Nx)}; + const adios2::Dims count{Ny, Nx}; + + const adios2::Box<adios2::Dims> sel(start, count); + + var_i8->SetSelection(sel); + var_i16->SetSelection(sel); + var_i32->SetSelection(sel); + var_i64->SetSelection(sel); + + var_u8->SetSelection(sel); + var_u16->SetSelection(sel); + var_u32->SetSelection(sel); + var_u64->SetSelection(sel); + + var_r32->SetSelection(sel); + var_r64->SetSelection(sel); + + for (size_t t = 0; t < NSteps; ++t) + { + var_i8->SetStepSelection({t + 1, 1}); + var_i16->SetStepSelection({t + 1, 1}); + var_i32->SetStepSelection({t + 1, 1}); + var_i64->SetStepSelection({t + 1, 1}); + + var_u8->SetStepSelection({t + 1, 1}); + var_u16->SetStepSelection({t + 1, 1}); + var_u32->SetStepSelection({t + 1, 1}); + var_u64->SetStepSelection({t + 1, 1}); + + var_r32->SetStepSelection({t + 1, 1}); + var_r64->SetStepSelection({t + 1, 1}); + + bpReader.GetDeferred(*var_i8, I8.data()); + bpReader.GetDeferred(*var_i16, I16.data()); + bpReader.GetDeferred(*var_i32, I32.data()); + bpReader.GetDeferred(*var_i64, I64.data()); + + bpReader.GetDeferred(*var_u8, U8.data()); + bpReader.GetDeferred(*var_u16, U16.data()); + bpReader.GetDeferred(*var_u32, U32.data()); + bpReader.GetDeferred(*var_u64, U64.data()); + + bpReader.GetDeferred(*var_r32, R32.data()); + bpReader.GetDeferred(*var_r64, R64.data()); + + bpReader.PerformGets(); + + // Generate test data for each rank uniquely + SmallTestData currentTestData = generateNewSmallTestData( + m_TestData, static_cast<int>(t), mpiRank, mpiSize); + + for (size_t i = 0; i < Nx * Ny; ++i) + { + std::stringstream ss; + ss << "t=" << t << " i=" << i << " rank=" << mpiRank; + std::string msg = ss.str(); + + EXPECT_EQ(I8[i], currentTestData.I8[i]) << msg; + EXPECT_EQ(I16[i], currentTestData.I16[i]) << msg; + EXPECT_EQ(I32[i], currentTestData.I32[i]) << msg; + EXPECT_EQ(I64[i], currentTestData.I64[i]) << msg; + EXPECT_EQ(U8[i], currentTestData.U8[i]) << msg; + EXPECT_EQ(U16[i], currentTestData.U16[i]) << msg; + EXPECT_EQ(U32[i], currentTestData.U32[i]) << msg; + EXPECT_EQ(U64[i], currentTestData.U64[i]) << msg; + EXPECT_EQ(R32[i], currentTestData.R32[i]) << msg; + EXPECT_EQ(R64[i], currentTestData.R64[i]) << msg; + } + } + bpReader.Close(); + } +} + +//****************************************************************************** +// 2D 4x2 test data +//****************************************************************************** + +TEST_F(BPWriteReadTestADIOS2, ADIOS2BPWriteRead2D4x2) +{ + // Each process would write a 4x2 array and all processes would + // form a 2D 4 * (NumberOfProcess * Nx) matrix where Nx is 2 here + const std::string fname("ADIOS2BPWriteRead2D4x2Test.bp"); + + int mpiRank = 0, mpiSize = 1; + // Number of rows + const std::size_t Nx = 2; + // Number of cols + const std::size_t Ny = 4; + + // Number of steps + const std::size_t NSteps = 3; + +#ifdef ADIOS2_HAVE_MPI + MPI_Comm_rank(MPI_COMM_WORLD, &mpiRank); + MPI_Comm_size(MPI_COMM_WORLD, &mpiSize); +#endif + +// Write test data using ADIOS2 + +#ifdef ADIOS2_HAVE_MPI + adios2::ADIOS adios(MPI_COMM_WORLD, adios2::DebugON); +#else + adios2::ADIOS adios(true); +#endif + { + adios2::IO &io = adios.DeclareIO("TestIO"); + + // Declare 2D variables (4 * (NumberOfProcess * Nx)) + // The local process' part (start, count) can be defined now or later + // before Write(). + { + adios2::Dims shape{static_cast<unsigned int>(Ny), + static_cast<unsigned int>(mpiSize * Nx)}; + adios2::Dims start{static_cast<unsigned int>(0), + static_cast<unsigned int>(mpiRank * Nx)}; + adios2::Dims count{static_cast<unsigned int>(Ny), + static_cast<unsigned int>(Nx)}; + auto &var_i8 = io.DefineVariable<int8_t>("i8", shape, start, count); + auto &var_i16 = + io.DefineVariable<int16_t>("i16", shape, start, count); + auto &var_i32 = + io.DefineVariable<int32_t>("i32", shape, start, count); + auto &var_i64 = + io.DefineVariable<int64_t>("i64", shape, start, count); + auto &var_u8 = + io.DefineVariable<uint8_t>("u8", shape, start, count); + auto &var_u16 = + io.DefineVariable<uint16_t>("u16", shape, start, count); + auto &var_u32 = + io.DefineVariable<uint32_t>("u32", shape, start, count); + auto &var_u64 = + io.DefineVariable<uint64_t>("u64", shape, start, count); + auto &var_r32 = + io.DefineVariable<float>("r32", shape, start, count); + auto &var_r64 = + io.DefineVariable<double>("r64", shape, start, count); + } + + // Create the BP Engine + io.SetEngine("BPFileWriter"); + + io.AddTransport("file"); + + adios2::Engine &bpWriter = io.Open(fname, adios2::Mode::Write); + + for (size_t step = 0; step < NSteps; ++step) + { + // Generate test data for each process uniquely + SmallTestData currentTestData = generateNewSmallTestData( + m_TestData, static_cast<int>(step), mpiRank, mpiSize); + + // Retrieve the variables that previously went out of scope + auto &var_i8 = *io.InquireVariable<int8_t>("i8"); + auto &var_i16 = *io.InquireVariable<int16_t>("i16"); + auto &var_i32 = *io.InquireVariable<int32_t>("i32"); + auto &var_i64 = *io.InquireVariable<int64_t>("i64"); + auto &var_u8 = *io.InquireVariable<uint8_t>("u8"); + auto &var_u16 = *io.InquireVariable<uint16_t>("u16"); + auto &var_u32 = *io.InquireVariable<uint32_t>("u32"); + auto &var_u64 = *io.InquireVariable<uint64_t>("u64"); + auto &var_r32 = *io.InquireVariable<float>("r32"); + auto &var_r64 = *io.InquireVariable<double>("r64"); + + // Make a 2D selection to describe the local dimensions of the + // variable we write and its offsets in the global spaces + adios2::Box<adios2::Dims> sel( + {0, static_cast<unsigned int>(mpiRank * Nx)}, {Ny, Nx}); + var_i8.SetSelection(sel); + var_i16.SetSelection(sel); + var_i32.SetSelection(sel); + var_i64.SetSelection(sel); + var_u8.SetSelection(sel); + var_u16.SetSelection(sel); + var_u32.SetSelection(sel); + var_u64.SetSelection(sel); + var_r32.SetSelection(sel); + var_r64.SetSelection(sel); + + // Write each one + // fill in the variable with values from starting index to + // starting index + count + bpWriter.BeginStep(); + bpWriter.PutSync(var_i8, currentTestData.I8.data()); + bpWriter.PutSync(var_i16, currentTestData.I16.data()); + bpWriter.PutSync(var_i32, currentTestData.I32.data()); + bpWriter.PutSync(var_i64, currentTestData.I64.data()); + bpWriter.PutSync(var_u8, currentTestData.U8.data()); + bpWriter.PutSync(var_u16, currentTestData.U16.data()); + bpWriter.PutSync(var_u32, currentTestData.U32.data()); + bpWriter.PutSync(var_u64, currentTestData.U64.data()); + bpWriter.PutSync(var_r32, currentTestData.R32.data()); + bpWriter.PutSync(var_r64, currentTestData.R64.data()); + bpWriter.EndStep(); + } + + // Close the file + bpWriter.Close(); + } + + { + adios2::IO &io = adios.DeclareIO("ReadIO"); + + adios2::Engine &bpReader = io.Open(fname, adios2::Mode::Read); + + auto var_i8 = io.InquireVariable<int8_t>("i8"); + ASSERT_NE(var_i8, nullptr); + ASSERT_EQ(var_i8->m_ShapeID, adios2::ShapeID::GlobalArray); + ASSERT_EQ(var_i8->m_AvailableStepsCount, NSteps); + ASSERT_EQ(var_i8->m_Shape[0], Ny); + ASSERT_EQ(var_i8->m_Shape[1], static_cast<size_t>(mpiSize * Nx)); + + auto var_i16 = io.InquireVariable<int16_t>("i16"); + ASSERT_NE(var_i16, nullptr); + ASSERT_EQ(var_i16->m_ShapeID, adios2::ShapeID::GlobalArray); + ASSERT_EQ(var_i16->m_AvailableStepsCount, NSteps); + ASSERT_EQ(var_i16->m_Shape[0], Ny); + ASSERT_EQ(var_i16->m_Shape[1], static_cast<size_t>(mpiSize * Nx)); + + auto var_i32 = io.InquireVariable<int32_t>("i32"); + ASSERT_NE(var_i32, nullptr); + ASSERT_EQ(var_i32->m_ShapeID, adios2::ShapeID::GlobalArray); + ASSERT_EQ(var_i32->m_AvailableStepsCount, NSteps); + ASSERT_EQ(var_i32->m_Shape[0], Ny); + ASSERT_EQ(var_i32->m_Shape[1], static_cast<size_t>(mpiSize * Nx)); + + auto var_i64 = io.InquireVariable<int64_t>("i64"); + ASSERT_NE(var_i64, nullptr); + ASSERT_EQ(var_i64->m_ShapeID, adios2::ShapeID::GlobalArray); + ASSERT_EQ(var_i64->m_AvailableStepsCount, NSteps); + ASSERT_EQ(var_i64->m_Shape[0], Ny); + ASSERT_EQ(var_i64->m_Shape[1], static_cast<size_t>(mpiSize * Nx)); + + auto var_u8 = io.InquireVariable<uint8_t>("u8"); + ASSERT_NE(var_u8, nullptr); + ASSERT_EQ(var_u8->m_ShapeID, adios2::ShapeID::GlobalArray); + ASSERT_EQ(var_u8->m_AvailableStepsCount, NSteps); + ASSERT_EQ(var_u8->m_Shape[0], Ny); + ASSERT_EQ(var_u8->m_Shape[1], static_cast<size_t>(mpiSize * Nx)); + + auto var_u16 = io.InquireVariable<uint16_t>("u16"); + ASSERT_NE(var_u16, nullptr); + ASSERT_EQ(var_u16->m_ShapeID, adios2::ShapeID::GlobalArray); + ASSERT_EQ(var_u16->m_AvailableStepsCount, NSteps); + ASSERT_EQ(var_u16->m_Shape[0], Ny); + ASSERT_EQ(var_u16->m_Shape[1], static_cast<size_t>(mpiSize * Nx)); + + auto var_u32 = io.InquireVariable<uint32_t>("u32"); + ASSERT_NE(var_u32, nullptr); + ASSERT_EQ(var_u32->m_ShapeID, adios2::ShapeID::GlobalArray); + ASSERT_EQ(var_u32->m_AvailableStepsCount, NSteps); + ASSERT_EQ(var_u32->m_Shape[0], Ny); + ASSERT_EQ(var_u32->m_Shape[1], static_cast<size_t>(mpiSize * Nx)); + + auto var_u64 = io.InquireVariable<uint64_t>("u64"); + ASSERT_NE(var_u64, nullptr); + ASSERT_EQ(var_u64->m_ShapeID, adios2::ShapeID::GlobalArray); + ASSERT_EQ(var_u64->m_AvailableStepsCount, NSteps); + ASSERT_EQ(var_u64->m_Shape[0], Ny); + ASSERT_EQ(var_u64->m_Shape[1], static_cast<size_t>(mpiSize * Nx)); + + auto var_r32 = io.InquireVariable<float>("r32"); + ASSERT_NE(var_r32, nullptr); + ASSERT_EQ(var_r32->m_ShapeID, adios2::ShapeID::GlobalArray); + ASSERT_EQ(var_r32->m_AvailableStepsCount, NSteps); + ASSERT_EQ(var_r32->m_Shape[0], Ny); + ASSERT_EQ(var_r32->m_Shape[1], static_cast<size_t>(mpiSize * Nx)); + + auto var_r64 = io.InquireVariable<double>("r64"); + ASSERT_NE(var_r64, nullptr); + ASSERT_EQ(var_r64->m_ShapeID, adios2::ShapeID::GlobalArray); + ASSERT_EQ(var_r64->m_AvailableStepsCount, NSteps); + ASSERT_EQ(var_r64->m_Shape[0], Ny); + ASSERT_EQ(var_r64->m_Shape[1], static_cast<size_t>(mpiSize * Nx)); + + // If the size of the array is smaller than the data + // the result is weird... double and uint64_t would get + // completely garbage data + std::array<int8_t, Nx * Ny> I8; + std::array<int16_t, Nx * Ny> I16; + std::array<int32_t, Nx * Ny> I32; + std::array<int64_t, Nx * Ny> I64; + std::array<uint8_t, Nx * Ny> U8; + std::array<uint16_t, Nx * Ny> U16; + std::array<uint32_t, Nx * Ny> U32; + std::array<uint64_t, Nx * Ny> U64; + std::array<float, Nx * Ny> R32; + std::array<double, Nx * Ny> R64; + + const adios2::Dims start{0, static_cast<size_t>(mpiRank * Nx)}; + const adios2::Dims count{Ny, Nx}; + + const adios2::Box<adios2::Dims> sel(start, count); + + var_i8->SetSelection(sel); + var_i16->SetSelection(sel); + var_i32->SetSelection(sel); + var_i64->SetSelection(sel); + + var_u8->SetSelection(sel); + var_u16->SetSelection(sel); + var_u32->SetSelection(sel); + var_u64->SetSelection(sel); + + var_r32->SetSelection(sel); + var_r64->SetSelection(sel); + + for (size_t t = 0; t < NSteps; ++t) + { + var_i8->SetStepSelection({t + 1, 1}); + var_i16->SetStepSelection({t + 1, 1}); + var_i32->SetStepSelection({t + 1, 1}); + var_i64->SetStepSelection({t + 1, 1}); + + var_u8->SetStepSelection({t + 1, 1}); + var_u16->SetStepSelection({t + 1, 1}); + var_u32->SetStepSelection({t + 1, 1}); + var_u64->SetStepSelection({t + 1, 1}); + + var_r32->SetStepSelection({t + 1, 1}); + var_r64->SetStepSelection({t + 1, 1}); + + bpReader.GetDeferred(*var_i8, I8.data()); + bpReader.GetDeferred(*var_i16, I16.data()); + bpReader.GetDeferred(*var_i32, I32.data()); + bpReader.GetDeferred(*var_i64, I64.data()); + + bpReader.GetDeferred(*var_u8, U8.data()); + bpReader.GetDeferred(*var_u16, U16.data()); + bpReader.GetDeferred(*var_u32, U32.data()); + bpReader.GetDeferred(*var_u64, U64.data()); + + bpReader.GetDeferred(*var_r32, R32.data()); + bpReader.GetDeferred(*var_r64, R64.data()); + + bpReader.PerformGets(); + + // Generate test data for each rank uniquely + SmallTestData currentTestData = generateNewSmallTestData( + m_TestData, static_cast<int>(t), mpiRank, mpiSize); + + for (size_t i = 0; i < Nx * Ny; ++i) + { + std::stringstream ss; + ss << "t=" << t << " i=" << i << " rank=" << mpiRank; + std::string msg = ss.str(); + + EXPECT_EQ(I8[i], currentTestData.I8[i]) << msg; + EXPECT_EQ(I16[i], currentTestData.I16[i]) << msg; + EXPECT_EQ(I32[i], currentTestData.I32[i]) << msg; + EXPECT_EQ(I64[i], currentTestData.I64[i]) << msg; + EXPECT_EQ(U8[i], currentTestData.U8[i]) << msg; + EXPECT_EQ(U16[i], currentTestData.U16[i]) << msg; + EXPECT_EQ(U32[i], currentTestData.U32[i]) << msg; + EXPECT_EQ(U64[i], currentTestData.U64[i]) << msg; + EXPECT_EQ(R32[i], currentTestData.R32[i]) << msg; + EXPECT_EQ(R64[i], currentTestData.R64[i]) << msg; + } + } + bpReader.Close(); + } +} + +//****************************************************************************** +// main +//****************************************************************************** + +int main(int argc, char **argv) +{ +#ifdef ADIOS2_HAVE_MPI + MPI_Init(nullptr, nullptr); +#endif + + ::testing::InitGoogleTest(&argc, argv); + int result = RUN_ALL_TESTS(); + +#ifdef ADIOS2_HAVE_MPI + MPI_Finalize(); +#endif + + return result; +}