diff --git a/cmake/FindADIOS1.cmake b/cmake/FindADIOS1.cmake new file mode 100644 index 0000000000000000000000000000000000000000..da0fdd08dbf1ae6c6f0f3257c719a9a8734d01d1 --- /dev/null +++ b/cmake/FindADIOS1.cmake @@ -0,0 +1,260 @@ +# - Find ADIOS 1.x library, routines for scientific, parallel IO +# https://www.olcf.ornl.gov/center-projects/adios/ +# +# Use this module by invoking find_package with the form: +# find_package(ADIOS1 +# [version] [EXACT] # Minimum or EXACT version, e.g. 1.6.0 +# [REQUIRED] # Fail with an error if ADIOS or a required +# # component is not found +# [QUIET] # ... +# [COMPONENTS <...>] # Compiled in components: fortran, readonly, + # sequential (all are case insentative) +# ) +# +# Module that finds the includes and libraries for a working ADIOS 1.x install. +# This module invokes the `adios_config` script that should be installed with +# the other ADIOS tools. +# +# To provide a hint to the module where to find the ADIOS installation, +# set the ADIOS1_ROOT or ADIOS1_DIR environment variable. +# +# If this variable is not set, make sure that at least the according `bin/` +# directory of ADIOS 1.x is in your PATH environment variable. +# +# Set the following CMake variables BEFORE calling find_packages to +# influence this module: +# ADIOS1_USE_STATIC_LIBS - Set to ON to force the use of static +# libraries. Default: OFF +# +# This module will define the following variables: +# ADIOS1_INCLUDE_DIRS - Include directories for the ADIOS 1.x headers. +# ADIOS1_LIBRARY_PATH - Full path of the libadios library (.a or .so file) +# ADIOS1_DEPENDENCY_LIBRARIES - ADIOS 1.x dependency libraries. +# ADIOS1_FOUND - TRUE if FindADIOS1 found a working install +# ADIOS1_VERSION - Version in format Major.Minor.Patch +# +# Not used for now: +# ADIOS1_DEFINITIONS - Compiler definitions you should add with +# add_definitions(${ADIOS1_DEFINITIONS}) +# +# Example to find ADIOS 1.x (default) +# find_package(ADIOS1) +# if(ADIOS1_FOUND) +# include_directories(${ADIOS1_INCLUDE_DIRS}) +# add_executable(foo foo.c) +# target_link_libraries(foo ${ADIOS1_LIBRARY_PATH} ADIOS1_DEPENDENCY_LIBRARIES) +# endif() + +# Example to find ADIOS 1.x using component +# find_package(ADIOS1 COMPONENTS fortran) +# if(ADIOS1_FOUND) +# include_directories(${ADIOS1_INCLUDE_DIRS}) +# add_executable(foo foo.c) +# target_link_libraries(foo ${ADIOS1_LIBRARY_PATH} ${ADIOS1_DEPENDENCY_LIBRARIES}) +# endif() +############################################################################### +#Copyright (c) 2014, Axel Huebl and Felix Schmitt from http://picongpu.hzdr.de +#All rights reserved. + +#Redistribution and use in source and binary forms, with or without +#modification, are permitted provided that the following conditions are met: + +#1. Redistributions of source code must retain the above copyright notice, this +#list of conditions and the following disclaimer. + +#2. Redistributions in binary form must reproduce the above copyright notice, +#this list of conditions and the following disclaimer in the documentation +#and/or other materials provided with the distribution. + +#3. Neither the name of the copyright holder nor the names of its contributors +#may be used to endorse or promote products derived from this software without +#specific prior written permission. + +#THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +#AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +#IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +#DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +#FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +#DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +#SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +#CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +#OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +#OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +############################################################################### + + +############################################################################### +# Required cmake version +############################################################################### + +cmake_minimum_required(VERSION 2.8.5) + + +############################################################################### +# ADIOS +############################################################################### +# get flags for adios_config, -l is the default +#-f for fortran, -r for readonly, -s for sequential (nompi) +set(OPTLIST "-l") +if(ADIOS1_FIND_COMPONENTS) + foreach(COMP ${ADIOS1_FIND_COMPONENTS}) + string(TOLOWER ${COMP} comp) + if(comp STREQUAL "fortran") + set(OPTLIST "${OPTLIST}f") + elseif(comp STREQUAL "readonly") + set(OPTLIST "${OPTLIST}r") + elseif(comp STREQUAL "sequential") + set(OPTLIST "${OPTLIST}s") + else() + message("ADIOS 1.x component ${COMP} is not supported. Please use fortran, readonly, or sequential") + endif() + endforeach() +endif() + +# we start by assuming we found ADIOS and falsify it if some +# dependencies are missing (or if we did not find ADIOS at all) +set(ADIOS1_FOUND TRUE) + + +# find `adios_config` program ################################################# +# check the ADIOS1_ROOT and ADIOS1_DIR hint and the normal PATH +find_file(ADIOS1_CONFIG + NAME adios_config + PATHS $ENV{ADIOS1_ROOT}/bin $ENV{ADIOS1_DIR}/bin $ENV{INSTALL_PREFIX}/bin $ENV{PATH}) + +if(ADIOS1_CONFIG) + message(STATUS "Found 'adios_config': ${ADIOS1_CONFIG}") +else(ADIOS1_CONFIG) + set(ADIOS1_FOUND FALSE) + message(STATUS "Can NOT find 'adios_config' - set ADIOS1_ROOT, ADIOS1_DIR or INSTALL_PREFIX, or check your PATH") +endif(ADIOS1_CONFIG) + +# check `adios_config` program ################################################ +if(ADIOS1_FOUND) + execute_process(COMMAND ${ADIOS1_CONFIG} ${OPTLIST} + OUTPUT_VARIABLE ADIOS1_LINKFLAGS + RESULT_VARIABLE ADIOS1_CONFIG_RETURN + OUTPUT_STRIP_TRAILING_WHITESPACE) + if(NOT ADIOS1_CONFIG_RETURN EQUAL 0) + set(ADIOS1_FOUND FALSE) + message(STATUS "Can NOT execute 'adios_config' - check file permissions") + endif() + + # find ADIOS1_ROOT_DIR + execute_process(COMMAND ${ADIOS1_CONFIG} -d + OUTPUT_VARIABLE ADIOS1_ROOT_DIR + OUTPUT_STRIP_TRAILING_WHITESPACE) + if(NOT IS_DIRECTORY "${ADIOS1_ROOT_DIR}") + set(ADIOS1_FOUND FALSE) + message(STATUS "The directory provided by 'adios_config -d' does not exist: ${ADIOS1_ROOT_DIR}") + endif() +endif(ADIOS1_FOUND) + +# option: use only static libs ################################################ +if(ADIOS1_USE_STATIC_LIBS) + # carfully: we have to restore the original path in the end + set(_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES}) + set(CMAKE_FIND_LIBRARY_SUFFIXES .a) +endif() + + +# we found something in ADIOS1_ROOT_DIR and adios_config works ################# +if(ADIOS1_FOUND) + # ADIOS headers + list(APPEND ADIOS1_INCLUDE_DIRS ${ADIOS1_ROOT_DIR}/include) + + # check for compiled in dependencies, recomve ";" in ADIOS1_LINKFLAGS (from cmake build) + string(REGEX REPLACE ";" " " ADIOS1_LINKFLAGS "${ADIOS1_LINKFLAGS}") + message(STATUS " ADIOS1 linker flags (unparsed): ${ADIOS1_LINKFLAGS}") + + # find all library paths -L + # note: this can cause trouble if some libs are specified twice from + # different sources (quite unlikely) + # http://www.cmake.org/pipermail/cmake/2008-November/025128.html + set(ADIOS1_LIBRARY_DIRS "") + string(REGEX MATCHALL " -L([A-Za-z_0-9/\\.-]+)" _ADIOS1_LIBDIRS " ${ADIOS1_LINKFLAGS}") + foreach(_LIBDIR ${_ADIOS1_LIBDIRS}) + string(REPLACE " -L" "" _LIBDIR ${_LIBDIR}) + list(APPEND ADIOS1_LIBRARY_DIRS ${_LIBDIR}) + endforeach() + # we could append ${CMAKE_PREFIX_PATH} now but that is not really necessary + + #message(STATUS "ADIOS1 DIRS to look for libs: ${ADIOS1_LIBRARY_DIRS}") + + # parse all -lname libraries and find an absolute path for them + string(REGEX MATCHALL " -l([A-Za-z_0-9\\.-]+)" _ADIOS1_LIBS " ${ADIOS1_LINKFLAGS}") + foreach(_LIB ${_ADIOS1_LIBS}) + string(REPLACE " -l" "" _LIB ${_LIB}) + + # find static lib: absolute path in -L then default + find_library(_LIB_DIR NAMES ${_LIB} PATHS ${ADIOS1_LIBRARY_DIRS} CMAKE_FIND_ROOT_PATH_BOTH) + + # found? + if(_LIB_DIR) + if(_LIB STREQUAL "adios") + message(STATUS " Found the main adios library in ${_LIB_DIR}") + set(ADIOS1_LIBRARY_PATH "${_LIB_DIR}") + #message(STATUS " ADIOS1_LIBRARY_PATH set to ${ADIOS1_LIBRARY_PATH}") + else() + message(STATUS " Found ${_LIB} in ${_LIB_DIR}") + list(APPEND ADIOS1_DEPENDENCY_LIBRARIES "${_LIB_DIR}") + endif() + else(_LIB_DIR) + set(ADIOS1_FOUND FALSE) + message(STATUS "ADIOS1: Could NOT find library '${_LIB}'") + endif(_LIB_DIR) + + # clean cached var + unset(_LIB_DIR CACHE) + unset(_LIB_DIR) + endforeach() + + #add libraries which are already using cmake format + string(REGEX MATCHALL "/([A-Za-z_0-9/\\.-]+)\\.([a|so]+)" _ADIOS1_LIBS_SUB "${ADIOS1_LINKFLAGS}") + list(APPEND ADIOS1_DEPENDENCY_LIBRARIES "${_ADIOS1_LIBS_SUB}") + + # add the version string + execute_process(COMMAND ${ADIOS1_CONFIG} -v + OUTPUT_VARIABLE ADIOS1_VERSION + OUTPUT_STRIP_TRAILING_WHITESPACE) + +endif(ADIOS1_FOUND) + +# unset checked variables if not found +if(NOT ADIOS1_FOUND) + unset(ADIOS1_INCLUDE_DIRS) + unset(ADIOS1_DEPENDENCY_LIBRARIES) + unset(ADIOS1_LIBRARY_PATH) +endif(NOT ADIOS1_FOUND) + + +# restore CMAKE_FIND_LIBRARY_SUFFIXES if manipulated by this module ########### +if(ADIOS1_USE_STATIC_LIBS) + set(CMAKE_FIND_LIBRARY_SUFFIXES ${_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES}) +endif() + + +############################################################################### +# FindPackage Options +############################################################################### + +# handles the REQUIRED, QUIET and version-related arguments for find_package +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(ADIOS1 + REQUIRED_VARS ADIOS1_LIBRARY_PATH ADIOS1_DEPENDENCY_LIBRARIES ADIOS1_INCLUDE_DIRS + VERSION_VAR ADIOS1_VERSION +) + +########################################################################## +# Add target and dependencies to ADIOS2 +########################################################################## +#message(STATUS "ADIOS1 Find ended with ${ADIOS1_FOUND}") + if(ADIOS1_FOUND AND NOT TARGET adios1::adios) + message(STATUS "Add library ADIOS1 to the build") + add_library(adios1::adios UNKNOWN IMPORTED) + set_target_properties(adios1::adios PROPERTIES + IMPORTED_LOCATION "${ADIOS1_LIBRARY_PATH}" + INTERFACE_LINK_LIBRARIES "${ADIOS1_DEPENDENCY_LIBRARIES}" + INTERFACE_INCLUDE_DIRECTORIES "${ADIOS1_INCLUDE_DIRS}" + ) + endif() diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index ffe6d00e4d8057f0e861d7e2209d16b7f2b26fe6..59d0aaef3e1741211ad8274c17dc9f2b361b879b 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -4,3 +4,4 @@ #------------------------------------------------------------------------------# add_subdirectory(hello) +add_subdirectory(heatTransfer) diff --git a/examples/heatTransfer/CMakeLists.txt b/examples/heatTransfer/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..bca588c58d2509e99148fb0d384df8b7a6b916f6 --- /dev/null +++ b/examples/heatTransfer/CMakeLists.txt @@ -0,0 +1,29 @@ +#------------------------------------------------------------------------------# +# Distributed under the OSI-approved Apache License, Version 2.0. See +# accompanying file Copyright.txt for details. +#------------------------------------------------------------------------------# + +add_executable(heatTransfer_adios main.cpp HeatTransfer.cpp Settings.cpp IO_adios2.cpp) + +if(ADIOS_USE_MPI) + find_package(MPI COMPONENTS C REQUIRED) + target_include_directories(heatTransfer_adios PRIVATE ${MPI_C_INCLUDE_PATH}) + target_link_libraries(heatTransfer_adios adios2 ${MPI_C_LIBRARIES}) +else(ADIOS_USE_MPI) + target_link_libraries(heatTransfer_adios adios2) +endif() + +if(ADIOS_USE_ADIOS1) + find_package(ADIOS1 REQUIRED) + add_executable(heatTransfer_adios1 main.cpp HeatTransfer.cpp Settings.cpp IO_adios1.cpp) + if(ADIOS_USE_MPI) + target_include_directories(heatTransfer_adios1 PRIVATE ${MPI_C_INCLUDE_PATH}) + target_link_libraries(heatTransfer_adios1 adios1::adios ${MPI_C_LIBRARIES}) + else(ADIOS_USE_MPI) + target_compile_definitions(heatTransfer_adios1 PRIVATE -D_NOMPI) + target_link_libraries(heatTransfer_adios1 adios1::adios) + endif() +endif() + +add_subdirectory(read) + diff --git a/examples/heatTransfer/HeatTransfer.cpp b/examples/heatTransfer/HeatTransfer.cpp index ac706e4c66d75c5e342faa915ae2edb8aa4519e2..29283fa776a39650cec330d1688402a6b7f83299 100644 --- a/examples/heatTransfer/HeatTransfer.cpp +++ b/examples/heatTransfer/HeatTransfer.cpp @@ -10,7 +10,6 @@ * Author: Norbert Podhorszki * */ -#include <mpi.h> #include <iomanip> #include <iostream> diff --git a/examples/heatTransfer/HeatTransfer.h b/examples/heatTransfer/HeatTransfer.h index 7d48eb558d2db274218e8b0030ad53cc2aa0f7f3..5233d3f5f48fdbc200149b4423c9c3824a4006dc 100644 --- a/examples/heatTransfer/HeatTransfer.h +++ b/examples/heatTransfer/HeatTransfer.h @@ -11,7 +11,10 @@ #ifndef HEATTRANSFER_H_ #define HEATTRANSFER_H_ +#define OMPI_SKIP_MPICXX 1 // workaround for OpenMPI forcing C++ bindings #include <mpi.h> +#undef OMPI_SKIP_MPICXX + #include <vector> #include "Settings.h" diff --git a/examples/heatTransfer/IO.h b/examples/heatTransfer/IO.h index 999866112e471e46f2136f804ed2ee5226bb0a0a..0f774336f18e81cee951f4c5879f7733e2f21943 100644 --- a/examples/heatTransfer/IO.h +++ b/examples/heatTransfer/IO.h @@ -13,7 +13,10 @@ #include "HeatTransfer.h" #include "Settings.h" + +#define OMPI_SKIP_MPICXX 1 // workaround for OpenMPI forcing C++ bindings #include <mpi.h> +#undef OMPI_SKIP_MPICXX class IO { diff --git a/examples/heatTransfer/IO_adios2.cpp b/examples/heatTransfer/IO_adios2.cpp index ac0567820549d3300ca410c9686fe8552fb9578f..966bfae203b9d3cc67332d12b923d624546ccdac 100644 --- a/examples/heatTransfer/IO_adios2.cpp +++ b/examples/heatTransfer/IO_adios2.cpp @@ -31,7 +31,7 @@ IO::IO(const Settings &s, MPI_Comm comm) if (!bpWriterSettings.isUserDefined()) { // if not defined by user, we can change the default settings - bpWriterSettings.SetEngine("BP"); // BP is the default engine + bpWriterSettings.SetEngine("BPFileWriter"); // BP is the default engine bpWriterSettings.AllowThreads( 1); // allow 1 extra thread for data processing bpWriterSettings.AddTransport( @@ -47,11 +47,13 @@ IO::IO(const Settings &s, MPI_Comm comm) // define T as 2D global array varT = &ad->DefineVariable<double>( - "T", {s.gndx, s.gndy}, // Global dimensions - {s.ndx, - s.ndy}, // local size, could be defined later using SetSelection() - {s.offsx, s.offsy} // offset of the local array in the global space - ); + "T", + // Global dimensions + {s.gndx, s.gndy}, + // local size, could be defined later using SetSelection() + {s.ndx, s.ndy}, + // offset of the local array in the global space + {s.offsx, s.offsy}); // add transform to variable // adios::Transform tr = adios::transform::BZIP2( ); @@ -71,28 +73,19 @@ IO::~IO() delete ad; } -void /*IO::*/ old_style_write(int step, const HeatTransfer &ht, - const Settings &s, MPI_Comm comm) -{ - bpWriter->Write<double>(*varT, ht.data_noghost().data()); - bpWriter->Advance(); -} - void IO::write(int step, const HeatTransfer &ht, const Settings &s, MPI_Comm comm) { +#if 1 + /* This selection is redundant and not required, since we defined * the selection already in DefineVariable(). It is here just as an example. */ // Make a selection to describe the local dimensions of the variable we - // write - // and - // its offsets in the global spaces. This could have been done in + // write and its offsets in the global spaces. This could have been done in // adios.DefineVariable() - adios::Selection sel = adios.SelectionBoundingBox( - {s.ndx, s.ndy}, - {s.offsx, s.offsy}); // local dims and offsets; both as list - var2D.SetSelection(sel); + adios::SelectionBoundingBox sel({s.ndx, s.ndy}, {s.offsx, s.offsy}); + varT->SetSelection(sel); /* Select the area that we want to write from the data pointer we pass to the @@ -105,10 +98,17 @@ void IO::write(int step, const HeatTransfer &ht, const Settings &s, above. Default memspace is always the full selection. */ - adios::Selection memspace = - adios.SelectionBoundingBox({s.ndx, s.ndy}, {1, 1}); - var2D.SetMemorySelection(memspace); + adios::SelectionBoundingBox memspace = + adios::SelectionBoundingBox({s.ndx, s.ndy}, {1, 1}); + varT->SetMemorySelection(memspace); - bpWriter->Write<double>(*varT, ht.data()); + bpWriter->Write<double>(*varT, ht.data_noghost().data()); bpWriter->Advance(); + +#else + + bpWriter->Write<double>(*varT, ht.data_noghost().data()); + bpWriter->Advance(); + +#endif } diff --git a/examples/heatTransfer/main.cpp b/examples/heatTransfer/main.cpp index 1d1372f401ff641f3dc0da71a1b175b9b5c5b1fb..ff1b6c44c9a5e0cbf836f60b475c3190d7e34e8f 100644 --- a/examples/heatTransfer/main.cpp +++ b/examples/heatTransfer/main.cpp @@ -10,7 +10,9 @@ * Author: Norbert Podhorszki * */ +#define OMPI_SKIP_MPICXX 1 // workaround for OpenMPI forcing C++ bindings #include <mpi.h> +#undef OMPI_SKIP_MPICXX #include <iostream> #include <memory> @@ -64,10 +66,10 @@ int main(int argc, char *argv[]) IO io(settings, mpiHeatTransferComm); ht.init(true); - ht.printT("Initialized T:", mpiHeatTransferComm); + // ht.printT("Initialized T:", mpiHeatTransferComm); ht.heatEdges(); - // ht.exchange( mpiHeatTransferComm ); - ht.printT("Heated T:", mpiHeatTransferComm); + ht.exchange(mpiHeatTransferComm); + // ht.printT("Heated T:", mpiHeatTransferComm); io.write(0, ht, settings, mpiHeatTransferComm); for (unsigned int t = 1; t <= settings.steps; ++t) diff --git a/examples/heatTransfer/read/CMakeLists.txt b/examples/heatTransfer/read/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..993d1d0474d30711d04b45206f366efecee04fcc --- /dev/null +++ b/examples/heatTransfer/read/CMakeLists.txt @@ -0,0 +1,27 @@ +#------------------------------------------------------------------------------# +# Distributed under the OSI-approved Apache License, Version 2.0. See +# accompanying file Copyright.txt for details. +#------------------------------------------------------------------------------# + +#add_executable(heatRead_adios heatRead_adios.cpp) +# +#if(ADIOS_USE_MPI) +# find_package(MPI COMPONENTS C REQUIRED) +# target_include_directories(heatRead_adios PRIVATE ${MPI_C_INCLUDE_PATH}) +# target_link_libraries(heatRead_adios adios2 ${MPI_C_LIBRARIES}) +#else(ADIOS_USE_MPI) +# target_link_libraries(heatRead_adios adios2) +#endif() + +if(ADIOS_USE_ADIOS1) + find_package(ADIOS1 REQUIRED) + add_executable(heatRead_adios1 heatRead_adios1.cpp PrintData.cpp) + if(ADIOS_USE_MPI) + target_include_directories(heatRead_adios1 PRIVATE ${MPI_C_INCLUDE_PATH}) + target_link_libraries(heatRead_adios1 adios1::adios ${MPI_C_LIBRARIES}) + else(ADIOS_USE_MPI) + target_compile_definitions(heatRead_adios1 PRIVATE -D_NOMPI) + target_link_libraries(heatRead_adios1 adios1::adios) + endif() +endif() + diff --git a/examples/heatTransfer/read/PrintData.cpp b/examples/heatTransfer/read/PrintData.cpp new file mode 100644 index 0000000000000000000000000000000000000000..030fa561f1cc1a6e3dc62b24d8cf45f98583bfcd --- /dev/null +++ b/examples/heatTransfer/read/PrintData.cpp @@ -0,0 +1,54 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * PrintData.cpp + * + * Created on: Apr 2017 + * Author: Norbert Podhorszki + */ + +#include "PrintData.h" +#include <fstream> +#include <iomanip> +#include <iostream> +#include <string> + +void printData(double *xy, uint64_t *size, uint64_t *offset, int rank, + int steps) +{ + std::ofstream myfile; + std::string filename = "data." + std::to_string(rank); + myfile.open(filename); + double *data = xy; + uint64_t nelems = size[0] * size[1]; + for (int step = 0; step < steps; step++) + { + myfile << "rank=" << rank << " size=" << size[0] << "x" << size[1] + << " offsets=" << offset[0] << ":" << offset[1] + << " step=" << step << std::endl; + + myfile << " time row columns " << offset[1] << "..." + << offset[1] + size[1] - 1 << std::endl; + myfile << " "; + for (int j = 0; j < size[1]; j++) + { + myfile << std::setw(9) << offset[1] + j; + } + myfile << std::endl; + myfile << "------------------------------------------------------------" + "--\n"; + for (int i = 0; i < size[0]; i++) + { + myfile << std::setw(5) << step << std::setw(5) << offset[0] + i; + for (int j = 0; j < size[1]; j++) + { + myfile << std::setw(9) << std::setprecision(2) + << data[i * size[1] + j]; + } + myfile << std::endl; + } + data += nelems; + } + myfile.close(); +} diff --git a/examples/heatTransfer/read/PrintData.h b/examples/heatTransfer/read/PrintData.h new file mode 100644 index 0000000000000000000000000000000000000000..308ace34007f88c15498464b1555b5cca3ed1f6b --- /dev/null +++ b/examples/heatTransfer/read/PrintData.h @@ -0,0 +1,19 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * PrintData.h + * + * Created on: Apr 2017 + * Author: Norbert Podhorszki + */ + +#ifndef PRINTDATA_H_ +#define PRINTDATA_H_ + +#include <cstdint> + +void printData(double *xy, uint64_t *size, uint64_t *offset, int rank, + int steps); + +#endif /* PRINTDATA_H_ */ diff --git a/examples/heatTransfer/read/heatRead_adios1.cpp b/examples/heatTransfer/read/heatRead_adios1.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d596d223efd8c5b11d06d42f0881ec85f15ffe34 --- /dev/null +++ b/examples/heatTransfer/read/heatRead_adios1.cpp @@ -0,0 +1,104 @@ + +#define OMPI_SKIP_MPICXX 1 // workaround for OpenMPI forcing C++ bindings +#include <mpi.h> +#undef OMPI_SKIP_MPICXX + +#include "adios_read.h" +#include <cstdint> +#include <iomanip> +#include <iostream> +#include <math.h> +#include <memory> +#include <stdexcept> +#include <string> + +#include "PrintData.h" + +int main(int argc, char *argv[]) +{ + MPI_Init(&argc, &argv); + + if (argc < 2) + { + std::cout << "Not enough arguments: need an input file\n"; + return 1; + } + const char *inputfile = argv[1]; + + /* World comm spans all applications started with the same aprun command + on a Cray XK6. So we have to split and create the local + 'world' communicator for the reader only. + In normal start-up, the communicator will just equal the MPI_COMM_WORLD. + */ + + int wrank, wnproc; + MPI_Comm_rank(MPI_COMM_WORLD, &wrank); + MPI_Comm_size(MPI_COMM_WORLD, &wnproc); + MPI_Barrier(MPI_COMM_WORLD); + + const unsigned int color = 2; + MPI_Comm mpiReaderComm; + MPI_Comm_split(MPI_COMM_WORLD, color, wrank, &mpiReaderComm); + + int rank, nproc; + MPI_Comm_rank(mpiReaderComm, &rank); + MPI_Comm_size(mpiReaderComm, &nproc); + + adios_read_init_method(ADIOS_READ_METHOD_BP, mpiReaderComm, "verbose=3"); + + ADIOS_FILE *f; + f = adios_read_open_file(inputfile, ADIOS_READ_METHOD_BP, mpiReaderComm); + if (f == NULL) + { + std::cout << adios_errmsg() << std::endl; + return -1; + } + + ADIOS_VARINFO *vgndx = adios_inq_var(f, "gndx"); + ADIOS_VARINFO *vgndy = adios_inq_var(f, "gndy"); + + unsigned int gndx = *(unsigned int *)vgndx->value; + unsigned int gndy = *(unsigned int *)vgndy->value; + + if (rank == 0) + { + std::cout << "gndx = " << gndx << std::endl; + std::cout << "gndy = " << gndy << std::endl; + } + adios_free_varinfo(vgndx); + adios_free_varinfo(vgndy); + + // 1D decomposition of the columns, which is inefficient for reading! + uint64_t readsize[2] = {gndx, gndy / nproc}; + uint64_t offset[2] = {0LL, rank * readsize[1]}; + if (rank == nproc - 1) + { + // last process should read all the rest of columns + readsize[1] = gndy - readsize[1] * (nproc - 1); + } + + std::cout << "rank " << rank << " reads " << readsize[1] + << " columns from offset " << offset[1] << std::endl; + + ADIOS_VARINFO *vT = adios_inq_var(f, "T"); + + double *T = new double[vT->nsteps * readsize[0] * readsize[1]]; + + // Create a 2D selection for the subset + ADIOS_SELECTION *sel = adios_selection_boundingbox(2, offset, readsize); + + // Arrays are read by scheduling one or more of them + // and performing the reads at once + adios_schedule_read(f, sel, "T", 0, vT->nsteps, T); + adios_perform_reads(f, 1); + + printData(T, readsize, offset, rank, vT->nsteps); + adios_read_close(f); + adios_free_varinfo(vT); + delete[] T; + // Terminate + adios_selection_delete(sel); + adios_read_finalize_method(ADIOS_READ_METHOD_BP); + MPI_Finalize(); + return 0; +} diff --git a/examples/hello/adios1Writer/CMakeLists.txt b/examples/hello/adios1Writer/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..b38cfb90d3a153197efaa99f88295187debcfc1b --- /dev/null +++ b/examples/hello/adios1Writer/CMakeLists.txt @@ -0,0 +1,14 @@ +#------------------------------------------------------------------------------# +# Distributed under the OSI-approved Apache License, Version 2.0. See +# accompanying file Copyright.txt for details. +#------------------------------------------------------------------------------# + +if(ADIOS_USE_MPI) + find_package(MPI COMPONENTS C REQUIRED) + add_executable(hello_adios1Writer helloADIOS1Writer.cpp) + target_include_directories(hello_adios1Writer PRIVATE ${MPI_C_INCLUDE_PATH}) + target_link_libraries(hello_adios1Writer adios2 ${MPI_C_LIBRARIES}) +endif() + +add_executable(hello_adios1Writer_nompi helloADIOS1Writer_nompi.cpp) +target_link_libraries(hello_adios1Writer_nompi adios2) diff --git a/examples/hello/adios1Writer/helloADIOS1Writer.cpp b/examples/hello/adios1Writer/helloADIOS1Writer.cpp index 2a7803ab6edac9adc2618699fb3be45c3960b6c7..87101533b4795379e3b2c94966c44d01fea83403 100644 --- a/examples/hello/adios1Writer/helloADIOS1Writer.cpp +++ b/examples/hello/adios1Writer/helloADIOS1Writer.cpp @@ -11,7 +11,9 @@ #include <iostream> #include <vector> +#define OMPI_SKIP_MPICXX 1 // workaround for OpenMPI forcing C++ bindings #include <mpi.h> +#undef OMPI_SKIP_MPICXX #include "ADIOS_CPP.h" diff --git a/examples/hello/adios1Writer/helloADIOS1Writer_nompi.cpp b/examples/hello/adios1Writer/helloADIOS1Writer_nompi.cpp index 44d4d5547050e79ef4a3cb3b0222b4d21433438f..5955b33436df32cd835391a75c85bf2bc8f7f53b 100644 --- a/examples/hello/adios1Writer/helloADIOS1Writer_nompi.cpp +++ b/examples/hello/adios1Writer/helloADIOS1Writer_nompi.cpp @@ -16,7 +16,7 @@ int main(int argc, char *argv[]) { const bool adiosDebug = true; - adios::ADIOS adios(adiosDebug); + adios::ADIOS adios(adios::Verbose::INFO, adiosDebug); // Application variable std::vector<double> myDoubles = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; diff --git a/include/core/VariableBase.h b/include/core/VariableBase.h index eea1d261c67e63b84e1db385117dfcb01781a9ce..d9d98c9160c341a9153ddd8fa7869af92590331f 100644 --- a/include/core/VariableBase.h +++ b/include/core/VariableBase.h @@ -12,14 +12,16 @@ #define VARIABLEBASE_H_ /// \cond EXCLUDE_FROM_DOXYGEN +#include <exception> #include <iterator> #include <sstream> #include <string> #include <vector> /// \endcond -#include "functions/adiosFunctions.h" //GetTotalSize -#include "functions/adiosTemplates.h" //GetType<T> +#include "functions/adiosFunctions.h" //GetTotalSize, ConvertUint64VectorToSizetVector +#include "functions/adiosTemplates.h" //GetType<T> +#include "selection/SelectionBoundingBox.h" //Selection namespace adios { @@ -71,11 +73,62 @@ public: return GetTotalSize(m_Dimensions); } + /** + * Set the local dimension and global offset of the variable using a + * selection + * Only bounding boxes are allowed + */ + void SetSelection(const SelectionBoundingBox &sel) + { + + if (m_GlobalDimensions.size() == 0) + { + throw std::invalid_argument("Variable.SetSelection() is an invalid " + "call for single value variables\n"); + } + if (m_GlobalDimensions.size() != sel.m_Count.size()) + { + throw std::invalid_argument("Variable.SetSelection() bounding box " + "dimension must equal the global " + "dimension of the variable\n"); + } + + ConvertUint64VectorToSizetVector(sel.m_Count, m_Dimensions); + ConvertUint64VectorToSizetVector(sel.m_Start, m_GlobalDimensions); + } + + /** + * Set the local dimension and global offset of the variable using a + * selection + * Only bounding boxes are allowed + */ + void SetMemorySelection(const SelectionBoundingBox &sel) + { + if (m_GlobalDimensions.size() == 0) + { + throw std::invalid_argument( + "Variable.SetMemorySelection() is an invalid " + "call for single value variables\n"); + } + if (m_GlobalDimensions.size() != sel.m_Count.size()) + { + throw std::invalid_argument( + "Variable.SetMemorySelection() bounding box " + "dimension must equal the global " + "dimension of the variable\n"); + } + + ConvertUint64VectorToSizetVector(sel.m_Count, m_MemoryDimensions); + ConvertUint64VectorToSizetVector(sel.m_Start, m_MemoryOffsets); + } + // protected: off for now Dims m_Dimensions; ///< array of local dimensions Dims m_GlobalDimensions; ///< array of global dimensions Dims m_GlobalOffsets; ///< array of global offsets + Dims m_MemoryDimensions; ///< array of memory dimensions + Dims m_MemoryOffsets; ///< array of memory offsets const bool m_DebugMode = false; std::string GetDimensionAsString() { return dimsToString(m_Dimensions); } diff --git a/include/engine/adios1/ADIOS1Reader.h b/include/engine/adios1/ADIOS1Reader.h index 22e2984765bac022d57ba63ba1b6c4b30906bd56..64566ec4edbdebda353e531560f2857ccbf7e45f 100644 --- a/include/engine/adios1/ADIOS1Reader.h +++ b/include/engine/adios1/ADIOS1Reader.h @@ -10,8 +10,8 @@ * Author: pnb */ -#ifndef BPFILEREADER_H_ -#define BPFILEREADER_H_ +#ifndef ADIOS1READER_H_ +#define ADIOS1READER_H_ #include <iostream> //this must go away @@ -23,7 +23,12 @@ namespace adios { -class BPFileReader : public Engine +#ifdef ADIOS_NOMPI +#define _NOMPI 1 +#endif +#include "adios_read_v2.h" // this is adios 1.x header file + +class ADIOS1Reader : public Engine { public: @@ -38,13 +43,13 @@ public: * @param debugMode * @param hostLanguage */ - BPFileReader(ADIOS &adios, const std::string name, + ADIOS1Reader(ADIOS &adios, const std::string name, const std::string accessMode, MPI_Comm mpiComm, const Method &method, const IOMode iomode, const float timeout_sec, const bool debugMode = false, const unsigned int nthreads = 1); - ~BPFileReader(); + ~ADIOS1Reader(); Variable<void> *InquireVariable(const std::string name, const bool readIn = true); @@ -93,26 +98,14 @@ public: void Close(const int transportIndex = -1); private: - capsule::STLVector - m_Buffer; ///< heap capsule, contains data and metadata buffers - // format::BP1Writer m_BP1Writer; ///< format object will provide the - // required - // BP functionality to be applied on m_Buffer and m_Transports - - void Init(); ///< calls InitCapsules and InitTransports based on Method, - /// called from constructor - void InitCapsules(); - void InitTransports(); ///< from Transports - - std::string - GetMdtmParameter(const std::string parameter, - const std::map<std::string, std::string> &mdtmParameters); + void Init(); ///< called from constructor, gets the selected ADIOS1 + /// transport method from settings template <class T> Variable<T> *InquireVariableCommon(const std::string name, const bool readIn) { - std::cout << "Hello BPReaderCommon\n"; + std::cout << "Hello ADIOS1Reader::InquireVariableCommon\n"; // here read variable metadata (dimensions, type, etc.)...then create a // Variable like below: @@ -121,8 +114,10 @@ private: // return &variable; //return address if success return nullptr; // on failure } + + enum ADIOS_READ_METHOD read_method = ADIOS_READ_METHOD_BP; }; } // end namespace adios -#endif /* BPFILEREADER_H_ */ +#endif /* ADIOS1READER_H_ */ diff --git a/include/external/adios_selection.h b/include/external/adios_selection.h new file mode 100644 index 0000000000000000000000000000000000000000..551d72ee5f8ea6297f5367e12b3759abdb6fdb1a --- /dev/null +++ b/include/external/adios_selection.h @@ -0,0 +1,240 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + */ + +/* + * Streaming/Chunking/Selection Read API in C for ADIOS BP format + * + * A SELECTION is the data ranges resulting from a QUERY over a file and + * variable(s). + * + * A SELECTION can be a list of bounding boxes and point-sets. Other data + * structures + * are not supported. Any query will result in such a selection. + * Other selections are the write-block and auto. + * + * Write block is a block of data written + * by a writer process, it is identified by an index. If each writer outputs + * one block + * then the index equals to the rank of the write process. With multi-var + * writing and + * multiple steps in a file, index runs from 0 as rank 0 process' first block. + * + * Auto selection lets the read method to automatically choose what to return. + * It will + * be a block / blocks of selected writers. + * + * If a query is a simple bounding box, the selection is the bounding box + * itself, so + * the application does not need to retrieve the selection to work on the read + * data. + */ +#ifndef __ADIOS_SELECTION_C_H__ +#define __ADIOS_SELECTION_C_H__ + +#include <stdint.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/*************************/ +/* Types used in the API */ +/*************************/ + +typedef struct ADIOS_SELECTION_STRUCT ADIOS_SELECTION; + +/* Type of selection */ +enum ADIOS_SELECTION_TYPE +{ + ADIOS_SELECTION_BOUNDINGBOX = 0, /* Contiguous block of data defined by + offsets and counts in each dimension */ + ADIOS_SELECTION_POINTS = 1, /* List of individual points */ + ADIOS_SELECTION_WRITEBLOCK = + 2, /* Selection of an individual block written by a writer process */ + ADIOS_SELECTION_AUTO = 3 /* Let the method decide what to return */ +}; + +/* A Bounding Box */ +typedef struct +{ + int ndim; + uint64_t *start; + uint64_t *count; +} ADIOS_SELECTION_BOUNDINGBOX_STRUCT; + +/* A list of points. + * It is a 1D array of indices, linearized for all dimension + * (e.g. [i1,j1,k1,i2,j2,k2,...,in,jn,kn] for n points in a 3D space. + * If a container selection is given, points are relative coordinates/offsets in + * the + * container box/writeblock. + * 1D offsets in N-dimensional container are allowed. Such selections are + * returned by + * FASTBIT and ALACRITY query method. File reading is supported for such + * selections. + * adios_selection_points_1DtoND() can be used to convert 1D to N-D points. + */ +typedef struct +{ + int ndim; + int _free_points_on_delete; // user provided points are not copied, won't + // free either + uint64_t npoints; + uint64_t *points; + ADIOS_SELECTION + *container_selection; // a writeblock, a bounding box, or NULL +} ADIOS_SELECTION_POINTS_STRUCT; + +/* A selected block produced by a writer + * Identified with an index in current versions. + */ +typedef struct +{ + int index; + + /* NCSU ALACRITY-ADIOS: + * Adding timestep-relative vs. absolute writeblock selections, as + * well as sub-PG selection support. Both of these are currently only + * used by the transform layer + */ + int is_absolute_index; /* 0 if 'index' is relative to the current timestep, + != 0 + otherwise (i.e., absolute index) */ + int is_sub_pg_selection; /* Whether this writeblock selection contains + sub-PG bounds. + The following fields only matter if this is != 0 + */ + + /* Reads the linear range of elements in [element_offset, element_offset + + * nelements) */ + uint64_t element_offset; + uint64_t nelements; +} ADIOS_SELECTION_WRITEBLOCK_STRUCT; + +/* Let the read method decide what to return to each reading client. + * Hints are method-dependent parameters to influence what and how to + * return (e.g. the ordering of returned chunks, decomposition among + * read processes, etc.) + */ +typedef struct +{ + char *hints; +} ADIOS_SELECTION_AUTO_STRUCT; + +/** Selection for reading a subset of a variable. + * A selection is an additive list of bounding boxes and point-sets + */ +struct ADIOS_SELECTION_STRUCT +{ + enum ADIOS_SELECTION_TYPE type; /* Type of selection */ + union { + ADIOS_SELECTION_BOUNDINGBOX_STRUCT bb; + ADIOS_SELECTION_POINTS_STRUCT points; + ADIOS_SELECTION_WRITEBLOCK_STRUCT block; + ADIOS_SELECTION_AUTO_STRUCT autosel; + } u; + // ADIOS_SELECTION *next; +}; + +#ifndef __INCLUDED_FROM_FORTRAN_API__ + +/** Boundingbox selection to read a subset of a non-scalar variable. + * IN: + * ndim Number of dimensions + * start array of offsets to start reading in each dimension + * count number of data elements to read in each dimension + * RETURN: A selection which can be used to read variables + */ +ADIOS_SELECTION *adios_selection_boundingbox(int ndim, const uint64_t *start, + const uint64_t *count); + +/** Selection for a selection of an enumeration of positions. + * IN: + * ndim Number of dimensions + * npoints Number of points of the selection + * points 1D array of indices, compacted for all dimension + * (e.g. [i1,j1,k1,i2,j2,k2,...,in,jn,kn] for + * n points in a 3D space. + */ +ADIOS_SELECTION *adios_selection_points(int ndim, uint64_t npoints, + const uint64_t *points); + +/** Selection for a block of data coming from a certain producer. + * + * IN: + * index Identifier of the written block, starting from 0 for the + * first block + * written by producer rank 0. If each writer outputs one block + * then the index equals to the rank of the write process. + * With multi-var writing and multiple steps in a file, index + * should be + * calculated by the reading application using outside + * information beyond + * what is provided by the ADIOS Read API. + */ +ADIOS_SELECTION *adios_selection_writeblock(int index); + +/** Let the method decide what data gets to what reader process. + * This selection enables each reading method to provide an 'optimal' + * data transfer from writers to readers. It depends on the method and the + * circumstances, what this selection actually means. + * + * E.g. in situ processing: readers on a compute node will receive all data + * from the writers on the same compute node. + * + * IN: + * hints Method dependent parameters to influence what and how to + * return (e.g. decomposition; ordering of returned chunks) + */ +ADIOS_SELECTION *adios_selection_auto(char *hints); + +/** Make a strided hyperslab selection the same way as in HDF5. + * IN: + * ndim Number of dimentsions + * start array of offsets to start reading in each dimension + * strides striding steps, NULL=1 in all dimensions (= boundingbox) + * count number of data elements to read in each dimension + * blocks block size at each stride, NULL=1 in all dimensions + */ +/* + No support: Klasky, Podhorszki + Support: + +ADIOS_SELECTION* adios_selection_hyperslab (uint64_t ndim, uint64_t *start, +uint64_t *strides, + uint64_t *count, uint64_t *blocks); +*/ + +/** Delete a selection and free up memory used by the selection. + * IN: selection + * RESULT: None + * The ADIOS_SELECTION object can be simply freed by free(), too. + */ +void adios_selection_delete(ADIOS_SELECTION *selection); + +/* Convert one selection of 1D point offsets in a bounding box, + * returned by FASTBIT and ALACRITY query methods, to N-dimensional points. + * This function works only if there is a bounding box in + * pointsinbox1D->u.points.container! + * It allocates memory for the result selection, after which the original can be + * freed. + * Return: + * If global==0, the points will be relative to the container, if not, the + * points will be + * global coordinates (container's starting offsets added to each point) and + * result's container + * will be NULL. + */ +ADIOS_SELECTION *adios_selection_points_1DtoND(ADIOS_SELECTION *pointsinbox1D, + int global); + +#endif /*__INCLUDED_FROM_FORTRAN_API__*/ + +#ifdef __cplusplus +} +#endif + +#endif /*__ADIOS_SELECTION_C_H__*/ diff --git a/include/functions/adiosFunctions.h b/include/functions/adiosFunctions.h index ab6edba1df018dfd6a17d5b740a6fabcdf8574b1..4f33c22675b8ee7072f0c4917785e6fc1bfb6311 100644 --- a/include/functions/adiosFunctions.h +++ b/include/functions/adiosFunctions.h @@ -182,6 +182,12 @@ BuildParametersMap(const std::vector<std::string> ¶meters, */ std::vector<int> CSVToVectorInt(const std::string csv); +/** Convert a vector of uint64_t elements to a vector of std::size_t elements + * @param input vector of uint64_t elements + * @param output vector of std::size_t elements + */ +void ConvertUint64VectorToSizetVector(const std::vector<std::uint64_t> &in, + std::vector<std::size_t> &out); /** * Common strategy to check for heap buffer allocation for data and metadata * typically calculated in Write @@ -190,7 +196,8 @@ std::vector<int> CSVToVectorInt(const std::string csv); * buffers ( default = 1.5 ) * @param maxBufferSize user provided maximum buffer size * @param buffer to be reallocated - * @return true: must do a transport flush, false: buffer sizes are enough to + * @return true: must do a transport flush, false: buffer sizes are enough + * to * contain incoming data, no need for transport flush */ bool CheckBufferAllocation(const std::size_t newSize, const float growthFactor, diff --git a/include/selection/Selection.h b/include/selection/Selection.h new file mode 100644 index 0000000000000000000000000000000000000000..70d4c831409cb0e1cd7beeee0e121470acf39d1f --- /dev/null +++ b/include/selection/Selection.h @@ -0,0 +1,70 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + */ + +/* + * Selection API in C++ + * + * A SELECTION is the data ranges resulting from a QUERY over a file and + * variable(s). + * + * A SELECTION can be a list of bounding boxes and point-sets. Other data + * structures + * are not supported. Any query will result in such a selection. + * Other selections are the write-block and auto. + * + * Write block is a block of data written + * by a writer process, it is identified by an index. If each writer outputs + * one block + * then the index equals to the rank of the write process. With multi-var + * writing and + * multiple steps in a file, index runs from 0 as rank 0 process' first block. + * + * Auto selection lets the read method to automatically choose what to return. + * It will + * be a block / blocks of selected writers. + * + * If a query is a simple bounding box, the selection is the bounding box + * itself, so + * the application does not need to retrieve the selection to work on the read + * data. + */ +#ifndef __ADIOS_SELECTION_H__ +#define __ADIOS_SELECTION_H__ + +/// \cond EXCLUDE_FROM_DOXYGEN +#include "external/adios_selection.h" +#include <stdint.h> +/// \endcond + +namespace adios +{ + +/*************************/ +/* Types used in the API */ +/*************************/ +/* Type of selection */ +enum class SelectionType +{ + // Contiguous block of data defined by offsets and counts in each + // dimension + BoundingBox = ADIOS_SELECTION_BOUNDINGBOX, + // List of individual points + Points = ADIOS_SELECTION_POINTS, + // Selection of an individual block written by a writer process + WriteBlock = ADIOS_SELECTION_WRITEBLOCK, + // Let the method decide what to return + Auto = ADIOS_SELECTION_AUTO +}; + +class Selection +{ +public: + Selection(const SelectionType t) : m_Type(t){}; + const SelectionType m_Type; +}; + +} // namespace adios + +#endif /*__ADIOS_SELECTION_H__*/ diff --git a/include/selection/SelectionBoundingBox.h b/include/selection/SelectionBoundingBox.h new file mode 100644 index 0000000000000000000000000000000000000000..b110fd96e517a2ee7854db1bad92d422dfd3d5e1 --- /dev/null +++ b/include/selection/SelectionBoundingBox.h @@ -0,0 +1,38 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + */ + +#ifndef __ADIOS_SELECTION_BOUNDINGBOX_H__ +#define __ADIOS_SELECTION_BOUNDINGBOX_H__ + +/// \cond EXCLUDE_FROM_DOXYGEN +#include <cstdint> +/// \endcond + +#include "selection/Selection.h" + +namespace adios +{ + +/** Boundingbox selection to read a subset of a non-scalar variable. + * @param start array of offsets to start reading in each dimension + * @param count number of data elements to read in each dimension + */ +class SelectionBoundingBox : public Selection +{ +public: + SelectionBoundingBox(const std::vector<std::uint64_t> start, + const std::vector<std::uint64_t> count) + : Selection(SelectionType::BoundingBox), m_Start(start), m_Count(count) + { + } + ~SelectionBoundingBox(){}; + + std::vector<std::uint64_t> m_Start; + std::vector<std::uint64_t> m_Count; +}; + +} // namespace adios + +#endif /*__ADIOS_SELECTION_BOUNDINGBOX_H__*/ diff --git a/include/selection/SelectionPoints.h b/include/selection/SelectionPoints.h new file mode 100644 index 0000000000000000000000000000000000000000..13fa951cbaa587c2f1592e64dd9eeb46601d29cd --- /dev/null +++ b/include/selection/SelectionPoints.h @@ -0,0 +1,55 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + */ + +#ifndef __ADIOS_SELECTION_POINTS_H__ +#define __ADIOS_SELECTION_POINTS_H__ + +/// \cond EXCLUDE_FROM_DOXYGEN +#include <cstdint> +/// \endcond + +#include "selection/Selection.h" +#include "selection/SelectionBoundingBox.h" + +namespace adios +{ + +/** Selection for a selection of an enumeration of positions. + * @param ndim Number of dimensions + * @param npoints Number of points of the selection + * @param points 1D array of indices, compacted for all dimension + * (e.g. [i1,j1,k1,i2,j2,k2,...,in,jn,kn] for + * n points in a 3D space. + */ +class SelectionPoints : public Selection +{ +public: + SelectionPoints(std::size_t ndim, std::size_t npoints, + std::vector<std::uint64_t> &points) + : Selection(SelectionType::Points), m_Ndim(ndim), m_Npoints(npoints), + m_Points(points) + { + } + + ///< C-style constructor to be used in the C-to-C++ wrapper + SelectionPoints(std::size_t ndim, std::size_t npoints, uint64_t *points) + : Selection(SelectionType::Points), m_Ndim(ndim), m_Npoints(npoints), + m_Points(std::vector<std::uint64_t>()), m_PointsC(points) + { + } + + ~SelectionPoints(){}; + + const std::size_t m_Ndim; + const std::size_t m_Npoints; + std::vector<std::uint64_t> &m_Points; + ///< C-to-C++ wrapper needs a pointer to hold the points created by the C + /// application + std::uint64_t *m_PointsC = nullptr; +}; + +} // namespace adios + +#endif /*__ADIOS_SELECTION_POINTS_H__*/ diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt index 1b3472a4020d6a4cfea8858aea614bb1a04b24b5..d3340d88ae711916eb5b02d6fef3173c3533abf3 100644 --- a/source/CMakeLists.txt +++ b/source/CMakeLists.txt @@ -79,4 +79,34 @@ if(ADIOS_USE_MPI) target_include_directories(adios2 PUBLIC ${MPI_C_INCLUDE_PATH}) target_compile_definitions(adios2 PUBLIC ADIOS_HAVE_MPI) target_link_libraries(adios2 PUBLIC ${MPI_C_LIBRARIES}) +else() + target_sources(adios2 PRIVATE mpidummy.cpp) +endif() + +if(ADIOS_USE_ADIOS1) + find_package(ADIOS1 REQUIRED) + target_sources(adios2 PRIVATE + engine/adios1/ADIOS1Reader.cpp + engine/adios1/ADIOS1Writer.cpp + ) + target_compile_definitions(adios2 PRIVATE ADIOS_HAVE_ADIOS1) + target_link_libraries(adios2 PRIVATE adios1::adios) +endif() + +if(ADIOS_USE_DataMan) + find_package(DataMan REQUIRED) + target_sources(adios2 PRIVATE + engine/dataman/DataManReader.cpp + engine/dataman/DataManWriter.cpp + transport/wan/MdtmMan.cpp + ) + target_compile_definitions(adios2 PRIVATE ADIOS_HAVE_DATAMAN) + target_link_libraries(adios2 PRIVATE DataMan::DataMan) +endif() + +if(ADIOS_USE_BZip2) + find_package(BZip2 REQUIRED) + target_sources(adios2 PRIVATE transform/BZip2.cpp) + target_compile_definitions(adios2 PRIVATE ADIOS_HAVE_BZIP2) + target_link_libraries(adios2 PRIVATE BZip2::BZip2) endif() diff --git a/source/engine/adios1/ADIOS1Reader.cpp b/source/engine/adios1/ADIOS1Reader.cpp index e3ff93ec01d049bebf8e00c5a03485cc85ef5c2a..6f8fd564a959a147fe436a0f888651fe0ba8bac8 100644 --- a/source/engine/adios1/ADIOS1Reader.cpp +++ b/source/engine/adios1/ADIOS1Reader.cpp @@ -2,224 +2,165 @@ * Distributed under the OSI-approved Apache License, Version 2.0. See * accompanying file Copyright.txt for details. * - * BPFileReader.cpp + * ADIOS1Reader.cpp * * Created on: Feb 27, 2017 * Author: wfg */ -#include "engine/bp/BPFileReader.h" +#include "engine/adios1/ADIOS1Reader.h" +#include "ADIOS.h" -#include "core/Support.h" -#include "functions/adiosFunctions.h" //CSVToVector -#include "transport/file/FileDescriptor.h" // uses POSIX -#include "transport/file/FilePointer.h" // uses C FILE* - -// supported transports -#include "transport/file/FStream.h" // uses C++ fstream +extern int adios_verbose_level; +extern int adios_errno; namespace adios { -BPFileReader::BPFileReader(ADIOS &adios, const std::string name, +ADIOS1Reader::ADIOS1Reader(ADIOS &adios, const std::string name, const std::string accessMode, MPI_Comm mpiComm, const Method &method, const IOMode iomode, const float timeout_sec, const bool debugMode, const unsigned int nthreads) -: Engine(adios, "BPFileReader", name, accessMode, mpiComm, method, debugMode, - nthreads, " BPFileReader constructor (or call to ADIOS Open).\n"), - m_Buffer(accessMode, m_RankMPI, m_DebugMode) +: Engine(adios, "ADIOS1Reader", name, accessMode, mpiComm, method, debugMode, + nthreads, " ADIOS1Reader constructor (or call to ADIOS Open).\n") { Init(); + adios_read_init_method(read_method, m_MPIComm, ""); } -BPFileReader::~BPFileReader() {} +ADIOS1Reader::~ADIOS1Reader() { adios_read_finalize_method(read_method); } Variable<void> * -BPFileReader::InquireVariable(const std::string name, +ADIOS1Reader::InquireVariable(const std::string name, const bool readIn) // not yet implemented { return nullptr; } -Variable<char> *BPFileReader::InquireVariableChar(const std::string name, +Variable<char> *ADIOS1Reader::InquireVariableChar(const std::string name, const bool readIn) { return InquireVariableCommon<char>(name, readIn); } Variable<unsigned char> * -BPFileReader::InquireVariableUChar(const std::string name, const bool readIn) +ADIOS1Reader::InquireVariableUChar(const std::string name, const bool readIn) { return InquireVariableCommon<unsigned char>(name, readIn); } -Variable<short> *BPFileReader::InquireVariableShort(const std::string name, +Variable<short> *ADIOS1Reader::InquireVariableShort(const std::string name, const bool readIn) { return InquireVariableCommon<short>(name, readIn); } Variable<unsigned short> * -BPFileReader::InquireVariableUShort(const std::string name, const bool readIn) +ADIOS1Reader::InquireVariableUShort(const std::string name, const bool readIn) { return InquireVariableCommon<unsigned short>(name, readIn); } -Variable<int> *BPFileReader::InquireVariableInt(const std::string name, +Variable<int> *ADIOS1Reader::InquireVariableInt(const std::string name, const bool readIn) { return InquireVariableCommon<int>(name, readIn); } Variable<unsigned int> * -BPFileReader::InquireVariableUInt(const std::string name, const bool readIn) +ADIOS1Reader::InquireVariableUInt(const std::string name, const bool readIn) { return InquireVariableCommon<unsigned int>(name, readIn); } -Variable<long int> *BPFileReader::InquireVariableLInt(const std::string name, +Variable<long int> *ADIOS1Reader::InquireVariableLInt(const std::string name, const bool readIn) { return InquireVariableCommon<long int>(name, readIn); } Variable<unsigned long int> * -BPFileReader::InquireVariableULInt(const std::string name, const bool readIn) +ADIOS1Reader::InquireVariableULInt(const std::string name, const bool readIn) { return InquireVariableCommon<unsigned long int>(name, readIn); } Variable<long long int> * -BPFileReader::InquireVariableLLInt(const std::string name, const bool readIn) +ADIOS1Reader::InquireVariableLLInt(const std::string name, const bool readIn) { return InquireVariableCommon<long long int>(name, readIn); } Variable<unsigned long long int> * -BPFileReader::InquireVariableULLInt(const std::string name, const bool readIn) +ADIOS1Reader::InquireVariableULLInt(const std::string name, const bool readIn) { return InquireVariableCommon<unsigned long long int>(name, readIn); } -Variable<float> *BPFileReader::InquireVariableFloat(const std::string name, +Variable<float> *ADIOS1Reader::InquireVariableFloat(const std::string name, const bool readIn) { return InquireVariableCommon<float>(name, readIn); } -Variable<double> *BPFileReader::InquireVariableDouble(const std::string name, +Variable<double> *ADIOS1Reader::InquireVariableDouble(const std::string name, const bool readIn) { return InquireVariableCommon<double>(name, readIn); } Variable<long double> * -BPFileReader::InquireVariableLDouble(const std::string name, const bool readIn) +ADIOS1Reader::InquireVariableLDouble(const std::string name, const bool readIn) { return InquireVariableCommon<long double>(name, readIn); } Variable<std::complex<float>> * -BPFileReader::InquireVariableCFloat(const std::string name, const bool readIn) +ADIOS1Reader::InquireVariableCFloat(const std::string name, const bool readIn) { return InquireVariableCommon<std::complex<float>>(name, readIn); } Variable<std::complex<double>> * -BPFileReader::InquireVariableCDouble(const std::string name, const bool readIn) +ADIOS1Reader::InquireVariableCDouble(const std::string name, const bool readIn) { return InquireVariableCommon<std::complex<double>>(name, readIn); } Variable<std::complex<long double>> * -BPFileReader::InquireVariableCLDouble(const std::string name, const bool readIn) +ADIOS1Reader::InquireVariableCLDouble(const std::string name, const bool readIn) { return InquireVariableCommon<std::complex<long double>>(name, readIn); } -VariableCompound *BPFileReader::InquireVariableCompound(const std::string name, +VariableCompound *ADIOS1Reader::InquireVariableCompound(const std::string name, const bool readIn) { return nullptr; } -void BPFileReader::Close(const int transportIndex) {} +void ADIOS1Reader::Close(const int transportIndex) {} // PRIVATE -void BPFileReader::Init() +void ADIOS1Reader::Init() { if (m_DebugMode == true) { if (m_AccessMode != "r" && m_AccessMode != "read") throw std::invalid_argument( - "ERROR: BPFileReader doesn't support access mode " + + "ERROR: ADIOS1Reader doesn't support access mode " + m_AccessMode + - ", in call to ADIOS Open or BPFileReader constructor\n"); - } - - InitCapsules(); - InitTransports(); -} - -void BPFileReader::InitCapsules() -{ - // here init memory capsules -} - -void BPFileReader::InitTransports() // maybe move this? -{ - if (m_DebugMode == true) - { - if (TransportNamesUniqueness() == false) - { - throw std::invalid_argument( - "ERROR: two transports of the same kind (e.g file IO) " - "can't have the same name, modify with name= in Method " - "AddTransport\n"); - } + ", in call to ADIOS Open or ADIOS1Reader constructor\n"); } for (const auto ¶meters : m_Method.m_TransportParameters) { auto itTransport = parameters.find("transport"); - if (itTransport->second == "file" || itTransport->second == "File") + if (itTransport->second == "file" || itTransport->second == "File" || + itTransport->second == "bp" || itTransport->second == "BP") { - auto itLibrary = parameters.find("library"); - if (itLibrary == parameters.end() || - itLibrary->second == "POSIX") // use default POSIX - { - auto file = std::make_shared<transport::FileDescriptor>( - m_MPIComm, m_DebugMode); - // m_BP1Reader.OpenRankFiles( m_Name, m_AccessMode, *file ); - m_Transports.push_back(std::move(file)); - } - else if (itLibrary->second == "FILE*" || - itLibrary->second == "stdio.h") - { - auto file = std::make_shared<transport::FilePointer>( - m_MPIComm, m_DebugMode); - // m_BP1Reader.OpenRankFiles( m_Name, m_AccessMode, *file ); - m_Transports.push_back(std::move(file)); - } - else if (itLibrary->second == "fstream" || - itLibrary->second == "std::fstream") - { - auto file = std::make_shared<transport::FStream>(m_MPIComm, - m_DebugMode); - // m_BP1Reader.OpenRankFiles( m_Name, m_AccessMode, *file ); - m_Transports.push_back(std::move(file)); - } - else if (itLibrary->second == "MPI-IO") - { - } - else - { - if (m_DebugMode == true) - throw std::invalid_argument( - "ERROR: file transport library " + itLibrary->second + - " not supported, in " + m_Name + m_EndMessage); - } + read_method = ADIOS_READ_METHOD_BP; } else { diff --git a/source/functions/adiosFunctions.cpp b/source/functions/adiosFunctions.cpp index f2d703b5b09c82f8f3775669ebdf8952d90e1d51..032d3aeb6238c0d8bfd0abe324971b465f49b8fe 100644 --- a/source/functions/adiosFunctions.cpp +++ b/source/functions/adiosFunctions.cpp @@ -633,6 +633,17 @@ std::vector<int> CSVToVectorInt(const std::string csv) return numbers; } +void ConvertUint64VectorToSizetVector(const std::vector<std::uint64_t> &in, + std::vector<std::size_t> &out) +{ + out.clear(); + out.reserve(in.size()); + for (const auto inElement : in) + { + out.push_back(static_cast<std::size_t>(inElement)); + } +} + bool CheckBufferAllocation(const std::size_t newSize, const float growthFactor, const std::size_t maxBufferSize, std::vector<char> &buffer)