From 656f627df44ff9325a1b44fcca4bb68a668b9a8c Mon Sep 17 00:00:00 2001 From: William F Godoy <williamfgc@yahoo.com> Date: Wed, 9 Aug 2017 17:14:20 -0400 Subject: [PATCH] ReadMe.md, tests and cmake infrastructure Added GetVariableBase* in IO needed by C bindings and real-time applications, nullptr is a valid state in return. Added c bindings test under testing/adios2/bindings/c Updating ReadMe.md to include ADIOS2_USE_C for C bindings --- ReadMe.md | 2 + bindings/c/Makefile | 17 --- bindings/c/adios2/adios2_c_enums.h | 2 + bindings/c/adios2_c.cpp | 14 +++ bindings/c/adios2_c.h | 49 ++++---- source/adios2/core/IO.cpp | 22 ++++ source/adios2/core/IO.h | 8 ++ testing/adios2/bindings/CMakeLists.txt | 4 + testing/adios2/bindings/c/CMakeLists.txt | 17 +++ testing/adios2/bindings/c/SmallTestData_c.h | 36 ++++++ testing/adios2/bindings/c/TestBPWriteTypes.c | 106 ++++++++++++++++++ .../bindings/c/TestBPWriteTypes_nompi.c | 96 ++++++++++++++++ testing/adios2/engine/SmallTestData.h | 2 + 13 files changed, 338 insertions(+), 37 deletions(-) delete mode 100644 bindings/c/Makefile create mode 100644 testing/adios2/bindings/c/CMakeLists.txt create mode 100644 testing/adios2/bindings/c/SmallTestData_c.h create mode 100644 testing/adios2/bindings/c/TestBPWriteTypes.c create mode 100644 testing/adios2/bindings/c/TestBPWriteTypes_nompi.c diff --git a/ReadMe.md b/ReadMe.md index 5781eadd3..273e623d1 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -72,6 +72,7 @@ ADIOS2 build configuration: HDF5 : ON ADIOS1 : OFF Python : ON + C : ON SysVShMem: ON -- Configuring done @@ -92,6 +93,7 @@ The following options can be specified with CMake's `-DVAR=VALUE` syntax to cont | `ADIOS2_USE_HDF5` | **`AUTO`**/``ON``/``OFF`` | Enable the [HDF5](https://www.hdfgroup.org) engine. | | `ADIOS2_USE_ADIOS1` | **`AUTO`**/``ON``/``OFF`` | Enable the [ADIOS 1.x](https://www.olcf.ornl.gov/center-projects/adios/) engine. | | `ADIOS2_USE_Python` | **`AUTO`**/``ON``/``OFF`` | Enable the Python >= 2.7 bindings. | +| `ADIOS2_USE_C` | **`AUTO`**/``ON``/``OFF`` | Enable the C bindings library libadios2_c.so or libadios2_c.a | Note: The `ADIOS2_USE_HDF5` and `ADIOS2_USE_ADIOS1` options require the use of a matching serial or parallel version depending on whether `ADIOS2_USE_MPI` is enabled. SImilary, enabling MPI and Python bindings requires the presence of `mpi4py`. diff --git a/bindings/c/Makefile b/bindings/c/Makefile deleted file mode 100644 index 2ee447c4b..000000000 --- a/bindings/c/Makefile +++ /dev/null @@ -1,17 +0,0 @@ - - -CXX=mpic++ -CXXFLAGS=-O0 -g -Wall -std=c++11 -fPIC -BASE=adios2_c - -ADIOS2_DIR=/home/wfg/tmp/adios2 - -all: $(BASE).h $(BASE).o $(BASE)_enums.h - $(CXX) -shared $(BASE).o -o libadios2_c.so -I./ -I$(ADIOS2_DIR)/include -L$(ADIOS2_DIR)/lib -ladios2 -ldataman - - -$(BASE).o: $(BASE).cpp - $(CXX) $(CXXFLAGS) $(BASE).cpp -c -I./ -I$(ADIOS2_DIR)/include - -clean: - rm libadios2_c.so $(BASE).o \ No newline at end of file diff --git a/bindings/c/adios2/adios2_c_enums.h b/bindings/c/adios2/adios2_c_enums.h index c10474464..4e00527ef 100644 --- a/bindings/c/adios2/adios2_c_enums.h +++ b/bindings/c/adios2/adios2_c_enums.h @@ -29,6 +29,8 @@ typedef enum { adios2_type_string, adios2_type_char, + adios2_type_signed_char, + adios2_type_short, adios2_type_int, adios2_type_long_int, diff --git a/bindings/c/adios2_c.cpp b/bindings/c/adios2_c.cpp index 432a3dac4..0e282216a 100644 --- a/bindings/c/adios2_c.cpp +++ b/bindings/c/adios2_c.cpp @@ -91,6 +91,12 @@ adios2_define_variable(adios2_IO *io, const char *name, const adios2_type type, name, shapeV, startV, countV, constantSizeBool)); break; + case (adios2_type_signed_char): + variable = dynamic_cast<adios2::Variable<signed char> *>( + &ioCpp.DefineVariable<char>(name, shapeV, startV, countV, + constantSizeBool)); + break; + case (adios2_type_short): variable = dynamic_cast<adios2::Variable<short> *>( &ioCpp.DefineVariable<short>(name, shapeV, startV, countV, @@ -222,6 +228,14 @@ adios2_define_variable(adios2_IO *io, const char *name, const adios2_type type, return reinterpret_cast<adios2_Variable *>(variable); } +adios2_Variable *adios2_get_variable(adios2_IO *io, const char *name) +{ + adios2::VariableBase *variable = + reinterpret_cast<adios2::IO *>(io)->GetVariableBase(name); + + return reinterpret_cast<adios2_Variable *>(variable); +} + void adios2_set_engine(adios2_IO *io, const char *engine_type) { reinterpret_cast<adios2::IO *>(io)->SetEngine(engine_type); diff --git a/bindings/c/adios2_c.h b/bindings/c/adios2_c.h index c0d94164e..2e85b9dc4 100644 --- a/bindings/c/adios2_c.h +++ b/bindings/c/adios2_c.h @@ -76,26 +76,6 @@ adios2_ADIOS *adios2_init_nompi(const adios2_debug_mode debug_mode); */ adios2_IO *adios2_declare_io(adios2_ADIOS *adios, const char *io_name); -/** - * - * @param io handler that owns the variable - * @param name unique variable name inside IO handler - * @param type primitive type - * @param ndims number of dimensions - * @param shape total MPI dimensions - * @param start local MPI start (offset) - * @param count local MPI count - * @param constant_size adios2_constant_dims_true: shape, start and count are - * constant, or - * adios2_constant_size_false - * @return variable handler - */ -adios2_Variable * -adios2_define_variable(adios2_IO *io, const char *name, const adios2_type type, - const size_t ndims, const size_t *shape, - const size_t *start, const size_t *count, - const adios2_constant_dims constant_dims); - /** * Sets engine type for current io handler * @param io handler @@ -132,6 +112,35 @@ void adios2_set_transport_param(adios2_IO *io, const unsigned int transport_index, const char *key, const char *value); +/** + * + * @param io handler that owns the variable + * @param name unique variable name inside IO handler + * @param type primitive type + * @param ndims number of dimensions + * @param shape total MPI dimensions + * @param start local MPI start (offset) + * @param count local MPI count + * @param constant_size adios2_constant_dims_true: shape, start and count are + * constant, or + * adios2_constant_size_false + * @return variable handler + */ +adios2_Variable * +adios2_define_variable(adios2_IO *io, const char *name, const adios2_type type, + const size_t ndims, const size_t *shape, + const size_t *start, const size_t *count, + const adios2_constant_dims constant_dims); + +/** + * Returns a handler to a previously defined variable identified by a unique + * name + * @param io handler to variable io owner + * @param name unique name input + * @return variable handler if found + */ +adios2_Variable *adios2_get_variable(adios2_IO *io, const char *name); + /** * Create an adios2_Engine, from adios2_IO, that executes all IO operations. * Resuse MPI_Comm passed to adios2_ADIOS that created adios2_IO io diff --git a/source/adios2/core/IO.cpp b/source/adios2/core/IO.cpp index 55146f100..6a6d0d776 100644 --- a/source/adios2/core/IO.cpp +++ b/source/adios2/core/IO.cpp @@ -112,6 +112,28 @@ VariableCompound &IO::GetVariableCompound(const std::string &name) return m_Compound.at(GetMapIndex(name, m_Variables, "VariableCompound")); } +VariableBase *IO::GetVariableBase(const std::string &name) noexcept +{ + VariableBase *variableBase = nullptr; + auto itVariable = m_Variables.find(name); + if (itVariable == m_Variables.end()) + { + return variableBase; + } + + const std::string type(itVariable->second.first); + if (type == "compound") + { + variableBase = &GetVariableCompound(name); + } +#define declare_type(T) \ + else if (type == GetType<T>()) { variableBase = &GetVariable<T>(name); } + ADIOS2_FOREACH_TYPE_1ARG(declare_type) +#undef declare_type + + return variableBase; +} + std::string IO::GetVariableType(const std::string &name) const { std::string type; diff --git a/source/adios2/core/IO.h b/source/adios2/core/IO.h index 01c7ad427..7a3d689ca 100644 --- a/source/adios2/core/IO.h +++ b/source/adios2/core/IO.h @@ -206,6 +206,14 @@ public: template <class T> Variable<T> &GetVariable(const std::string &name); + /** + * Runtime function: return a pointer to VariableBase + * @param name unique variable identifier + * @return nullptr if not found, pointer to VariableBase if variable is + * found + */ + VariableBase *GetVariableBase(const std::string &name) noexcept; + /** * Gets an existing variable of compound type by name * @param name of variable to be retrieved diff --git a/testing/adios2/bindings/CMakeLists.txt b/testing/adios2/bindings/CMakeLists.txt index 8aa1ecd22..e7b873c60 100644 --- a/testing/adios2/bindings/CMakeLists.txt +++ b/testing/adios2/bindings/CMakeLists.txt @@ -6,3 +6,7 @@ if(ADIOS2_HAVE_Python) add_subdirectory(python) endif() + +if(ADIOS2_HAVE_C) + add_subdirectory(c) +endif() \ No newline at end of file diff --git a/testing/adios2/bindings/c/CMakeLists.txt b/testing/adios2/bindings/c/CMakeLists.txt new file mode 100644 index 000000000..ce9b7301f --- /dev/null +++ b/testing/adios2/bindings/c/CMakeLists.txt @@ -0,0 +1,17 @@ +#------------------------------------------------------------------------------# +# Distributed under the OSI-approved Apache License, Version 2.0. See +# accompanying file Copyright.txt for details. +#------------------------------------------------------------------------------# + +if(NOT ADIOS2_HAVE_MPI) + add_executable(TestBPWriteTypes_c TestBPWriteTypes_nompi.c) + target_link_libraries(TestBPWriteTypes_c adios2_c adios2) +endif() + +if(ADIOS2_HAVE_MPI) + add_executable(TestBPWriteTypes_c TestBPWriteTypes.c) + target_include_directories(TestBPWriteTypes_c PRIVATE ${MPI_C_INCLUDE_PATH}) + target_link_libraries(TestBPWriteTypes_c adios2_c adios2 ${MPI_C_LIBRARIES}) +endif() + +add_test(NAME BPWrite_c COMMAND TestBPWriteTypes_c) \ No newline at end of file diff --git a/testing/adios2/bindings/c/SmallTestData_c.h b/testing/adios2/bindings/c/SmallTestData_c.h new file mode 100644 index 000000000..09ad0b7c3 --- /dev/null +++ b/testing/adios2/bindings/c/SmallTestData_c.h @@ -0,0 +1,36 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + */ + +#ifndef TESTING_ADIOS2_BINDINGS_C_SMALLTESTDATA_C_H_ +#define TESTING_ADIOS2_BINDINGS_C_SMALLTESTDATA_C_H_ + +size_t data_Nx = 10; +char data_I8[10] = {0, 1, -2, 3, -4, 5, -6, 7, -8, 9}; +signed char data_SI8[10] = {0, -1, 2, -3, 4, -5, 6, -7, 8, -9}; +short data_I16[10] = {512, 513, -510, 515, -508, 517, -506, 519, -504, 521}; +int data_I32[10] = {131072, 131073, -131070, 131075, -131068, + 131077, -131066, 131079, -131064, 131081}; +long int data_I64[10] = {8589934592, 8589934593, -8589934590, 8589934595, + -8589934588, 8589934597, -8589934586, 8589934599, + -8589934584, 8589934601}; + +unsigned char data_U8[10] = {128, 129, 130, 131, 132, 133, 134, 135, 136, 137}; + +unsigned short data_U16[10] = {32768, 32769, 32770, 32771, 32772, + 32773, 32774, 32775, 32776, 32777}; + +unsigned int data_U32[10] = {2147483648, 2147483649, 2147483650, 2147483651, + 2147483652, 2147483653, 2147483654, 2147483655, + 2147483656, 2147483657}; + +unsigned long int data_U64[10] = {9223372036854775808UL, 9223372036854775809UL, + 9223372036854775810UL, 9223372036854775811UL, + 9223372036854775812UL, 9223372036854775813UL, + 9223372036854775814UL, 9223372036854775815UL, + 9223372036854775816UL, 9223372036854775817UL}; +float data_R32[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; +double data_R64[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + +#endif /* TESTING_ADIOS2_BINDINGS_C_SMALLTESTDATA_C_H_ */ diff --git a/testing/adios2/bindings/c/TestBPWriteTypes.c b/testing/adios2/bindings/c/TestBPWriteTypes.c new file mode 100644 index 000000000..4adf7122f --- /dev/null +++ b/testing/adios2/bindings/c/TestBPWriteTypes.c @@ -0,0 +1,106 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * TestBPWriteTypes.c + * + * Created on: Aug 9, 2017 + * Author: wgodoy + */ + +#include <mpi.h> + +#include <adios2_c.h> + +#include "SmallTestData_c.h" + +int main(int argc, char *argv[]) +{ + MPI_Init(&argc, &argv); + int rank, size; + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + MPI_Comm_size(MPI_COMM_WORLD, &size); + + adios2_ADIOS *adiosH = adios2_init(MPI_COMM_WORLD, adios2_debug_mode_on); + + // IO + adios2_IO *ioH = adios2_declare_io(adiosH, "CArrayTypes"); + // Set engine parameters + adios2_set_engine(ioH, "BPFileWriter"); + adios2_set_param(ioH, "ProfileUnits", "Microseconds"); + adios2_set_param(ioH, "Threads", "1"); + + // Set transport and parameters + const unsigned int transportID = adios2_add_transport(ioH, "File"); + adios2_set_transport_param(ioH, transportID, "library", "fstream"); + + // count dims are allocated in stack + size_t count[1]; + count[0] = data_Nx; + + // Define variables in ioH + { + + adios2_define_variable(ioH, "varI8", adios2_type_char, 1, NULL, NULL, + count, adios2_constant_dims_true); + adios2_define_variable(ioH, "varSI8", adios2_type_signed_char, 1, NULL, + NULL, count, adios2_constant_dims_true); + adios2_define_variable(ioH, "varI16", adios2_type_short, 1, NULL, NULL, + count, adios2_constant_dims_true); + adios2_define_variable(ioH, "varI32", adios2_type_int, 1, NULL, NULL, + count, adios2_constant_dims_true); + adios2_define_variable(ioH, "varI64", adios2_type_long_int, 1, NULL, + NULL, count, adios2_constant_dims_true); + + adios2_define_variable(ioH, "varU8", adios2_type_unsigned_char, 1, NULL, + NULL, count, adios2_constant_dims_true); + adios2_define_variable(ioH, "varU16", adios2_type_unsigned_short, 1, + NULL, NULL, count, adios2_constant_dims_true); + adios2_define_variable(ioH, "varU32", adios2_type_unsigned_int, 1, NULL, + NULL, count, adios2_constant_dims_true); + adios2_define_variable(ioH, "varU64", adios2_type_unsigned_long_int, 1, + NULL, NULL, count, adios2_constant_dims_true); + adios2_define_variable(ioH, "varR32", adios2_type_float, 1, NULL, NULL, + count, adios2_constant_dims_true); + adios2_define_variable(ioH, "varR64", adios2_type_double, 1, NULL, NULL, + count, adios2_constant_dims_true); + } + // get variables + adios2_Variable *varI8 = adios2_get_variable(ioH, "varI8"); + adios2_Variable *varSI8 = adios2_get_variable(ioH, "varSI8"); + adios2_Variable *varI16 = adios2_get_variable(ioH, "varI16"); + adios2_Variable *varI32 = adios2_get_variable(ioH, "varI32"); + adios2_Variable *varI64 = adios2_get_variable(ioH, "varI64"); + adios2_Variable *varU8 = adios2_get_variable(ioH, "varU8"); + adios2_Variable *varU16 = adios2_get_variable(ioH, "varU16"); + adios2_Variable *varU32 = adios2_get_variable(ioH, "varU32"); + adios2_Variable *varU64 = adios2_get_variable(ioH, "varU64"); + adios2_Variable *varR32 = adios2_get_variable(ioH, "varR32"); + adios2_Variable *varR64 = adios2_get_variable(ioH, "varR64"); + + // Open Engine handler, Write and Close + adios2_Engine *engineH = + adios2_open(ioH, "ctypes.bp", adios2_open_mode_write); + + adios2_write(engineH, varI8, data_I8); + adios2_write(engineH, varSI8, data_SI8); + adios2_write(engineH, varI16, data_I16); + adios2_write(engineH, varI32, data_I32); + adios2_write(engineH, varI64, data_I64); + + adios2_write(engineH, varU8, data_U8); + adios2_write(engineH, varU16, data_U16); + adios2_write(engineH, varU32, data_U32); + adios2_write(engineH, varU64, data_U64); + + adios2_write(engineH, varR32, data_R32); + adios2_write(engineH, varR64, data_R64); + + adios2_close(engineH); + + // deallocate adiosH + adios2_finalize(adiosH); + + MPI_Finalize(); + return 0; +} diff --git a/testing/adios2/bindings/c/TestBPWriteTypes_nompi.c b/testing/adios2/bindings/c/TestBPWriteTypes_nompi.c new file mode 100644 index 000000000..8f4a2f147 --- /dev/null +++ b/testing/adios2/bindings/c/TestBPWriteTypes_nompi.c @@ -0,0 +1,96 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * TestBPWriteTypes.c + * + * Created on: Aug 9, 2017 + * Author: wgodoy + */ + +#include <adios2_c.h> + +#include "SmallTestData_c.h" + +int main(int argc, char *argv[]) +{ + adios2_ADIOS *adiosH = adios2_init_nompi(adios2_debug_mode_on); + + // IO + adios2_IO *ioH = adios2_declare_io(adiosH, "CArrayTypes"); + // Set engine parameters + adios2_set_engine(ioH, "BPFileWriter"); + adios2_set_param(ioH, "ProfileUnits", "Microseconds"); + adios2_set_param(ioH, "Threads", "1"); + + // Set transport and parameters + const unsigned int transportID = adios2_add_transport(ioH, "File"); + adios2_set_transport_param(ioH, transportID, "library", "fstream"); + + // count dims are allocated in stack + size_t count[1]; + count[0] = data_Nx; + + // Define variables in ioH + { + adios2_define_variable(ioH, "varI8", adios2_type_char, 1, NULL, NULL, + count, adios2_constant_dims_true); + adios2_define_variable(ioH, "varSI8", adios2_type_signed_char, 1, NULL, + NULL, count, adios2_constant_dims_true); + adios2_define_variable(ioH, "varI16", adios2_type_short, 1, NULL, NULL, + count, adios2_constant_dims_true); + adios2_define_variable(ioH, "varI32", adios2_type_int, 1, NULL, NULL, + count, adios2_constant_dims_true); + adios2_define_variable(ioH, "varI64", adios2_type_long_int, 1, NULL, + NULL, count, adios2_constant_dims_true); + + adios2_define_variable(ioH, "varU8", adios2_type_unsigned_char, 1, NULL, + NULL, count, adios2_constant_dims_true); + adios2_define_variable(ioH, "varU16", adios2_type_unsigned_short, 1, + NULL, NULL, count, adios2_constant_dims_true); + adios2_define_variable(ioH, "varU32", adios2_type_unsigned_int, 1, NULL, + NULL, count, adios2_constant_dims_true); + adios2_define_variable(ioH, "varU64", adios2_type_unsigned_long_int, 1, + NULL, NULL, count, adios2_constant_dims_true); + adios2_define_variable(ioH, "varR32", adios2_type_float, 1, NULL, NULL, + count, adios2_constant_dims_true); + adios2_define_variable(ioH, "varR64", adios2_type_double, 1, NULL, NULL, + count, adios2_constant_dims_true); + } + // get variables + adios2_Variable *varI8 = adios2_get_variable(ioH, "varI8"); + adios2_Variable *varSI8 = adios2_get_variable(ioH, "varSI8"); + adios2_Variable *varI16 = adios2_get_variable(ioH, "varI16"); + adios2_Variable *varI32 = adios2_get_variable(ioH, "varI32"); + adios2_Variable *varI64 = adios2_get_variable(ioH, "varI64"); + adios2_Variable *varU8 = adios2_get_variable(ioH, "varU8"); + adios2_Variable *varU16 = adios2_get_variable(ioH, "varU16"); + adios2_Variable *varU32 = adios2_get_variable(ioH, "varU32"); + adios2_Variable *varU64 = adios2_get_variable(ioH, "varU64"); + adios2_Variable *varR32 = adios2_get_variable(ioH, "varR32"); + adios2_Variable *varR64 = adios2_get_variable(ioH, "varR64"); + + // Open Engine handler, Write and Close + adios2_Engine *engineH = + adios2_open(ioH, "ctypes.bp", adios2_open_mode_write); + + adios2_write(engineH, varI8, data_I8); + adios2_write(engineH, varSI8, data_SI8); + adios2_write(engineH, varI16, data_I16); + adios2_write(engineH, varI32, data_I32); + adios2_write(engineH, varI64, data_I64); + + adios2_write(engineH, varU8, data_U8); + adios2_write(engineH, varU16, data_U16); + adios2_write(engineH, varU32, data_U32); + adios2_write(engineH, varU64, data_U64); + + adios2_write(engineH, varR32, data_R32); + adios2_write(engineH, varR64, data_R64); + + adios2_close(engineH); + + // deallocate adiosH + adios2_finalize(adiosH); + return 0; +} diff --git a/testing/adios2/engine/SmallTestData.h b/testing/adios2/engine/SmallTestData.h index b008d09f3..ba6b50244 100644 --- a/testing/adios2/engine/SmallTestData.h +++ b/testing/adios2/engine/SmallTestData.h @@ -5,6 +5,8 @@ #ifndef TESTING_ADIOS2_ENGINE_SMALLTESTDATA_H_ #define TESTING_ADIOS2_ENGINE_SMALLTESTDATA_H_ +#include <array> + // Test data for each type. Make sure our values exceed the range of the // previous size to make sure we all bytes for each element struct SmallTestData -- GitLab