diff --git a/.github/ISSUE_TEMPLATE/new_release.md b/.github/ISSUE_TEMPLATE/new_release.md index a60870a8a8..809132eebc 100644 --- a/.github/ISSUE_TEMPLATE/new_release.md +++ b/.github/ISSUE_TEMPLATE/new_release.md @@ -33,7 +33,7 @@ git push - [ ] Create PR (BASE to master if release_@MAJOR@@MINOR@ does not exists; otherwise release_@MAJOR@@MINOR@) - [ ] Ask for review - [ ] Merge PR -- [ ] Create Tag commit `git tag -a v@VERSION@ the_merge_commit` +- [ ] Create Tag commit `git tag -a -m 'v@VERSION' v@VERSION@ the_merge_commit` - [ ] Create Release in GitHub page - Use the following script for getting the PR of this release - `./scripts/developer/create-changelog.sh v@VERSION@ v@OLD_RELEASE@` @@ -66,5 +66,8 @@ git push origin master - CondaForge robot should do this for you automatically, expect a new PR at https://github.com/conda-forge/adios2-feedstock a couple of hours after the release. +- [ ] Submit a MR for ParaView Superbuild to use v@VERSION@ release. +- [ ] Update the website to point to the v@VERSION@ release - [ ] Write an announcement in the ADIOS-ECP mail-list (https://groups.google.com/a/kitware.com/g/adios-ecp) + diff --git a/.github/workflows/everything.yml b/.github/workflows/everything.yml index ea3e35d732..a2eb4a60de 100644 --- a/.github/workflows/everything.yml +++ b/.github/workflows/everything.yml @@ -51,7 +51,7 @@ jobs: outputs: num_code_changes: ${{ steps.get_code_changes.outputs.num_code_changes }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Check for appropriately named topic branch @@ -80,10 +80,10 @@ jobs: image: ghcr.io/ornladios/adios2:ci-formatting steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: path: gha - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: ref: ${{ github.event.pull_request.head.sha }} path: source @@ -153,10 +153,10 @@ jobs: shared: static parallel: serial steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: path: gha - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: ref: ${{ github.event.pull_request.head.sha }} path: source @@ -218,10 +218,10 @@ jobs: parallel: [ompi] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: path: gha - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: ref: ${{ github.event.pull_request.head.sha }} path: source @@ -285,10 +285,10 @@ jobs: compiler: xcode13_4_1 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: path: gha - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: ref: ${{ github.event.pull_request.head.sha }} path: source @@ -352,10 +352,10 @@ jobs: shell: bash steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: path: gha - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: ref: ${{ github.event.pull_request.head.sha }} path: source @@ -386,7 +386,7 @@ jobs: baseos: [ubuntu-bionic] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: ref: ${{ github.event.pull_request.head.sha }} path: ci-source @@ -448,24 +448,19 @@ jobs: strategy: fail-fast: false matrix: - code: [examples, lammps, tau] + code: [lammps, tau] include: - - code: examples - repo: ornladios/ADIOS2-Examples - ref: master - code: lammps repo: pnorbert/lammps ref: fix-deprecated-adios-init - code: tau - repo: ornladios/ADIOS2-Examples - ref: master - defaults: run: shell: bash -c "docker exec adios2-ci bash --login -e $(echo {0} | sed 's|/home/runner/work|/__w|g')" steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 + if: ${{ matrix.repo != '' }} with: repository: ${{ matrix.repo }} ref: ${{ matrix.ref }} @@ -523,10 +518,10 @@ jobs: language: [ 'cpp' ] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: path: gha - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: ref: ${{ github.event.pull_request.head.sha }} path: source @@ -535,8 +530,10 @@ jobs: with: languages: ${{ matrix.language }} config: | + paths: + - source paths-ignore: - - source/thirdparty/ + - source/thirdparty - name: Setup run: gha/scripts/ci/gh-actions/linux-setup.sh - name: Update diff --git a/.gitlab/config/SpackCIBridge.py b/.gitlab/config/SpackCIBridge.py index 72c189e480..07838725dd 100755 --- a/.gitlab/config/SpackCIBridge.py +++ b/.gitlab/config/SpackCIBridge.py @@ -169,7 +169,7 @@ def list_github_prs(self): # Check if we should defer pushing/testing this PR because it is based on "too new" of a commit # of the main branch. tmp_pr_branch = f"temporary_{pr_string}" - subprocess.run(["git", "fetch", "--unshallow", "github", + subprocess.run(["git", "fetch", "github", f"refs/pull/{pull.number}/head:{tmp_pr_branch}"], check=True) # Get the merge base between this PR and the main branch. try: @@ -226,7 +226,7 @@ def list_github_prs(self): # then we will push the merge commit that was automatically created by GitHub to GitLab # where it will kick off a CI pipeline. try: - subprocess.run(["git", "fetch", "--unshallow", "github", + subprocess.run(["git", "fetch", "github", f"{pull.merge_commit_sha}:{pr_string}"], check=True) except subprocess.CalledProcessError: print("Failed to locally checkout PR {0} ({1}). Skipping" @@ -306,7 +306,7 @@ def setup_git_repo(self): self.gitlab_shallow_fetch() if self.main_branch: - subprocess.run(["git", "fetch", "--unshallow", "github", self.main_branch], check=True) + subprocess.run(["git", "fetch", "github", self.main_branch], check=True) def get_gitlab_pr_branches(self): """Query GitLab for branches that have already been copied over from GitHub PRs. @@ -350,7 +350,7 @@ def update_refspecs_for_tags(self, tags, open_refspecs, fetch_refspecs): def fetch_github_branches(self, fetch_refspecs): """Perform `git fetch` for a given list of refspecs.""" print("Fetching GitHub refs for open PRs") - fetch_args = ["git", "fetch", "-q", "--unshallow", "github"] + fetch_refspecs + fetch_args = ["git", "fetch", "-q", "github"] + fetch_refspecs subprocess.run(fetch_args, check=True) def build_local_branches(self, protected_branches): diff --git a/.gitlab/config/generate_pipelines.py b/.gitlab/config/generate_pipelines.py index 15a70cfde3..bb8528ccf1 100755 --- a/.gitlab/config/generate_pipelines.py +++ b/.gitlab/config/generate_pipelines.py @@ -18,9 +18,43 @@ urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) -def request_as_dict(url): - r = requests.get(url + '?per_page=100', verify=False) - return r.json() +class skip_after_n_successes: + def __init__(self, default_value, n): + self.runs_max = n + self.runs_current = 0 + self.default_value = default_value + + def __call__(self, fn, *args, **kwargs): + if self.runs_current >= self.runs_max: + return self.default_value + + ret = fn(*args, **kwargs) + if ret: + self.runs_current += 1 + return ret + + +def http_get_request(*args, **kwargs): + kwargs['verify'] = False + return requests.get(*args, **kwargs) + + +def request_as_list(url, *args, **kwargs): + current_url = url + body_json = [] + while current_url: + response = http_get_request(current_url, *args, **kwargs) + body_json += response.json() + + header = response.headers + current_url = None + if 'link' in header: + links = re.search( + r'(?<=\<)([\S]*)(?=>; rel="next")', header['link'], flags=re.IGNORECASE) + if links is not None: + current_url = links.group(0) + + return body_json def add_timestamp(branch): @@ -44,7 +78,12 @@ def has_no_status(branch): gh_commit_sha = branch['commit']['parent_ids'][1] # Query GitHub for the status of this commit - commit = request_as_dict(gh_url + '/commits/' + gh_commit_sha + '/status') + response = http_get_request( + gh_url + '/commits/' + gh_commit_sha + '/status') + if int(response.headers['x-ratelimit-remaining']) <= 0: + raise ConnectionError(response.json()) + + commit = response.json() if commit is None or 'sha' not in commit: return False @@ -88,14 +127,15 @@ def has_no_status(branch): with open(args.template_file, 'r') as fd: template_str = fd.read() - branches = request_as_dict(gl_url + '/repository/branches') - branches = map(add_timestamp, branches) - branches = filter(is_recent, branches) - branches = filter(has_no_status, branches) - - # Select the arg.max most least recent branches + branches = request_as_list(gl_url + '/repository/branches') + branches = [add_timestamp(branch) for branch in branches] + branches = [b for b in branches if is_recent(b)] branches = sorted(branches, key=lambda x: x['dt']) - branches = itertools.islice(branches, args.max) + + # Skip running (and return true) has_no_status after returning True args.max times. + # We need this not to hog the Github Rest API draconian ratelimit. + run_n_times = skip_after_n_successes(default_value=False, n=args.max) + branches = [b for b in branches if run_n_times(has_no_status, b)] for branch in branches: print(template_str.format( diff --git a/.shellcheck_exclude_paths b/.shellcheck_exclude_paths index 1ef95d56a2..e84d523737 100644 --- a/.shellcheck_exclude_paths +++ b/.shellcheck_exclude_paths @@ -15,3 +15,18 @@ scripts/developer/setup.sh scripts/docker/setup-user.sh scripts/runconf/runconf.sh scripts/runconf/runconf_olcf.sh +testing/contract/lammps/build.sh +testing/contract/lammps/config.sh +testing/contract/lammps/install.sh +testing/contract/lammps/setup.sh +testing/contract/lammps/test.sh +testing/contract/scorpio/build.sh +testing/contract/scorpio/config.sh +testing/contract/scorpio/install.sh +testing/contract/scorpio/setup.sh +testing/contract/scorpio/test.sh +testing/contract/tau/build.sh +testing/contract/tau/config.sh +testing/contract/tau/install.sh +testing/contract/tau/setup.sh +testing/contract/tau/test.sh diff --git a/CMakeLists.txt b/CMakeLists.txt index fe60999754..3205c66ff6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -137,7 +137,11 @@ if((NOT BUILD_SHARED_LIBS) AND (NOT DEFINED CMAKE_POSITION_INDEPENDENT_CODE)) set(CMAKE_POSITION_INDEPENDENT_CODE ON) endif() +# Ctest creates BUILD_TESTING option and sets it to true by default +# Here we disable BUILD_TESTING option by default +option(BUILD_TESTING "Build testing" OFF) include(CTest) +mark_as_advanced(CLEAR BUILD_TESTING) adios_option(Blosc2 "Enable support for c-blosc-2 transforms" AUTO) adios_option(BZip2 "Enable support for BZip2 transforms" AUTO) @@ -166,8 +170,10 @@ adios_option(Profiling "Enable support for profiling" AUTO) adios_option(Endian_Reverse "Enable support for Little/Big Endian Interoperability" AUTO) adios_option(Sodium "Enable support for Sodium for encryption" AUTO) adios_option(Catalyst "Enable support for in situ visualization plugin using ParaView Catalyst" AUTO) -adios_option(AWSSDK "Enable support for S3 compatible storage using AWS SDK's S3 module" AUTO) -adios_option(SQLite3 "Enable support for SQLite3 required by campaign manager" AUTO) +adios_option(SQLite3 "Enable support for SQLite3 required by campaign manager" OFF) +adios_option(AWSSDK "Enable support for S3 compatible storage using AWS SDK's S3 module" OFF) +adios_option(Derived_Variable "Enable support for derived variables" OFF) +>>>>>>> master include(${PROJECT_SOURCE_DIR}/cmake/DetectOptions.cmake) if(ADIOS2_HAVE_CUDA OR ADIOS2_HAVE_Kokkos_CUDA) @@ -177,7 +183,7 @@ if(ADIOS2_HAVE_CUDA OR ADIOS2_HAVE_Kokkos_CUDA) if(DEFINED Kokkos_CUDA_ARCHITECTURES) set(CMAKE_CUDA_ARCHITECTURES ${Kokkos_CUDA_ARCHITECTURES}) else() - # Mininum common non-deprecated architecture + # Minimum common non-deprecated architecture set(CMAKE_CUDA_ARCHITECTURES 52) endif() endif() @@ -240,8 +246,8 @@ endif() set(ADIOS2_CONFIG_OPTS DataMan DataSpaces HDF5 HDF5_VOL MHS SST Fortran MPI Python Blosc2 BZip2 LIBPRESSIO MGARD PNG SZ ZFP DAOS IME O_DIRECT Sodium Catalyst SysVShMem UCX - ZeroMQ Profiling Endian_Reverse AWSSDK GPU_Support CUDA Kokkos Kokkos_CUDA - Kokkos_HIP Kokkos_SYCL SQLite3 + ZeroMQ Profiling Endian_Reverse Derived_Variable AWSSDK GPU_Support CUDA Kokkos + Kokkos_CUDA Kokkos_HIP Kokkos_SYCL SQLite3 ) GenerateADIOSHeaderConfig(${ADIOS2_CONFIG_OPTS}) @@ -288,12 +294,15 @@ if(BUILD_SHARED_LIBS AND ADIOS2_RUN_INSTALL_TEST) endif() endif() +if(MSVC AND BUILD_SHARED_LIBS AND ADIOS2_HAVE_HDF5) + # See note about building with visual studio and shared libs, here: + # https://github.com/HDFGroup/hdf5/blob/develop/release_docs/USING_HDF5_VS.txt + add_definitions(-DH5_BUILT_AS_DYNAMIC_LIB=1) +endif() #------------------------------------------------------------------------------# # Third party libraries #------------------------------------------------------------------------------# -include(CTest) -mark_as_advanced(BUILD_TESTING) add_subdirectory(thirdparty) #------------------------------------------------------------------------------# @@ -314,8 +323,7 @@ add_subdirectory(plugins) #------------------------------------------------------------------------------# # Examples #------------------------------------------------------------------------------# -option(ADIOS2_BUILD_EXAMPLES "Build examples" ON) -option(ADIOS2_BUILD_EXAMPLES_EXPERIMENTAL "Build experimental examples" OFF) +option(ADIOS2_BUILD_EXAMPLES "Build examples" OFF) if(ADIOS2_BUILD_EXAMPLES) add_subdirectory(examples) endif() diff --git a/ReadMe.md b/ReadMe.md index 4cc8e72b88..9e73588a36 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -70,7 +70,7 @@ Once ADIOS2 is installed refer to: ## Releases -* Latest release: [v2.9.0](https://github.com/ornladios/ADIOS2/releases/tag/v2.9.0) +* Latest release: [v2.9.2](https://github.com/ornladios/ADIOS2/releases/tag/v2.9.2) * Previous releases: [https://github.com/ornladios/ADIOS2/releases](https://github.com/ornladios/ADIOS2/releases) @@ -78,7 +78,6 @@ Once ADIOS2 is installed refer to: ADIOS2 is an open source project: Questions, discussion, and contributions are welcome. Join us at: -- Slack workspace: [![Slack](https://img.shields.io/badge/slack-ADIOS2-pink.svg)](https://adios2.spack.io) - Mailing list: adios-ecp@kitware.com - Github Discussions: https://github.com/ornladios/ADIOS2/discussions diff --git a/bindings/CXX11/CMakeLists.txt b/bindings/CXX11/CMakeLists.txt index 861764313b..76cf76120b 100644 --- a/bindings/CXX11/CMakeLists.txt +++ b/bindings/CXX11/CMakeLists.txt @@ -37,6 +37,12 @@ target_include_directories(adios2_cxx11 add_library(adios2::cxx11 ALIAS adios2_cxx11) +if (ADIOS2_HAVE_Derived_Variable) + target_sources(adios2_cxx11 PRIVATE + adios2/cxx11/VariableDerived.cpp + ) +endif() + if(ADIOS2_HAVE_MPI) add_library(adios2_cxx11_mpi adios2/cxx11/ADIOSMPI.cpp @@ -79,6 +85,14 @@ install( COMPONENT adios2_cxx11-development ) +if (ADIOS2_HAVE_Derived_Variable) + install( + FILES adios2/cxx11/VariableDerived.h + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/adios2/cxx11 + COMPONENT adios2_cxx11-development + ) +endif() + install( FILES adios2/cxx11/ADIOS.h adios2/cxx11/ADIOS.inl diff --git a/bindings/CXX11/adios2/cxx11/IO.cpp b/bindings/CXX11/adios2/cxx11/IO.cpp index 8018c06d77..e8edb54528 100644 --- a/bindings/CXX11/adios2/cxx11/IO.cpp +++ b/bindings/CXX11/adios2/cxx11/IO.cpp @@ -179,6 +179,16 @@ VariableNT IO::DefineVariable(const DataType type, const std::string &name, cons } } +#ifdef ADIOS2_HAVE_DERIVED_VARIABLE +VariableDerived IO::DefineDerivedVariable(const std::string &name, const std::string &expression, + const DerivedVarType varType) +{ + helper::CheckForNullptr(m_IO, + "for variable name " + name + ", in call to IO::DefineDerivedVariable"); + + return VariableDerived(&m_IO->DefineDerivedVariable(name, expression, varType)); +} +#endif StructDefinition IO::DefineStruct(const std::string &name, const size_t size) { helper::CheckForNullptr(m_IO, "for struct name " + name + ", in call to IO::DefineStruct"); diff --git a/bindings/CXX11/adios2/cxx11/IO.h b/bindings/CXX11/adios2/cxx11/IO.h index 1702c769f4..2b599e3695 100644 --- a/bindings/CXX11/adios2/cxx11/IO.h +++ b/bindings/CXX11/adios2/cxx11/IO.h @@ -20,6 +20,9 @@ #include "Group.h" #include "Operator.h" #include "Variable.h" +#ifdef ADIOS2_HAVE_DERIVED_VARIABLE +#include "VariableDerived.h" +#endif #include "VariableNT.h" #include "adios2/common/ADIOSMacros.h" #include "adios2/common/ADIOSTypes.h" @@ -151,7 +154,11 @@ class IO Variable DefineVariable(const std::string &name, const Dims &shape = Dims(), const Dims &start = Dims(), const Dims &count = Dims(), const bool constantDims = false); - +#ifdef ADIOS2_HAVE_DERIVED_VARIABLE + VariableDerived + DefineDerivedVariable(const std::string &name, const std::string &expression, + const DerivedVarType varType = DerivedVarType::MetadataOnly); +#endif VariableNT DefineVariable(const DataType type, const std::string &name, const Dims &shape = Dims(), const Dims &start = Dims(), const Dims &count = Dims(), const bool constantDims = false); diff --git a/bindings/CXX11/adios2/cxx11/Query.cpp b/bindings/CXX11/adios2/cxx11/Query.cpp index 23bbd8c6c6..099b68a818 100644 --- a/bindings/CXX11/adios2/cxx11/Query.cpp +++ b/bindings/CXX11/adios2/cxx11/Query.cpp @@ -14,10 +14,22 @@ QueryWorker::QueryWorker(const std::string &configFile, adios2::Engine &reader) delete m; } -void QueryWorker::GetResultCoverage(adios2::Box &outputSelection, +void QueryWorker::GetResultCoverage(std::vector &touched_blockIDs) +{ + m_Worker->GetResultCoverage(touched_blockIDs); +} + +void QueryWorker::GetResultCoverage(std::vector> &touched_blocks) +{ + adios2::Box empty; + GetResultCoverage(empty, touched_blocks); +} + +void QueryWorker::GetResultCoverage(const adios2::Box &outputSelection, std::vector> &touched_blocks) { if (m_Worker) return m_Worker->GetResultCoverage(outputSelection, touched_blocks); } -} + +} // namespace diff --git a/bindings/CXX11/adios2/cxx11/Query.h b/bindings/CXX11/adios2/cxx11/Query.h index a4dd046d38..0cd5750bbf 100644 --- a/bindings/CXX11/adios2/cxx11/Query.h +++ b/bindings/CXX11/adios2/cxx11/Query.h @@ -26,9 +26,16 @@ class Worker; class QueryWorker { public: + // configFile has query, can be either xml or json QueryWorker(const std::string &configFile, adios2::Engine &engine); - void GetResultCoverage(adios2::Box &, + void GetResultCoverage(std::vector &touched_block_ids); + // touched_blocks is a list of regions specified by (start, count), + // that contains data that satisfies the query file + void GetResultCoverage(std::vector> &touched_blocks); + + // supply output bound for the results + void GetResultCoverage(const adios2::Box &, std::vector> &touched_blocks); private: diff --git a/bindings/CXX11/adios2/cxx11/VariableDerived.cpp b/bindings/CXX11/adios2/cxx11/VariableDerived.cpp new file mode 100644 index 0000000000..ce6a4dc0e5 --- /dev/null +++ b/bindings/CXX11/adios2/cxx11/VariableDerived.cpp @@ -0,0 +1,8 @@ +#include "VariableDerived.h" + +#include "adios2/core/VariableDerived.h" + +namespace adios2 +{ +VariableDerived::VariableDerived(core::VariableDerived *variable) : m_VariableDerived(variable) {} +} // end namespace adios2 diff --git a/bindings/CXX11/adios2/cxx11/VariableDerived.h b/bindings/CXX11/adios2/cxx11/VariableDerived.h new file mode 100644 index 0000000000..cc69273c2e --- /dev/null +++ b/bindings/CXX11/adios2/cxx11/VariableDerived.h @@ -0,0 +1,43 @@ +#ifndef ADIOS2_BINDINGS_CXX11_VARIABLE_DERIVED_H_ +#define ADIOS2_BINDINGS_CXX11_VARIABLE_DERIVED_H_ + +#include "Operator.h" +#include "adios2/common/ADIOSTypes.h" + +namespace adios2 +{ + +/// \cond EXCLUDE_FROM_DOXYGEN +// forward declare +class IO; // friend +namespace core +{ + +class VariableDerived; // private implementation +} +/// \endcond + +class VariableDerived +{ + friend class IO; + +public: + /** + * Empty (default) constructor, use it as a placeholder for future + * variables from IO:DefineVariableDerived or IO:InquireVariableDerived. + * Can be used with STL containers. + */ + VariableDerived() = default; + + /** Default, using RAII STL containers */ + ~VariableDerived() = default; + +private: + core::VariableDerived *m_VariableDerived = nullptr; + + VariableDerived(core::VariableDerived *variable); +}; + +} // end namespace adios2 + +#endif // ADIOS2_BINDINGS_CXX11_VARIABLE_DERIVED_H_ diff --git a/bindings/Fortran/CMakeLists.txt b/bindings/Fortran/CMakeLists.txt index 2e0cb2c1b3..1a998bbe95 100644 --- a/bindings/Fortran/CMakeLists.txt +++ b/bindings/Fortran/CMakeLists.txt @@ -103,7 +103,7 @@ if(ADIOS2_HAVE_MPI) PRIVATE adios2_c_mpi adios2_core_mpi - PUBLIC + INTERFACE MPI::MPI_Fortran ) target_compile_definitions(adios2_fortran_mpi PRIVATE "$<$:ADIOS2_HAVE_FORTRAN_SUBMODULES;ADIOS2_HAVE_MPI_F>") diff --git a/bindings/Matlab/README.txt b/bindings/Matlab/README.txt index 4c43c89ffe..0a5b412ce0 100644 --- a/bindings/Matlab/README.txt +++ b/bindings/Matlab/README.txt @@ -43,5 +43,5 @@ $ cd $ git pull $ mkdir build.lean $ cd build.lean -$ cmake -DCMAKE_INSTALL_PREFIX=/opt/adios/lean -DADIOS2_USE_MPI=OFF -DADIOS2_USE_Fortran=OFF -DADIOS2_USE_Python=OFF -DADIOS2_BUILD_EXAMPLES_EXPERIMENTAL=OFF -DCMAKE_BUILD_TYPE=RelWithDebInfo -DADIOS2_ENABLE_PIC=ON -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DBUILD_TESTING=OFF -DADIOS2_USE_SST=OFF -DADIOS2_USE_BZip2=OFF -DADIOS2_USE_DataMan=OFF .. +$ cmake -DCMAKE_INSTALL_PREFIX=/opt/adios/lean -DADIOS2_USE_MPI=OFF -DADIOS2_USE_Fortran=OFF -DADIOS2_USE_Python=OFF -DCMAKE_BUILD_TYPE=RelWithDebInfo -DADIOS2_ENABLE_PIC=ON -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DADIOS2_USE_SST=OFF -DADIOS2_USE_BZip2=OFF -DADIOS2_USE_DataMan=OFF .. diff --git a/bindings/Python/py11Query.cpp b/bindings/Python/py11Query.cpp index 87c2014967..01c8cdb050 100644 --- a/bindings/Python/py11Query.cpp +++ b/bindings/Python/py11Query.cpp @@ -30,12 +30,18 @@ Query::operator bool() const noexcept { return (m_QueryWorker == nullptr) ? fals std::vector> Query::GetResult() { - // std::cout<<"Do something"< empty; // look into all data std::vector> touched_blocks; + adios2::Box empty; m_QueryWorker->GetResultCoverage(empty, touched_blocks); return touched_blocks; } +std::vector Query::GetBlockIDs() +{ + std::vector touched_block_ids; + m_QueryWorker->GetResultCoverage(touched_block_ids); + return touched_block_ids; +} + } // py11 } // adios2 diff --git a/bindings/Python/py11Query.h b/bindings/Python/py11Query.h index df04fd3e59..64768f0b7d 100644 --- a/bindings/Python/py11Query.h +++ b/bindings/Python/py11Query.h @@ -34,8 +34,7 @@ class Query explicit operator bool() const noexcept; std::vector> GetResult(); - // const Box< Dims > & refinedSelectionIfAny, - // std::vector< Box< Dims > > &touched_blocks + std::vector GetBlockIDs(); private: Query(adios2::query::Worker *qw); diff --git a/bindings/Python/py11glue.cpp b/bindings/Python/py11glue.cpp index b9f239b603..128c52d941 100644 --- a/bindings/Python/py11glue.cpp +++ b/bindings/Python/py11glue.cpp @@ -357,7 +357,8 @@ PYBIND11_MODULE(ADIOS2_PYTHON_MODULE_NAME, m) "adios2 query construction, a xml query File and a read engine", pybind11::arg("queryFile"), pybind11::arg("reader") = true) - .def("GetResult", &adios2::py11::Query::GetResult); + .def("GetResult", &adios2::py11::Query::GetResult) + .def("GetBlockIDs", &adios2::py11::Query::GetBlockIDs); pybind11::class_(m, "Variable") // Python 2 diff --git a/cmake/ADIOSFunctions.cmake b/cmake/ADIOSFunctions.cmake index 7d26bcc355..71d6ab994c 100644 --- a/cmake/ADIOSFunctions.cmake +++ b/cmake/ADIOSFunctions.cmake @@ -97,7 +97,7 @@ function(GenerateADIOSHeaderConfig) foreach(OPT IN LISTS ARGN) string(TOUPPER ${OPT} OPT_UPPER) string(APPEND ADIOS2_CONFIG_DEFINES " -/* CMake Option: ADIOS_USE_${OPT}=OFF */ +/* CMake Option: ADIOS2_USE_${OPT}=OFF */ #cmakedefine ADIOS2_HAVE_${OPT_UPPER} ") if(ADIOS2_HAVE_${OPT}) diff --git a/cmake/DetectOptions.cmake b/cmake/DetectOptions.cmake index e8b6d09718..33684354c0 100644 --- a/cmake/DetectOptions.cmake +++ b/cmake/DetectOptions.cmake @@ -67,6 +67,9 @@ function(lists_get_prefix listVars outVar) set(${outVar} "${prefix}" PARENT_SCOPE) endfunction() +# Multithreading +find_package(Threads REQUIRED) + # Blosc2 if(ADIOS2_USE_Blosc2 STREQUAL AUTO) # Prefect CONFIG mode @@ -76,7 +79,7 @@ if(ADIOS2_USE_Blosc2 STREQUAL AUTO) endif() elseif(ADIOS2_USE_Blosc2) # Prefect CONFIG mode - find_package(Blosc2 2.4 CONFIG REQUIRED) + find_package(Blosc2 2.4 CONFIG) if(NOT Blosc2_FOUND) find_package(Blosc2 2.4 MODULE REQUIRED) endif() @@ -193,8 +196,12 @@ endif() set(mpi_find_components C) -if(ADIOS_USE_Kokkos AND ADIOS_USE_CUDA) - message(FATAL_ERROR "ADIOS2_USE_Kokkos is incompatible with ADIOS_USE_CUDA") +if(ADIOS2_USE_Derived_Variable) + set(ADIOS2_HAVE_Derived_Variable TRUE) +endif() + +if(ADIOS2_USE_Kokkos AND ADIOS2_USE_CUDA) + message(FATAL_ERROR "ADIOS2_USE_Kokkos is incompatible with ADIOS2_USE_CUDA") endif() # Kokkos @@ -216,7 +223,7 @@ if(ADIOS2_USE_Kokkos) enable_language(HIP) endif() if(Kokkos_ENABLE_SYCL) - set(ADIOS2_HAVE_Kokkos_SYCL TRUE) + set(ADIOS2_HAVE_Kokkos_SYCL TRUE) endif() set(ADIOS2_HAVE_GPU_Support TRUE) endif() @@ -239,7 +246,7 @@ if(ADIOS2_USE_CUDA) endif() endif() -if(ADIOS_HAVE_Kokkos AND ADIOS_HAVE_CUDA) +if(ADIOS2_HAVE_Kokkos AND ADIOS2_HAVE_CUDA) message(FATAL_ERROR "The Kokkos and CUDA backends cannot be active concurrently") endif() @@ -445,9 +452,11 @@ if(ADIOS2_USE_SST AND NOT WIN32) endif() endif() if(ADIOS2_HAVE_MPI) - set(CMAKE_REQUIRED_LIBRARIES MPI::MPI_C) - include(CheckCSourceRuns) - check_c_source_runs([=[ + set(CMAKE_REQUIRED_LIBRARIES "MPI::MPI_C;Threads::Threads") + include(CheckCXXSourceRuns) + check_cxx_source_runs([=[ + #include + #include #include #include @@ -457,9 +466,18 @@ if(ADIOS2_USE_SST AND NOT WIN32) int main() { + // Timeout after 5 second + auto task = std::async(std::launch::async, []() { + std::this_thread::sleep_for(std::chrono::seconds(5)); + exit(EXIT_FAILURE); + }); + + char* port_name = new char[MPI_MAX_PORT_NAME]; MPI_Init_thread(NULL, NULL, MPI_THREAD_MULTIPLE, NULL); - MPI_Open_port(MPI_INFO_NULL, malloc(sizeof(char) * MPI_MAX_PORT_NAME)); + MPI_Open_port(MPI_INFO_NULL, port_name); + MPI_Close_port(port_name); MPI_Finalize(); + exit(EXIT_SUCCESS); }]=] ADIOS2_HAVE_MPI_CLIENT_SERVER) unset(CMAKE_REQUIRED_LIBRARIES) @@ -535,9 +553,9 @@ endif() # AWS S3 if(ADIOS2_USE_AWSSDK STREQUAL AUTO) - find_package(AWSSDK QUIET COMPONENTS s3) + find_package(AWSSDK 1.10.15 COMPONENTS s3) elseif(ADIOS2_USE_AWSSDK) - find_package(AWSSDK REQUIRED COMPONENTS s3) + find_package(AWSSDK 1.10.15 REQUIRED COMPONENTS s3) endif() if(AWSSDK_FOUND) set(ADIOS2_HAVE_AWSSDK TRUE) diff --git a/cmake/adios2-config-common.cmake.in b/cmake/adios2-config-common.cmake.in index 0d536e8904..04a41531f1 100644 --- a/cmake/adios2-config-common.cmake.in +++ b/cmake/adios2-config-common.cmake.in @@ -12,6 +12,11 @@ endif() set(ADIOS2_HAVE_Fortran @ADIOS2_HAVE_Fortran@) set(ADIOS2_HAVE_MPI @ADIOS2_HAVE_MPI@) +set(ADIOS2_HAVE_CUDA @ADIOS2_HAVE_CUDA@) +set(ADIOS2_HAVE_Kokkos @ADIOS2_HAVE_Kokkos@) +set(ADIOS2_HAVE_Kokkos_CUDA @ADIOS2_HAVE_Kokkos_CUDA@) +set(ADIOS2_HAVE_Kokkos_HIP @ADIOS2_HAVE_Kokkos_HIP@) +set(ADIOS2_HAVE_Kokkos_SYCL @ADIOS2_HAVE_Kokkos_SYCL@) function(adios2_add_thirdparty_target PackageName) add_library(adios2::thirdparty::${PackageName} INTERFACE IMPORTED) diff --git a/cmake/adios2-config-install.cmake.in b/cmake/adios2-config-install.cmake.in index 86d3ef64ef..a0d6cf1def 100644 --- a/cmake/adios2-config-install.cmake.in +++ b/cmake/adios2-config-install.cmake.in @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.1) +cmake_minimum_required(VERSION 3.12) set(_ADIOS2_CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH}) list(INSERT CMAKE_MODULE_PATH 0 "${CMAKE_CURRENT_LIST_DIR}") diff --git a/cmake/install/post/adios2-config-dummy/CMakeLists.txt b/cmake/install/post/adios2-config-dummy/CMakeLists.txt index 7b31c5c911..83db648edd 100644 --- a/cmake/install/post/adios2-config-dummy/CMakeLists.txt +++ b/cmake/install/post/adios2-config-dummy/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.0) +cmake_minimum_required(VERSION 3.12) project(adios2-config-dummy C CXX) diff --git a/cmake/install/post/generate-adios2-config.sh.in b/cmake/install/post/generate-adios2-config.sh.in index 4603420ffd..1c5139367b 100755 --- a/cmake/install/post/generate-adios2-config.sh.in +++ b/cmake/install/post/generate-adios2-config.sh.in @@ -64,6 +64,12 @@ if [ "${1:0:1}" != "/" ] then # Convert relative paths to absolute based on DESTDIR PREFIX="${DESTDIR:-$(pwd)}/$1" +else + # check if the PREFIX directory exists and prepend DESTDIR if not + if [ ! -d "${PREFIX}" ] + then + PREFIX="${DESTDIR}$1" + fi fi shift diff --git a/docs/user_guide/source/advanced/ecp_hardware.rst b/docs/user_guide/source/advanced/ecp_hardware.rst index 5f79efb49b..37e410fa2f 100644 --- a/docs/user_guide/source/advanced/ecp_hardware.rst +++ b/docs/user_guide/source/advanced/ecp_hardware.rst @@ -33,27 +33,29 @@ your tests. Examples of launching ADIOS2 SST unit tests using MPI DP: .. code-block:: bash - # We omit some of the srun (SLURM) arguments which are specific of the project - # you are working on. Note that you could avoid calling srun directly by - # setting the CMAKE variable `MPIEXEC_EXECUTABLE`. - # Launch simple writer test instance - srun {PROJFLAGS }-N 1 /gpfs/alpine/proj-shared/csc331/vbolea/ADIOS2-build/bin/TestCommonWrite SST mpi_dp_test CPCommPattern=Min,MarshalMethod=BP5' + # We omit some of the srun (SLURM) arguments which are specific of the project + # you are working on. Note that you could avoid calling srun directly by + # setting the CMAKE variable `MPIEXEC_EXECUTABLE`. - # On another terminal launch multiple instances of the Reader test - srun {PROJFLAGS} -N 2 /gpfs/alpine/proj-shared/csc331/vbolea/ADIOS2-build/bin/TestCommonRead SST mpi_dp_test + # Launch simple writer test instance + srun {PROJFLAGS } -N 1 /gpfs/alpine/proj-shared/csc331/vbolea/ADIOS2-build/bin/TestCommonWrite SST mpi_dp_test CPCommPattern=Min,MarshalMethod=BP5 + + # On another terminal launch multiple instances of the Reader test + srun {PROJFLAGS} -N 2 /gpfs/alpine/proj-shared/csc331/vbolea/ADIOS2-build/bin/TestCommonRead SST mpi_dp_test Alternatively, you can configure your CMake build to use srun directly: .. code-block:: bash - cmake . -DMPIEXEC_EXECUTABLE:FILEPATH="/usr/bin/srun" \ - -DMPIEXEC_EXTRA_FLAGS:STRING="-A{YourProject} -pbatch -t10" \ - -DMPIEXEC_NUMPROC_FLAG:STRING="-N" \ - -DMPIEXEC_MAX_NUMPROCS:STRING="-8" \ - -DADIOS2_RUN_MPI_MPMD_TESTS=OFF - cmake --build . - ctest + cmake . -DMPIEXEC_EXECUTABLE:FILEPATH="/usr/bin/srun" \ + -DMPIEXEC_EXTRA_FLAGS:STRING="-A{YourProject} -pbatch -t10" \ + -DMPIEXEC_NUMPROC_FLAG:STRING="-N" \ + -DMPIEXEC_MAX_NUMPROCS:STRING="-8" \ + -DADIOS2_RUN_MPI_MPMD_TESTS=OFF + + cmake --build . + ctest - # monitor your jobs - watch -n1 squeue -l -u $USER + # monitor your jobs + watch -n1 squeue -l -u $USER diff --git a/docs/user_guide/source/advanced/gpu_aware.rst b/docs/user_guide/source/advanced/gpu_aware.rst index ee4c600180..0cf34a893d 100644 --- a/docs/user_guide/source/advanced/gpu_aware.rst +++ b/docs/user_guide/source/advanced/gpu_aware.rst @@ -35,7 +35,7 @@ If there is no CUDA toolkit installed, cmake will turn CUDA off automatically. A When building ADIOS2 with CUDA enabled, the user is responsible with setting the correct ``CMAKE_CUDA_ARCHITECTURES`` (e.g. for Summit the ``CMAKE_CUDA_ARCHITECTURES`` needs to be set to 70 to match the NVIDIA Volta V100). Building with Kokkos enabled --------------------------- +---------------------------- The Kokkos library can be used to enable GPU within ADIOS2. Based on how Kokkos is build, either the CUDA, HIP or SYCL backend will be enabled. Building with Kokkos requires ``-DADIOS2_USE_Kokkos=ON``. The ``CMAKE_CUDA_ARCHITECTURES`` is set automanically to point to the same architecture used when configuring the Kokkos library. @@ -43,9 +43,9 @@ The Kokkos library can be used to enable GPU within ADIOS2. Based on how Kokkos Kokkos version >= 3.7 is required to enable the GPU backend in ADIOS2 -************* +**************** Writing GPU code -************* +**************** The following is a simple example of writing data to storage directly from a GPU buffer allocated with CUDA relying on the automatic detection of device pointers in ADIOS2. The ADIOS2 API is identical to codes using Host buffers for both the read and write logic. diff --git a/docs/user_guide/source/advanced/query.rst b/docs/user_guide/source/advanced/query.rst new file mode 100644 index 0000000000..e1a967cdfb --- /dev/null +++ b/docs/user_guide/source/advanced/query.rst @@ -0,0 +1,93 @@ +################# +ADIOS2 query API +################# + +The query API in ADIOS2 allows a client to pass a query in XML or json format, +and get back a list of blocks or sub-blocks that contains hits. +Both BP4 and BP5 engines are supported. + + +The interface +============= +User is expected to pass a query file (configFile), and init a read engine (engine) +to construct a query and evaluate using the engine. +(note that the engine and query should be using the same ADIOS IO) + +.. code-block:: c++ + + class QueryWorker + { + public: + // configFile has query, can be either xml or json + QueryWorker(const std::string &configFile, adios2::Engine &engine); + + // touched_blocks is a list of regions specified by (start, count), + // that contains data that satisfies the query file + void GetResultCoverage(std::vector> &touched_blocks); + ... + } + +A Sample Compound Query +----------------------- + +This query targets a 1D variable "doubleV", data of interest is (x > 6.6) or (x < -0.17) or (2.8 < x < 2.9) +In addition, this query also specied an output region [start=5,count=80]. + + +.. code-block:: xml + + + + + + + + + + + + + + + + + + +Code EXAMPLES: +============== +C++: +---- +.. code-block:: c++ + + while (reader.BeginStep() == adios2::StepStatus::OK) + { + adios2::QueryWorker w = adios2::QueryWorker(queryFile, reader); + w.GetResultCoverage(touched_blocks); + + std::cout << " ... now can read out touched blocks ... size=" << touched_blocks.size() + << std::endl; + } + + +The Full C++ example is here: + https://github.com/ornladios/ADIOS2/blob/master/examples/query/test.cpp + + +Python: +------- + +.. code-block:: python + + while (reader.BeginStep() == adios2.StepStatus.OK): + # say only rank 0 wants to process result + var = [queryIO.InquireVariable("T")] + + if (rank == 0): + touched_blocks = w.GetResult() + doAnalysis(reader, touched_blocks, var) + +Full python example is here: + https://github.com/ornladios/ADIOS2/blob/master/testing/adios2/bindings/python/TestQuery.py + + This example generates data, the query file (in xml) and runs the query, all in python. + diff --git a/docs/user_guide/source/components/engine.rst b/docs/user_guide/source/components/engine.rst index 2dc0babf48..4a5377e3c9 100644 --- a/docs/user_guide/source/components/engine.rst +++ b/docs/user_guide/source/components/engine.rst @@ -2,6 +2,8 @@ Engine ****** +.. _sec:basics_interface_components_engine: + The Engine abstraction component serves as the base interface to the actual IO systems executing the heavy-load tasks performed when producing and consuming data. Engine functionality works around two concepts: @@ -309,8 +311,8 @@ The ``data`` fed to the ``Put`` function is assumed to be allocated on the Host Only the BP4 and BP5 engines are capable of receiving device allocated buffers. -PerformsPuts ------------- +PerformPuts +----------- Executes all pending ``Put`` calls in deferred mode and collects span data. Specifically this call copies Put(Deferred) data into @@ -322,8 +324,8 @@ PerformsPuts impact performance on some engines. -PerformsDataWrite ------------- +PerformDataWrite +---------------- If supported by the engine, moves data from prior ``Put`` calls to disk @@ -361,13 +363,13 @@ The following table summarizes the memory contracts required by ADIOS2 engines b +----------+-------------+-----------------------------------------------+ | Get | Data Memory | Contract | +----------+-------------+-----------------------------------------------+ -| | Pointer | do not modify until PerformPuts/EndStep/Close | +| | Pointer | do not modify until PerformGets/EndStep/Close | | Deferred | | | -| | Contents | populated at Put or PerformPuts/EndStep/Close | +| | Contents | populated at Get or PerformGets/EndStep/Close | +----------+-------------+-----------------------------------------------+ -| | Pointer | modify after Put | +| | Pointer | modify after Get | | Sync | | | -| | Contents | populated at Put | +| | Contents | populated at Get | +----------+-------------+-----------------------------------------------+ @@ -452,8 +454,8 @@ Only use it if absolutely necessary (*e.g.* memory bound application or out of s ``Get`` doesn't support returning spans. -PerformsGets ------------- +PerformGets +----------- Executes all pending ``Get`` calls in deferred mode. diff --git a/docs/user_guide/source/components/operator.rst b/docs/user_guide/source/components/operator.rst index 04f30bc686..d1fce6591a 100644 --- a/docs/user_guide/source/components/operator.rst +++ b/docs/user_guide/source/components/operator.rst @@ -2,6 +2,8 @@ Operator ******** +.. _sec:basics_interface_components_operator: + The Operator abstraction allows ADIOS2 to act upon the user application data, either from a ``adios2::Variable`` or a set of Variables in an ``adios2::IO`` object. Current supported operations are: diff --git a/docs/user_guide/source/components/variable.rst b/docs/user_guide/source/components/variable.rst index c3a27545d8..baf071defb 100644 --- a/docs/user_guide/source/components/variable.rst +++ b/docs/user_guide/source/components/variable.rst @@ -142,9 +142,10 @@ Dims value. For example, the definition below defines a 2-D Joined array where the first dimension is the one along which blocks will be joined and the 2nd dimension is 5. Here this rank is contributing two rows to this array. - .. code-block:: c++ - auto var = outIO.DefineVariable("table", {adios2::JoinedDim, 5}, - {}, {2, 5}); + +.. code-block:: c++ + + auto var = outIO.DefineVariable("table", {adios2::JoinedDim, 5}, {}, {2, 5}); If each of N writer ranks were to declare a variable like this and do a single Put() in a timestep, the reader-side GlobalArray would have @@ -152,8 +153,6 @@ shape {2*N, 5} and all normal reader-side GlobalArray operations would be applicable to it. - - .. note:: JoinedArrays are currently only supported by BP4 and BP5 engines, diff --git a/docs/user_guide/source/ecosystem/h5vol/vol.rst b/docs/user_guide/source/ecosystem/h5vol/vol.rst index 6315e1dc62..c8f7b87026 100644 --- a/docs/user_guide/source/ecosystem/h5vol/vol.rst +++ b/docs/user_guide/source/ecosystem/h5vol/vol.rst @@ -1,11 +1,12 @@ -*********** +********** Disclaimer -*********** +********** + .. note:: -The Virtual Object Layer (VOL) is a feature introduced in recent release of HDF5 1.12 (https://hdf5.wiki/index.php/New_Features_in_HDF5_Release_1.12). + The Virtual Object Layer (VOL) is a feature introduced in recent release of HDF5 1.12 (https://hdf5.wiki/index.php/New_Features_in_HDF5_Release_1.12). -So please do make sure your HDF5 version supports the latest VOL. + So please do make sure your HDF5 version supports the latest VOL. Once the ADIOS VOL is compiled, There are two ways to apply it: @@ -20,8 +21,8 @@ External .. code-block:: c++ - HDF5_VOL_CONNECTOR=ADIOS2_VOL - HDF5_PLUGIN_PATH=/replace/with/your/adios2_vol/lib/path/ + HDF5_VOL_CONNECTOR=ADIOS2_VOL + HDF5_PLUGIN_PATH=/replace/with/your/adios2_vol/lib/path/ Without code change, ADIOS2 VOL will be loaded at runtime by HDF5, to access ADIOS files without changing user code. @@ -36,26 +37,22 @@ Internal .. code-block:: c++ - // other includes - #include // ADD THIS LINE TO INCLUDE ADIOS VOL - - hid_t pid = H5Pcreate(H5P_FILE_ACCESS); - // other declarations - hid_t fid = H5Fopen(filename, mode, pid); - - H5VL_ADIOS2_set(pid); // ADD THIS LINE TO USE ADIOS VOL + // other includes + #include // ADD THIS LINE TO INCLUDE ADIOS VOL - H5Fclose(fid); + hid_t pid = H5Pcreate(H5P_FILE_ACCESS); + // other declarations + hid_t fid = H5Fopen(filename, mode, pid); - H5VL_ADIOS2_unset(); // ADD THIS LINE TO EXIT ADIOS VOL + H5VL_ADIOS2_set(pid); // ADD THIS LINE TO USE ADIOS VOL + H5Fclose(fid); + H5VL_ADIOS2_unset(); // ADD THIS LINE TO EXIT ADIOS VOL .. To choose what ADIOS2 Engine to use, set env variable: ADIOS2_ENGINE (default is BP5) - - **Note:** The following features are not supported in this VOL: * hyperslab support diff --git a/docs/user_guide/source/engines/bp3.rst b/docs/user_guide/source/engines/bp3.rst index 4f46c7b44e..b9a18a71bd 100644 --- a/docs/user_guide/source/engines/bp3.rst +++ b/docs/user_guide/source/engines/bp3.rst @@ -1,6 +1,6 @@ -**** +*** BP3 -**** +*** The BP3 Engine writes and reads files in ADIOS2 native binary-pack (bp) format. BP files are backwards compatible with ADIOS1.x and have the following structure given a "name" string passed as the first argument of ``IO::Open``: diff --git a/docs/user_guide/source/engines/dataspaces.rst b/docs/user_guide/source/engines/dataspaces.rst index a9627a833b..6f88a55704 100644 --- a/docs/user_guide/source/engines/dataspaces.rst +++ b/docs/user_guide/source/engines/dataspaces.rst @@ -1,6 +1,6 @@ -********************************* +********** DataSpaces -********************************* +********** The DataSpaces engine for ADIOS2 is experimental. DataSpaces is an asynchronous I/O transfer method within ADIOS that enables low-overhead, high-throughput data extraction from a running simulation. diff --git a/docs/user_guide/source/engines/engines.rst b/docs/user_guide/source/engines/engines.rst index a6591322c0..948143453b 100644 --- a/docs/user_guide/source/engines/engines.rst +++ b/docs/user_guide/source/engines/engines.rst @@ -23,6 +23,7 @@ Parameters are passed at: .. include:: sst.rst .. include:: ssc.rst .. include:: dataman.rst +.. include:: dataspaces.rst .. include:: inline.rst .. include:: null.rst .. include:: plugin.rst diff --git a/docs/user_guide/source/engines/hdf5.rst b/docs/user_guide/source/engines/hdf5.rst index c785c32e8f..a3ece47766 100644 --- a/docs/user_guide/source/engines/hdf5.rst +++ b/docs/user_guide/source/engines/hdf5.rst @@ -9,9 +9,9 @@ or, set it in client code. For example, here is how to create a hdf5 reader: .. code-block:: c++ - adios2::IO h5IO = adios.DeclareIO("SomeName"); - h5IO.SetEngine("HDF5"); - adios2::Engine h5Reader = h5IO.Open(filename, adios2::Mode::Read); + adios2::IO h5IO = adios.DeclareIO("SomeName"); + h5IO.SetEngine("HDF5"); + adios2::Engine h5Reader = h5IO.Open(filename, adios2::Mode::Read); To read back the h5 files generated with VDS to ADIOS2, one can use the HDF5 engine. Please make sure you are using the HDF5 library that has version greater than or equal to 1.11 in ADIOS2. @@ -33,10 +33,11 @@ After the subfile feature is introduced in HDF5 version 1.14, the ADIOS2 HDF5 e To use the subfile feature, client needs to support MPI_Init_thread with MPI_THREAD_MULTIPLE. -Useful parameters from the HDF lirbary to tune subfiles are: +Useful parameters from the HDF library to tune subfiles are: + .. code-block:: xml -H5FD_SUBFILING_IOC_PER_NODE (num of subfiles per node) - set H5FD_SUBFILING_IOC_PER_NODE to 0 if the regular h5 file is prefered, before using ADIOS2 HDF5 engine. -H5FD_SUBFILING_STRIPE_SIZE -H5FD_IOC_THREAD_POOL_SIZE + H5FD_SUBFILING_IOC_PER_NODE (num of subfiles per node) + set H5FD_SUBFILING_IOC_PER_NODE to 0 if the regular h5 file is preferred, before using ADIOS2 HDF5 engine. + H5FD_SUBFILING_STRIPE_SIZE + H5FD_IOC_THREAD_POOL_SIZE diff --git a/docs/user_guide/source/engines/sst.rst b/docs/user_guide/source/engines/sst.rst index 61a2e0aa87..83adf8d85e 100644 --- a/docs/user_guide/source/engines/sst.rst +++ b/docs/user_guide/source/engines/sst.rst @@ -280,24 +280,24 @@ single reader, but only upon request (with a request being initiated by the reader doing BeginStep()). Normal reader-side rules (like BeginStep timeouts) and writer-side rules (like queue limit behavior) apply. -============================= ===================== ==================================================== - **Key** **Value Format** **Default** and Examples -============================= ===================== ==================================================== - RendezvousReaderCount integer **1** - RegistrationMethod string **File**, Screen - QueueLimit integer **0** (no queue limits) - QueueFullPolicy string **Block**, Discard - ReserveQueueLimit integer **0** (no queue limits) - DataTransport string **default varies by platform**, UCX, MPI, RDMA, WAN - WANDataTransport string **sockets**, enet, ib - ControlTransport string **TCP**, Scalable - MarshalMethod string **BP5**, BP, FFS - NetworkInterface string **NULL** - ControlInterface string **NULL** - DataInterface string **NULL** - FirstTimestepPrecious boolean **FALSE**, true, no, yes - AlwaysProvideLatestTimestep boolean **FALSE**, true, no, yes - OpenTimeoutSecs integer **60** - SpeculativePreloadMode string **AUTO**, ON, OFF - SpecAutoNodeThreshold integer **1** -============================= ===================== ===================================================== ++-----------------------------+---------------------+----------------------------------------------------+ +| **Key** | **Value Format** | **Default** and Examples | ++-----------------------------+---------------------+----------------------------------------------------+ +| RendezvousReaderCount | integer | **1** | +| RegistrationMethod | string | **File**, Screen | +| QueueLimit | integer | **0** (no queue limits) | +| QueueFullPolicy | string | **Block**, Discard | +| ReserveQueueLimit | integer | **0** (no queue limits) | +| DataTransport | string | **default varies by platform**, UCX, MPI, RDMA, WAN| +| WANDataTransport | string | **sockets**, enet, ib | +| ControlTransport | string | **TCP**, Scalable | +| MarshalMethod | string | **BP5**, BP, FFS | +| NetworkInterface | string | **NULL** | +| ControlInterface | string | **NULL** | +| DataInterface | string | **NULL** | +| FirstTimestepPrecious | boolean | **FALSE**, true, no, yes | +| AlwaysProvideLatestTimestep | boolean | **FALSE**, true, no, yes | +| OpenTimeoutSecs | integer | **60** | +| SpeculativePreloadMode | string | **AUTO**, ON, OFF | +| SpecAutoNodeThreshold | integer | **1** | ++-----------------------------+---------------------+----------------------------------------------------+ diff --git a/docs/user_guide/source/index.rst b/docs/user_guide/source/index.rst index 6fd178f524..c976e6826d 100644 --- a/docs/user_guide/source/index.rst +++ b/docs/user_guide/source/index.rst @@ -37,9 +37,17 @@ Funded by the `Exascale Computing Project (ECP) `_. + +1. In an MPI application first we need to always initialize MPI. We do that with the following lines: + +.. code-block:: cpp + + int rank, size; + int provided; + + // MPI_THREAD_MULTIPLE is only required if you enable the SST MPI_DP + MPI_Init_thread(&argc, &argv, MPI_THREAD_MULTIPLE, &provided); + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + MPI_Comm_size(MPI_COMM_WORLD, &size); + +2. Now we need to create a application variable which will be used to define an ADIOS2 variable. + +.. code-block:: cpp + + std::vector myFloats = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + +3. Then, we need to create an ADIOS2 instance. + +.. code-block:: cpp + + adios2::ADIOS adios(MPI_COMM_WORLD); + +4. Then, we create the following writer function: + +.. code-block:: cpp + + void writer(adios2::ADIOS &adios, int rank, int size, std::vector &myFloats) + { + ... + } + +5. In this writer function, we define an IO object, and a float vector variable as follows: + +.. code-block:: cpp + + adios2::IO bpIO = adios.DeclareIO("BPFile_N2N"); + + const std::size_t Nx = myFloats.size(); + adios2::Variable bpFloats = bpIO.DefineVariable( + "bpFloats", {size * Nx}, {rank * Nx}, {Nx}, adios2::ConstantDims); + +6. Now, we will define various types of attributes as follows: + +.. code-block:: cpp + + bpIO.DefineAttribute("Single_String", "File generated with ADIOS2"); + + std::vector myStrings = {"one", "two", "three"}; + bpIO.DefineAttribute("Array_of_Strings", myStrings.data(), myStrings.size()); + + bpIO.DefineAttribute("Attr_Double", 0.f); + std::vector myDoubles = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + bpIO.DefineAttribute("Array_of_Doubles", myDoubles.data(), myDoubles.size()); + +.. note:: + + if we want to define an attribute for a specific variable, we can use one of the following API: + + .. code-block:: cpp + + template + Attribute DefineAttribute(const std::string &name, const T *data, const size_t size, + const std::string &variableName = "", const std::string separator = "/", + const bool allowModification = false); + + template + Attribute DefineAttribute(const std::string &name, const T &value, + const std::string &variableName = "", const std::string separator = "/", + const bool allowModification = false); + + As we can see, by default the attributes don't change over multiple steps, but we can change that by setting + ``allowModification`` to ``true``. + +7. Then, we open a file for writing: + +.. code-block:: cpp + + adios2::Engine bpWriter = bpIO.Open("fileAttributes.bp", adios2::Mode::Write); + +8. Now, we write the data and close the file: + +.. code-block:: cpp + + bpWriter.BeginStep(); + bpWriter.Put(bpFloats, myFloats.data()); + bpWriter.EndStep(); + bpWriter.Close(); + +9. Steps 1-8 are used for writing, we will define a reader function in the rest of the steps: + +.. code-block:: cpp + + void reader(adios2::ADIOS &adios, int rank, int size) + { + ... + } + +10. In this reader function, we define an IO object, and open the file for reading: + +.. code-block:: cpp + + adios2::IO bpIO = adios.DeclareIO("BPFile_N2N"); + adios2::Engine bpReader = bpIO.Open("fileAttributes.bp", adios2::Mode::Read); + +11. Now, we check the available attributes as follows: + +.. code-block:: cpp + + bpReader.BeginStep(); + const auto attributesInfo = bpIO.AvailableAttributes(); + + for (const auto &attributeInfoPair : attributesInfo) + { + std::cout << "Attribute: " << attributeInfoPair.first; + for (const auto &attributePair : attributeInfoPair.second) + { + std::cout << "\tKey: " << attributePair.first << "\tValue: " << attributePair.second + << "\n"; + } + std::cout << "\n"; + } + +12. Now we will inquire and get the attributes as follows: + +.. code-block:: cpp + + adios2::Attribute singleString = bpIO.InquireAttribute("Single_String"); + if (singleString) + { + std::cout << singleString.Name() << ": " << singleString.Data()[0] << "\n"; + } + adios2::Attribute arrayOfStrings = + bpIO.InquireAttribute("Array_of_Strings"); + if (arrayOfStrings) + { + std::cout << arrayOfStrings.Name() << ": "; + for (const auto &value : arrayOfStrings.Data()) + { + std::cout << value << " "; + } + std::cout << "\n"; + } + adios2::Attribute attrDouble = bpIO.InquireAttribute("Attr_Double"); + if (attrDouble) + { + std::cout << attrDouble.Name() << ": " << attrDouble.Data()[0] << "\n"; + } + adios2::Attribute arrayOfDoubles = bpIO.InquireAttribute("Array_of_Doubles"); + if (arrayOfDoubles) + { + std::cout << arrayOfDoubles.Name() << ": "; + for (const auto &value : arrayOfDoubles.Data()) + { + std::cout << value << " "; + } + std::cout << "\n"; + } + +13. Afterward, we will inquire and get the variable as follows: + +.. code-block:: cpp + + adios2::Variable bpFloats = bpIO.InquireVariable("bpFloats"); + const std::size_t Nx = 10; + std::vector myFloats(Nx); + if (bpFloats) + { + bpFloats.SetSelection({{Nx * rank}, {Nx}}); + bpReader.Get(bpFloats, myFloats.data()); + } + bpReader.EndStep(); + +14. Finally, we close the file: + +.. code-block:: cpp + + bpReader.Close(); + +15. In the main function, we call the writer and reader functions as follows: + +.. code-block:: cpp + + writer(adios, rank, size, myFloats); + reader(adios, rank, size); + +16. Finally, we finalize MPI: + +.. code-block:: cpp + + MPI_Finalize(); + +17. The final code should look as follows (excluding try/catch and optional usage MPI), and it was derived from the + example `ADIOS2/examples/hello/bpAttributeWriteRead/bpAttributeWriteRead.cpp `_. + +.. literalinclude:: ../../../../examples/hello/bpAttributeWriteRead/bpAttributeWriteRead.cpp + :language: cpp + +18. You can compile and run it as follows: + +.. code-block:: bash + + cd Path-To-ADIOS2/examples/hello/bpAttributeWriteRead + mkdir build + cd build + cmake -DADIOS2_DIR=Path-To-ADIOS2/build/ .. + cmake --build . + mpirun -np 2 ./adios2_hello_bpAttributeWriteRead_mpi + +19. You can check the content of the output file "fileAttributes.bp" using *bpls* as follows: + +.. code-block:: bash + + Path-To-ADIOS2/build/bin/bpls ./fileAttributes.bp + + float bpFloats {20} diff --git a/docs/user_guide/source/tutorials/basicTutorials.rst b/docs/user_guide/source/tutorials/basicTutorials.rst new file mode 100644 index 0000000000..c1c7a44de2 --- /dev/null +++ b/docs/user_guide/source/tutorials/basicTutorials.rst @@ -0,0 +1,10 @@ +Basic Tutorials +=============== + +.. toctree:: + + helloWorld + variables + attributes + operators + steps diff --git a/docs/user_guide/source/tutorials/downloadAndBuild.rst b/docs/user_guide/source/tutorials/downloadAndBuild.rst new file mode 100644 index 0000000000..637955e069 --- /dev/null +++ b/docs/user_guide/source/tutorials/downloadAndBuild.rst @@ -0,0 +1,42 @@ +Download And Build +================== + +.. _sec:tutorials_download_and_build: + +First, you need to clone the ADIOS2 repository. You can do this by running the following command: + +.. code-block:: bash + + git clone https://github.com/ornladios/ADIOS2.git ADIOS2 + +.. note:: + + ADIOS2 uses `CMake `_ for building, testing and installing the library and utilities. + So you need to have CMake installed on your system. + +Then, create a build directory, run CMake, and build ADIOS2: + +.. code-block:: bash + + cd ADIOS2 + mkdir build + cd build + cmake -DADIOS2_USE_MPI=ON .. + cmake --build . + +.. note:: + + If you want to know more about the ADIOS2's CMake options, see section + :ref:`CMake Options `. + +All the tutorials that we will explore are existing ADIOS2 examples located in the ``ADIOS2/examples`` directory. + +To build any of the examples, e.g. the ``helloWorld`` example, you can run the following commands: + +.. code-block:: bash + + cd Path-To-ADIOS2/examples/hello/helloWorld + mkdir build + cd build + cmake -DADIOS2_DIR=Path-To-ADIOS2/build/ .. + cmake --build . diff --git a/docs/user_guide/source/tutorials/helloWorld.rst b/docs/user_guide/source/tutorials/helloWorld.rst new file mode 100644 index 0000000000..a0e424a097 --- /dev/null +++ b/docs/user_guide/source/tutorials/helloWorld.rst @@ -0,0 +1,143 @@ +Hello World +=========== + +.. _sec:tutorials_basics_hello_world: + +Like in any language, the first program you write is the "Hello World" program. + +In this tutorial, we will see how to write "Hello World from ADIOS2" and read it back with ADIOS2. +So let's dig in! + +Start editing the skeleton file `ADIOS2/examples/hello/helloWorld/hello-world_tutorialSkeleton.cpp `_. + + +1. We create an ADIOS instance, and define the greeting message in our main function as follows: + +.. code-block:: c++ + + int main() + { + adios2::ADIOS adios(); + const std::string greeting("Hello World from ADIOS2"); + ... + return 0; + } + +2. Then we create a writer function in which we pass the adios instance, and the greeting message as follows: + +.. code-block:: c++ + + void writer(adios2::ADIOS& adios, const std::string& greeting) + { + ... + } + +3. In this writer function, we define an IO object, a string variable for the message as follows: + +.. code-block:: c++ + + adios2::IO io = adios.DeclareIO("hello-world-writer"); + adios2::Variable varGreeting = io.DefineVariable("Greeting"); + +.. note:: + + Using the IO object, we can define the engine type that we want to utilize using the *io.SetEngine()* function. + If *SetEngine()* is not used, the default engine type is *BPFile* which is an alias for the latest version of the BP + engine of the ADIOS2 library. See :ref:`Available Engines` and :ref:`Supported Engines` for more information. + It's important to note that the file extension of an output file, although it's not a good practice, it can differ + from the engine type, e.g. write a foo.h5 file with the BPFile engine. When reading foo.h5 you should explicitly + specify the engine type as BPFile to read it properly. + +4. Then we open a file with the name "hello-world-cpp.bp" and write the greeting message to it as follows: + +.. code-block:: c++ + + adios2::Engine writer = io.Open("hello-world-cpp.bp", adios2::Mode::Write); + writer.BeginStep(); + writer.Put(varGreeting, greeting); + writer.EndStep(); + writer.Close(); + +.. note:: + + The ``BeginStep`` and ``EndStep`` calls are optional when **writing** one step, but they are required + for multiple steps, so it is a good practice to always use them. + +5. Now we create a reader function in which we pass the adios instance, and get the greeting message back as follows: + +.. code-block:: c++ + + std::string reader(adios2::ADIOS& adios) + { + ... + } + +6. In this reader function, we define an IO object and inquire a string variable for the message as follows: + +.. code-block:: c++ + + adios2::IO io = adios.DeclareIO("hello-world-reader"); + reader.BeginStep(); + adios2::Variable varGreeting = io.InquireVariable("Greeting"); + +7. Then we open the file with the name "hello-world-cpp.bp", read the greeting message from it and return it as follows: + +.. code-block:: c++ + + adios2::Engine reader = io.Open("hello-world-cpp.bp", adios2::Mode::Read); + std::string greeting; + reader.Get(varGreeting, greeting); + reader.EndStep(); + reader.Close(); + return greeting; + +.. note:: + + The ``BeginStep`` and ``EndStep`` calls are required when **reading** one step and multiple steps. We will see in + another tutorial how to read multiple steps. It's important to note that the ``BeginStep`` should be called **before** + all ``Inquire*`` / ``Available*`` function calls. + +8. Finally, we call the writer and reader functions in our main function as follows: + +.. code-block:: c++ + + int main() + { + adios2::ADIOS adios(); + const std::string greeting("Hello World from ADIOS2"); + writer(adios, greeting); + std::string message = reader(adios); + std::cout << message << std::endl; + return 0; + } + +9. The final code should look as follows (excluding try/catch and the optional usage of MPI), and it was derived from + the example `ADIOS2/examples/hello/helloWorld/hello-world.cpp `_. + +.. literalinclude:: ../../../../examples/hello/helloWorld/hello-world.cpp + :language: cpp + +10. You can compile and run it as follows: + +.. code-block:: bash + + cd Path-To-ADIOS2/examples/hello/helloWorld + mkdir build + cd build + cmake -DADIOS2_DIR=Path-To-ADIOS2/build/ .. + cmake --build . + ./adios2_hello_helloWorld + +11. You can check the content of the output file "hello-world-cpp.bp" using *bpls* as follows: + +.. code-block:: bash + + Path-To-ADIOS2/build/bin/bpls ./hello-world-cpp.bp + + string Greeting scalar + +12. The Python version of this tutorial can be found at `ADIOS2/examples/hello/helloWorld/hello-world.py `_. + and it looks as follows: + +.. literalinclude:: ../../../../examples/hello/helloWorld/hello-world.py + :language: python diff --git a/docs/user_guide/source/tutorials/operators.rst b/docs/user_guide/source/tutorials/operators.rst new file mode 100644 index 0000000000..8fa400fb53 --- /dev/null +++ b/docs/user_guide/source/tutorials/operators.rst @@ -0,0 +1,156 @@ +Operators +========= + +.. _sec:tutorials_basics_operators: + +In the previous tutorial we learned how to write and read attributes. + +For this example to work, you would need to have the SZ compression library installed, which ADIOS automatically detects. +The easiest way to install SZ is with Spack, and you can do that as follows: + +.. code-block:: bash + + git clone https://github.com/spack/spack.git ~/spack + cd ~/spack + . share/spack/setup-env.sh + spack install sz + spack load sz + +In this tutorial we will learn how to use operators. Operators are used for Data compression/decompression, lossy and +lossless. They act upon the user application data, either from a variable or a set of variables in a IO object. + +Additionally, we will explore how to simply write variables across multiple steps. + +So, let's dig in! + +Start editing the skeleton file `ADIOS2/examples/hello/bpOperatorSZWriter/bpOperatorSZWriter_tutorialSkeleton.cpp `_. + +1. In an MPI application first we need to always initialize MPI. We do that with the following lines: + +.. code-block:: cpp + + + int rank, size; + int rank, size; + int provided; + + // MPI_THREAD_MULTIPLE is only required if you enable the SST MPI_DP + MPI_Init_thread(&argc, &argv, MPI_THREAD_MULTIPLE, &provided); + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + MPI_Comm_size(MPI_COMM_WORLD, &size); + +2. This application has command line arguments for the size of the data, and the compression accuracy, + which we can read as follows: + +.. code-block:: cpp + + const std::size_t Nx = static_cast(std::stoull(argv[1])); + const double accuracy = std::stod(argv[2]); + +3. Now we need to create some application variables which will be used to define ADIOS2 variables. + +.. code-block:: cpp + + std::vector myFloats(Nx); + std::vector myDoubles(Nx); + std::iota(myFloats.begin(), myFloats.end(), 0.); + std::iota(myDoubles.begin(), myDoubles.end(), 0.); + +4. Now we need to create an ADIOS2 instance and IO object. + +.. code-block:: cpp + + adios2::ADIOS adios(MPI_COMM_WORLD); + adios2::IO bpIO = adios.DeclareIO("BPFile_SZ"); + +5. Now we need to define the variables we want to write. + +.. code-block:: cpp + + adios2::Variable bpFloats = bpIO.DefineVariable( + "bpFloats", {size * Nx}, {rank * Nx}, {Nx}, adios2::ConstantDims); + adios2::Variable bpDoubles = bpIO.DefineVariable( + "bpDoubles", {size * Nx}, {rank * Nx}, {Nx}, adios2::ConstantDims); + +6. Now we need to define the compression operator we want to use. In this case we will use the SZ compressor. + +.. code-block:: cpp + + adios2::Operator op = bpIO.DefineOperator("SZCompressor", "sz"); + varFloats.AddOperation(op, {{"accuracy", std::to_string(accuracy)}}); + varDoubles.AddOperation(op, {{"accuracy", std::to_string(accuracy)}}); + +.. note:: + + ``DefineOperator()'`` s second parameter can be either zfp or sz. For more information regarding operators and their + properties you can look at :ref:`Basics: Interface Components: Operator `. + +7. Let's also create an attribute to store the accuracy value. + +.. code-block:: cpp + + adios2::Attribute attribute = bpIO.DefineAttribute("accuracy", accuracy); + +8. Now we need to open the file for writing. + +.. code-block:: cpp + + adios2::Engine bpWriter = bpIO.Open("SZexample.bp", adios2::Mode::Write); + +9. Now we need to write the data. We will write the data for 3 steps, and edit them in between. + +.. code-block:: cpp + + for (unsigned int step = 0; step < 3; ++step) + { + bpWriter.BeginStep(); + + bpWriter.Put(bpDoubles, myDoubles.data()); + bpWriter.Put(bpFloats, myFloats.data()); + + bpWriter.EndStep(); + + // here you can modify myFloats, myDoubles per step + std::transform(myFloats.begin(), myFloats.end(), myFloats.begin(), + [&](float v) -> float { return 2 * v; }); + std::transform(myDoubles.begin(), myDoubles.end(), myDoubles.begin(), + [&](double v) -> double { return 3 * v; }); + } + +10. Now we need to close the file. + +.. code-block:: cpp + + bpWriter.Close(); + +11. Finally we need to finalize MPI. + +.. code-block:: cpp + + MPI_Finalize(); + +12. The final code should look as follows (excluding try/catch and optional usage of MPI), and it was derived from the + example `ADIOS2/examples/hello/bpOperatorSZWriter/bpOperatorSZWriter.cpp `_. + +.. literalinclude:: ../../../../examples/hello/bpOperatorSZWriter/bpOperatorSZWriter.cpp + :language: cpp + +13. You can compile and run it as follows: + +.. code-block:: bash + + cd Path-To-ADIOS2/examples/hello/bpOperatorSZWriter + mkdir build + cd build + cmake -DADIOS2_DIR=Path-To-ADIOS2/build/ .. + cmake --build . + mpirun -np 2 ./adios2_hello_bpOperatorSZWriter_mpi 20 0.000001 + +12. You can check the content of the output file "SZexample.bp" using *bpls* as follows: + +.. code-block:: bash + + Path-To-ADIOS2/build/bin/bpls ./SZexample.bp + + double bpDoubles 3*{40} + float bpFloats 3*{40} diff --git a/docs/user_guide/source/tutorials/overview.rst b/docs/user_guide/source/tutorials/overview.rst new file mode 100644 index 0000000000..b9cb47a573 --- /dev/null +++ b/docs/user_guide/source/tutorials/overview.rst @@ -0,0 +1,15 @@ +Overview +======== + +In this tutorial we will learn about how to build ADIOS2, and go through several tutorials explaining basic topics. + +More specifically, we will go through the following examples: + +1. :ref:`Download And Build ` +2. Basic tutorials: + + 1. :ref:`Hello World ` + 2. :ref:`Array Variables ` + 3. :ref:`Attributes ` + 4. :ref:`Operators ` + 5. :ref:`Steps ` diff --git a/docs/user_guide/source/tutorials/steps.rst b/docs/user_guide/source/tutorials/steps.rst new file mode 100644 index 0000000000..d7d6f8cac0 --- /dev/null +++ b/docs/user_guide/source/tutorials/steps.rst @@ -0,0 +1,212 @@ +Steps +===== + +.. _sec:tutorials_basics_steps: + +In the previous tutorial, we introduced the concept of operators, and briefly touched upon the concept of steps. + +In this tutorial, we will explore how to write data for multiple steps, and how to read them back. + +So let's dig in! + +Start editing the skeleton file `ADIOS2/examples/hello/bpStepsWriteRead/bpStepsWriteRead_tutorialSkeleton.cpp `_. + +1. In an MPI application first we need to always initialize MPI. We do that with the following lines: + +.. code-block:: cpp + + int rank, size; + int rank, size; + int provided; + + // MPI_THREAD_MULTIPLE is only required if you enable the SST MPI_DP + MPI_Init_thread(&argc, &argv, MPI_THREAD_MULTIPLE, &provided); + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + MPI_Comm_size(MPI_COMM_WORLD, &size); + +2. This application has an optional command line argument for engine being used. If + no argument is provided, the default engine is BPFile. + +.. code-block:: cpp + + const std::string engine = argv[1] ? argv[1] : "BPFile"; + +3. We will define the number of steps and the size of the data that we will create. + +.. code-block:: cpp + + const std::string filename = engine + "StepsWriteRead.bp"; + const unsigned int nSteps = 10; + const unsigned int Nx = 60000; + +4. Now we need to create an ADIOS2 instance. + +.. code-block:: cpp + + adios2::ADIOS adios(MPI_COMM_WORLD); + +5. Now we will populate the writer function with the following signature: + +.. code-block:: + + void writer(adios2::ADIOS &adios, const std::string &engine, const std::string &fname, + const size_t Nx, unsigned int nSteps, int rank, int size) + { + ... + } + +6. Let's create some simulation data. We will create a 1D array of size Nx, and fill it with 0.block + +.. code-block:: cpp + + std::vector simData(Nx, 0.0); + +7. Now we will create an IO object and set the engine type.block + +.. code-block:: cpp + + adios2::IO bpIO = adios.DeclareIO("SimulationOutput"); + io.SetEngine(engine); + +.. note:: + + The beauty of ADIOS2 is that you write the same code for all engines. The only thing that changes is the engine name. + The underlying engine handles all the intricacies of the engine's format, and the user enjoys the API's simplicity. + +8. Now we will create a variable for the simulation data and the step. + +.. code-block:: cpp + + const adios2::Dims shape{static_cast(size * Nx)}; + const adios2::Dims start{static_cast(rank * Nx)}; + const adios2::Dims count{Nx}; + auto bpFloats = bpIO.DefineVariable("bpFloats", shape, start, count); + + auto bpStep = bpIO.DefineVariable("bpStep"); + +9. Now we will open the file for writing. + +.. code-block:: cpp + + adios2::Engine bpWriter = bpIO.Open(fname, adios2::Mode::Write); + +10. Now we will write the data for each step. + +.. code-block:: cpp + + for (unsigned int step = 0; step < nSteps; ++step) + { + const adios2::Box sel({0}, {Nx}); + bpFloats.SetSelection(sel); + + bpWriter.BeginStep(); + bpWriter.Put(bpFloats, simData.data()); + bpWriter.Put(bpStep, step); + bpWriter.EndStep(); + + // Update values in the simulation data + update_array(simData, 10); + } + +11. Now we will close the file. + +.. code-block:: cpp + + bpWriter.Close(); + +12. Now we will populate the reader function with the following signature: + +.. code-block:: cpp + + void reader(adios2::ADIOS &adios, const std::string &engine, const std::string &fname, + const size_t Nx, unsigned int /*nSteps*/, int rank, int /*size*/) + { + ... + } + +13. Now we will create an IO object and set the engine type. + +.. code-block:: cpp + + adios2::IO bpIO = adios.DeclareIO("SimulationOutput"); + io.SetEngine(engine); + +14. Now we will open the file for reading. + +.. code-block:: cpp + + adios2::Engine bpReader = bpIO.Open(fname, adios2::Mode::Read); + +15. Now we will create a vector to store simData and a variable for the step. + +.. code-block:: cpp + + std::vector simData(Nx, 0); + unsigned int inStep = 0; + +16. Now we will read the data for each step. + +.. code-block:: cpp + + for (unsigned int step = 0; bpReader.BeginStep() == adios2::StepStatus::OK; ++step) + { + auto bpFloats = bpIO.InquireVariable("bpFloats"); + if (bpFloats) + { + const adios2::Box sel({{Nx * rank}, {Nx}}); + bpFloats.SetSelection(sel); + bpReader.Get(bpFloats, simData.data()); + } + auto bpStep = bpIO.InquireVariable("bpStep"); + if (bpStep) + { + bpReader.Get(bpStep, &inStep); + } + + bpReader.EndStep(); + } + +17. Now we will close the file. + +.. code-block:: cpp + + bpReader.Close(); + +18. Now we will call the writer and reader functions: + +.. code-block:: cpp + + writer(adios, engine, filename, Nx, nSteps, rank, size); + reader(adios, engine, filename, Nx, nSteps, rank, size); + +19. Finally we need to finalize MPI. + +.. code-block:: cpp + + MPI_Finalize(); + +20. The final code should look as follows (excluding try/catch and optional usage of MPI), and it was derived from the + example `ADIOS2/examples/hello/bpStepsWriteRead/bpStepsWriteRead.cpp `_. + +.. literalinclude:: ../../../../examples/hello/bpStepsWriteRead/bpStepsWriteRead.cpp + :language: cpp + +21. You can compile and run it as follows: + +.. code-block:: bash + + cd Path-To-ADIOS2/examples/hello/bpStepsWriteRead + mkdir build + cd build + cmake -DADIOS2_DIR=Path-To-ADIOS2/build/ .. + cmake --build . + mpirun -np 2 ./adios2_hello_bpStepsWriteRead_mpi + +22. You can check the content of the output file "BPFileStepsWriteRead.bp" using *bpls* as follows: + +.. code-block:: bash + + Path-To-ADIOS2/build/bin/bpls ./BPFileStepsWriteRead.bp + + float bpFloats 10*{120000} + uint32_t bpStep 10*scalar diff --git a/docs/user_guide/source/tutorials/variables.rst b/docs/user_guide/source/tutorials/variables.rst new file mode 100644 index 0000000000..1d05acf8b3 --- /dev/null +++ b/docs/user_guide/source/tutorials/variables.rst @@ -0,0 +1,246 @@ +Variables +========= + +.. _sec:tutorials_basics_variables: + +In the previous tutorial we learned how to define a simple string variable, write it, and read it back. + +In this tutorial we will go two steps further: + +1. We will define variables which include arrays, and we will write them and read them back. +2. We will use MPI to write and read the above variables in parallel. + +Let's start with the writing part. + +Start editing the skeleton file `ADIOS2/examples/hello/bpWriter/bpWriter_tutorialSkeleton.cpp `_. + +1. In an MPI application first we need to always initialize MPI. We do that with the following lines: + +.. code-block:: cpp + + int rank, size; + int provided; + + // MPI_THREAD_MULTIPLE is only required if you enable the SST MPI_DP + MPI_Init_thread(&argc, &argv, MPI_THREAD_MULTIPLE, &provided); + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + MPI_Comm_size(MPI_COMM_WORLD, &size); + +2. Now we need to create some application variables which will be used to define ADIOS2 variables. + +.. code-block:: cpp + + // Application variable + std::vector myFloats = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + std::vector myInts = {0, -1, -2, -3, -4, -5, -6, -7, -8, -9}; + const std::size_t Nx = myFloats.size(); + const std::string myString("Hello Variable String from rank " + std::to_string(rank)); + +3. Now we need to define an ADIOS2 instance and the ADIOS2 variables. + +.. code-block:: cpp + + adios2::ADIOS adios(MPI_COMM_WORLD); + adios2::IO bpIO = adios.DeclareIO("BPFile_N2N"); + + adios2::Variable bpFloats = bpIO.DefineVariable( + "bpFloats", {size * Nx}, {rank * Nx}, {Nx}, adios2::ConstantDims); + + adios2::Variable bpInts = bpIO.DefineVariable("bpInts", {size * Nx}, {rank * Nx}, + {Nx}, adios2::ConstantDims); + + // For the sake of the tutorial we create an unused variable + adios2::Variable bpString = bpIO.DefineVariable("bpString"); + +.. note:: + + The above int/float variables are global arrays. The 1st argument of the ``DefineVariable`` function is the variable + name, the 2nd are the global dimensions, the 3rd is the start index for a rank, the 4th are the rank/local + dimensions, and the 5th is a boolean variable to indicate if the dimensions are constant or not over multiple steps, + where ``adios2::ConstantDims == true`` We will explore other tutorials that don't use constant dimensions. + +4. Now we need to open the ADIOS2 engine and write the variables. + +.. code-block:: cpp + + adios2::Engine bpWriter = bpIO.Open("myVector_cpp.bp", adios2::Mode::Write); + + bpWriter.BeginStep(); + bpWriter.Put(bpFloats, myFloats.data()); + bpWriter.Put(bpInts, myInts.data()); + // bpWriter.Put(bpString, myString); + bpWriter.EndStep(); + + bpWriter.Close(); + +5. Finally we need to finalize MPI. + +.. code-block:: cpp + + MPI_Finalize(); + +6. The final code should look as follows (excluding try/catch and the optional usage of MPI), and it was derived + from the example `ADIOS2/examples/hello/bpWriter/bpWriter.cpp `_. + +.. literalinclude:: ../../../../examples/hello/bpWriter/bpWriter.cpp + :language: cpp + +7. You can compile and run it as follows: + +.. code-block:: bash + + cd Path-To-ADIOS2/examples/hello/bpWriter + mkdir build + cd build + cmake -DADIOS2_DIR=Path-To-ADIOS2/build/ .. + cmake --build . + mpirun -np 2 ./adios2_hello_bpWriter_mpi + +8. You can check the content of the output file "myVector_cpp.bp" using *bpls* as follows: + +.. code-block:: bash + + Path-To-ADIOS2/build/bin/bpls ./myVector_cpp.bp + + float bpFloats {10} + int32_t bpInts {10} + +Now let's move to the reading part. + +Start editing the skeleton file `ADIOS2/examples/hello/bpReader/bpReader_tutorialSkeleton.cpp `_. + +9. In an MPI application first we need to always initialize MPI. We do that with the following line: + +.. code-block:: cpp + + int rank, size; + int provided; + + // MPI_THREAD_MULTIPLE is only required if you enable the SST MPI_DP + MPI_Init_thread(&argc, &argv, MPI_THREAD_MULTIPLE, &provided); + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + MPI_Comm_size(MPI_COMM_WORLD, &size); + +10. Now we need to define an ADIOS2 instance and open the ADIOS2 engine. + +.. code-block:: cpp + + adios2::ADIOS adios(MPI_COMM_WORLD); + + adios2::IO bpIO = adios.DeclareIO("BPFile_N2N"); + + adios2::Engine bpReader = bpIO.Open("myVector_cpp.bp", adios2::Mode::Read); + +11. Now we need to read the variables. In this case we know the variables that we need to inquire, so we can use the + ``InquireVariable`` function immediately. But let's explore how to check the available variables in a file first, + and then we will use the ``InquireVariable`` function. + +.. code-block:: cpp + + bpReader.BeginStep(); + const std::map variables = bpIO.AvailableVariables(); + + for (const auto &variablePair : variables) + { + std::cout << "Name: " << variablePair.first; + for (const auto ¶meter : variablePair.second) + { + std::cout << "\t" << parameter.first << ": " << parameter.second << "\n"; + } + } + + adios2::Variable bpFloats = bpIO.InquireVariable("bpFloats"); + adios2::Variable bpInts = bpIO.InquireVariable("bpInts"); + +12. Now we need to read the variables from each rank. We will use the ``SetSelection`` to set the start index and rank + dimensions, then ``Get`` function to read the variables, and print the contents from rank 0. + +.. code-block:: cpp + + const std::size_t Nx = 10; + if (bpFloats) // means found + { + std::vector myFloats; + + // read only the chunk corresponding to our rank + bpFloats.SetSelection({{Nx * rank}, {Nx}}); + bpReader.Get(bpFloats, myFloats, adios2::Mode::Sync); + + if (rank == 0) + { + std::cout << "MyFloats: \n"; + for (const auto number : myFloats) + { + std::cout << number << " "; + } + std::cout << "\n"; + } + } + + if (bpInts) // means not found + { + std::vector myInts; + // read only the chunk corresponding to our rank + bpInts.SetSelection({{Nx * rank}, {Nx}}); + + bpReader.Get(bpInts, myInts, adios2::Mode::Sync); + + if (rank == 0) + { + std::cout << "myInts: \n"; + for (const auto number : myInts) + { + std::cout << number << " "; + } + std::cout << "\n"; + } + } + +.. note:: + + While using the ``Get`` function, we used the third parameter named ``Mode``. The mode parameter can also be used + for the ``Put`` function. + + For the ``Put`` function, there are three modes: ``Deferred`` (default), ``Sync``, and ``Span``. and for the ``Get`` + there are two modes: ``Deferred`` (default) and ``Sync``. + + 1. The ``Deferred`` mode is the default mode, because it is the fastest mode, as it allows ``Put`` / ``Get`` to be + grouped before potential data transport at the first encounter of ``PerformPuts`` / ``PerformGets``, ``EndStep`` + or ``Close``. + + 2. The ``Sync`` mode forces ``Put`` / ``Get`` to be performed immediately so that the data are available immediately. + + 3. The ``Span`` mode is special mode of ``Deferred`` that allows population from non-contiguous memory structures. + + For more information about the ``Mode`` parameter for both ``Put`` and ``Get`` functions, and when you should use + each option see :ref:`Basics: Interface Components: Engine `. + +13. Now we need close the ADIOS2 engine. + +.. code-block:: cpp + + bpReader.EndStep(); + bpReader.Close(); + +14. Finally we need to finalize MPI. + +.. code-block:: cpp + + MPI_Finalize(); + +15. The final code should look as follows (excluding try/catch), and it was derived from the example + `ADIOS2/examples/hello/bpWriter/bpWriter.cpp `_. + +.. literalinclude:: ../../../../examples/hello/bpReader/bpReader.cpp + :language: cpp + +16. You can compile and run it as follows: + +.. code-block:: bash + + cd Path-To-ADIOS2/examples/hello/bpReader + mkdir build + cd build + cmake -DADIOS2_DIR=Path-To-ADIOS2/build/ .. + cmake --build . + mpirun -np 2 ./adios2_hello_bpReader_mpi diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 54a32a8c9b..316e77723e 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -5,28 +5,6 @@ add_subdirectory(basics) add_subdirectory(hello) -add_subdirectory(query) -add_subdirectory(useCases) -add_subdirectory(inlineMWE) add_subdirectory(plugins) -add_subdirectory(fides) -add_subdirectory(campaign) - -if(ADIOS2_HAVE_MPI) - add_subdirectory(heatTransfer) -endif() - -if(ADIOS2_BUILD_EXAMPLES_EXPERIMENTAL) - add_subdirectory(experimental) -endif() - -if(ADIOS2_HAVE_CUDA OR ADIOS2_HAVE_Kokkos_CUDA) - add_subdirectory(cuda) -endif() - - -if(ADIOS2_HAVE_MPI AND ADIOS2_HAVE_HDF5) - if(HDF5_VERSION VERSION_GREATER_EQUAL 1.14) - add_subdirectory(h5subfile) - endif() -endif() +add_subdirectory(simulations) +add_subdirectory(useCases) diff --git a/examples/ReadMe.md b/examples/ReadMe.md new file mode 100644 index 0000000000..b0c91cd9a8 --- /dev/null +++ b/examples/ReadMe.md @@ -0,0 +1,16 @@ +# ADIOS2 Examples + +This directory contains examples of how to use ADIOS2 in different scenarios. +The examples are written mostly in C++, but also C, Fortran, Python, and Julia. + +They can be found in the following subdirectories, and they should be explored in the order that they are listed: + +1. [hello](hello): The _hello_ examples are meant to introduce you to ADIOS2's IO capabilities and engines. +2. [basics](basics): The _basics_ examples are meant to introduce you to basic concepts of ADIOS2, such as + global/joined/local arrays, values, and variables shapes. +3. [useCases](useCases): The _useCases_ examples are meant to demonstrate how to use ADIOS2 in different scenarios, + such as in situ visualization, and fides schema. +4. [plugins](plugins): The _plugins_ examples are meant to introduce you to the plugin capabilities of ADIOS2, such as + how to develop your own engine or operators. +5. [simulations](simulations): The _simulations_ examples are meant to demonstrate how to integrate ADIOS2 within your + simulation code to read, write and/or stream your simulation data. diff --git a/examples/basics/CMakeLists.txt b/examples/basics/CMakeLists.txt index 94fa54cd4c..972125c4df 100644 --- a/examples/basics/CMakeLists.txt +++ b/examples/basics/CMakeLists.txt @@ -3,7 +3,12 @@ # accompanying file Copyright.txt for details. #------------------------------------------------------------------------------# -add_subdirectory(globalArray) +if(ADIOS2_HAVE_MPI) + add_subdirectory(globalArray1D) +endif() +add_subdirectory(globalArrayND) add_subdirectory(joinedArray) add_subdirectory(localArray) +add_subdirectory(queryWorker) add_subdirectory(values) +add_subdirectory(variablesShapes) diff --git a/examples/basics/ReadMe.md b/examples/basics/ReadMe.md new file mode 100644 index 0000000000..c33c5545c6 --- /dev/null +++ b/examples/basics/ReadMe.md @@ -0,0 +1,29 @@ +## ADIOS2 basics examples + +The _basics_ examples are meant to introduce you to basic concepts of ADIOS2, such as +global/joined/local arrays, values, and variables shapes. + +They can be found in the following subdirectories, and they should be explored in the order that they are listed: + +1. [globalArray1D](globalArray1D): The _globalArray1D_ example demonstrates how to read and write an + 1-D global array with constant dimensions over time from multiple processors using ADIOS2's BP engine. + * Languages: C, Fortran +2. [globalArrayND](globalArrayND): The _globalArrayND_ example demonstrates how to write an N-D global array with + constant dimensions over time from multiple processors using ADIOS2's BP engine. + * Languages: C++ +3. [localArray](localArray): The _localArray_ example demonstrates how to write and read a local array per processor + with the same name from multiple processors using ADIOS2's BP engine. + * Languages: C++ +4. [joinedArray](joinedArray): The _joinedArray_ example demonstrates how to write local array that is different only in + one dimension so that it can be joined into a global array with the same name from multiple processors at read time + using ADIOS2's ADIOS2's BP engine. + * Languages: C++ +5. [values](values): The _values_ example demonstrates how to write and read a multiple types of variables with a single + value, such as global constant, global value, local constant, and local value using ADIOS2's BP engine. + * Languages: C++, Fortran +6. [variablesShapes](variablesShapes): The _variablesShapes_ example demonstrates how to write supported variables + shapes using stepping and ADIOS2's BP engine. + * Languages: C++, C++ using high-level API +7. [queryWorker](queryWorker): The _queryWorker_ example demonstrates how to read variables using ADIOS2's BP engine + and perform queries on the read data and streams the results. + * Languages: C++ diff --git a/examples/basics/globalArray/CMakeLists.txt b/examples/basics/globalArray/CMakeLists.txt deleted file mode 100644 index a145a8939b..0000000000 --- a/examples/basics/globalArray/CMakeLists.txt +++ /dev/null @@ -1,12 +0,0 @@ -#------------------------------------------------------------------------------# -# Distributed under the OSI-approved Apache License, Version 2.0. See -# accompanying file Copyright.txt for details. -#------------------------------------------------------------------------------# - -add_executable(globalArray_write globalArray_write.cpp) -target_link_libraries(globalArray_write adios2::cxx11) - -if(ADIOS2_HAVE_MPI) - add_executable(globalArray_write_mpi globalArray_write.cpp) - target_link_libraries(globalArray_write_mpi adios2::cxx11_mpi MPI::MPI_C) -endif() diff --git a/examples/basics/globalArray1D/CMakeLists.txt b/examples/basics/globalArray1D/CMakeLists.txt new file mode 100644 index 0000000000..1173b5fab5 --- /dev/null +++ b/examples/basics/globalArray1D/CMakeLists.txt @@ -0,0 +1,80 @@ +#------------------------------------------------------------------------------# +# Distributed under the OSI-approved Apache License, Version 2.0. See +# accompanying file Copyright.txt for details. +#------------------------------------------------------------------------------# + +cmake_minimum_required(VERSION 3.12) +project(ADIOS2BasicsGlobalArray1DExample) + +if(NOT TARGET adios2_core) + set(_components C) + + include(CheckLanguage) + check_language(Fortran) + if(CMAKE_Fortran_COMPILER) + enable_language(Fortran) + endif() + if(CMAKE_Fortran_COMPILER_LOADED) + list(APPEND _components Fortran) + endif() + + find_package(MPI COMPONENTS ${_components}) + if(MPI_FOUND) + # Workaround for various MPI implementations forcing the link of C++ bindings + add_definitions(-DOMPI_SKIP_MPICXX -DMPICH_SKIP_MPICXX) + + list(APPEND _components MPI) + endif() + + find_package(ADIOS2 REQUIRED COMPONENTS ${_components}) +endif() + +if(ADIOS2_HAVE_MPI) + add_library(adios2_basics_globalArray1D_mpivars_c OBJECT mpivars.c) + target_link_libraries(adios2_basics_globalArray1D_mpivars_c MPI::MPI_C) + install(TARGETS adios2_basics_globalArray1D_mpivars_c RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + + add_library(adios2_basics_globalArray1D_decomp_c OBJECT decomp.c) + target_link_libraries(adios2_basics_globalArray1D_decomp_c + adios2_basics_globalArray1D_mpivars_c MPI::MPI_C) + install(TARGETS adios2_basics_globalArray1D_decomp_c RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + + add_executable(adios2_basics_globalArray1DWrite_c globalArray1DWrite.c) + target_link_libraries(adios2_basics_globalArray1DWrite_c + adios2_basics_globalArray1D_mpivars_c + adios2_basics_globalArray1D_decomp_c + adios2::c_mpi MPI::MPI_C) + install(TARGETS adios2_basics_globalArray1DWrite_c RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + + add_executable(adios2_basics_globalArray1DRead_c globalArray1DRead.c) + target_link_libraries(adios2_basics_globalArray1DRead_c + adios2_basics_globalArray1D_mpivars_c + adios2_basics_globalArray1D_decomp_c + adios2::c_mpi MPI::MPI_C) + install(TARGETS adios2_basics_globalArray1DRead_c RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + + if(ADIOS2_HAVE_Fortran) + add_library(adios2_basics_globalArray1D_mpivars_f OBJECT mpivars.F90) + target_link_libraries(adios2_basics_globalArray1D_mpivars_f MPI::MPI_Fortran) + install(TARGETS adios2_basics_globalArray1D_mpivars_f RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + + add_library(adios2_basics_globalArray1D_decomp_f OBJECT decomp.F90) + target_link_libraries(adios2_basics_globalArray1D_decomp_f + adios2_basics_globalArray1D_mpivars_f MPI::MPI_Fortran) + install(TARGETS adios2_basics_globalArray1D_decomp_f RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + + add_executable(adios2_basics_globalArray1DWrite_f globalArray1DWrite.F90) + target_link_libraries(adios2_basics_globalArray1DWrite_f + adios2_basics_globalArray1D_mpivars_f + adios2_basics_globalArray1D_decomp_f + adios2::fortran_mpi MPI::MPI_Fortran) + install(TARGETS adios2_basics_globalArray1DWrite_f RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + + add_executable(adios2_basics_globalArray1DRead_f globalArray1DRead.F90) + target_link_libraries(adios2_basics_globalArray1DRead_f + adios2_basics_globalArray1D_mpivars_f + adios2_basics_globalArray1D_decomp_f + adios2::fortran_mpi MPI::MPI_Fortran) + install(TARGETS adios2_basics_globalArray1DRead_f RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + endif() +endif() diff --git a/examples/basics/globalArray1D/decomp.F90 b/examples/basics/globalArray1D/decomp.F90 new file mode 100644 index 0000000000..b39d93d92c --- /dev/null +++ b/examples/basics/globalArray1D/decomp.F90 @@ -0,0 +1,53 @@ +! Helper functions for all examples +module decomp +contains + +! random integer from {minv, minv+1, ..., maxv} +! including minv and maxv +function get_random(minv, maxv) result(n) + implicit none + integer, intent(in) :: minv, maxv + real :: r + integer :: n + call random_number(r) + n = minv + FLOOR((maxv+1-minv)*r) +end function get_random + +! gather the local sizes of arrays and sum them up +! so that each process knows the global shape +! and its own offset in the global space +subroutine gather_decomp_1d(mysize, myshape, myoffset) + use mpivars + implicit none + integer*8, intent(in) :: mysize + integer*8, intent(out) :: myshape, myoffset + integer*8, dimension(:), allocatable :: sizes + + allocate(sizes(nproc)) + call MPI_Allgather( mysize, 1, MPI_LONG_LONG, & + sizes, 1, MPI_LONG_LONG, & + app_comm, ierr) + myshape = sum(sizes) + myoffset = sum(sizes(1:rank)) + deallocate(sizes) +end subroutine gather_decomp_1d + +subroutine decompose_1d(globalsize, myoffset, mysize) + use mpivars + implicit none + integer*8, intent(in) :: globalsize + integer*8, intent(out) :: myoffset, mysize + integer*8 :: rem + + mysize = globalsize/nproc + rem = globalsize-(nproc*mysize) + if (rank < rem) then + mysize = mysize + 1 + myoffset = rank*mysize + else + myoffset = rank*mysize + rem + endif +end subroutine decompose_1d + +end module decomp + diff --git a/examples/basics/globalArray1D/decomp.c b/examples/basics/globalArray1D/decomp.c new file mode 100644 index 0000000000..bb7d3300a5 --- /dev/null +++ b/examples/basics/globalArray1D/decomp.c @@ -0,0 +1,67 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * Created by Dmitry Ganyushin ganyushindi@ornl.gov + * + * Helper functions for all examples + */ +#include "decomp.h" +#include "mpivars.h" +#include +#include +#include +#include + +/* random integer from {minv, minv+1, ..., maxv} + including minv and maxv */ +long long int get_random(int minv, int maxv) +{ + long long int n; + time_t t; + /* Intializes random number generator */ + srand((unsigned)time(&t)); + n = (rand() % (maxv - minv + 1)) + minv; + return n; +} +/* gather the local sizes of arrays and sum them up + so that each process knows the global shape + and its own offset in the global space */ +void gather_decomp_1d(long long int *mysize, long long int *myshape, long long int *myoffset) +{ + long long int *sizes; + int i; + sizes = malloc(sizeof(long long int) * (size_t)nproc); + MPI_Allgather(mysize, 1, MPI_LONG_LONG, sizes, 1, MPI_LONG_LONG, app_comm); + + *myshape = 0; + for (i = 0; i < nproc; i++) + { + *myshape += sizes[i]; + } + *myoffset = 0; + for (i = 0; i < rank; i++) + { + *myoffset += sizes[i]; + } + + free(sizes); + return; +} + +void decomp_1d(long long int globalsize, long long int *myoffset, long long int *mysize) +{ + long long int rem; + *mysize = globalsize / nproc; + rem = globalsize - (nproc * *mysize); + if (rank < rem) + { + mysize = mysize + 1; + *myoffset = rank * *mysize; + } + else + { + *myoffset = rank * *mysize + rem; + } + return; +} diff --git a/examples/basics/globalArray1D/decomp.h b/examples/basics/globalArray1D/decomp.h new file mode 100644 index 0000000000..e972714844 --- /dev/null +++ b/examples/basics/globalArray1D/decomp.h @@ -0,0 +1,14 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * Created by Dmitry Ganyushin ganyushindi@ornl.gov + */ + +#ifndef ADIOS2EXAMPLES_DECOMP_H +#define ADIOS2EXAMPLES_DECOMP_H + +extern long long int get_random(int, int); +extern void gather_decomp_1d(long long int *, long long int *, long long int *); +extern void decomp_1d(long long int, long long int *, long long int *); +#endif // ADIOS2EXAMPLES_DECOMP_H diff --git a/examples/basics/globalArray1D/globalArray1DRead.F90 b/examples/basics/globalArray1D/globalArray1DRead.F90 new file mode 100644 index 0000000000..725f1992cd --- /dev/null +++ b/examples/basics/globalArray1D/globalArray1DRead.F90 @@ -0,0 +1,104 @@ +program adios2_global_array_1d_read + use mpivars + use adios2 + implicit none + + ! ADIOS2 variables + type(adios2_adios) :: adios + + ! MPI then ADIOS2 initialization + call init_mpi(234) + call adios2_init(adios, app_comm, ierr) + + call reader() + + ! ADIOS2 then MPI finalization + call adios2_finalize(adios, ierr) + call finalize_mpi() + +contains + +subroutine reader + use mpivars + use decomp + use adios2 + implicit none + + character(len=256), parameter :: streamname = "adios2-global-array-1d-f.bp" + + type(adios2_io) :: io + type(adios2_engine) :: engine + type(adios2_variable) :: var_g + integer :: step, istatus + + ! Application variables + ! g = 1D distributed array, global shape and per-process size is fixed + + real*4, dimension(:), allocatable :: g + integer :: ndims + integer*8, dimension(:), allocatable :: fixed_shape + integer*8, dimension(1) :: fixed_start, fixed_count + + call adios2_declare_io (io, adios, 'input', ierr) + call adios2_open(engine, io, streamname, adios2_mode_read, ierr) + if (ierr .ne. 0) then + print '(" Failed to open stream: ",a)', streamname + print '(" open stream ierr=: ",i0)', ierr + return + endif + + ! Reading steps + step = 0 + do + call adios2_begin_step(engine, adios2_step_mode_read, 0.0, istatus, ierr) + if (ierr /= 0) then + print '(" Failure when trying to get next step: ",a)', streamname + exit + endif + if (istatus == adios2_step_status_end_of_stream) then + ! Stream has terminated, no more steps are available + !print '(" Input stream has terminated: ",a)', streamname + exit + endif + + ! Variable pointer MUST be retrieved every step, the reference + ! will go invalid after adios2_end_step + call adios2_inquire_variable(var_g, io, "GlobalArray", ierr ) + + ! Get variable dimensions and do decomposition in the first step + ! These don't change for the stream in this example + if (step == 0) then + ! fixed_shape is allocated in the next call + call adios2_variable_shape(fixed_shape, ndims, var_g, ierr) + + call decompose_1d(fixed_shape(1), fixed_start(1), fixed_count(1)) + allocate(g(fixed_count(1))) + + write (*,100) "Read plan rank=", rank, & + " global shape = ", fixed_shape(1), & + " local count = ", fixed_count(1), & + " offset = ", fixed_start(1) +100 format (a,i2,a,i4,a,i1,a,i4) + endif + + call adios2_set_selection(var_g, 1, fixed_start, fixed_count, ierr) + call adios2_get(engine, var_g, g, ierr) + call adios2_end_step(engine, ierr) + + ! g[] is now filled with data AFTER adios2_end_step/adios2_perform_gets + ! or should call adios2_get(engine, var_g, g, adios2_mode_sync, ierr) + ! to get it immediately in the get() call + + step = step + 1 + enddo + + ! Close the output + call adios2_close(engine, ierr) + + deallocate(g) + deallocate(fixed_shape) + +end subroutine reader + + +end program adios2_global_array_1d_read diff --git a/examples/basics/globalArray1D/globalArray1DRead.c b/examples/basics/globalArray1D/globalArray1DRead.c new file mode 100644 index 0000000000..288ce9f11b --- /dev/null +++ b/examples/basics/globalArray1D/globalArray1DRead.c @@ -0,0 +1,86 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * Created by Dmitry Ganyushin ganyushindi@ornl.gov + */ +#include "decomp.h" +#include "mpivars.h" +#include +#include +#include + +void reader(adios2_adios *adios) +{ + int step; + float *g; + const char *streamname = "adios2-global-array-1d-c.bp"; + adios2_step_status err; + + long long int fixed_shape = 0, fixed_start = 0, fixed_count = 0; + + adios2_io *io = adios2_declare_io(adios, "input"); + size_t shape[1]; + shape[0] = (size_t)fixed_shape; + + adios2_engine *engine = adios2_open(io, streamname, adios2_mode_read); + step = 0; + do + { + adios2_begin_step(engine, adios2_step_mode_read, 10.0, &err); + adios2_variable *var_g = adios2_inquire_variable(io, "GlobalArray"); + if (step == 0) + { + /* fixed_shape is allocated in the next call*/ + adios2_variable_shape(shape, var_g); + fixed_shape = (long long int)shape[0]; + decomp_1d(fixed_shape, &fixed_start, &fixed_count); + g = malloc((size_t)fixed_count * sizeof(float)); + + printf("Read plan rank = %d global shape = %lld local count = %lld " + "offset = %lld\n", + rank, fixed_shape, fixed_count, fixed_start); + } + adios2_end_step(engine); + step++; + } while (err != adios2_step_status_end_of_stream); + // Close the output + adios2_close(engine); + free(g); + + if (rank == 0) + { + printf("Try the following: \n"); + printf(" bpls -la adios2-global-array-1d-c.bp GlobalArray -d -n " + "%lld \n", + fixed_shape); + printf(" bpls -la adios2-global-array-1d-c.bp GlobalArray -d -t -n " + "%lld \n ", + fixed_shape); + printf(" mpirun -n 2 ./adios2-global-array-1d-read-c \n"); + } +} + +int main(int argc, char *argv[]) +{ +#if ADIOS2_USE_MPI + init_mpi(123, argc, argv); +#endif + + { +#if ADIOS2_USE_MPI + + adios2_adios *adios = adios2_init_mpi(MPI_COMM_WORLD); +#else + adios2_adios *adios = adios2_init(); +#endif + reader(adios); + adios2_finalize(adios); + } + +#if ADIOS2_USE_MPI + finalize_mpi(); +#endif + + return 0; +} diff --git a/examples/basics/globalArray1D/globalArray1DWrite.F90 b/examples/basics/globalArray1D/globalArray1DWrite.F90 new file mode 100644 index 0000000000..90d0778909 --- /dev/null +++ b/examples/basics/globalArray1D/globalArray1DWrite.F90 @@ -0,0 +1,93 @@ +program adios2_global_array_1d_write + use mpivars + use adios2 + implicit none + integer, parameter :: numsteps = 5 + + ! ADIOS2 variables + type(adios2_adios) :: adios + + ! MPI then ADIOS2 initialization + call init_mpi(123) + call adios2_init(adios, app_comm, ierr) + + call writer() + + ! ADIOS2 then MPI finalization + call adios2_finalize(adios, ierr) + call finalize_mpi() + +contains + +subroutine writer + use mpivars + use decomp + use adios2 + implicit none + + type(adios2_io) :: io + type(adios2_engine) :: engine + type(adios2_variable) :: var_g + type(adios2_attribute) :: attr + integer :: step + + ! Application variables + ! g = 1D distributed array, + ! global shape and per-process size is fixed + + real*4, dimension(:), allocatable :: g + character(80), parameter :: ga = "Global Array with fixed shape and decomposition" + + integer, parameter :: mincount = 2, maxcount = 5 + integer*8, dimension(1) :: fixed_shape, fixed_start, fixed_count + + fixed_count(1) = get_random(mincount, maxcount) + allocate(g(fixed_count(1))) + call gather_decomp_1d(fixed_count(1), fixed_shape(1), fixed_start(1)) + + call adios2_declare_io (io, adios, 'output', ierr) + + call adios2_define_variable(var_g, io, "GlobalArray", & + adios2_type_real4, 1, & + fixed_shape, fixed_start, fixed_count, & + adios2_constant_dims, ierr) + + call adios2_define_attribute(attr, io, "GlobalArray/info", ga, ierr) + + call adios2_open(engine, io, "adios2-global-array-1d-f.bp", adios2_mode_write, ierr) + + write (*,100) "Decomp rank=", rank, & + " global shape = ", fixed_shape(1), & + " local count = ", fixed_count(1), & + " offset = ", fixed_start(1) +100 format (a,i2,a,i4,a,i1,a,i4) + + ! Computation/output loop + do step=0,numsteps-1 + g = rank + (step+1)/100.0 + ! Output all data + call adios2_begin_step(engine, adios2_step_mode_append, ierr) + call adios2_put(engine, var_g, g, ierr); + call adios2_end_step(engine, ierr) + enddo + + ! Close the output + call adios2_close(engine, ierr) + + deallocate(g) + + if (rank == 0) then + write (*,*) "Try the following: " + write (*,'(a,a,i4)') & + " bpls -la adios2-global-array-1d-f.bp ", & + "GlobalArray -d -n ", fixed_shape(1) + write (*,'(a,a,i4)') & + " bpls -la adios2-global-array-1d-f.bp ", & + "GlobalArray -d -t -n ", fixed_shape(1) + write (*,'(a)') & + " mpirun -n 2 ./adios2-global-array-1d-read-f " + endif +end subroutine writer + + +end program adios2_global_array_1d_write diff --git a/examples/basics/globalArray1D/globalArray1DWrite.c b/examples/basics/globalArray1D/globalArray1DWrite.c new file mode 100644 index 0000000000..4ae38ed3da --- /dev/null +++ b/examples/basics/globalArray1D/globalArray1DWrite.c @@ -0,0 +1,99 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * Created by Dmitry Ganyushin ganyushindi@ornl.gov + */ +#include "decomp.h" +#include "mpivars.h" +#include +#include +#include + +void writer(adios2_adios *adios) +{ + int step, i; + float *g; + const int mincount = 2; + const int maxcount = 5; + const int numsteps = 5; + adios2_step_status err; + + long long int fixed_shape = 0, fixed_start = 0, fixed_count = 0; + + /* Application variables + g = 1D distributed array, + global shape and per-process size is fixed */ + fixed_count = get_random(mincount, maxcount); + g = malloc((size_t)fixed_count * sizeof(float)); + gather_decomp_1d(&fixed_count, &fixed_shape, &fixed_start); + + adios2_io *io = adios2_declare_io(adios, "output"); + size_t shape[1]; + shape[0] = (size_t)fixed_shape; + + size_t start[1]; + start[0] = (size_t)fixed_start; + + size_t count[1]; + count[0] = (size_t)fixed_count; + + adios2_variable *var_g = adios2_define_variable(io, "GlobalArray", adios2_type_float, 1, shape, + start, count, adios2_constant_dims_true); + + adios2_engine *engine = adios2_open(io, "adios2-global-array-1d-c.bp", adios2_mode_write); + printf("Decmp rank = %d global shape = %lld local count = %lld offset = " + "%lld\n", + rank, fixed_shape, fixed_count, fixed_start); + for (step = 0; step < numsteps; step++) + { + for (i = 0; i < fixed_count; i++) + { + g[i] = (float)(rank + (step + 1) / 100.0); + } + + adios2_begin_step(engine, adios2_step_mode_append, 10.0f, &err); + adios2_put(engine, var_g, g, adios2_mode_deferred); + adios2_end_step(engine); + } + // Close the output + adios2_close(engine); + free(g); + + if (rank == 0) + { + printf("Try the following: \n"); + printf(" bpls -la adios2-global-array-1d-c.bp GlobalArray -d -n " + "%lld \n", + fixed_shape); + printf(" bpls -la adios2-global-array-1d-c.bp GlobalArray -d -t -n " + "%lld \n ", + fixed_shape); + printf(" mpirun -n 2 ./adios2-global-array-1d-read-c \n"); + } +} + +int main(int argc, char *argv[]) +{ +#if ADIOS2_USE_MPI + init_mpi(123, argc, argv); +#endif + + { +#if ADIOS2_USE_MPI + + adios2_adios *adios = adios2_init_mpi(MPI_COMM_WORLD); +#else + adios2_adios *adios = adios2_init(); +#endif + + writer(adios); + adios2_finalize(adios); + } + +#if ADIOS2_USE_MPI + finalize_mpi(); +#endif + + return 0; +} diff --git a/examples/basics/globalArray1D/mpivars.F90 b/examples/basics/globalArray1D/mpivars.F90 new file mode 100644 index 0000000000..323e4b0c15 --- /dev/null +++ b/examples/basics/globalArray1D/mpivars.F90 @@ -0,0 +1,30 @@ +module mpivars + implicit none + include 'mpif.h' + + integer:: app_comm, rank, nproc + integer:: wrank, wnproc + integer:: ierr + +contains + +subroutine init_mpi(color) + integer, intent(in):: color + call MPI_Init(ierr) + ! World comm spans all applications started with the same mpirun command + call MPI_Comm_rank(MPI_COMM_WORLD, wrank, ierr) + call MPI_Comm_size(MPI_COMM_WORLD, wnproc, ierr) + + ! Have to split and create a 'world' communicator for this app only + ! color must be unique for each application + call MPI_Comm_split (MPI_COMM_WORLD, color, wrank, app_comm, ierr) + call MPI_Comm_rank (app_comm, rank, ierr) + call MPI_Comm_size (app_comm, nproc , ierr) +end subroutine init_mpi + +subroutine finalize_mpi() + call MPI_Finalize(ierr) +end subroutine finalize_mpi + +end module mpivars + diff --git a/examples/basics/globalArray1D/mpivars.c b/examples/basics/globalArray1D/mpivars.c new file mode 100644 index 0000000000..5c4aa5634b --- /dev/null +++ b/examples/basics/globalArray1D/mpivars.c @@ -0,0 +1,29 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * Created by Dmitry Ganyushin ganyushindi@ornl.gov + */ +#include "mpivars.h" +#include + +int rank, nproc; +int wrank, wnproc; +MPI_Comm app_comm; + +void init_mpi(int color, int argc, char *argv[]) +{ + MPI_Init(&argc, &argv); + /* World comm spans all applications started with the same mpirun command */ + MPI_Comm_rank(MPI_COMM_WORLD, &wrank); + MPI_Comm_size(MPI_COMM_WORLD, &wnproc); + + /* Have to split and create a 'world' communicator for this app only + color must be unique for each application*/ + MPI_Comm_split(MPI_COMM_WORLD, color, wrank, &app_comm); + MPI_Comm_rank(app_comm, &rank); + MPI_Comm_size(app_comm, &nproc); + return; +} + +void finalize_mpi() { MPI_Finalize(); } diff --git a/examples/basics/globalArray1D/mpivars.h b/examples/basics/globalArray1D/mpivars.h new file mode 100644 index 0000000000..98c00586d3 --- /dev/null +++ b/examples/basics/globalArray1D/mpivars.h @@ -0,0 +1,14 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * Created by Dmitry Ganyushin ganyushindi@ornl.gov + */ +#ifndef ADIOS2EXAMPLES_MPIVARS_H +#define ADIOS2EXAMPLES_MPIVARS_H +#include +extern int rank, nproc; +extern MPI_Comm app_comm; +void init_mpi(int, int, char *argv[]); +void finalize_mpi(); +#endif // ADIOS2EXAMPLES_MPIVARS_H diff --git a/examples/basics/globalArrayND/CMakeLists.txt b/examples/basics/globalArrayND/CMakeLists.txt new file mode 100644 index 0000000000..f1d131c5fa --- /dev/null +++ b/examples/basics/globalArrayND/CMakeLists.txt @@ -0,0 +1,31 @@ +#------------------------------------------------------------------------------# +# Distributed under the OSI-approved Apache License, Version 2.0. See +# accompanying file Copyright.txt for details. +#------------------------------------------------------------------------------# + +cmake_minimum_required(VERSION 3.12) +project(ADIOS2BasicsGlobalArrayNDExample) + +if(NOT TARGET adios2_core) + set(_components CXX) + + find_package(MPI COMPONENTS C) + if(MPI_FOUND) + # Workaround for various MPI implementations forcing the link of C++ bindings + add_definitions(-DOMPI_SKIP_MPICXX -DMPICH_SKIP_MPICXX) + + list(APPEND _components MPI) + endif() + + find_package(ADIOS2 REQUIRED COMPONENTS ${_components}) +endif() + +add_executable(adios2_basics_globalArrayNDWrite globalArrayNDWrite.cpp) +target_link_libraries(adios2_basics_globalArrayNDWrite adios2::cxx11) +install(TARGETS adios2_basics_globalArrayNDWrite RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + +if(ADIOS2_HAVE_MPI) + add_executable(adios2_basics_globalArrayNDWrite_mpi globalArrayNDWrite.cpp) + target_link_libraries(adios2_basics_globalArrayNDWrite_mpi adios2::cxx11_mpi MPI::MPI_C) + install(TARGETS adios2_basics_globalArrayNDWrite_mpi RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) +endif() diff --git a/examples/basics/globalArray/globalArray_write.cpp b/examples/basics/globalArrayND/globalArrayNDWrite.cpp similarity index 96% rename from examples/basics/globalArray/globalArray_write.cpp rename to examples/basics/globalArrayND/globalArrayNDWrite.cpp index 45c63c5c25..b1509b7b54 100644 --- a/examples/basics/globalArray/globalArray_write.cpp +++ b/examples/basics/globalArrayND/globalArrayNDWrite.cpp @@ -68,7 +68,7 @@ int main(int argc, char *argv[]) // Get io settings from the config file or // create one with default settings here adios2::IO io = adios.DeclareIO("Output"); - io.SetEngine("BP5"); + io.SetEngine("BPFile"); io.SetParameter("AggregationType", "TwoLevelShm"); io.SetParameter("AggregatorRatio", "4"); @@ -94,7 +94,8 @@ int main(int argc, char *argv[]) for (size_t i = 0; i < Nx; i++) { - row[i] = step * Nx * nproc * 1.0 + rank * Nx * 1.0 + (double)i; + row[i] = static_cast(step) * Nx * nproc * 1.0 + rank * Nx * 1.0 + + static_cast(i); } // Make a 2D selection to describe the local dimensions of the diff --git a/examples/basics/joinedArray/CMakeLists.txt b/examples/basics/joinedArray/CMakeLists.txt index 0ac015c3a1..a342d75293 100644 --- a/examples/basics/joinedArray/CMakeLists.txt +++ b/examples/basics/joinedArray/CMakeLists.txt @@ -3,10 +3,29 @@ # accompanying file Copyright.txt for details. #------------------------------------------------------------------------------# -add_executable(joinedArray_write joinedArray_write.cpp) -target_link_libraries(joinedArray_write adios2::cxx11) +cmake_minimum_required(VERSION 3.12) +project(ADIOS2BasicsJoinedArrayExample) + +if(NOT TARGET adios2_core) + set(_components CXX) + + find_package(MPI COMPONENTS C) + if(MPI_FOUND) + # Workaround for various MPI implementations forcing the link of C++ bindings + add_definitions(-DOMPI_SKIP_MPICXX -DMPICH_SKIP_MPICXX) + + list(APPEND _components MPI) + endif() + + find_package(ADIOS2 REQUIRED COMPONENTS ${_components}) +endif() + +add_executable(adios2_basics_joinedArrayWrite joinedArrayWrite.cpp) +target_link_libraries(adios2_basics_joinedArrayWrite adios2::cxx11) +install(TARGETS adios2_basics_joinedArrayWrite RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) if(ADIOS2_HAVE_MPI) - add_executable(joinedArray_write_mpi joinedArray_write.cpp) - target_link_libraries(joinedArray_write_mpi adios2::cxx11_mpi MPI::MPI_C) + add_executable(adios2_basics_joinedArrayWrite_mpi joinedArrayWrite.cpp) + target_link_libraries(adios2_basics_joinedArrayWrite_mpi adios2::cxx11_mpi MPI::MPI_C) + install(TARGETS adios2_basics_joinedArrayWrite_mpi RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) endif() diff --git a/examples/basics/joinedArray/joinedArray_write.cpp b/examples/basics/joinedArray/joinedArrayWrite.cpp similarity index 99% rename from examples/basics/joinedArray/joinedArray_write.cpp rename to examples/basics/joinedArray/joinedArrayWrite.cpp index 066ffd83f7..e54f1206a4 100644 --- a/examples/basics/joinedArray/joinedArray_write.cpp +++ b/examples/basics/joinedArray/joinedArrayWrite.cpp @@ -73,7 +73,7 @@ int main(int argc, char *argv[]) // Get io settings from the config file or // create one with default settings here adios2::IO io = adios.DeclareIO("Output"); - io.SetEngine("BP4"); + io.SetEngine("BPFile"); /* * Define joinable local array: type, name, global and local size diff --git a/examples/basics/localArray/CMakeLists.txt b/examples/basics/localArray/CMakeLists.txt index 1d304a647e..a43a61550f 100644 --- a/examples/basics/localArray/CMakeLists.txt +++ b/examples/basics/localArray/CMakeLists.txt @@ -3,13 +3,33 @@ # accompanying file Copyright.txt for details. #------------------------------------------------------------------------------# -add_executable(localArray_write localArray_write.cpp) -target_link_libraries(localArray_write adios2::cxx11) +cmake_minimum_required(VERSION 3.12) +project(ADIOS2BasicsLocalArrayExample) -add_executable(localArray_read localArray_read.cpp) -target_link_libraries(localArray_read adios2::cxx11) +if(NOT TARGET adios2_core) + set(_components CXX) + + find_package(MPI COMPONENTS C) + if(MPI_FOUND) + # Workaround for various MPI implementations forcing the link of C++ bindings + add_definitions(-DOMPI_SKIP_MPICXX -DMPICH_SKIP_MPICXX) + + list(APPEND _components MPI) + endif() + + find_package(ADIOS2 REQUIRED COMPONENTS ${_components}) +endif() + +add_executable(adios2_basics_localArrayWrite localArrayWrite.cpp) +target_link_libraries(adios2_basics_localArrayWrite adios2::cxx11) +install(TARGETS adios2_basics_localArrayWrite RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + +add_executable(adios2_basics_localArrayRead localArrayRead.cpp) +target_link_libraries(adios2_basics_localArrayRead adios2::cxx11) +install(TARGETS adios2_basics_localArrayRead RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) if(ADIOS2_HAVE_MPI) - add_executable(localArray_write_mpi localArray_write.cpp) - target_link_libraries(localArray_write_mpi adios2::cxx11_mpi MPI::MPI_C) + add_executable(adios2_basics_localArrayWrite_mpi localArrayWrite.cpp) + target_link_libraries(adios2_basics_localArrayWrite_mpi adios2::cxx11_mpi MPI::MPI_C) + install(TARGETS adios2_basics_localArrayWrite_mpi RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) endif() diff --git a/examples/basics/localArray/localArray_read.cpp b/examples/basics/localArray/localArrayRead.cpp similarity index 100% rename from examples/basics/localArray/localArray_read.cpp rename to examples/basics/localArray/localArrayRead.cpp diff --git a/examples/basics/localArray/localArray_write.cpp b/examples/basics/localArray/localArrayWrite.cpp similarity index 99% rename from examples/basics/localArray/localArray_write.cpp rename to examples/basics/localArray/localArrayWrite.cpp index 1bd4f4e199..cdef7fbf96 100644 --- a/examples/basics/localArray/localArray_write.cpp +++ b/examples/basics/localArray/localArrayWrite.cpp @@ -91,7 +91,7 @@ int main(int argc, char *argv[]) // Get io settings from the config file or // create one with default settings here adios2::IO io = adios.DeclareIO("Output"); - io.SetEngine("BP5"); + io.SetEngine("BPFile"); io.SetParameters({{"verbose", "4"}}); /* diff --git a/examples/basics/queryWorker/CMakeLists.txt b/examples/basics/queryWorker/CMakeLists.txt new file mode 100644 index 0000000000..7cce9e5c4c --- /dev/null +++ b/examples/basics/queryWorker/CMakeLists.txt @@ -0,0 +1,28 @@ +#------------------------------------------------------------------------------# +# Distributed under the OSI-approved Apache License, Version 2.0. See +# accompanying file Copyright.txt for details. +#------------------------------------------------------------------------------# + +cmake_minimum_required(VERSION 3.12) +project(ADIOS2BasicsQueryWorkerExample) + +if(NOT TARGET adios2_core) + set(_components CXX) + + find_package(MPI COMPONENTS C) + if(MPI_FOUND) + # Workaround for various MPI implementations forcing the link of C++ bindings + add_definitions(-DOMPI_SKIP_MPICXX -DMPICH_SKIP_MPICXX) + + list(APPEND _components MPI) + endif() + + find_package(ADIOS2 REQUIRED COMPONENTS ${_components}) +endif() + +if(ADIOS2_HAVE_MPI) + add_executable(adios2_basics_queryWorker queryWorker.cpp) + target_link_libraries(adios2_basics_queryWorker adios2::cxx11_mpi MPI::MPI_C) + install(TARGETS adios2_basics_queryWorker RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) +endif() + diff --git a/examples/basics/queryWorker/ReadMe.md b/examples/basics/queryWorker/ReadMe.md new file mode 100644 index 0000000000..a241abfefd --- /dev/null +++ b/examples/basics/queryWorker/ReadMe.md @@ -0,0 +1,11 @@ +### ADIOS2 queryWorker example + +The _queryWorker_ example demonstrates how to read variables using ADIOS2's BP engine +and perform queries on the read data and streams the results. + +1. q1.json is a json query file for one var + +2. q2.json is a composite query + +3. The bp*xml are the from heat transfer example with bp4 engine, and tag is added at the end for xml + query spec diff --git a/examples/query/configs/bp4io.xml b/examples/basics/queryWorker/configs/bp4io.xml similarity index 99% rename from examples/query/configs/bp4io.xml rename to examples/basics/queryWorker/configs/bp4io.xml index 65245c97e6..d921181b65 100644 --- a/examples/query/configs/bp4io.xml +++ b/examples/basics/queryWorker/configs/bp4io.xml @@ -1,6 +1,6 @@ diff --git a/examples/query/configs/bp4io_composite.xml b/examples/basics/queryWorker/configs/bp4io_composite.xml similarity index 98% rename from examples/query/configs/bp4io_composite.xml rename to examples/basics/queryWorker/configs/bp4io_composite.xml index 4e6136b4e4..412f883bcd 100644 --- a/examples/query/configs/bp4io_composite.xml +++ b/examples/basics/queryWorker/configs/bp4io_composite.xml @@ -1,7 +1,7 @@ diff --git a/examples/query/configs/q1.json b/examples/basics/queryWorker/configs/q1.json similarity index 100% rename from examples/query/configs/q1.json rename to examples/basics/queryWorker/configs/q1.json diff --git a/examples/query/configs/q2.json b/examples/basics/queryWorker/configs/q2.json similarity index 100% rename from examples/query/configs/q2.json rename to examples/basics/queryWorker/configs/q2.json diff --git a/examples/basics/queryWorker/queryWorker.cpp b/examples/basics/queryWorker/queryWorker.cpp new file mode 100644 index 0000000000..c6cd4e32b9 --- /dev/null +++ b/examples/basics/queryWorker/queryWorker.cpp @@ -0,0 +1,128 @@ +#include "adios2.h" +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +// touched block ids are printed. +void queryIDs(adios2::IO &queryIO, std::string &dataFileName, std::string &queryFile) +{ + adios2::Engine reader = queryIO.Open(dataFileName, adios2::Mode::Read, MPI_COMM_WORLD); + // adios2::QueryWorker* worker = NULL; + queryIO.SetParameter("StreamReader", "true"); + std::vector touched_blockIDs; + + while (reader.BeginStep() == adios2::StepStatus::OK) + { + adios2::QueryWorker w = adios2::QueryWorker(queryFile, reader); + w.GetResultCoverage(touched_blockIDs); + + std::cout << " Num touched blocks =" << touched_blockIDs.size() << std::endl; + for (auto n : touched_blockIDs) + { + std::cout << "\t[" << n << "] " << std::endl; + } + + reader.EndStep(); + } + reader.Close(); +} + +void queryWithStreaming(adios2::IO &queryIO, std::string &dataFileName, std::string &queryFile) +{ + adios2::Engine reader = queryIO.Open(dataFileName, adios2::Mode::Read, MPI_COMM_WORLD); + // adios2::QueryWorker* worker = NULL; + queryIO.SetParameter("StreamReader", "true"); + std::vector> touched_blocks; + + while (reader.BeginStep() == adios2::StepStatus::OK) + { + adios2::QueryWorker w = adios2::QueryWorker(queryFile, reader); + w.GetResultCoverage(touched_blocks); + + std::cout << " Num touched regions =" + << touched_blocks.size() + // std::cout << " ... now can read out touched blocks ... size=" << + // touched_blocks.size() + << std::endl; + for (auto n : touched_blocks) + { + std::ostringstream startStr; + std::ostringstream countStr; + for (size_t k = 0; k < n.first.size(); k++) + { + startStr << n.first[k] << " "; + countStr << n.second[k] << " "; + } + std::cout << "\t[" << startStr.str() << "] [" << countStr.str() << "]" << std::endl; + } + reader.EndStep(); + } + reader.Close(); +} + +int main(int argc, char *argv[]) +{ + int provided; + + // MPI_THREAD_MULTIPLE is only required if you enable the SST MPI_DP + MPI_Init_thread(&argc, &argv, MPI_THREAD_MULTIPLE, &provided); + int rank, size; + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + MPI_Comm_size(MPI_COMM_WORLD, &size); + + try + { + std::string configFileName = "query.xml"; + std::string dataFileName = "/tmp/heatbp4.bp"; + if (argc <= 2) + { + std::cout << "Usage: " << argv[0] << " configFileName dataFilePath (queryFile)" + << std::endl; + std::cout << " e.g. " << argv[0] << " bp4io.xml heat_bp4.bp/ " << std::endl; + std::cout << " or " << argv[0] << " bp4io.xml heat_bp4.bp/ q1.json" << std::endl; + return 0; + } + + configFileName = argv[1]; + dataFileName = argv[2]; + + adios2::ADIOS ad = adios2::ADIOS(configFileName, MPI_COMM_WORLD); + + adios2::IO queryIO = ad.DeclareIO("query"); + + std::string queryFile = configFileName; + if (argc > 3) + { + queryFile = argv[3]; + } + if (rank == 0) + { + std::cout << " using config file = " << configFileName << std::endl; + std::cout << " data file = " << dataFileName << std::endl; + std::cout << " queryfile = " << queryFile << std::endl; + } + + queryIDs(queryIO, dataFileName, queryFile); + + std::cout << "\n" << std::endl; + queryWithStreaming(queryIO, dataFileName, queryFile); + + return 0; + } + catch (std::exception &e) + { + std::cout << "Exception, STOPPING PROGRAM from rank " << rank << "\n"; + std::cout << e.what() << "\n"; + } + + MPI_Finalize(); + + return 0; +} diff --git a/examples/basics/values/CMakeLists.txt b/examples/basics/values/CMakeLists.txt index f36b4c745a..f37b7da6ab 100644 --- a/examples/basics/values/CMakeLists.txt +++ b/examples/basics/values/CMakeLists.txt @@ -3,10 +3,51 @@ # accompanying file Copyright.txt for details. #------------------------------------------------------------------------------# -add_executable(values_write values_write.cpp) -target_link_libraries(values_write adios2::cxx11) +cmake_minimum_required(VERSION 3.12) +project(ADIOS2BasicsValuesExample) + +if(NOT TARGET adios2_core) + set(_components C) + + include(CheckLanguage) + check_language(Fortran) + if(CMAKE_Fortran_COMPILER) + enable_language(Fortran) + endif() + if(CMAKE_Fortran_COMPILER_LOADED) + list(APPEND _components Fortran) + endif() + + find_package(MPI COMPONENTS ${_components}) + if(MPI_FOUND) + # Workaround for various MPI implementations forcing the link of C++ bindings + add_definitions(-DOMPI_SKIP_MPICXX -DMPICH_SKIP_MPICXX) + + list(APPEND _components MPI) + endif() + list(APPEND _components CXX) + + find_package(ADIOS2 REQUIRED COMPONENTS ${_components}) +endif() + +add_executable(adios2_basics_valuesWrite valuesWrite.cpp) +target_link_libraries(adios2_basics_valuesWrite adios2::cxx11) +install(TARGETS adios2_basics_valuesWrite RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) if(ADIOS2_HAVE_MPI) - add_executable(values_write_mpi values_write.cpp) - target_link_libraries(values_write_mpi adios2::cxx11_mpi MPI::MPI_C) + add_executable(adios2_basics_valuesWrite_mpi valuesWrite.cpp) + target_link_libraries(adios2_basics_valuesWrite_mpi adios2::cxx11_mpi MPI::MPI_C) + install(TARGETS adios2_basics_valuesWrite_mpi RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + + if(ADIOS2_HAVE_Fortran) + add_library(adios2_basics_values_mpivars_f OBJECT mpivars.F90) + target_link_libraries(adios2_basics_values_mpivars_f MPI::MPI_Fortran) + install(TARGETS adios2_basics_values_mpivars_f RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + + add_executable(adios2_basics_values_f values.F90) + target_link_libraries(adios2_basics_values_f + adios2_basics_values_mpivars_f + adios2::fortran_mpi MPI::MPI_Fortran) + install(TARGETS adios2_basics_values_f RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + endif() endif() diff --git a/examples/basics/values/mpivars.F90 b/examples/basics/values/mpivars.F90 new file mode 100644 index 0000000000..323e4b0c15 --- /dev/null +++ b/examples/basics/values/mpivars.F90 @@ -0,0 +1,30 @@ +module mpivars + implicit none + include 'mpif.h' + + integer:: app_comm, rank, nproc + integer:: wrank, wnproc + integer:: ierr + +contains + +subroutine init_mpi(color) + integer, intent(in):: color + call MPI_Init(ierr) + ! World comm spans all applications started with the same mpirun command + call MPI_Comm_rank(MPI_COMM_WORLD, wrank, ierr) + call MPI_Comm_size(MPI_COMM_WORLD, wnproc, ierr) + + ! Have to split and create a 'world' communicator for this app only + ! color must be unique for each application + call MPI_Comm_split (MPI_COMM_WORLD, color, wrank, app_comm, ierr) + call MPI_Comm_rank (app_comm, rank, ierr) + call MPI_Comm_size (app_comm, nproc , ierr) +end subroutine init_mpi + +subroutine finalize_mpi() + call MPI_Finalize(ierr) +end subroutine finalize_mpi + +end module mpivars + diff --git a/examples/basics/values/values.F90 b/examples/basics/values/values.F90 new file mode 100644 index 0000000000..608ecf37b6 --- /dev/null +++ b/examples/basics/values/values.F90 @@ -0,0 +1,169 @@ +program adios2_values + use mpivars + use adios2 + implicit none + integer, parameter :: numsteps = 5 + ! ADIOS2 variables + type(adios2_adios) :: adios + + ! MPI then ADIOS2 initialization + call init_mpi(12345) + call adios2_init(adios, app_comm, ierr) + + call writer() + call reader() + + ! ADIOS2 then MPI finalization + call adios2_finalize(adios, ierr) + call finalize_mpi() + +contains + +subroutine writer + use mpivars + use adios2 + implicit none + + type(adios2_variable) :: var_gc, var_gv, var_lc, var_lv, var_gs + type(adios2_io) :: io + type(adios2_engine) :: engine + integer :: step + + ! Application variables + ! gc = Global Constant (a single value from the entire application, once per run (e.g. NPROC)) + ! gv = Global Value (a single value from the entire application, changes over time) + ! lc = Local Constant (one value per process, once per run (e.g. RANK)) + ! lv = Local Value (one value per process, changes over time) + ! gs = a string, same as a global value + integer :: gc, gv, lc, lv + character(len=80) :: gs + + call adios2_declare_io (io, adios, 'Values', ierr) + + call adios2_define_variable(var_gc, io, "GlobalConstant", adios2_type_integer4, ierr) + call adios2_define_variable(var_gv, io, "GlobalValue", adios2_type_integer4, ierr) + ! Local values will show up in reading as a 1D array of nproc elements + ! the write side definition is quite cumbersome in Fortran :-( + ! We have to define it almost like a distributed global array with a special + ! dimension value to indicate its type + call adios2_define_variable(var_lc, io, "LocalConstant", adios2_type_integer4, & + 1, (/ adios2_local_value_dim /), & + adios2_null_dims, & + adios2_null_dims, & + adios2_constant_dims, ierr) + + call adios2_define_variable(var_lv, io, "LocalValue", adios2_type_integer4, & + 1, (/ adios2_local_value_dim /), & + adios2_null_dims, & + adios2_null_dims, & + adios2_constant_dims, ierr) + + call adios2_define_variable(var_gs, io, "GlobalString", adios2_type_string, ierr) + + call adios2_open(engine, io, "adios2-values-f.bp", adios2_mode_write, ierr) + + ! Computation/output loop + gc = nproc + lc = rank + do step=0,numsteps-1 + gv = step + lv = nproc*(step)+rank + write (gs,'(a,i3)') "This is step ", step + + call adios2_begin_step(engine, adios2_step_mode_append, ierr) + if (step == 0) then + call adios2_put(engine, var_lc, lc, ierr); + if (rank == 0) then + ! could be written from every process but it is useless + call adios2_put(engine, var_gc, gc, ierr); + endif + endif + if (rank == 0) then + ! could be written from every process but it is useless + call adios2_put(engine, var_gv, gv, ierr); + call adios2_put(engine, var_gs, gs, ierr); + endif + call adios2_put(engine, var_lv, lv, ierr); + call adios2_end_step(engine, ierr) + enddo + + ! Close the output + call adios2_close(engine, ierr) + +end subroutine writer + + +subroutine reader + use mpivars + implicit none + + type(adios2_variable) :: var_gc, var_gv, var_lc, var_lv + type(adios2_io) :: io + type(adios2_engine) :: engine + integer*8 :: numsteps, i + integer*4 :: gc + integer*4, dimension(:), allocatable :: gvs, lcs + integer*4, dimension(:,:), allocatable :: lvs + character(len=80)::fmt + integer*8, dimension(:), allocatable :: shape_lv, shape_lc + integer :: ndims_lv, ndims_lc + + ! Note, every process reads everything in this example + + call adios2_declare_io(io, adios, "ValuesInput", ierr) + call adios2_open(engine, io, "adios2-values-f.bp", adios2_mode_read, MPI_COMM_SELF, ierr) + + call adios2_inquire_variable(var_gc, io, "GlobalConstant", ierr) + call adios2_get(engine, var_gc, gc , ierr) + + call adios2_inquire_variable(var_gv, io, "GlobalValue", ierr) + call adios2_variable_steps(numsteps, var_gv, ierr) + call adios2_set_step_selection(var_gv, 0_8, numsteps, ierr) + allocate(gvs(numsteps)) + call adios2_get(engine, var_gv, gvs , ierr) + + ! Read Local Values and Local Constants as a 1D array + ! shape array is allocated inside adios2_variable_shape() + + call adios2_inquire_variable(var_lc, io, "LocalConstant", ierr) + call adios2_variable_shape(shape_lc, ndims_lc, var_lc, ierr) + allocate(lcs(shape_lc(1))) + call adios2_get(engine, var_lc, lcs , ierr) + + call adios2_inquire_variable(var_lv, io, "LocalValue", ierr) + call adios2_variable_shape(shape_lv, ndims_lv, var_lv, ierr) + call adios2_set_step_selection(var_lv, 0_8, numsteps, ierr) + allocate(lvs(shape_lv(1),numsteps)) + call adios2_get(engine, var_lv, lvs , ierr) + + call adios2_close(engine, ierr) + + ! By default, get()s are deferred and content is available AFTER + ! adios2_close() or adios2_perform_gets() + ! Use adios2_mode_sync option in adios2_get() to get the content immediately + + if (rank == 0) then + write(*,'("Number of steps in file = ",i5)') numsteps + write(*,'("GlobalConstant = ", i5)') gc + + write(fmt,'(a,i5,a)') '(a18,',numsteps,'i4,a2)' + !write(*,'(a)') fmt + write(*,fmt) "GlobalValue(s) = [", gvs, " ]" + + write(fmt,'(a,i5,a)') '(a20,',shape_lc(1),'i4,a2)' + !write(*,'(a)') fmt + write(*,fmt) "LocalConstant(s) = [", lcs, " ]" + + write(fmt,'(a,i5,a)') '(a6,i3,a4,',shape_lv(1),'i4)' + !write(*,'(a)') fmt + write(*,'(a)') "LocalValues = [" + do i = 1, numsteps + write(*,fmt) " step", i-1, ":", lvs(:,i) + enddo + write(*,*) " ]" + endif + + deallocate(gvs, lcs, lvs) +end subroutine reader + +end program adios2_values diff --git a/examples/basics/values/values_write.cpp b/examples/basics/values/valuesWrite.cpp similarity index 99% rename from examples/basics/values/values_write.cpp rename to examples/basics/values/valuesWrite.cpp index abdc33436d..4f9f556798 100644 --- a/examples/basics/values/values_write.cpp +++ b/examples/basics/values/valuesWrite.cpp @@ -68,7 +68,7 @@ int main(int argc, char *argv[]) // Get io settings from the config file or // create one with default settings here adios2::IO io = adios.DeclareIO("Output"); - io.SetEngine("BP5"); + io.SetEngine("BPFile"); io.SetParameters({{"verbose", "4"}}); /* * Define variables diff --git a/examples/basics/variablesShapes/CMakeLists.txt b/examples/basics/variablesShapes/CMakeLists.txt new file mode 100644 index 0000000000..2dbd92f4fd --- /dev/null +++ b/examples/basics/variablesShapes/CMakeLists.txt @@ -0,0 +1,39 @@ +#------------------------------------------------------------------------------# +# Distributed under the OSI-approved Apache License, Version 2.0. See +# accompanying file Copyright.txt for details. +#------------------------------------------------------------------------------# + +cmake_minimum_required(VERSION 3.12) +project(ADIOS2BasicsVariablesShapesExample) + +if(NOT TARGET adios2_core) + set(_components CXX) + + find_package(MPI COMPONENTS C) + if(MPI_FOUND) + # Workaround for various MPI implementations forcing the link of C++ bindings + add_definitions(-DOMPI_SKIP_MPICXX -DMPICH_SKIP_MPICXX) + + list(APPEND _components MPI) + endif() + + find_package(ADIOS2 REQUIRED COMPONENTS ${_components}) +endif() + +add_executable(adios2_basics_variablesShapes variablesShapes.cpp) +target_link_libraries(adios2_basics_variablesShapes adios2::cxx11) +install(TARGETS adios2_basics_variablesShapes RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + +add_executable(adios2_basics_variablesShapes_hl variablesShapes_hl.cpp) +target_link_libraries(adios2_basics_variablesShapes_hl adios2::cxx11) +install(TARGETS adios2_basics_variablesShapes_hl RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + +if(ADIOS2_HAVE_MPI) + add_executable(adios2_basics_variablesShapes_mpi variablesShapes.cpp) + target_link_libraries(adios2_basics_variablesShapes_mpi adios2::cxx11_mpi MPI::MPI_C) + install(TARGETS adios2_basics_variablesShapes_mpi RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + + add_executable(adios2_basics_variablesShapes_hl_mpi variablesShapes_hl.cpp) + target_link_libraries(adios2_basics_variablesShapes_hl_mpi adios2::cxx11_mpi MPI::MPI_C) + install(TARGETS adios2_basics_variablesShapes_hl_mpi RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) +endif() diff --git a/examples/basics/variablesShapes/variablesShapes.cpp b/examples/basics/variablesShapes/variablesShapes.cpp new file mode 100644 index 0000000000..6dce0f8fae --- /dev/null +++ b/examples/basics/variablesShapes/variablesShapes.cpp @@ -0,0 +1,269 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * * variablesShapes.cpp : adios2 low-level API example to write and read + * supported Variables shapes using stepping + * (streaming) mode + * + * Created on: Nov 14, 2019 + * Author: William F Godoy godoywf@ornl.gov + */ + +#include //std::size_t +#include // std::cout +#include // std::numeric_limits +#include //std::iota +#include //std::exception + +#include +#if ADIOS2_USE_MPI +#include +#endif + +void writer(adios2::ADIOS &adios, const std::size_t nx, const std::size_t nsteps, const int rank, + const int size) +{ + auto lf_compute = [](const std::size_t step, const std::size_t nx, + const int rank) -> std::vector { + const float value = static_cast(step + rank * nx); + std::vector array(nx); + std::iota(array.begin(), array.end(), value); + return array; + }; + + adios2::IO io = adios.DeclareIO("variables-shapes_writer"); + + // You can define variables according to: + // type : string, uint8_t, int8_t8, ... , float, double + // shape: global : value or array + // local : value (return a global array), array + + /********** GLOBAL VALUE *************/ + // string variables are always of value type, can't pass dimensions + adios2::Variable varGlobalValueString = + io.DefineVariable("GlobalValueString"); + + // global value can change on each step. Example: Step + adios2::Variable varStep = io.DefineVariable("Step"); + + /********** GLOBAL ARRAYS *************/ + // For a regular 1D decomposition: + + // 0*nx 1*nx 2*nx 3*nx shape (4*nx) + //--------//-------//--------//---------// + // nx nx nx nx + + // global shape -> this is the physical dimension across MPI processes + const adios2::Dims shape = {static_cast(size * nx)}; + + // local start for rank offset -> this is the local origin for the rank + // domain + const adios2::Dims start = {static_cast(rank * nx)}; + + // local count -> this is the local size from the local start for the rank + // domain + const adios2::Dims count = {nx}; + + // adios2::Dims is an alias to std::vector + // helps remember the inputs to adios2 functions DefineVariable (write) and + // SetSelection (read) make sure you always pass std::size_t types + + // global array with dimensions (shape, start, count) + // last argument indicates to adios2 that dimensions won't change + adios2::Variable varGlobalArray = + io.DefineVariable("GlobalArray", shape, start, count, adios2::ConstantDims); + + /********** LOCAL VALUE **************/ + // Independent values per rank at write, but presented as a global array at + // read Example: store current rank, but presented as an array of ranks + adios2::Variable varLocalValueInt32 = + io.DefineVariable("Rank", {adios2::LocalValueDim}); + + /********** LOCAL ARRAY **************/ + // Independent values and dimensions per rank, there is no notion of + // "continuity", each start from 0-origin to count. Example: mesh + // nodes-per-rank + adios2::Variable varLocalArray = + io.DefineVariable("LocalArray", {}, {}, count, adios2::ConstantDims); + + adios2::Engine writer = io.Open("variables-shapes.bp", adios2::Mode::Write); + + for (size_t step = 0; step < nsteps; ++step) + { + // this part mimics the compute portion in an application + const std::vector array = lf_compute(step, nx, rank); + + // ADIOS2 I/O portion + + // BeginStep/EndStep is the streaming API -> supported by all engines + writer.BeginStep(); + + // minimize global and local values footprint, by only one rank putting + // the variables + if (rank == 0) + { + // Global value changing over steps + writer.Put(varStep, static_cast(step)); + + if (step == 0) + { + // Global absolute value + writer.Put(varGlobalValueString, std::string("ADIOS2 Basics Variable Example")); + // Local absolute value + writer.Put(varLocalValueInt32, static_cast(rank)); + } + } + + // for this example all ranks put a global and a local array + writer.Put(varGlobalArray, array.data()); + writer.Put(varLocalArray, array.data()); + writer.EndStep(); + } + writer.Close(); +} + +void reader(adios2::ADIOS &adios, const int rank, const int size) +{ + adios2::IO io = adios.DeclareIO("variables-shapes_reader"); + // all ranks opening the bp file have access to the entire metadata + adios2::Engine reader = io.Open("variables-shapes.bp", adios2::Mode::Read); + + // reading in streaming mode + while (reader.BeginStep() != adios2::StepStatus::EndOfStream) + { + // scope between BeginStep and EndStep is only for the current step + const size_t currentStep = reader.CurrentStep(); + + // Typical flow: InquireVariable + adios2::Variable varStep = io.InquireVariable("Step"); + uint64_t step = std::numeric_limits::max(); + // check Variable existence + if (varStep) + { + if (rank == 0) + { + // variable objects are "printable" reporting Name and Type + std::cout << "Found Global Value " << varStep << " in step " << currentStep << "\n"; + // output: Found Global Value Variable(Name: "Step") + // in step 0 + } + reader.Get(varStep, step); + } + + // GlobalValueString + adios2::Variable varGlobalValueString = + io.InquireVariable("GlobalValueString"); + std::string globalValueString; + // check Variable existence and Get + if (varGlobalValueString) + { + if (rank == 0) + { + std::cout << "Found Global Value " << varGlobalValueString << " in step " + << currentStep << "\n"; + } + reader.Get(varGlobalValueString, globalValueString); + } + + // Global Arrays at read from local values at write + adios2::Variable varRanks = io.InquireVariable("Ranks"); + std::vector ranks; + if (varRanks) + { + if (rank == 0) + { + std::cout << "Found Global Array " << varRanks << " in step " << currentStep + << "\n"; + } + // passing a vector convenience: adios2 would resize it + // automatically + reader.Get(varRanks, ranks); + } + + // Global Array + adios2::Variable varGlobalArray = io.InquireVariable("GlobalArray"); + std::vector globalArray; + if (varGlobalArray) + { + if (rank == 0) + { + std::cout << "Found GlobalArray " << varGlobalArray << " in step " << currentStep + << "\n"; + } + reader.Get(varGlobalArray, globalArray); + } + + // Local Array + adios2::Variable varLocalArray = io.InquireVariable("LocalArray"); + std::vector localArray; + if (varLocalArray) + { + // local arrays require an extra step to select the block of + // interest (0 is default) we only select block 0 in this example + varLocalArray.SetBlockSelection(0); + if (rank == 0) + { + std::cout << "Found LocalArray " << varLocalArray << " in step " << currentStep + << "\n"; + } + reader.Get(varLocalArray, localArray); + } + + // since all Get calls are "deferred" all the data would be populated at + // EndStep + reader.EndStep(); + + // data is available + + if (rank == 0) + { + std::cout << "\n"; + } + } + + reader.Close(); +} + +int main(int argc, char *argv[]) +{ +#if ADIOS2_USE_MPI + MPI_Init(&argc, &argv); +#endif + + int rank = 0; + int size = 1; + +#if ADIOS2_USE_MPI + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + MPI_Comm_size(MPI_COMM_WORLD, &size); +#endif + + try + { +#if ADIOS2_USE_MPI + adios2::ADIOS adios(MPI_COMM_WORLD); +#else + adios2::ADIOS adios; +#endif + + constexpr std::size_t nx = 10; + constexpr std::size_t nsteps = 3; + + writer(adios, nx, nsteps, rank, size); + reader(adios, rank, size); + } + catch (const std::exception &e) + { + std::cout << "ERROR: ADIOS2 exception: " << e.what() << "\n"; +#if ADIOS2_USE_MPI + MPI_Abort(MPI_COMM_WORLD, -1); +#endif + } + +#if ADIOS2_USE_MPI + MPI_Finalize(); +#endif + + return 0; +} diff --git a/examples/basics/variablesShapes/variablesShapes_hl.cpp b/examples/basics/variablesShapes/variablesShapes_hl.cpp new file mode 100644 index 0000000000..5977b2c311 --- /dev/null +++ b/examples/basics/variablesShapes/variablesShapes_hl.cpp @@ -0,0 +1,194 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * variablesShapes_hl.cpp : adios2 high-level API example to write and read + * supported Variables shapes using stepping (streaming) mode + * + * Created on: Nov 14, 2019 + * Author: William F Godoy godoywf@ornl.gov + */ + +#include //std::size_t +#include // std::cout +#include // std::numeric_limits +#include //std::iota +#include //std::exception + +#include +#if ADIOS2_USE_MPI +#include +#endif + +void writer(const std::size_t nx, const std::size_t nsteps, const int rank, const int size) +{ + auto lf_compute = [](const std::size_t step, const std::size_t nx, + const int rank) -> std::vector { + const float value = static_cast(step + rank * nx); + std::vector array(nx); + std::iota(array.begin(), array.end(), value); + return array; + }; + + // You can define variables according to: + // type : string, uint8_t, int8_t8, ... , float, double + // shape: global : value or array + // local : value (return a global array), array + + // global shape -> this is the physical dimension across MPI processes + const adios2::Dims shape = {static_cast(size * nx)}; + + // local start for rank offset -> this is the local origin for the rank + // domain + const adios2::Dims start = {static_cast(rank * nx)}; + + // local count -> this is the local size from the local start for the rank + // domain + const adios2::Dims count = {nx}; + + // adios2::Dims is an alias to std::vector + // helps remember the inputs to adios2 functions DefineVariable (write) and + // SetSelection (read) make sure you always pass std::size_t types + +#if ADIOS2_USE_MPI + adios2::fstream out("variables-shapes_hl.bp", adios2::fstream::out, MPI_COMM_WORLD); +#else + adios2::fstream out("variables-shapes_hl.bp", adios2::fstream::out); +#endif + + for (size_t step = 0; step < nsteps; ++step) + { + // this part mimics the compute portion in an application + const std::vector array = lf_compute(step, nx, rank); + + // ADIOS2 I/O portion + + // minimize global and local values footprint, by only one rank writing + // the variables + if (rank == 0) + { + // Global value changing over steps + out.write("Step", static_cast(step)); + + if (step == 0) + { + // Constant Global value + out.write("GlobalValueString", std::string("ADIOS2 Basics Variable Example")); + + // Constant Local value + out.write("LocalValueInt32", static_cast(rank), adios2::LocalValue); + } + } + + // for this example all ranks write a global and a local array + out.write("GlobalArray", array.data(), shape, start, count); + out.write("LocalArray", array.data(), {}, {}, count); + + out.end_step(); + } + out.close(); +} + +void reader(const int rank, const int size) +{ + auto lf_ArrayToString = [](const std::vector &array) -> std::string { + std::string contents = "{ "; + for (const float value : array) + { + contents += std::to_string(static_cast(value)) + " "; + } + contents += "}"; + return contents; + }; + +// all ranks opening the bp file have access to the entire metadata +#if ADIOS2_USE_MPI + adios2::fstream in("variables-shapes_hl.bp", adios2::fstream::in, MPI_COMM_WORLD); +#else + adios2::fstream in("variables-shapes_hl.bp", adios2::fstream::in); +#endif + + // reading in streaming mode, supported by all engines + // similar to std::getline in std::fstream + adios2::fstep inStep; + while (adios2::getstep(in, inStep)) + { + const std::size_t currentStep = inStep.current_step(); + + const std::vector steps = inStep.read("Step"); + if (!steps.empty() && rank == 0) + { + std::cout << "Found Step " << steps.front() << " in currentStep " << currentStep + << "\n"; + } + + const std::vector globalValueString = + inStep.read("GlobalValueString"); + if (!globalValueString.empty() && rank == 0) + { + std::cout << "Found GlobalValueString " << globalValueString.front() + << " in currentStep " << currentStep << "\n"; + } + + const std::vector ranks = inStep.read("Ranks"); + if (!ranks.empty() && rank == 0) + { + std::cout << "Found rank " << ranks.front() << " in currentStep " << currentStep + << "\n"; + } + + const std::vector globalArray = inStep.read("GlobalArray"); + if (!globalArray.empty() && rank == 0) + { + std::cout << "Found globalArray " << lf_ArrayToString(globalArray) + " in currentStep " + << currentStep << "\n"; + } + + // default reads block 0 + const std::vector localArray = inStep.read("LocalArray"); + if (!localArray.empty() && rank == 0) + { + std::cout << "Found localArray " << lf_ArrayToString(localArray) + " in currentStep " + << currentStep << "\n"; + } + // indicate end of adios2 operations for this step + in.end_step(); + } + in.close(); +} + +int main(int argc, char *argv[]) +{ +#if ADIOS2_USE_MPI + MPI_Init(&argc, &argv); +#endif + int rank = 0; + int size = 1; + +#if ADIOS2_USE_MPI + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + MPI_Comm_size(MPI_COMM_WORLD, &size); +#endif + + try + { + constexpr std::size_t nx = 10; + constexpr std::size_t nsteps = 3; + + writer(nx, nsteps, rank, size); + reader(rank, size); + } + catch (std::exception &e) + { + std::cout << "ERROR: ADIOS2 exception: " << e.what() << "\n"; +#if ADIOS2_USE_MPI + MPI_Abort(MPI_COMM_WORLD, -1); +#endif + } + +#if ADIOS2_USE_MPI + MPI_Finalize(); +#endif + + return 0; +} diff --git a/examples/cuda/CMakeLists.txt b/examples/cuda/CMakeLists.txt deleted file mode 100644 index 6a613392f4..0000000000 --- a/examples/cuda/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -#------------------------------------------------------------------------------# -# Distributed under the OSI-approved Apache License, Version 2.0. See -# accompanying file Copyright.txt for details. -#------------------------------------------------------------------------------# - -add_executable(CudaBPWriteRead_cuda cudaBPWriteRead.cu) -target_link_libraries(CudaBPWriteRead_cuda PUBLIC adios2::cxx11 CUDA::cudart) -set_target_properties(CudaBPWriteRead_cuda PROPERTIES CUDA_SEPARABLE_COMPILATION ON) diff --git a/examples/cuda/cudaBPWriteRead.cu b/examples/cuda/cudaBPWriteRead.cu deleted file mode 100644 index 1d2dcd4eda..0000000000 --- a/examples/cuda/cudaBPWriteRead.cu +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Simple example of writing and reading data - * through ADIOS2 BP engine with multiple simulations steps - * for every IO step. - */ - -#include -#include -#include -#include - -#include - -#include - -__global__ void update_array(float *vect, int val) { vect[blockIdx.x] += val; } - -std::string engine("BP5"); - -int BPWrite(const std::string fname, const size_t N, int nSteps, const std::string engine) -{ - // Initialize the simulation data - float *gpuSimData; - cudaMalloc(&gpuSimData, N * sizeof(float)); - cudaMemset(gpuSimData, 0, N); - - // Set up the ADIOS structures - adios2::ADIOS adios; - adios2::IO io = adios.DeclareIO("WriteIO"); - io.SetEngine(engine); - - // Declare an array for the ADIOS data of size (NumOfProcesses * N) - const adios2::Dims shape{static_cast(N)}; - const adios2::Dims start{static_cast(0)}; - const adios2::Dims count{N}; - auto data = io.DefineVariable("data", shape, start, count); - - adios2::Engine bpWriter = io.Open(fname, adios2::Mode::Write); - - // Simulation steps - for (size_t step = 0; step < nSteps; ++step) - { - // Make a 1D selection to describe the local dimensions of the - // variable we write and its offsets in the global spaces - adios2::Box sel({0}, {N}); - data.SetSelection(sel); - - // Start IO step every write step - bpWriter.BeginStep(); - data.SetMemorySpace(adios2::MemorySpace::GPU); - bpWriter.Put(data, gpuSimData); - bpWriter.EndStep(); - - // Update values in the simulation data - update_array<<>>(gpuSimData, 10); - } - - bpWriter.Close(); - return 0; -} - -int BPRead(const std::string fname, const size_t N, int nSteps, const std::string engine) -{ - // Create ADIOS structures - adios2::ADIOS adios; - adios2::IO io = adios.DeclareIO("ReadIO"); - io.SetEngine(engine); - - adios2::Engine bpReader = io.Open(fname, adios2::Mode::Read); - - unsigned int step = 0; - float *gpuSimData; - cudaMalloc(&gpuSimData, N * sizeof(float)); - cudaMemset(gpuSimData, 0, N); - for (; bpReader.BeginStep() == adios2::StepStatus::OK; ++step) - { - auto data = io.InquireVariable("data"); - std::vector simData(N); - const adios2::Dims start{0}; - const adios2::Dims count{N}; - const adios2::Box sel(start, count); - data.SetSelection(sel); - - data.SetMemorySpace(adios2::MemorySpace::GPU); - bpReader.Get(data, gpuSimData); //, adios2::Mode::Deferred); - bpReader.EndStep(); - cudaMemcpy(simData.data(), gpuSimData, N * sizeof(float), cudaMemcpyDeviceToHost); - std::cout << "Simualation step " << step << " : "; - std::cout << simData.size() << " elements: " << simData[1] << std::endl; - } - bpReader.Close(); - return 0; -} - -int main(int argc, char **argv) -{ - if (argv[1]) - engine = argv[1]; - std::cout << "Using engine " << engine << std::endl; - - const std::string fname("Cuda" + engine + "wr.bp"); - const int device_id = 1; - cudaSetDevice(device_id); - const size_t N = 6000; - int nSteps = 10, ret = 0; - - ret += BPWrite(fname, N, nSteps, engine); - ret += BPRead(fname, N, nSteps, engine); - return ret; -} diff --git a/examples/experimental/CMakeLists.txt b/examples/experimental/CMakeLists.txt deleted file mode 100644 index 23240d2bae..0000000000 --- a/examples/experimental/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -#------------------------------------------------------------------------------# -# Distributed under the OSI-approved Apache License, Version 2.0. See -# accompanying file Copyright.txt for details. -#------------------------------------------------------------------------------# - -add_subdirectory(runtimeconfig) diff --git a/examples/experimental/runtimeconfig/CMakeLists.txt b/examples/experimental/runtimeconfig/CMakeLists.txt deleted file mode 100644 index 33bde8ad15..0000000000 --- a/examples/experimental/runtimeconfig/CMakeLists.txt +++ /dev/null @@ -1 +0,0 @@ -add_subdirectory(hello) diff --git a/examples/experimental/runtimeconfig/configs/grandSchema.xml b/examples/experimental/runtimeconfig/configs/grandSchema.xml deleted file mode 100644 index 71d80bd30b..0000000000 --- a/examples/experimental/runtimeconfig/configs/grandSchema.xml +++ /dev/null @@ -1,76 +0,0 @@ - - - - - - - - BlockSize100K=3; - - - Tolerance=1e-3; - - - - - - - Threads=4; - Verbose=4; - ProfileUnits=Microseconds; - MaxBufferSize=20Mb; - InitialBufferSize=1Mb; - BufferGrowthFactor=2; - - - - ProfileUnits=Microseconds; - Library=stdio; - CacheSize=8192; - CollectiveMetadata=Yes; - - - - ProfileUnits=Microseconds; - Library=hdf5; - Name=data.h5; - - - - ProfileUnits=Microseconds; - Library=SystemV; - Name=data.shmem; - SetSize=10Mb; - - - - ProfileUnits=Microseconds; - Library=POSIX; - Name=/bb_location/data.bb; - SetSize=10Mb; - - - - ProfileUnits=Microseconds; - IPAddress=128.219.4.85; - Port=500; - Library=zmq; - CacheSize=8192; - - - - ProfileUnits=Microseconds; - Library=ibverbs; - Port=18515; - IBPort=1; - SetSize=1Mb; - TXDepth=100; - SocketFD=-1; - ServerName=NULL; - RemoteConnection=NULL; - IBDev=NULL; - - - - - \ No newline at end of file diff --git a/examples/experimental/runtimeconfig/configs/multipleIOResolutions.xml b/examples/experimental/runtimeconfig/configs/multipleIOResolutions.xml deleted file mode 100644 index 28fe854084..0000000000 --- a/examples/experimental/runtimeconfig/configs/multipleIOResolutions.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - Tolerance=1e-2; - - - - - - - - - - Tolerance=1e-5; - - - - - - - \ No newline at end of file diff --git a/examples/experimental/runtimeconfig/configs/multipleTransformedVariables.xml b/examples/experimental/runtimeconfig/configs/multipleTransformedVariables.xml deleted file mode 100644 index 8338320d5c..0000000000 --- a/examples/experimental/runtimeconfig/configs/multipleTransformedVariables.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - Tolerance=1e-2; - - - - - - - - - - - Tolerance=1e-5; - - - - - - - - - diff --git a/examples/experimental/runtimeconfig/hello/CMakeLists.txt b/examples/experimental/runtimeconfig/hello/CMakeLists.txt deleted file mode 100644 index dac3c8499f..0000000000 --- a/examples/experimental/runtimeconfig/hello/CMakeLists.txt +++ /dev/null @@ -1,13 +0,0 @@ -add_executable(helloBPWriterXML helloBPWriterXML_nompi.cpp) -target_link_libraries(helloBPWriterXML adios2::cxx11) -target_compile_definitions(helloBPWriterXML PRIVATE - -DDEFAULT_CONFIG=${CMAKE_CURRENT_SOURCE_DIR}/helloBPWriter.xml -) - -if(ADIOS2_HAVE_MPI) - add_executable(helloBPWriterXML_mpi helloBPWriterXML.cpp) - target_link_libraries(helloBPWriterXML_mpi adios2::cxx11_mpi MPI::MPI_C) - target_compile_definitions(helloBPWriterXML_mpi PRIVATE - -DDEFAULT_CONFIG=${CMAKE_CURRENT_SOURCE_DIR}/helloBPWriter.xml - ) -endif() diff --git a/examples/experimental/runtimeconfig/hello/helloBPWriter.xml b/examples/experimental/runtimeconfig/hello/helloBPWriter.xml deleted file mode 100644 index 27a01d5db8..0000000000 --- a/examples/experimental/runtimeconfig/hello/helloBPWriter.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/experimental/runtimeconfig/hello/helloBPWriterXML.cpp b/examples/experimental/runtimeconfig/hello/helloBPWriterXML.cpp deleted file mode 100644 index f6634b8ac4..0000000000 --- a/examples/experimental/runtimeconfig/hello/helloBPWriterXML.cpp +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Distributed under the OSI-approved Apache License, Version 2.0. See - * accompanying file Copyright.txt for details. - * - * helloBPWriter.cpp: Simple self-descriptive example of how to write a variable - * to a BP File that lives in several MPI processes. - * - * Created on: Feb 16, 2017 - * Author: William F Godoy godoywf@ornl.gov - */ - -#include //std::ios_base::failure -#include //std::cout -#include -#include //std::invalid_argument std::exception -#include - -#include - -#define str_helper(X) #X -#define str(X) str_helper(X) - -#ifndef DEFAULT_CONFIG -#define DEFAULT_CONFIG helloBPWriter.xml -#endif -#define DEFAULT_CONFIG_STR str(DEFAULT_CONFIG) - -int main(int argc, char *argv[]) -{ - int provided; - - // MPI_THREAD_MULTIPLE is only required if you enable the SST MPI_DP - MPI_Init_thread(&argc, &argv, MPI_THREAD_MULTIPLE, &provided); - int rank, size; - MPI_Comm_rank(MPI_COMM_WORLD, &rank); - MPI_Comm_size(MPI_COMM_WORLD, &size); - - std::string configFile; - if (argc == 1) - { - configFile = DEFAULT_CONFIG_STR; - } - else if (argc == 2) - { - configFile = argv[1]; - } - else - { - if (rank == 0) - { - std::cerr << "Usage: " << argv[0] << " [/path/to/config.xml]" << std::endl; - } - return 1; - } - if (rank == 0) - { - std::cout << "Using config file: " << configFile << std::endl; - } - - /** Application variable */ - std::vector myFloats = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; - const std::size_t Nx = myFloats.size(); - - try - { - /** ADIOS class factory of IO class objects */ - adios2::ADIOS adios(configFile, MPI_COMM_WORLD); - - /*** IO class object: settings and factory of Settings: Variables, - * Parameters, Transports, and Execution: Engines */ - adios2::IO bpIO = adios.DeclareIO("BPFile_N2N"); - - /** global array : name, { shape (total) }, { start (local) }, { count - * (local) }, all are constant dimensions */ - adios2::Variable &bpFloats = bpIO.DefineVariable( - "bpFloats", {size * Nx}, {rank * Nx}, {Nx}, adios2::ConstantDims); - - /** Engine derived class, spawned to start IO operations */ - auto bpWriter = bpIO.Open("myVector.bp", adios2::Mode::Write); - - if (!bpWriter) - { - throw std::ios_base::failure("ERROR: bpWriter not created at Open\n"); - } - - /** Write variable for buffering */ - bpWriter->Write(bpFloats, myFloats.data()); - - /** Create bp file, engine becomes unreachable after this*/ - bpWriter->Close(); - } - catch (std::invalid_argument &e) - { - std::cout << "Invalid argument exception, STOPPING PROGRAM from rank " << rank << "\n"; - std::cout << e.what() << "\n"; - } - catch (std::ios_base::failure &e) - { - std::cout << "IO System base failure exception, STOPPING PROGRAM from rank " << rank - << "\n"; - std::cout << e.what() << "\n"; - } - catch (std::exception &e) - { - std::cout << "Exception, STOPPING PROGRAM from rank " << rank << "\n"; - std::cout << e.what() << "\n"; - } - - MPI_Finalize(); - - return 0; -} diff --git a/examples/experimental/runtimeconfig/hello/helloBPWriterXML.py b/examples/experimental/runtimeconfig/hello/helloBPWriterXML.py deleted file mode 100644 index a4c2c4b6b0..0000000000 --- a/examples/experimental/runtimeconfig/hello/helloBPWriterXML.py +++ /dev/null @@ -1,36 +0,0 @@ -# -# Distributed under the OSI-approved Apache License, Version 2.0. See -# accompanying file Copyright.txt for details. -# -# helloBPWriterXML.py -# Created on: Feb 2, 2017 -# Author: William F Godoy godoywf@ornl.gov - -from mpi4py import MPI -import adios2 -import numpy - -# MPI -comm = MPI.COMM_WORLD -rank = comm.Get_rank() -size = comm.Get_size() - -# User data -myArray = numpy.array([0., 1., 2., 3., 4., 5., 6., 7., 8., 9.]) -Nx = myArray.size - -# ADIOS config file, MPI communicator -adios = adios2.ADIOS("helloBPWriter.xml", comm) - -# ADIOS IO, name must be the same as in helloBPWriter.xml for runtime settings -bpIO = adios.DeclareIO("BPFile_N2N") - -# Variable name, shape, start, count, ConstantDims = True -ioArray = bpIO.DefineVariable( - "bpArray", [size * Nx], [rank * Nx], [Nx], adios2.ConstantDims) - -# Engine name, open mode -bpFileWriter = bpIO.Open("npArray.bp", adios2.OpenModeWrite) -# Write variable, numpy object -bpFileWriter.Write(ioArray, myArray) -bpFileWriter.Close() diff --git a/examples/experimental/runtimeconfig/hello/helloBPWriterXML_nompi.cpp b/examples/experimental/runtimeconfig/hello/helloBPWriterXML_nompi.cpp deleted file mode 100644 index 07f5bedc19..0000000000 --- a/examples/experimental/runtimeconfig/hello/helloBPWriterXML_nompi.cpp +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Distributed under the OSI-approved Apache License, Version 2.0. See - * accompanying file Copyright.txt for details. - * - * helloBPWriterXML_nompi.cpp: sequential non-mpi version of helloBPWriterXML - * - * Created on: Feb 16, 2017 - * Author: William F Godoy godoywf@ornl.gov - */ - -#include //std::ios_base::failure -#include //std::cout -#include //std::invalid_argument std::exception -#include - -#include - -#define str_helper(X) #X -#define str(X) str_helper(X) - -#ifndef DEFAULT_CONFIG -#define DEFAULT_CONFIG helloBPWriter.xml -#endif -#define DEFAULT_CONFIG_STR str(DEFAULT_CONFIG) - -int main(int argc, char *argv[]) -{ - std::string configFile; - if (argc == 1) - { - configFile = DEFAULT_CONFIG_STR; - } - else if (argc == 2) - { - configFile = argv[1]; - } - else - { - std::cerr << "Usage: " << argv[0] << " [/path/to/config.xml]" << std::endl; - return 1; - } - std::cout << "Using config file: " << configFile << std::endl; - - /** Application variable */ - std::vector myFloats = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; - const std::size_t Nx = myFloats.size(); - - try - { - /** ADIOS class factory of IO class objects */ - adios2::ADIOS adios(configFile); - - /*** IO class object: settings and factory of Settings: Variables, - * Parameters, Transports, and Execution: Engines */ - adios2::IO bpIO = adios.DeclareIO("BPFile_N2N"); - - /** global array : name, { shape (total) }, { start (local) }, { count - * (local) }, all are constant dimensions */ - adios2::Variable &bpFloats = - bpIO.DefineVariable("bpFloats", {}, {}, {Nx}, adios2::ConstantDims); - - /** Engine derived class, spawned to start IO operations */ - auto bpWriter = bpIO.Open("myVector.bp", adios2::Mode::Write); - - if (!bpWriter) - { - throw std::ios_base::failure("ERROR: bpWriter not created at Open\n"); - } - - /** Write variable for buffering */ - bpWriter->Write(bpFloats, myFloats.data()); - - /** Create bp file, engine becomes unreachable after this*/ - bpWriter->Close(); - } - catch (std::invalid_argument &e) - { - std::cout << "Invalid argument exception, STOPPING PROGRAM\n"; - std::cout << e.what() << "\n"; - } - catch (std::ios_base::failure &e) - { - std::cout << "IO System base failure exception, STOPPING PROGRAM\n"; - std::cout << e.what() << "\n"; - } - catch (std::exception &e) - { - std::cout << "Exception, STOPPING PROGRAM from rank\n"; - std::cout << e.what() << "\n"; - } - - return 0; -} diff --git a/examples/experimental/runtimeconfig/hello/helloBPWriterXML_nompi.py b/examples/experimental/runtimeconfig/hello/helloBPWriterXML_nompi.py deleted file mode 100644 index 2ef26916ea..0000000000 --- a/examples/experimental/runtimeconfig/hello/helloBPWriterXML_nompi.py +++ /dev/null @@ -1,30 +0,0 @@ -# -# Distributed under the OSI-approved Apache License, Version 2.0. See -# accompanying file Copyright.txt for details. -# -# helloBPWriterXML_nompi.py serial non-MPI version of helloBPWriter.py -# Created on: Feb 2, 2017 -# Author: William F Godoy godoywf@ornl.gov - -import numpy -import adios2 - - -# User data -myArray = numpy.array([0., 1., 2., 3., 4., 5., 6., 7., 8., 9.]) -Nx = myArray.size - -# ADIOS config file -adios = adios2.ADIOS("helloBPWriter.xml") - -# ADIOS IO, name must be the same as in helloBPWriter.xml for runtime settings -bpIO = adios.DeclareIO("BPFile_N2N") - -# ADIOS local array: Variable name, shape, start, offset -ioArray = bpIO.DefineVariable( - "bpArray", [], [], [Nx], adios2.ConstantDims) - -# ADIOS Engine -bpFileWriter = bpIO.Open("npArray.bp", adios2.OpenModeWrite) -bpFileWriter.Write(ioArray, myArray) -bpFileWriter.Close() diff --git a/examples/fides/01_onecell/CMakeLists.txt b/examples/fides/01_onecell/CMakeLists.txt deleted file mode 100644 index e553b37ccc..0000000000 --- a/examples/fides/01_onecell/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ -#------------------------------------------------------------------------------# -# Distributed under the OSI-approved Apache License, Version 2.0. See -# accompanying file Copyright.txt for details. -#------------------------------------------------------------------------------# - -add_executable(fides_onecell fides_onecell.cpp) -target_link_libraries(fides_onecell adios2::cxx11) diff --git a/examples/fides/01_onecell/README.md b/examples/fides/01_onecell/README.md deleted file mode 100644 index d55174b571..0000000000 --- a/examples/fides/01_onecell/README.md +++ /dev/null @@ -1,28 +0,0 @@ -Single cell example for visualization with Fides schema in ParaView -------------------------------------------------------------------- - -This example writes 8 points in 3D space, the corners of a box, and then defines a single hexagon cell of those eight points. -The coordinates of the points are stored in three 1D arrays, separating the X-Y-Z coordinates. - -The cell is the enumeration of the points connected in the order of a hexagon prescribed by VTK, see -Figure 19-20 in the VTK User Guide, type VTK_HEXAHEDRON in page 480 (page 494 in the PDF). -https://vtk.org/wp-content/uploads/2021/08/VTKUsersGuide.pdf - -The visualization schema is described in the fides-onecell.json file, according to https://fides.readthedocs.io/en/latest/schema/schema.html - -We compose the coordinate system as a composite of the three 1D arrays for X, Y and Z coordinates. This is just an enumeration of the N points in space (N = size of X = size of Y = size of Z) , in contrast to other examples where X, Y, Z is combined to specify a structured grid (number of points = size of X * size of Y * size of Z). - -In ParaView, one opens the fides-onecell.json file and adds an property "source" with the value of the full path of the onecell.bp. See left-middle Properties box in the ParaView window in the image paraview-onecell-step0.png. Then hit Apply button and a gray box should appear (the single cell visualized). which can be rotated on screen. Then one must color the box with the data ("pointdata") to get the pictures shown in the included images. - -Note that the dataset over the points is called "DataOnPoints" in the onecell.bp file, but it is called "pointdata" in the Fides schema to demonstrate which name is which (ParaView presents pointdata to the user while reading the DataOnPoints array from the file). - -First step of onecell.bp in ParaView: - -paraview-onecell-step0.png - -Last step of onecell.bp in ParaView: - -paraview-onecell-step9.png - diff --git a/examples/fides/CMakeLists.txt b/examples/fides/CMakeLists.txt deleted file mode 100644 index 98d3e0e647..0000000000 --- a/examples/fides/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -#------------------------------------------------------------------------------# -# Distributed under the OSI-approved Apache License, Version 2.0. See -# accompanying file Copyright.txt for details. -#------------------------------------------------------------------------------# - -add_subdirectory(01_onecell) diff --git a/examples/h5subfile/CMakeLists.txt b/examples/h5subfile/CMakeLists.txt deleted file mode 100644 index 0d94ae241b..0000000000 --- a/examples/h5subfile/CMakeLists.txt +++ /dev/null @@ -1,10 +0,0 @@ -#------------------------------------------------------------------------------# -# Distributed under the OSI-approved Apache License, Version 2.0. See -# accompanying file Copyright.txt for details. -#------------------------------------------------------------------------------# - -if(ADIOS2_HAVE_MPI) - add_executable(H5EngineSubfileTest h5_subfile.cpp) - target_link_libraries(H5EngineSubfileTest adios2::cxx11_mpi MPI::MPI_C) -endif() - diff --git a/examples/heatTransfer/ReadMe.md b/examples/heatTransfer/ReadMe.md deleted file mode 100644 index 9ad00c1681..0000000000 --- a/examples/heatTransfer/ReadMe.md +++ /dev/null @@ -1,73 +0,0 @@ -examples/heatTransfer - -This example solves a 2D Poisson equation for temperature in homogeneous media -using finite differences. This examples shows a straight-forward way to hook -an application to the ADIOS2 library for its IO. - - -1. write: illustrates the Write API as well as has implementations of other IO libraries - - * adios 1.x - * hdf5 sequential, separate file per process per step - * phdf5 parallel, steps appended to the same one file - -2. read: illustrates the Read API that allows running the reader either as - - * post-mortem to read all output steps - * in situ to read step by step as the writer outputs them - (need to run with a suitable engine) - -3. read_fileonly: illustrates reading all output steps at once (a single read - statement) into a single contiguous memory block. This approach only works - for post-mortem processing. - - - -Example - - -1. Produce an output - -Writer usage: heatTransfer config output N M nx ny steps iterations - config: XML config file to use - output: name of output data file/stream - N: number of processes in X dimension - M: number of processes in Y dimension - nx: local array size in X dimension per processor - ny: local array size in Y dimension per processor - steps: the total number of steps to output - iterations: one step consist of this many iterations - -The ADIOS2 executable needs an XML config file to select the Engine used for the output. The engines are: File, BP4 and HDF5, the corresponding XML config files are in the examples/heatTransfer/ directory. The "File" engine will be BP4 or HDF5 depending on the extension of the file name. - -The adios1, ph5 and hdf5 versions of the example do not use XML config files, so just type "none" for the config argument. - -$ mpirun -np 12 ./bin/heatTransfer_write_adios2 ../examples/heatTransfer/heat_file.xml heat.bp 4 3 5 10 10 10 -$ mpirun -np 12 ./bin/heatTransfer_write_adios2 ../examples/heatTransfer/heat_file.xml heat.h5 4 3 5 10 10 10 - - -2. Read the output step-by-step and print data into text files (data. per reader process) - -Reader Usage: heatRead config input N M - config: XML config file to use - input: name of input data file/stream - N: number of processes in X dimension - M: number of processes in Y dimension - - -$ mpirun -np 2 ./bin/heatTransfer_read ../examples/heatTransfer/heat_file.xml heat 2 1 - - -Notes: -1. Engines for file-based output and post-mortem reading: i - - * BPFileWriter/BPFileReader - * HDF5Writer/HDF5Reader - -2. Engines for in situ execution - - * DataManWriter/DataManReader - (Must run writer and reader with the same number of processes and same decomposition) - - - diff --git a/examples/heatTransfer/inline/CMakeLists.txt b/examples/heatTransfer/inline/CMakeLists.txt deleted file mode 100644 index 54fd8de038..0000000000 --- a/examples/heatTransfer/inline/CMakeLists.txt +++ /dev/null @@ -1,14 +0,0 @@ -#------------------------------------------------------------------------------# -# Distributed under the OSI-approved Apache License, Version 2.0. See -# accompanying file Copyright.txt for details. -#------------------------------------------------------------------------------# - -add_executable(heatTransfer_inline_adios2 - main.cpp - InlineIO.cpp - ../write/HeatTransfer.cpp - ../write/Settings.cpp -) -target_link_libraries(heatTransfer_inline_adios2 - adios2::cxx11_mpi MPI::MPI_C ${CMAKE_THREAD_LIBS_INIT} -) diff --git a/examples/heatTransfer/read/CMakeLists.txt b/examples/heatTransfer/read/CMakeLists.txt deleted file mode 100644 index dd1adbe0cb..0000000000 --- a/examples/heatTransfer/read/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -#------------------------------------------------------------------------------# -# Distributed under the OSI-approved Apache License, Version 2.0. See -# accompanying file Copyright.txt for details. -#------------------------------------------------------------------------------# - -add_executable(heatTransfer_read - heatRead.cpp - PrintDataStep.h - ReadSettings.cpp -) -target_link_libraries(heatTransfer_read adios2::cxx11_mpi MPI::MPI_C) diff --git a/examples/heatTransfer/read_fileonly/CMakeLists.txt b/examples/heatTransfer/read_fileonly/CMakeLists.txt deleted file mode 100644 index d0ab4b830b..0000000000 --- a/examples/heatTransfer/read_fileonly/CMakeLists.txt +++ /dev/null @@ -1,12 +0,0 @@ -#------------------------------------------------------------------------------# -# Distributed under the OSI-approved Apache License, Version 2.0. See -# accompanying file Copyright.txt for details. -#------------------------------------------------------------------------------# - -add_executable(heatTransfer_read_fileonly_adios2 heatRead_adios2.cpp PrintData.h) -target_link_libraries(heatTransfer_read_fileonly_adios2 adios2::cxx11_mpi MPI::MPI_C) - -#if(ADIOS2_HAVE_HDF5) - #add_executable(heatTransfer_read_fileonly_h5_mpi heatRead_h5.cpp PrintData.h) - #target_link_libraries(heatTransfer_read_fileonly_h5_mpi adios2::cxx11_mpi MPI::MPI_C) -#endif() diff --git a/examples/heatTransfer/read_fileonly/heatRead_adios1.cpp b/examples/heatTransfer/read_fileonly/heatRead_adios1.cpp deleted file mode 100644 index c727a9e825..0000000000 --- a/examples/heatTransfer/read_fileonly/heatRead_adios1.cpp +++ /dev/null @@ -1,101 +0,0 @@ -#include - -#include -#include -#include -#include -#include -#include - -#include -#include - -#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); - - 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/heatTransfer/write/CMakeLists.txt b/examples/heatTransfer/write/CMakeLists.txt deleted file mode 100644 index 268b05fe28..0000000000 --- a/examples/heatTransfer/write/CMakeLists.txt +++ /dev/null @@ -1,66 +0,0 @@ -#------------------------------------------------------------------------------# -# Distributed under the OSI-approved Apache License, Version 2.0. See -# accompanying file Copyright.txt for details. -#------------------------------------------------------------------------------# - -add_executable(heatTransfer_write_adios2 - main.cpp - HeatTransfer.cpp - Settings.cpp - IO_adios2.cpp -) -target_link_libraries(heatTransfer_write_adios2 - adios2::cxx11_mpi MPI::MPI_C ${CMAKE_THREAD_LIBS_INIT} -) - -add_executable(heatTransfer_write_ascii - main.cpp - HeatTransfer.cpp - Settings.cpp - IO_ascii.cpp -) -target_link_libraries(heatTransfer_write_ascii - MPI::MPI_C ${CMAKE_THREAD_LIBS_INIT} -) - -if(ADIOS2_HAVE_HDF5) - add_executable(heatTransfer_write_hdf5 - main.cpp - HeatTransfer.cpp - Settings.cpp - IO_hdf5_a.cpp - ) - target_include_directories(heatTransfer_write_hdf5 - PRIVATE ${HDF5_C_INCLUDE_DIRS} - ) - target_link_libraries(heatTransfer_write_hdf5 - ${HDF5_C_LIBRARIES} MPI::MPI_C ${CMAKE_THREAD_LIBS_INIT} - ) - - if(HDF5_IS_PARALLEL) - add_executable(heatTransfer_write_ph5 - main.cpp - HeatTransfer.cpp - Settings.cpp - IO_ph5.cpp - ) - target_include_directories(heatTransfer_write_ph5 - PRIVATE ${HDF5_C_INCLUDE_DIRS} - ) - target_link_libraries(heatTransfer_write_ph5 - ${HDF5_C_LIBRARIES} MPI::MPI_C ${CMAKE_THREAD_LIBS_INIT} - ) - endif() - - if(NOT (HDF5_VERSION VERSION_LESS 1.11)) - add_executable(heatTransfer_write_h5mixer - main.cpp - HeatTransfer.cpp - Settings.cpp - IO_h5mixer.cpp - ) - target_link_libraries(heatTransfer_write_h5mixer - adios2::cxx11_mpi MPI::MPI_C ${CMAKE_THREAD_LIBS_INIT} - ) - endif() -endif() diff --git a/examples/hello/CMakeLists.txt b/examples/hello/CMakeLists.txt index 1de325635a..4d0d447a77 100644 --- a/examples/hello/CMakeLists.txt +++ b/examples/hello/CMakeLists.txt @@ -3,13 +3,35 @@ # accompanying file Copyright.txt for details. #------------------------------------------------------------------------------# -add_subdirectory(bpWriter) -add_subdirectory(bpReader) -add_subdirectory(bpTimeWriter) +add_subdirectory(bpAttributeWriteRead) add_subdirectory(bpFlushWriter) -add_subdirectory(bpAttributeWriter) -add_subdirectory(inlineReaderWriter) -add_subdirectory(skeleton) + +if(ADIOS2_HAVE_MPI) + add_subdirectory(bpFWriteCRead) +endif() + +if(ADIOS2_HAVE_SZ) + add_subdirectory(bpOperatorSZWriter) +endif() + +add_subdirectory(bpReader) + +add_subdirectory(bpStepsWriteRead) +if(ADIOS2_HAVE_CUDA OR ADIOS2_HAVE_Kokkos_CUDA) + add_subdirectory(bpStepsWriteReadCuda) +endif() +if(ADIOS2_HAVE_Kokkos_HIP) + add_subdirectory(bpStepsWriteReadHip) +endif() +if(ADIOS2_HAVE_Kokkos) + add_subdirectory(bpStepsWriteReadKokkos) + if(ADIOS2_HAVE_SST) + add_subdirectory(sstKokkos) + endif() +endif() + +add_subdirectory(bpThreadWrite) +add_subdirectory(bpWriter) if(ADIOS2_HAVE_DataMan) add_subdirectory(datamanReader) @@ -21,20 +43,25 @@ if(ADIOS2_HAVE_DataSpaces) add_subdirectory(dataspacesWriter) endif() -if(ADIOS2_HAVE_SST) - add_subdirectory(sstReader) - add_subdirectory(sstWriter) -endif() - if(ADIOS2_HAVE_HDF5) add_subdirectory(hdf5Writer) add_subdirectory(hdf5Reader) + if(HDF5_VERSION VERSION_GREATER_EQUAL 1.14) + add_subdirectory(hdf5SubFile) + endif() endif() -if(ADIOS2_HAVE_MPI) - add_subdirectory(bpFWriteCRead) -endif() +add_subdirectory(helloWorld) if(ADIOS2_HAVE_Fortran) - add_subdirectory(inlineFWriteCppRead) + add_subdirectory(inlineFWriteCppRead) +endif() + +add_subdirectory(inlineMWE) +add_subdirectory(inlineReaderWriter) +add_subdirectory(skeleton) + +if(ADIOS2_HAVE_SST) + add_subdirectory(sstReader) + add_subdirectory(sstWriter) endif() diff --git a/examples/hello/README.md b/examples/hello/README.md deleted file mode 100644 index 01b109ccc7..0000000000 --- a/examples/hello/README.md +++ /dev/null @@ -1,18 +0,0 @@ -examples/hello - -Provides tests and illustrates how to use very basic functionality in adios2 - -1. bpWriter - * Write BP format files for one Variable - -1. bpTimeWriter - * Write BP format files for two Variables (one is timestep) using time aggregation - -1. datamanReader (to be deprecated, ADIOS_USE_DataMan=ON) - * Read real-time WAN streams using dataman - -1. datamanWriter - * Write real-time WAN streams using dataman - -1. hdf5Writer (-DADIOS_USE_HDF5=ON) - * Write HDF5 files using interoperability through the adios2 interface diff --git a/examples/hello/ReadMe.md b/examples/hello/ReadMe.md new file mode 100644 index 0000000000..ed45bec50c --- /dev/null +++ b/examples/hello/ReadMe.md @@ -0,0 +1,72 @@ +## ADIOS2 hello examples + +The _hello_ examples are meant to introduce you to ADIOS2's IO capabilities and engines. + +They can be found in the following subdirectories, and they should be explored in the order that they are listed: + +1. [helloWorld](helloWorld): The _helloWorld_ example demonstrates how to write a simple word and read it back using + ADIOS2's BP engine. + * Languages: C++, C++ using high-level API, C, Python, Python using high-level API +2. [bpWriter](bpWriter): The _bpWriter_ examples demonstrate how to write a variable to using ADIOS2's BP engine. + * Languages: C++, C, Fortran, Python +3. [bpReader](bpReader): The _bpReader_ examples demonstrate how to read a 1D/2D/3D variable using ADIOS2's BP engine. + * Languages: C++, Fortran, Python +4. [bpAttributeWriterReader](bpAttributeWriterReader): The _bpAttributeWriterReader_ example demonstrates how to + write/read attributes using ADIOS2's BP engine. + * Languages: C++ +5. [bpOperatorSZWriter](bpOperatorSZWriter): The _bpOperatorSZWriter_ example demonstrates how to write variables with + the SZ operator using ADIOS2's BP engine. + * Languages: C++ +6. [bpStepsWriteRead](bpStepsWriteRead): The _bpStepsWriteRead_ example demonstrates how to write and read + multiple steps using ADIOS2's BP engine. + * Languages: C++ +7. [bpStepsWriteReadCuda](bpStepsWriteReadCuda): The _bpStepsWriteReadCuda_ example demonstrates how to write and read a + variable with multiple steps using ADIOS2's BP engine and leveraging CUDA. + * Languages: C++ +8. [bpStepsWriteReadHip](bpStepsWriteReadHip): The _bpStepsWriteReadHip_ example demonstrates how to write and read a + variable with multiple steps using ADIOS2's BP engine and leveraging HIP. + * Languages: C++ +9. [bpStepsWriteReadKokkos](bpStepsWriteReadKokkos): The _bpStepsWriteReadKokkos_ example demonstrates how to write and + read a variable with multiple steps using ADIOS2's BP engine and leveraging Kokkos. + * Languages: C++ +10. [bpFlushWriter](bpFlushWriter): The _bpFlushWriter_ example demonstrates how to flush a variable using ADIOS2's BP + engine. + * Languages: C++ +11. [bpFWriteCRead](bpFWriteCRead): The _bpFWriteCRead_ example demonstrates how to write a 2D variable with + Fortran and read a subset of it with C++, and vice versa using ADIOS2's BP engine. + * Languages: C++, Fortran +12. [datamanReader](datamanReader): The _datamanReader_ example demonstrates how to read variables in real-time WAN + streams using ADIOS's DataMan engine. + * Languages: C++, Python +13. [datamanWriter](datamanWriter): The _datamanWriter_ example demonstrates how to write variables in real-time WAN + streams using ADIOS's DataMan engine. + * Languages: C++, Python +14. [dataspacesReader](dataspacesReader): The _dataspacesReader_ example demonstrates how to read a variable using + ADIOS2's DATASPACES engine. + * Languages: C++ +15. [dataspacesWriter](dataspacesWriter): The _dataspacesWriter_ example demonstrates how to write a variable using + ADIOS2's DATASPACES engine. + * Languages: C++ +16. [hdf5Reader](hdf5Reader): The _hdf5Reader_ example demonstrates how to read variables using ADIOS2's HDF5 engine. + * Languages: C++ +17. [hdf5Writer](hdf5Writer): The _hdf5Writer_ example demonstrates how to write variables using ADIOS2's HDF5 engine. + * Languages: C++ +18. [hdf5SubFile](hdf5SubFile): The _hdf5SubFile_ example demonstrates how to write variables using ADIOS2's parallel + HDF5 engine leveraging the subfile feature. + * Languages: C++ +19. [inlineMWE](inlineMWE): The _inlineMWE_ example demonstrates how to write and read a variable using ADIOS2's inline + engine. + * Languages: C++ +20. [inlineFWriteCppRead](inlineFWriteCppRead): The _inlineFWriteCppRead_ example demonstrates how to write a 2D + variable with Fortran and read it back a subset of it with C++ using ADIOS2's inline engine. + * Languages: C++, Fortran +21. [inlineReaderWriter](inlineReaderWriter): The _inlineReaderWriter_ example demonstrates how to write two Variables + (one is timestep) using time aggregation and ADIOS2's inline engine. + * Languages: C++ +22. [sstReader](sstReader): The _sstReader_ example demonstrates how to read a variable using ADIOS2's SST engine. + * Languages: C++ +23. [sstWriter](sstWriter): The _sstWriter_ example demonstrates how to write a variable using ADIOS2's SST engine. + * Languages: C++ +24. [skeleton](skeleton): The _skeleton_ example demonstrates how to write and read a variable using an ADIOS2 skeleton + engine. + * Languages: C++ diff --git a/examples/hello/bpAttributeWriteRead/CMakeLists.txt b/examples/hello/bpAttributeWriteRead/CMakeLists.txt new file mode 100644 index 0000000000..cfc777fef2 --- /dev/null +++ b/examples/hello/bpAttributeWriteRead/CMakeLists.txt @@ -0,0 +1,31 @@ +#------------------------------------------------------------------------------# +# Distributed under the OSI-approved Apache License, Version 2.0. See +# accompanying file Copyright.txt for details. +#------------------------------------------------------------------------------# + +cmake_minimum_required(VERSION 3.12) +project(ADIOS2HelloBPAttributeWriteReadExample) + +if(NOT TARGET adios2_core) + set(_components CXX) + + find_package(MPI COMPONENTS C) + if(MPI_FOUND) + # Workaround for various MPI implementations forcing the link of C++ bindings + add_definitions(-DOMPI_SKIP_MPICXX -DMPICH_SKIP_MPICXX) + + list(APPEND _components MPI) + endif() + + find_package(ADIOS2 REQUIRED COMPONENTS ${_components}) +endif() + +add_executable(adios2_hello_bpAttributeWriteRead bpAttributeWriteRead.cpp) +target_link_libraries(adios2_hello_bpAttributeWriteRead adios2::cxx11) +install(TARGETS adios2_hello_bpAttributeWriteRead RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + +if(ADIOS2_HAVE_MPI) + add_executable(adios2_hello_bpAttributeWriteRead_mpi bpAttributeWriteRead.cpp) + target_link_libraries(adios2_hello_bpAttributeWriteRead_mpi adios2::cxx11_mpi MPI::MPI_C) + install(TARGETS adios2_hello_bpAttributeWriteRead_mpi RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) +endif() diff --git a/examples/hello/bpAttributeWriteRead/bpAttributeWriteRead.cpp b/examples/hello/bpAttributeWriteRead/bpAttributeWriteRead.cpp new file mode 100644 index 0000000000..0d55e703e8 --- /dev/null +++ b/examples/hello/bpAttributeWriteRead/bpAttributeWriteRead.cpp @@ -0,0 +1,188 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * bpAttributeWriteRead.cpp: Simple self-descriptive example of how to write/read attributes and + * a variable to a BP File that lives in several MPI processes. + * + * Created on: Feb 16, 2017 + * Author: William F Godoy godoywf@ornl.gov + */ + +#include //std::ios_base::failure +#include //std::cout +#if ADIOS2_USE_MPI +#include +#endif +#include //std::invalid_argument std::exception +#include +#include + +#include + +void writer(adios2::ADIOS &adios, int rank, int size, std::vector &myFloats) +{ + /*** IO class object: settings and factory of Settings: Variables, + * Parameters, Transports, and Execution: Engines */ + adios2::IO bpIO = adios.DeclareIO("BPFile_N2N"); + + const std::size_t Nx = myFloats.size(); + + /** global array : name, { shape (total) }, { start (local) }, { count + * (local) }, all are constant dimensions */ + adios2::Variable bpFloats = bpIO.DefineVariable( + "bpFloats", {size * Nx}, {rank * Nx}, {Nx}, adios2::ConstantDims); + + bpIO.DefineAttribute("Single_String", "File generated with ADIOS2"); + + std::vector myStrings = {"one", "two", "three"}; + bpIO.DefineAttribute("Array_of_Strings", myStrings.data(), myStrings.size()); + + bpIO.DefineAttribute("Attr_Double", 0.f); + std::vector myDoubles = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + bpIO.DefineAttribute("Array_of_Doubles", myDoubles.data(), myDoubles.size()); + + /** Engine derived class, spawned to start IO operations */ + adios2::Engine bpWriter = bpIO.Open("fileAttributes.bp", adios2::Mode::Write); + + bpWriter.BeginStep(); + + /** Write variable for buffering */ + bpWriter.Put(bpFloats, myFloats.data()); + + bpWriter.EndStep(); + + /** Create bp file, engine becomes unreachable after this*/ + bpWriter.Close(); +} + +void reader(adios2::ADIOS &adios, int rank, int /*size*/) +{ + adios2::IO bpIO = adios.DeclareIO("BPReader"); + + adios2::Engine bpReader = bpIO.Open("fileAttributes.bp", adios2::Mode::Read); + + bpReader.BeginStep(); + const auto attributesInfo = bpIO.AvailableAttributes(); + + for (const auto &attributeInfoPair : attributesInfo) + { + std::cout << "Attribute: " << attributeInfoPair.first; + for (const auto &attributePair : attributeInfoPair.second) + { + std::cout << "\tKey: " << attributePair.first << "\tValue: " << attributePair.second + << "\n"; + } + std::cout << "\n"; + } + + adios2::Attribute singleString = bpIO.InquireAttribute("Single_String"); + if (singleString) + { + std::cout << singleString.Name() << ": " << singleString.Data()[0] << "\n"; + } + adios2::Attribute arrayOfStrings = + bpIO.InquireAttribute("Array_of_Strings"); + if (arrayOfStrings) + { + std::cout << arrayOfStrings.Name() << ": "; + for (const auto &value : arrayOfStrings.Data()) + { + std::cout << value << " "; + } + std::cout << "\n"; + } + adios2::Attribute attrDouble = bpIO.InquireAttribute("Attr_Double"); + if (attrDouble) + { + std::cout << attrDouble.Name() << ": " << attrDouble.Data()[0] << "\n"; + } + adios2::Attribute arrayOfDoubles = bpIO.InquireAttribute("Array_of_Doubles"); + if (arrayOfDoubles) + { + std::cout << arrayOfDoubles.Name() << ": "; + for (const auto &value : arrayOfDoubles.Data()) + { + std::cout << value << " "; + } + std::cout << "\n"; + } + + adios2::Variable bpFloats = bpIO.InquireVariable("bpFloats"); + const std::size_t Nx = 10; + std::vector myFloats(Nx); + if (bpFloats) + { + bpFloats.SetSelection({{Nx * rank}, {Nx}}); + bpReader.Get(bpFloats, myFloats.data()); + } + + bpReader.EndStep(); + + bpReader.Close(); +} + +int main(int argc, char *argv[]) +{ + int rank, size; +#if ADIOS2_USE_MPI + int provided; + + // MPI_THREAD_MULTIPLE is only required if you enable the SST MPI_DP + MPI_Init_thread(&argc, &argv, MPI_THREAD_MULTIPLE, &provided); + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + MPI_Comm_size(MPI_COMM_WORLD, &size); +#else + rank = 0; + size = 1; +#endif + + /** Application variable */ + std::vector myFloats = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + try + { + /** ADIOS class factory of IO class objects */ +#if ADIOS2_USE_MPI + adios2::ADIOS adios(MPI_COMM_WORLD); +#else + adios2::ADIOS adios; +#endif + + writer(adios, rank, size, myFloats); + reader(adios, rank, size); + } + catch (std::invalid_argument &e) + { + std::cout << "Invalid argument exception, STOPPING PROGRAM from rank " << rank << "\n"; + std::cout << e.what() << "\n"; +#if ADIOS2_USE_MPI + std::cerr << "STOPPING PROGRAM from rank " << rank << "\n"; + MPI_Abort(MPI_COMM_WORLD, 1); +#endif + } + catch (std::ios_base::failure &e) + { + std::cout << "IO System base failure exception, STOPPING PROGRAM from rank " << rank + << "\n"; + std::cout << e.what() << "\n"; +#if ADIOS2_USE_MPI + std::cerr << "STOPPING PROGRAM from rank " << rank << "\n"; + MPI_Abort(MPI_COMM_WORLD, 1); +#endif + } + catch (std::exception &e) + { + std::cout << "Exception, STOPPING PROGRAM from rank " << rank << "\n"; + std::cout << e.what() << "\n"; +#if ADIOS2_USE_MPI + std::cerr << "STOPPING PROGRAM from rank " << rank << "\n"; + MPI_Abort(MPI_COMM_WORLD, 1); +#endif + } + +#if ADIOS2_USE_MPI + MPI_Finalize(); +#endif + + return 0; +} diff --git a/examples/hello/bpAttributeWriteRead/bpAttributeWriteRead_tutorialSkeleton.cpp b/examples/hello/bpAttributeWriteRead/bpAttributeWriteRead_tutorialSkeleton.cpp new file mode 100644 index 0000000000..ef78c5efe0 --- /dev/null +++ b/examples/hello/bpAttributeWriteRead/bpAttributeWriteRead_tutorialSkeleton.cpp @@ -0,0 +1,91 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * bpAttributeWriteRead.cpp: Simple self-descriptive example of how to write/read attributes and + * a variable to a BP File that lives in several MPI processes. + * + * Created on: Feb 16, 2017 + * Author: William F Godoy godoywf@ornl.gov + */ + +#include //std::ios_base::failure +#include //std::cout +#include +#include //std::invalid_argument std::exception +#include +#include + +#include + +void writer(adios2::ADIOS &adios, int rank, int size, std::vector &myFloats) +{ + // Add code to create IO object + + // Add code to create variable + + // Add code to create attributes + + // Add code to open file + + // Add code to write variables + + // Add code to close file +} + +void reader(adios2::ADIOS &adios, int rank, int /*size*/) +{ + // Add code to create IO object + + // Add code to open file + + // add code to check available attributes + + // Add code to read attributes + + // Add code to read variables + + // Add code to close file +} + +int main(int argc, char *argv[]) +{ + int rank, size; + int provided; + + // Add code to init MPI + + // Add code to create array + try + { + // Add code to create ADIOS object + + // Call writer and reader functions + } + catch (std::invalid_argument &e) + { + std::cout << "Invalid argument exception, STOPPING PROGRAM from rank " << rank << "\n"; + std::cout << e.what() << "\n"; + std::cerr << "STOPPING PROGRAM from rank " << rank << "\n"; + MPI_Abort(MPI_COMM_WORLD, 1); + } + catch (std::ios_base::failure &e) + { + std::cout << "IO System base failure exception, STOPPING PROGRAM from rank " << rank + << "\n"; + std::cout << e.what() << "\n"; + std::cerr << "STOPPING PROGRAM from rank " << rank << "\n"; + MPI_Abort(MPI_COMM_WORLD, 1); + } + catch (std::exception &e) + { + std::cout << "Exception, STOPPING PROGRAM from rank " << rank << "\n"; + std::cout << e.what() << "\n"; + std::cerr << "STOPPING PROGRAM from rank " << rank << "\n"; + MPI_Abort(MPI_COMM_WORLD, 1); + } + + // Add code to finalize MPI + + return 0; +} diff --git a/examples/hello/bpAttributeWriter/CMakeLists.txt b/examples/hello/bpAttributeWriter/CMakeLists.txt deleted file mode 100644 index 6222de2122..0000000000 --- a/examples/hello/bpAttributeWriter/CMakeLists.txt +++ /dev/null @@ -1,14 +0,0 @@ -#------------------------------------------------------------------------------# -# Distributed under the OSI-approved Apache License, Version 2.0. See -# accompanying file Copyright.txt for details. -#------------------------------------------------------------------------------# - -add_executable(hello_bpAttributeWriter helloBPAttributeWriter_nompi.cpp) -target_link_libraries(hello_bpAttributeWriter adios2::cxx11) - -if(ADIOS2_HAVE_MPI) - find_package(MPI COMPONENTS C REQUIRED) - add_executable(hello_bpAttributeWriter_mpi helloBPAttributeWriter.cpp) - target_link_libraries(hello_bpAttributeWriter_mpi adios2::cxx11_mpi MPI::MPI_C) -endif() - diff --git a/examples/hello/bpAttributeWriter/helloBPAttributeWriter.cpp b/examples/hello/bpAttributeWriter/helloBPAttributeWriter.cpp deleted file mode 100644 index dce3946fa1..0000000000 --- a/examples/hello/bpAttributeWriter/helloBPAttributeWriter.cpp +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Distributed under the OSI-approved Apache License, Version 2.0. See - * accompanying file Copyright.txt for details. - * - * helloBPWriter.cpp: Simple self-descriptive example of how to write a variable - * to a BP File that lives in several MPI processes. - * - * Created on: Feb 16, 2017 - * Author: William F Godoy godoywf@ornl.gov - */ - -#include //std::ios_base::failure -#include //std::cout -#include -#include //std::invalid_argument std::exception -#include -#include - -#include - -int main(int argc, char *argv[]) -{ - int provided; - - // MPI_THREAD_MULTIPLE is only required if you enable the SST MPI_DP - MPI_Init_thread(&argc, &argv, MPI_THREAD_MULTIPLE, &provided); - int rank, size; - MPI_Comm_rank(MPI_COMM_WORLD, &rank); - MPI_Comm_size(MPI_COMM_WORLD, &size); - - /** Application variable */ - std::vector myFloats = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; - const std::size_t Nx = myFloats.size(); - - try - { - /** ADIOS class factory of IO class objects */ - adios2::ADIOS adios(MPI_COMM_WORLD); - - /*** IO class object: settings and factory of Settings: Variables, - * Parameters, Transports, and Execution: Engines */ - adios2::IO bpIO = adios.DeclareIO("BPFile_N2N"); - - /** global array : name, { shape (total) }, { start (local) }, { count - * (local) }, all are constant dimensions */ - adios2::Variable bpFloats = bpIO.DefineVariable( - "bpFloats", {size * Nx}, {rank * Nx}, {Nx}, adios2::ConstantDims); - - bpIO.DefineAttribute("Single_String", "File generated with ADIOS2"); - - std::vector myStrings = {"one", "two", "three"}; - bpIO.DefineAttribute("Array_of_Strings", myStrings.data(), myStrings.size()); - - bpIO.DefineAttribute("Attr_Double", 0.f); - std::vector myDoubles = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; - bpIO.DefineAttribute("Array_of_Doubles", myDoubles.data(), myDoubles.size()); - - /** Engine derived class, spawned to start IO operations */ - adios2::Engine bpWriter = bpIO.Open("fileAttributes.bp", adios2::Mode::Write); - - /** Write variable for buffering */ - bpWriter.Put(bpFloats, myFloats.data()); - - /** Create bp file, engine becomes unreachable after this*/ - bpWriter.Close(); - - adios2::IO bpReader = adios.DeclareIO("BPReader"); - - adios2::Engine bpReaderEngine = bpReader.Open("fileAttributes.bp", adios2::Mode::Read); - - const auto attributesInfo = bpReader.AvailableAttributes(); - - for (const auto &attributeInfoPair : attributesInfo) - { - std::cout << "Attribute: " << attributeInfoPair.first; - for (const auto &attributePair : attributeInfoPair.second) - { - std::cout << "\tKey: " << attributePair.first << "\tValue: " << attributePair.second - << "\n"; - } - std::cout << "\n"; - } - - bpReaderEngine.Close(); - } - catch (std::invalid_argument &e) - { - std::cout << "Invalid argument exception, STOPPING PROGRAM from rank " << rank << "\n"; - std::cout << e.what() << "\n"; - } - catch (std::ios_base::failure &e) - { - std::cout << "IO System base failure exception, STOPPING PROGRAM from rank " << rank - << "\n"; - std::cout << e.what() << "\n"; - } - catch (std::exception &e) - { - std::cout << "Exception, STOPPING PROGRAM from rank " << rank << "\n"; - std::cout << e.what() << "\n"; - } - - MPI_Finalize(); - - return 0; -} diff --git a/examples/hello/bpAttributeWriter/helloBPAttributeWriter_nompi.cpp b/examples/hello/bpAttributeWriter/helloBPAttributeWriter_nompi.cpp deleted file mode 100644 index 9b9fedd9ab..0000000000 --- a/examples/hello/bpAttributeWriter/helloBPAttributeWriter_nompi.cpp +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Distributed under the OSI-approved Apache License, Version 2.0. See - * accompanying file Copyright.txt for details. - * - * helloBPWriter_nompi.cpp sequential non-mpi version of helloBPWriter - * - * Created on: Jan 9, 2017 - * Author: William F Godoy godoywf@ornl.gov - */ - -#include //std::ios_base::failure -#include //std::cout -#include //std::invalid_argument std::exception -#include -#include - -#include - -int main(int argc, char *argv[]) -{ - /** Application variable */ - std::vector myFloats = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; - const std::size_t Nx = myFloats.size(); - - try - { - /** ADIOS class factory of IO class objects */ - adios2::ADIOS adios; - - /*** IO class object: settings and factory of Settings: Variables, - * Parameters, Transports, and Execution: Engines */ - adios2::IO bpIO = adios.DeclareIO("BPFile_N2N"); - - /** global array: name, { shape (total dimensions) }, { start (local) }, - * { count (local) }, all are constant dimensions */ - adios2::Variable bpFloats = - bpIO.DefineVariable("bpFloats", {}, {}, {Nx}, adios2::ConstantDims); - - bpIO.DefineAttribute("Single_String", "File generated with ADIOS2"); - - std::vector myStrings = {"one", "two", "three"}; - bpIO.DefineAttribute("Array_of_Strings", myStrings.data(), myStrings.size()); - - bpIO.DefineAttribute("Attr_Double", 0.f); - std::vector myDoubles = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; - bpIO.DefineAttribute("Array_of_Doubles", myDoubles.data(), myDoubles.size()); - - /** Engine derived class, spawned to start IO operations */ - adios2::Engine bpWriter = bpIO.Open("myVector.bp", adios2::Mode::Write); - - /** Write variable for buffering */ - bpWriter.Put(bpFloats, myFloats.data()); - - /** Create bp file, engine becomes unreachable after this*/ - bpWriter.Close(); - } - catch (std::invalid_argument &e) - { - std::cout << "Invalid argument exception, STOPPING PROGRAM\n"; - std::cout << e.what() << "\n"; - } - catch (std::ios_base::failure &e) - { - std::cout << "IO System base failure exception, STOPPING PROGRAM\n"; - std::cout << e.what() << "\n"; - } - catch (std::exception &e) - { - std::cout << "Exception, STOPPING PROGRAM from rank\n"; - std::cout << e.what() << "\n"; - } - - return 0; -} diff --git a/examples/hello/bpFWriteCRead/CMakeLists.txt b/examples/hello/bpFWriteCRead/CMakeLists.txt index ff5dcc1b2b..759d6919c6 100644 --- a/examples/hello/bpFWriteCRead/CMakeLists.txt +++ b/examples/hello/bpFWriteCRead/CMakeLists.txt @@ -3,18 +3,49 @@ # accompanying file Copyright.txt for details. #------------------------------------------------------------------------------# -add_executable(CppWriter CppWriter.cpp) -target_link_libraries(CppWriter adios2::cxx11_mpi MPI::MPI_C) - -add_executable(CppReader CppReader.cpp) -target_link_libraries(CppReader adios2::cxx11_mpi MPI::MPI_C) - -if(ADIOS2_HAVE_Fortran) - add_executable(FWriter FWriter.f90) - add_executable(FReader FReader.f90) - target_link_libraries(FWriter adios2::fortran_mpi MPI::MPI_Fortran) - target_link_libraries(FReader adios2::fortran_mpi MPI::MPI_Fortran) - set_target_properties(FWriter FReader PROPERTIES - LINKER_LANGUAGE Fortran - ) +cmake_minimum_required(VERSION 3.12) +project(ADIOS2HelloBPFWriteCReadExample) + +if(NOT TARGET adios2_core) + set(_components C) + + include(CheckLanguage) + check_language(Fortran) + if(CMAKE_Fortran_COMPILER) + enable_language(Fortran) + endif() + if(CMAKE_Fortran_COMPILER_LOADED) + list(APPEND _components Fortran) + endif() + + find_package(MPI COMPONENTS ${_components}) + if(MPI_FOUND) + # Workaround for various MPI implementations forcing the link of C++ bindings + add_definitions(-DOMPI_SKIP_MPICXX -DMPICH_SKIP_MPICXX) + + list(APPEND _components MPI) + endif() + list(APPEND _components CXX) + + find_package(ADIOS2 REQUIRED COMPONENTS ${_components}) +endif() + +if (ADIOS2_HAVE_MPI) + add_executable(adios2_hello_CppWriter CppWriter.cpp) + target_link_libraries(adios2_hello_CppWriter adios2::cxx11_mpi MPI::MPI_C) + install(TARGETS adios2_hello_CppWriter RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + + add_executable(adios2_hello_CppReader CppReader.cpp) + target_link_libraries(adios2_hello_CppReader adios2::cxx11_mpi MPI::MPI_C) + install(TARGETS adios2_hello_CppReader RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + + if(ADIOS2_HAVE_Fortran) + add_executable(adios2_hello_FWriter FWriter.f90) + target_link_libraries(adios2_hello_FWriter adios2::fortran_mpi MPI::MPI_Fortran) + install(TARGETS adios2_hello_FWriter RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + + add_executable(adios2_hello_FReader FReader.f90) + target_link_libraries(adios2_hello_FReader adios2::fortran_mpi MPI::MPI_Fortran) + install(TARGETS adios2_hello_FReader RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + endif() endif() diff --git a/examples/hello/bpFWriteCRead/CppReader.cpp b/examples/hello/bpFWriteCRead/CppReader.cpp index 6e4ff552ad..0c4af26d6c 100644 --- a/examples/hello/bpFWriteCRead/CppReader.cpp +++ b/examples/hello/bpFWriteCRead/CppReader.cpp @@ -35,6 +35,8 @@ int main(int argc, char *argv[]) /** Engine derived class, spawned to start IO operations */ adios2::Engine bpReader = bpIO.Open("FWriter.bp", adios2::Mode::Read); + bpReader.BeginStep(); + const std::map variables = bpIO.AvailableVariables(); for (const auto &variablePair : variables) @@ -52,6 +54,9 @@ int main(int argc, char *argv[]) std::vector data(bpData.SelectionSize()); bpReader.Get(bpData, data.data()); + + bpReader.EndStep(); + bpReader.Close(); std::cout << "Selection size: " << bpData.SelectionSize() << "\n"; diff --git a/examples/hello/bpFWriteCRead/CppWriter.cpp b/examples/hello/bpFWriteCRead/CppWriter.cpp index 5e93990736..82c82532aa 100644 --- a/examples/hello/bpFWriteCRead/CppWriter.cpp +++ b/examples/hello/bpFWriteCRead/CppWriter.cpp @@ -42,7 +42,9 @@ int main(int argc, char *argv[]) "data2D", {size * nx, ny}, {rank * nx, 0}, {nx, ny}, adios2::ConstantDims); adios2::Engine engine = io.Open("CppWriter.bp", adios2::Mode::Write); + engine.BeginStep(); engine.Put(bpFloats, data.data()); + engine.EndStep(); engine.Close(); MPI_Finalize(); diff --git a/examples/hello/bpFlushWriter/CMakeLists.txt b/examples/hello/bpFlushWriter/CMakeLists.txt index 351282fa3c..61c78ebc7b 100644 --- a/examples/hello/bpFlushWriter/CMakeLists.txt +++ b/examples/hello/bpFlushWriter/CMakeLists.txt @@ -3,10 +3,29 @@ # accompanying file Copyright.txt for details. #------------------------------------------------------------------------------# -add_executable(hello_bpFlushWriter helloBPFlushWriter_nompi.cpp) -target_link_libraries(hello_bpFlushWriter adios2::cxx11) +cmake_minimum_required(VERSION 3.12) +project(ADIOS2HelloBPFlushWriterExample) + +if(NOT TARGET adios2_core) + set(_components CXX) + + find_package(MPI COMPONENTS C) + if(MPI_FOUND) + # Workaround for various MPI implementations forcing the link of C++ bindings + add_definitions(-DOMPI_SKIP_MPICXX -DMPICH_SKIP_MPICXX) + + list(APPEND _components MPI) + endif() + + find_package(ADIOS2 REQUIRED COMPONENTS ${_components}) +endif() + +add_executable(adios2_hello_bpFlushWriter bpFlushWriter_nompi.cpp) +target_link_libraries(adios2_hello_bpFlushWriter adios2::cxx11) +install(TARGETS adios2_hello_bpFlushWriter RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) if(ADIOS2_HAVE_MPI) - add_executable(hello_bpFlushWriter_mpi helloBPFlushWriter.cpp) - target_link_libraries(hello_bpFlushWriter_mpi adios2::cxx11_mpi MPI::MPI_C) + add_executable(adios2_hello_bpFlushWriter_mpi bpFlushWriter.cpp) + target_link_libraries(adios2_hello_bpFlushWriter_mpi adios2::cxx11_mpi MPI::MPI_C) + install(TARGETS adios2_hello_bpFlushWriter_mpi RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) endif() diff --git a/examples/hello/bpFlushWriter/helloBPFlushWriter.cpp b/examples/hello/bpFlushWriter/bpFlushWriter.cpp similarity index 95% rename from examples/hello/bpFlushWriter/helloBPFlushWriter.cpp rename to examples/hello/bpFlushWriter/bpFlushWriter.cpp index bcdfc441f9..9299c190e4 100644 --- a/examples/hello/bpFlushWriter/helloBPFlushWriter.cpp +++ b/examples/hello/bpFlushWriter/bpFlushWriter.cpp @@ -2,7 +2,7 @@ * Distributed under the OSI-approved Apache License, Version 2.0. See * accompanying file Copyright.txt for details. * - * helloBPFlushWriter.cpp: Example that tests buffer overflow forcing a flush to + * bpFlushWriter.cpp: Example that tests buffer overflow forcing a flush to * transports when writing a large variable in independent N-to-N mode. This * will have performance penalties, but it's safer. * @@ -55,6 +55,7 @@ int main(int argc, char *argv[]) /** Engine derived class, spawned to start IO operations */ adios2::Engine bpWriter = bpIO.Open("myVectorFlush.bp", adios2::Mode::Write); + bpWriter.BeginStep(); for (unsigned int t = 0; t < 100; ++t) { /** values to time step */ @@ -62,6 +63,7 @@ int main(int argc, char *argv[]) /** Write variable for buffering */ bpWriter.Put(bpFloats, myFloats.data()); } + bpWriter.EndStep(); /** Create bp file, engine becomes unreachable after this*/ bpWriter.Close(); diff --git a/examples/hello/bpFlushWriter/helloBPFlushWriter_nompi.cpp b/examples/hello/bpFlushWriter/bpFlushWriter_nompi.cpp similarity index 94% rename from examples/hello/bpFlushWriter/helloBPFlushWriter_nompi.cpp rename to examples/hello/bpFlushWriter/bpFlushWriter_nompi.cpp index edd92663ac..54565f41bf 100644 --- a/examples/hello/bpFlushWriter/helloBPFlushWriter_nompi.cpp +++ b/examples/hello/bpFlushWriter/bpFlushWriter_nompi.cpp @@ -2,7 +2,7 @@ * Distributed under the OSI-approved Apache License, Version 2.0. See * accompanying file Copyright.txt for details. * - * helloBPWriter_nompi.cpp sequential non-mpi version of helloBPWriter + * bpFlushWriter_nompi.cpp sequential non-mpi version of bpFlushWriter * * Created on: Jan 9, 2017 * Author: William F Godoy godoywf@ornl.gov @@ -38,9 +38,13 @@ int main(int argc, char *argv[]) /** Engine derived class, spawned to start IO operations */ adios2::Engine bpWriter = bpIO.Open("myVector.bp", adios2::Mode::Write); + bpWriter.BeginStep(); + /** Write variable for buffering */ bpWriter.Put(bpFloats, myFloats.data()); + bpWriter.EndStep(); + /** Create bp file, engine becomes unreachable after this*/ bpWriter.Close(); } diff --git a/examples/hello/bpOperatorSZWriter/CMakeLists.txt b/examples/hello/bpOperatorSZWriter/CMakeLists.txt new file mode 100644 index 0000000000..c54aadf81e --- /dev/null +++ b/examples/hello/bpOperatorSZWriter/CMakeLists.txt @@ -0,0 +1,36 @@ +#------------------------------------------------------------------------------# +# Distributed under the OSI-approved Apache License, Version 2.0. See +# accompanying file Copyright.txt for details. +#------------------------------------------------------------------------------# + +cmake_minimum_required(VERSION 3.12) +project(ADIOS2HelloBPOperatorSZWriterExample) + +if(NOT TARGET adios2_core) + set(_components C) + + find_package(MPI COMPONENTS ${_components}) + if(MPI_FOUND) + # Workaround for various MPI implementations forcing the link of C++ bindings + add_definitions(-DOMPI_SKIP_MPICXX -DMPICH_SKIP_MPICXX) + + list(APPEND _components MPI) + endif() + list(APPEND _components CXX) + + find_package(SZ QUIET) + + find_package(ADIOS2 REQUIRED COMPONENTS ${_components}) +endif() + +if(ADIOS2_HAVE_SZ) + add_executable(adios2_hello_bpOperatorSZWriter bpOperatorSZWriter.cpp) + target_link_libraries(adios2_hello_bpOperatorSZWriter adios2::cxx11) + install(TARGETS adios2_hello_bpOperatorSZWriter RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + + if (ADIOS2_HAVE_MPI) + add_executable(adios2_hello_bpOperatorSZWriter_mpi bpOperatorSZWriter.cpp) + target_link_libraries(adios2_hello_bpOperatorSZWriter_mpi adios2::cxx11_mpi MPI::MPI_C) + install(TARGETS adios2_hello_bpOperatorSZWriter_mpi RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + endif () +endif() diff --git a/examples/hello/bpWriter/helloBPSZ.cpp b/examples/hello/bpOperatorSZWriter/bpOperatorSZWriter.cpp similarity index 79% rename from examples/hello/bpWriter/helloBPSZ.cpp rename to examples/hello/bpOperatorSZWriter/bpOperatorSZWriter.cpp index 5678ecb12c..2fb96876a1 100644 --- a/examples/hello/bpWriter/helloBPSZ.cpp +++ b/examples/hello/bpOperatorSZWriter/bpOperatorSZWriter.cpp @@ -2,19 +2,20 @@ * Distributed under the OSI-approved Apache License, Version 2.0. See * accompanying file Copyright.txt for details. * - * helloBPSZ.cpp : example passing runtime compression arguments + * bpOperatorSZWriter.cpp : example using operator by passing compression arguments * * Created on: Aug 3, 2018 * Author: William F Godoy godoywf@ornl.gov */ +#include //std::transform #include //std::ios_base::failure #include //std::cout #include //std::iota #include //std::invalid_argument std::exception #include -#include +#include "adios2.h" #if ADIOS2_USE_MPI #include #endif @@ -23,7 +24,7 @@ void Usage() { std::cout << "\n"; std::cout << "USAGE:\n"; - std::cout << "./helloBPSZ Nx sz_accuracy\n"; + std::cout << "./adios2_hello_bpOperatorSZWriter Nx sz_accuracy\n"; std::cout << "\t Nx: size of float and double arrays to be compressed\n"; std::cout << "\t sz_accuracy: absolute accuracy e.g. 0.1, 0.001, to skip " "compression: -1\n\n"; @@ -31,8 +32,13 @@ void Usage() int main(int argc, char *argv[]) { - int rank, size; + if (argc != 3) + { + Usage(); + return EXIT_SUCCESS; + } + int rank, size; #if ADIOS2_USE_MPI int provided; @@ -47,12 +53,6 @@ int main(int argc, char *argv[]) try { - if (argc != 3) - { - throw std::invalid_argument("ERROR: need sz accuracy e.g. 0.01, 0.1 as " - "2nd parameter in argv\n"); - } - const std::size_t Nx = static_cast(std::stoull(argv[1])); const double accuracy = std::stod(argv[2]); @@ -92,21 +92,26 @@ int main(int argc, char *argv[]) (void)attribute; /** Engine derived class, spawned to start IO operations */ - adios2::Engine bpFileWriter = bpIO.Open("SZexample.bp", adios2::Mode::Write); + adios2::Engine bpWriter = bpIO.Open("SZexample.bp", adios2::Mode::Write); - for (unsigned int t = 0; t < 3; ++t) + for (unsigned int step = 0; step < 3; ++step) { - bpFileWriter.BeginStep(); + bpWriter.BeginStep(); - // here you can modify myFloats, myDoubles per step + bpWriter.Put(varFloats, myFloats.data()); + bpWriter.Put(varDoubles, myDoubles.data()); - bpFileWriter.Put(varFloats, myFloats.data()); - bpFileWriter.Put(varDoubles, myDoubles.data()); - bpFileWriter.EndStep(); + bpWriter.EndStep(); + + // here you can modify myFloats, myDoubles per step + std::transform(myFloats.begin(), myFloats.end(), myFloats.begin(), + [&](float v) -> float { return 2 * v; }); + std::transform(myDoubles.begin(), myDoubles.end(), myDoubles.begin(), + [&](double v) -> double { return 3 * v; }); } /** Create bp file, engine becomes unreachable after this*/ - bpFileWriter.Close(); + bpWriter.Close(); } catch (std::invalid_argument &e) { diff --git a/examples/hello/bpOperatorSZWriter/bpOperatorSZWriter_tutorialSkeleton.cxx b/examples/hello/bpOperatorSZWriter/bpOperatorSZWriter_tutorialSkeleton.cxx new file mode 100644 index 0000000000..618ea7f50b --- /dev/null +++ b/examples/hello/bpOperatorSZWriter/bpOperatorSZWriter_tutorialSkeleton.cxx @@ -0,0 +1,94 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * bpSZ.cpp : example passing runtime compression arguments + * + * Created on: Aug 3, 2018 + * Author: William F Godoy godoywf@ornl.gov + */ + +#include //std::transform +#include //std::ios_base::failure +#include //std::cout +#include //std::iota +#include //std::invalid_argument std::exception +#include + +#include +#include + +void Usage() +{ + std::cout << "\n"; + std::cout << "USAGE:\n"; + std::cout << "./adios2_hello_bpSZ Nx sz_accuracy\n"; + std::cout << "\t Nx: size of float and double arrays to be compressed\n"; + std::cout << "\t sz_accuracy: absolute accuracy e.g. 0.1, 0.001, to skip " + "compression: -1\n\n"; +} + +int main(int argc, char *argv[]) +{ + if (argc != 3) + { + Usage(); + return EXIT_SUCCESS; + } + + int rank, size; + int provided; + + // Add code to init MPI + + try + { + // Add code to get command line arguments + + // Add code to create arrays + + // Add code to create ADIOS object + + // Add code to create IO object + + // Add code to create variables + + // Add code to add SZ compressor operation + + // Add code to add attribute + + // Add code to open file + + // Add code to write variables for 3 time steps and edit them + + // Add code to close file + } + catch (std::invalid_argument &e) + { + std::cerr << "Invalid argument exception: " << e.what() << "\n"; +#if ADIOS2_USE_MPI + std::cerr << "STOPPING PROGRAM from rank " << rank << "\n"; + MPI_Abort(MPI_COMM_WORLD, 1); +#endif + } + catch (std::ios_base::failure &e) + { + std::cerr << "IO System base failure exception: " << e.what() << "\n"; +#if ADIOS2_USE_MPI + std::cerr << "STOPPING PROGRAM from rank " << rank << "\n"; + MPI_Abort(MPI_COMM_WORLD, 1); +#endif + } + catch (std::exception &e) + { + std::cerr << "Exception: " << e.what() << "\n"; +#if ADIOS2_USE_MPI + std::cerr << "STOPPING PROGRAM from rank " << rank << "\n"; + MPI_Abort(MPI_COMM_WORLD, 1); +#endif + } + + // Add code to finalize MPI + + return 0; +} diff --git a/examples/hello/bpReader/CMakeLists.txt b/examples/hello/bpReader/CMakeLists.txt index 462227301f..47a5140944 100644 --- a/examples/hello/bpReader/CMakeLists.txt +++ b/examples/hello/bpReader/CMakeLists.txt @@ -3,28 +3,59 @@ # accompanying file Copyright.txt for details. #------------------------------------------------------------------------------# -add_executable(hello_bpReader helloBPReader_nompi.cpp) -target_link_libraries(hello_bpReader adios2::cxx11) +cmake_minimum_required(VERSION 3.12) +project(ADIOS2HelloBPReaderExample) -if(ADIOS2_HAVE_Fortran) - add_executable(hello_bpReaderHeatMap3D_f helloBPReaderHeatMap3D.F90) - set_property(TARGET hello_bpReaderHeatMap3D_f PROPERTY LINKER_LANGUAGE Fortran) - target_link_libraries(hello_bpReaderHeatMap3D_f adios2::fortran) +if(NOT TARGET adios2::cxx11) + set(_components C) + + include(CheckLanguage) + check_language(Fortran) + if(CMAKE_Fortran_COMPILER) + enable_language(Fortran) + endif() + if(CMAKE_Fortran_COMPILER_LOADED) + list(APPEND _components Fortran) + endif() + + find_package(MPI COMPONENTS ${_components}) + if(MPI_FOUND) + # Workaround for various MPI implementations forcing the link of C++ bindings + add_definitions(-DOMPI_SKIP_MPICXX -DMPICH_SKIP_MPICXX) + + list(APPEND _components MPI) + endif() + list(APPEND _components CXX) + + find_package(ADIOS2 REQUIRED COMPONENTS ${_components}) endif() +add_executable(adios2_hello_bpReader bpReader.cpp) +target_link_libraries(adios2_hello_bpReader adios2::cxx11) +install(TARGETS adios2_hello_bpReader RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + if(ADIOS2_HAVE_MPI) - add_executable(hello_bpReader_mpi helloBPReader.cpp) - target_link_libraries(hello_bpReader_mpi adios2::cxx11_mpi MPI::MPI_C) - - add_executable(hello_bpReaderHeatMap2D helloBPReaderHeatMap2D.cpp) - target_link_libraries(hello_bpReaderHeatMap2D adios2::cxx11_mpi MPI::MPI_C) - - add_executable(hello_bpReaderHeatMap3D helloBPReaderHeatMap3D.cpp) - target_link_libraries(hello_bpReaderHeatMap3D adios2::cxx11_mpi MPI::MPI_C) - - if(ADIOS2_HAVE_Fortran) - add_executable(hello_bpReaderHeatMap3D_f_mpi helloBPReaderHeatMap3D.F90) - target_link_libraries(hello_bpReaderHeatMap3D_f_mpi adios2::fortran_mpi MPI::MPI_Fortran) - set_property(TARGET hello_bpReaderHeatMap3D_f_mpi PROPERTY LINKER_LANGUAGE Fortran) + add_executable(adios2_hello_bpReader_mpi bpReader.cpp) + target_link_libraries(adios2_hello_bpReader_mpi adios2::cxx11_mpi MPI::MPI_C) + install(TARGETS adios2_hello_bpReader_mpi RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + + add_executable(adios2_hello_bpReaderHeatMap2D bpReaderHeatMap2D.cpp) + target_link_libraries(adios2_hello_bpReaderHeatMap2D adios2::cxx11_mpi MPI::MPI_C) + install(TARGETS adios2_hello_bpReaderHeatMap2D RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + + add_executable(adios2_hello_bpReaderHeatMap3D bpReaderHeatMap3D.cpp) + target_link_libraries(adios2_hello_bpReaderHeatMap3D adios2::cxx11_mpi MPI::MPI_C) + install(TARGETS adios2_hello_bpReaderHeatMap3D RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) +endif() + +if(ADIOS2_HAVE_Fortran) + add_executable(adios2_hello_bpReaderHeatMap3D_f bpReaderHeatMap3D.F90) + target_link_libraries(adios2_hello_bpReaderHeatMap3D_f adios2::fortran) + install(TARGETS adios2_hello_bpReaderHeatMap3D_f RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + + if(ADIOS2_HAVE_MPI) + add_executable(adios2_hello_bpReaderHeatMap3D_f_mpi bpReaderHeatMap3D.F90) + target_link_libraries(adios2_hello_bpReaderHeatMap3D_f_mpi adios2::fortran_mpi MPI::MPI_Fortran) + install(TARGETS adios2_hello_bpReaderHeatMap3D_f_mpi RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) endif() endif() diff --git a/examples/hello/bpReader/helloBPReader.cpp b/examples/hello/bpReader/bpReader.cpp similarity index 79% rename from examples/hello/bpReader/helloBPReader.cpp rename to examples/hello/bpReader/bpReader.cpp index 9da7f3c83e..a987faeba8 100644 --- a/examples/hello/bpReader/helloBPReader.cpp +++ b/examples/hello/bpReader/bpReader.cpp @@ -2,18 +2,17 @@ * Distributed under the OSI-approved Apache License, Version 2.0. See * accompanying file Copyright.txt for details. * - * helloBPReader.cpp: Simple self-descriptive example of how to read a variable - * to a BP File. - * - * Try running like this from the build directory: - * mpirun -np 3 ./bin/hello_bpReader + * bpReader.cpp: Simple self-descriptive example of how to read a variable + * from a BP File. * * Created on: Feb 16, 2017 * Author: William F Godoy godoywf@ornl.gov */ #include //std::ios_base::failure #include //std::cout +#if ADIOS2_USE_MPI #include +#endif #include //std::invalid_argument std::exception #include @@ -21,26 +20,36 @@ int main(int argc, char *argv[]) { - int provided; + int rank, size; +#if ADIOS2_USE_MPI + int provided; // MPI_THREAD_MULTIPLE is only required if you enable the SST MPI_DP MPI_Init_thread(&argc, &argv, MPI_THREAD_MULTIPLE, &provided); - int rank, size; MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &size); - std::string filename = "myVector_cpp.bp"; +#else + rank = 0; + size = 1; +#endif + std::cout << "rank " << rank << " size " << size << "\n"; try { +#if ADIOS2_USE_MPI /** ADIOS class factory of IO class objects */ adios2::ADIOS adios(MPI_COMM_WORLD); +#else + adios2::ADIOS adios; +#endif /*** IO class object: settings and factory of Settings: Variables, * Parameters, Transports, and Execution: Engines */ - adios2::IO bpIO = adios.DeclareIO("ReadBP"); + adios2::IO bpIO = adios.DeclareIO("BPFile_N2N"); /** Engine derived class, spawned to start IO operations */ - adios2::Engine bpReader = bpIO.Open(filename, adios2::Mode::Read); + adios2::Engine bpReader = bpIO.Open("myVector_cpp.bp", adios2::Mode::Read); + bpReader.BeginStep(); const std::map variables = bpIO.AvailableVariables(); for (const auto &variablePair : variables) @@ -65,7 +74,7 @@ int main(int argc, char *argv[]) // read only the chunk corresponding to our rank bpFloats.SetSelection({{Nx * rank}, {Nx}}); // myFloats.data is pre-allocated - bpReader.Get(bpFloats, myFloats, adios2::Mode::Sync); + bpReader.Get(bpFloats, myFloats, adios2::Mode::Sync); if (rank == 0) { @@ -84,7 +93,7 @@ int main(int argc, char *argv[]) // read only the chunk corresponding to our rank bpInts.SetSelection({{Nx * rank}, {Nx}}); - bpReader.Get(bpInts, myInts, adios2::Mode::Sync); + bpReader.Get(bpInts, myInts, adios2::Mode::Sync); if (rank == 0) { @@ -96,6 +105,7 @@ int main(int argc, char *argv[]) std::cout << "\n"; } } + bpReader.EndStep(); /** Close bp file, engine becomes unreachable after this*/ bpReader.Close(); @@ -107,7 +117,9 @@ int main(int argc, char *argv[]) std::cerr << "Invalid argument exception, STOPPING PROGRAM from rank " << rank << "\n"; std::cerr << e.what() << "\n"; } +#if ADIOS2_USE_MPI MPI_Abort(MPI_COMM_WORLD, 1); +#endif } catch (std::ios_base::failure &e) { @@ -117,12 +129,14 @@ int main(int argc, char *argv[]) "from rank " << rank << "\n"; std::cerr << e.what() << "\n"; - std::cerr << "The file " << filename << " does not exist." - << " Presumably this is because hello_bpWriter has not " + std::cerr << "The file myVector_cpp.bp does not exist." + << " Presumably this is because adios2_hello_bpWriter has not " "been run." - << " Run ./hello_bpWriter before running this program.\n"; + << " Run ./adios2_hello_bpWriter before running this program.\n"; } +#if ADIOS2_USE_MPI MPI_Abort(MPI_COMM_WORLD, 1); +#endif } catch (std::exception &e) { @@ -131,10 +145,14 @@ int main(int argc, char *argv[]) std::cerr << "Exception, STOPPING PROGRAM from rank " << rank << "\n"; std::cerr << e.what() << "\n"; } +#if ADIOS2_USE_MPI MPI_Abort(MPI_COMM_WORLD, 1); +#endif } +#if ADIOS2_USE_MPI MPI_Finalize(); +#endif return 0; } diff --git a/examples/hello/bpReader/helloBPReaderHeatMap2D.cpp b/examples/hello/bpReader/bpReaderHeatMap2D.cpp similarity index 95% rename from examples/hello/bpReader/helloBPReaderHeatMap2D.cpp rename to examples/hello/bpReader/bpReaderHeatMap2D.cpp index 184d5730c2..17a5ecbc08 100644 --- a/examples/hello/bpReader/helloBPReaderHeatMap2D.cpp +++ b/examples/hello/bpReader/bpReaderHeatMap2D.cpp @@ -2,7 +2,7 @@ * 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, + * bpReaderHeatMap2D.cpp : Writes a heat map in a regular 2D mesh, * values grow from 0 in increments of 1 * * temperature[gNx, Ny] @@ -75,7 +75,9 @@ int main(int argc, char *argv[]) /** Will create HeatMap.bp */ adios2::Engine bpWriter = putHeatMap.Open("HeatMap2D.bp", adios2::Mode::Write); + bpWriter.BeginStep(); bpWriter.Put(outTemperature, temperatures.data()); + bpWriter.EndStep(); bpWriter.Close(); // ************************** READ @@ -85,6 +87,7 @@ int main(int argc, char *argv[]) adios2::Engine bpReader = getHeatMap.Open("HeatMap2D.bp", adios2::Mode::Read, MPI_COMM_SELF); + bpReader.BeginStep(); // this just discovers in the metadata file that the variable exists adios2::Variable inTemperature = getHeatMap.InquireVariable("temperature"); @@ -111,6 +114,7 @@ int main(int argc, char *argv[]) } std::cout << "\n"; } + bpReader.EndStep(); bpReader.Close(); } diff --git a/examples/hello/bpReader/helloBPReaderHeatMap2D.py b/examples/hello/bpReader/bpReaderHeatMap2D.py similarity index 73% rename from examples/hello/bpReader/helloBPReaderHeatMap2D.py rename to examples/hello/bpReader/bpReaderHeatMap2D.py index 9aa8925a39..7400b65e10 100644 --- a/examples/hello/bpReader/helloBPReaderHeatMap2D.py +++ b/examples/hello/bpReader/bpReaderHeatMap2D.py @@ -2,7 +2,7 @@ # Distributed under the OSI-approved Apache License, Version 2.0. See # accompanying file Copyright.txt for details. # -# helloBPReaderHeatMap2D.py +# bpReaderHeatMap2D.py # # # Created on: Dec 5th, 2017 @@ -41,18 +41,23 @@ adios = adios2.ADIOS(comm) ioWrite = adios.DeclareIO("ioWriter") -varTemperature = ioWrite.DefineVariable("temperature2D", temperatures, shape, - start, count, adios2.ConstantDims) +varTemperature = ioWrite.DefineVariable( + "temperature2D", temperatures, shape, start, count, adios2.ConstantDims +) -obpStream = ioWrite.Open('HeatMap2D_py.bp', adios2.Mode.Write) +obpStream = ioWrite.Open("HeatMap2D_py.bp", adios2.Mode.Write) +obpStream.BeginStep() obpStream.Put(varTemperature, temperatures) +obpStream.EndStep() obpStream.Close() if rank == 0: ioRead = adios.DeclareIO("ioReader") - ibpStream = ioRead.Open('HeatMap2D_py.bp', adios2.Mode.Read, MPI.COMM_SELF) + ibpStream = ioRead.Open("HeatMap2D_py.bp", adios2.Mode.Read, MPI.COMM_SELF) + + ibpStream.BeginStep() var_inTemperature = ioRead.InquireVariable("temperature2D") @@ -60,17 +65,18 @@ var_inTemperature.SetSelection([[2, 2], [4, 4]]) inSize = var_inTemperature.SelectionSize() - print('Incoming size ' + str(inSize)) + print("Incoming size " + str(inSize)) inTemperatures = numpy.zeros(inSize, dtype=numpy.int) ibpStream.Get(var_inTemperature, inTemperatures, adios2.Mode.Sync) - print('Incoming temperature map') + print("Incoming temperature map") for i in range(0, inTemperatures.size): - print(str(inTemperatures[i]) + ' ') + print(str(inTemperatures[i]) + " ") if (i + 1) % 4 == 0: print() + ibpStream.EndStep() ibpStream.Close() diff --git a/examples/hello/bpReader/helloBPReaderHeatMap3D.F90 b/examples/hello/bpReader/bpReaderHeatMap3D.F90 similarity index 98% rename from examples/hello/bpReader/helloBPReaderHeatMap3D.F90 rename to examples/hello/bpReader/bpReaderHeatMap3D.F90 index e44d9c53bf..3bd7251e89 100644 --- a/examples/hello/bpReader/helloBPReaderHeatMap3D.F90 +++ b/examples/hello/bpReader/bpReaderHeatMap3D.F90 @@ -1,4 +1,4 @@ -program helloBPReaderHeatMap3D +program bpReaderHeatMap3D #if ADIOS2_USE_MPI use mpi #endif @@ -130,4 +130,4 @@ program helloBPReaderHeatMap3D call MPI_Finalize(ierr) #endif -end program helloBPReaderHeatMap3D +end program bpReaderHeatMap3D diff --git a/examples/hello/bpReader/helloBPReaderHeatMap3D.cpp b/examples/hello/bpReader/bpReaderHeatMap3D.cpp similarity index 97% rename from examples/hello/bpReader/helloBPReaderHeatMap3D.cpp rename to examples/hello/bpReader/bpReaderHeatMap3D.cpp index e0bbd331e5..a4f98fb5b8 100644 --- a/examples/hello/bpReader/helloBPReaderHeatMap3D.cpp +++ b/examples/hello/bpReader/bpReaderHeatMap3D.cpp @@ -87,7 +87,9 @@ int main(int argc, char *argv[]) /** Will create HeatMap3D.bp */ adios2::Engine bpWriter = putHeatMap.Open("HeatMap3D.bp", adios2::Mode::Write); + bpWriter.BeginStep(); bpWriter.Put(outTemperature, temperatures.data()); + bpWriter.EndStep(); bpWriter.Close(); // ************************** READ @@ -97,6 +99,7 @@ int main(int argc, char *argv[]) adios2::Engine bpReader = getHeatMap.Open("HeatMap3D.bp", adios2::Mode::Read, MPI_COMM_SELF); + bpReader.BeginStep(); // this just discovers in the metadata file that the variable exists adios2::Variable inTemperature = getHeatMap.InquireVariable("temperature"); @@ -124,6 +127,7 @@ int main(int argc, char *argv[]) } std::cout << "\n"; } + bpReader.EndStep(); bpReader.Close(); } diff --git a/examples/hello/bpReader/bpReader_tutorialSkeleton.cpp b/examples/hello/bpReader/bpReader_tutorialSkeleton.cpp new file mode 100644 index 0000000000..d0f4713ec3 --- /dev/null +++ b/examples/hello/bpReader/bpReader_tutorialSkeleton.cpp @@ -0,0 +1,76 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * bpReader.cpp: Simple self-descriptive example of how to read a variable + * from a BP File. + * + * Created on: Feb 16, 2017 + * Author: William F Godoy godoywf@ornl.gov + */ +#include //std::ios_base::failure +#include //std::cout +#include +#include //std::invalid_argument std::exception +#include + +#include + +int main(int argc, char *argv[]) +{ + int rank, size; + int provided; + + // Add code to init MPI + try + { + // Add code to create ADIOS object + + // Add code to create IO object + + // Add code to open file + + // Add code to inquire variables and optionally check all available variables + + // Add code to read variables + + // Add code to close file + } + catch (std::invalid_argument &e) + { + if (rank == 0) + { + std::cerr << "Invalid argument exception, STOPPING PROGRAM from rank " << rank << "\n"; + std::cerr << e.what() << "\n"; + } + MPI_Abort(MPI_COMM_WORLD, 1); + } + catch (std::ios_base::failure &e) + { + if (rank == 0) + { + std::cerr << "IO System base failure exception, STOPPING PROGRAM " + "from rank " + << rank << "\n"; + std::cerr << e.what() << "\n"; + std::cerr << "The file myVector_cpp.bp does not exist." + << " Presumably this is because adios2_hello_bpWriter has not " + "been run." + << " Run ./adios2_hello_bpWriter before running this program.\n"; + } + MPI_Abort(MPI_COMM_WORLD, 1); + } + catch (std::exception &e) + { + if (rank == 0) + { + std::cerr << "Exception, STOPPING PROGRAM from rank " << rank << "\n"; + std::cerr << e.what() << "\n"; + } + MPI_Abort(MPI_COMM_WORLD, 1); + } + + MPI_Finalize(); + + return 0; +} diff --git a/examples/hello/bpReader/helloBPReader_nompi.cpp b/examples/hello/bpReader/helloBPReader_nompi.cpp deleted file mode 100644 index 629fa2e1f9..0000000000 --- a/examples/hello/bpReader/helloBPReader_nompi.cpp +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Distributed under the OSI-approved Apache License, Version 2.0. See - * accompanying file Copyright.txt for details. - * - * helloBPReader.cpp: Simple self-descriptive example of how to read a variable - * from a BP File. - * - * Created on: Feb 16, 2017 - * Author: William F Godoy godoywf@ornl.gov - */ - -#include //std::ios_base::failure -#include //std::cout -#include //std::invalid_argument std::exception -#include - -#include - -int main(int argc, char *argv[]) -{ - std::string filename = "myVector_cpp.bp"; - - try - { - /** ADIOS class factory of IO class objects */ - adios2::ADIOS adios; - - /*** IO class object: settings and factory of Settings: Variables, - * Parameters, Transports, and Execution: Engines */ - adios2::IO bpIO = adios.DeclareIO("ReadBP"); - - /** Engine derived class, spawned to start IO operations */ - adios2::Engine bpReader = bpIO.Open(filename, adios2::Mode::Read); - - const std::map variables = bpIO.AvailableVariables(true); - - std::cout << "List of variables:"; - for (const auto &variablePair : variables) - { - std::cout << " " << variablePair.first; - } - std::cout << std::endl; - - /** Write variable for buffering */ - adios2::Variable bpFloats = bpIO.InquireVariable("bpFloats"); - - adios2::Variable bpInts = bpIO.InquireVariable("bpInts"); - - if (bpFloats) - { - std::vector myFloats; - bpReader.Get(bpFloats, myFloats, adios2::Mode::Sync); - std::cout << "Float vector inside " << filename << ": {"; - for (auto &x : myFloats) - { - std::cout << x << ", "; - } - std::cout << "}\n"; - } - - if (bpInts) - { - std::vector myInts; - bpReader.Get(bpInts, myInts, adios2::Mode::Sync); - } - else - { - std::cout << "There are no integer datasets in " << filename << ".\n"; - } - - /** Close bp file, engine becomes unreachable after this*/ - bpReader.Close(); - } - catch (std::invalid_argument &e) - { - std::cerr << "Invalid argument exception, STOPPING PROGRAM\n"; - std::cerr << e.what() << "\n"; - } - catch (std::ios_base::failure &e) - { - std::cerr << "IO System base failure exception, STOPPING PROGRAM\n"; - std::cerr << e.what() << "\n"; - std::cerr << "The file " << filename << " does not exist." - << " Presumably this is because hello_bpWriter has not been " - "run. Run ./hello_bpWriter before running this program.\n"; - } - catch (std::exception &e) - { - std::cerr << "Exception, STOPPING PROGRAM\n"; - std::cerr << e.what() << "\n"; - } - - return 0; -} diff --git a/examples/hello/bpStepsWriteRead/CMakeLists.txt b/examples/hello/bpStepsWriteRead/CMakeLists.txt new file mode 100644 index 0000000000..6acf9698dd --- /dev/null +++ b/examples/hello/bpStepsWriteRead/CMakeLists.txt @@ -0,0 +1,31 @@ +#------------------------------------------------------------------------------# +# Distributed under the OSI-approved Apache License, Version 2.0. See +# accompanying file Copyright.txt for details. +#------------------------------------------------------------------------------# + +cmake_minimum_required(VERSION 3.12) +project(ADIOS2HelloBPStepsWriteReadExample) + +if(NOT TARGET adios2_core) + set(_components CXX) + + find_package(MPI COMPONENTS C) + if(MPI_FOUND) + # Workaround for various MPI implementations forcing the link of C++ bindings + add_definitions(-DOMPI_SKIP_MPICXX -DMPICH_SKIP_MPICXX) + + list(APPEND _components MPI) + endif() + + find_package(ADIOS2 REQUIRED COMPONENTS ${_components}) +endif() + +add_executable(adios2_hello_bpStepsWriteRead bpStepsWriteRead.cpp) +target_link_libraries(adios2_hello_bpStepsWriteRead adios2::cxx11) +install(TARGETS adios2_hello_bpStepsWriteRead RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + +if(ADIOS2_HAVE_MPI) + add_executable(adios2_hello_bpStepsWriteRead_mpi bpStepsWriteRead.cpp) + target_link_libraries(adios2_hello_bpStepsWriteRead_mpi adios2::cxx11_mpi MPI::MPI_C) + install(TARGETS adios2_hello_bpStepsWriteRead_mpi RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) +endif() diff --git a/examples/hello/bpStepsWriteRead/bpStepsWriteRead.cpp b/examples/hello/bpStepsWriteRead/bpStepsWriteRead.cpp new file mode 100644 index 0000000000..e06a2e80da --- /dev/null +++ b/examples/hello/bpStepsWriteRead/bpStepsWriteRead.cpp @@ -0,0 +1,154 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * bpStepsWriteRead.cpp Simple example of writing and reading data through ADIOS2 BP engine with + * multiple simulations steps for every IO step. + * + * Created on: Feb 16, 2017 + * Author: William F Godoy godoywf@ornl.gov + */ + +#include // std::for_each +#include // std::ios_base::failure +#include // std::cout +#if ADIOS2_USE_MPI +#include +#endif +#include //std::invalid_argument std::exception +#include + +#include + +void update_array(std::vector &array, int val) +{ + std::transform(array.begin(), array.end(), array.begin(), + [val](float v) -> float { return v + static_cast(val); }); +} + +void writer(adios2::ADIOS &adios, const std::string &engine, const std::string &fname, + const size_t Nx, unsigned int nSteps, int rank, int size) +{ + std::vector simData(Nx, 0); + + adios2::IO bpIO = adios.DeclareIO("WriteIO"); + bpIO.SetEngine(engine); + + const adios2::Dims shape{static_cast(size * Nx)}; + const adios2::Dims start{static_cast(rank * Nx)}; + const adios2::Dims count{Nx}; + auto bpFloats = bpIO.DefineVariable("bpFloats", shape, start, count); + + auto bpStep = bpIO.DefineVariable("bpStep"); + + adios2::Engine bpWriter = bpIO.Open(fname, adios2::Mode::Write); + + for (unsigned int step = 0; step < nSteps; ++step) + { + const adios2::Box sel({0}, {Nx}); + bpFloats.SetSelection(sel); + + bpWriter.BeginStep(); + bpWriter.Put(bpFloats, simData.data()); + bpWriter.Put(bpStep, step); + bpWriter.EndStep(); + + // Update values in the simulation data + update_array(simData, 10); + } + + bpWriter.Close(); +} + +void reader(adios2::ADIOS &adios, const std::string &engine, const std::string &fname, + const size_t Nx, unsigned int /*nSteps*/, int rank, int /*size*/) +{ + adios2::IO bpIO = adios.DeclareIO("ReadIO"); + bpIO.SetEngine(engine); + + adios2::Engine bpReader = bpIO.Open(fname, adios2::Mode::Read); + + std::vector simData(Nx, 0); + unsigned int inStep = 0; + for (unsigned int step = 0; bpReader.BeginStep() == adios2::StepStatus::OK; ++step) + { + auto bpFloats = bpIO.InquireVariable("bpFloats"); + if (bpFloats) + { + const adios2::Box sel({{Nx * rank}, {Nx}}); + bpFloats.SetSelection(sel); + bpReader.Get(bpFloats, simData.data()); + } + auto bpStep = bpIO.InquireVariable("bpStep"); + if (bpStep) + { + bpReader.Get(bpStep, &inStep); + } + + bpReader.EndStep(); + if (inStep != step) + { + std::cout << "ERROR: step mismatch\n"; + return; + } + } + bpReader.Close(); +} + +int main(int argc, char *argv[]) +{ + int rank, size; + +#if ADIOS2_USE_MPI + int provided; + // MPI_THREAD_MULTIPLE is only required if you enable the SST MPI_DP + MPI_Init_thread(&argc, &argv, MPI_THREAD_MULTIPLE, &provided); + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + MPI_Comm_size(MPI_COMM_WORLD, &size); +#else + rank = 0; + size = 1; +#endif + + const std::string engine = argv[1] ? argv[1] : "BPFile"; + std::cout << "Using engine " << engine << std::endl; + + const std::string filename = engine + "StepsWriteRead.bp"; + const unsigned int nSteps = 10; + const unsigned int Nx = 60000; + try + { + /** ADIOS class factory of IO class objects */ +#if ADIOS2_USE_MPI + adios2::ADIOS adios(MPI_COMM_WORLD); +#else + adios2::ADIOS adios; +#endif + + writer(adios, engine, filename, Nx, nSteps, rank, size); + reader(adios, engine, filename, Nx, nSteps, rank, size); + } + catch (std::invalid_argument &e) + { + std::cout << "Invalid argument exception, STOPPING PROGRAM from rank " << rank << "\n"; + std::cout << e.what() << "\n"; + } + catch (std::ios_base::failure &e) + { + std::cout << "IO System base failure exception, STOPPING PROGRAM " + "from rank " + << rank << "\n"; + std::cout << e.what() << "\n"; + } + catch (std::exception &e) + { + std::cout << "Exception, STOPPING PROGRAM from rank " << rank << "\n"; + std::cout << e.what() << "\n"; + } + +#if ADIOS2_USE_MPI + MPI_Finalize(); +#endif + + return 0; +} diff --git a/examples/hello/bpStepsWriteRead/bpStepsWriteRead_tutorialSkeleton.cxx b/examples/hello/bpStepsWriteRead/bpStepsWriteRead_tutorialSkeleton.cxx new file mode 100644 index 0000000000..faceff681d --- /dev/null +++ b/examples/hello/bpStepsWriteRead/bpStepsWriteRead_tutorialSkeleton.cxx @@ -0,0 +1,98 @@ +/* +* Distributed under the OSI-approved Apache License, Version 2.0. See +* accompanying file Copyright.txt for details. +* +* bpStepsWriteRead.cpp Simple example of writing and reading data through ADIOS2 BP engine with +* multiple simulations steps for every IO step. +* +* Created on: Feb 16, 2017 +* Author: William F Godoy godoywf@ornl.gov + */ + +#include //std::for_each +#include //std::ios_base::failure +#include //std::cout +#include +#include //std::invalid_argument std::exception +#include + +#include + +void update_array(std::vector &array, int val) +{ + std::transform(array.begin(), array.end(), array.begin(), + [val](float v) -> float { return v + static_cast(val); }); +} + +void writer(adios2::ADIOS &adios, const std::string &engine, const std::string &fname, + const size_t Nx, unsigned int nSteps, int rank, int size) +{ + // Add code to create the simulation data + + // Add code to create ADIOS io and set engine type + + // Add code to define sim data variable + + // Add code to define step variable + + // Add code to open file + + // Add code to write data across multiple steps, and update the simulation data + + // Add code to close file +} + +void reader(adios2::ADIOS &adios, const std::string &engine, const std::string &fname, + const size_t Nx, unsigned int /*nSteps*/, int rank, int /*size*/) +{ + // Add code to create ADIOS io and set engine type + + // Add code to open file + + // Add code to create variable for sim data and step + + // Add code to read data across multiple steps + + // Add code to close file +} + +int main(int argc, char *argv[]) +{ + int rank, size; + int provided; + + // Add code to initialize MPI + + const std::string engine = argv[1] ? argv[1] : "BPFile"; + std::cout << "Using engine " << engine << std::endl; + + // Add Code to set filename, nSteps, Nx + try + { + // Add code to create ADIOS object + + // Add code to call writer + // Add code to call reader + } + catch (std::invalid_argument &e) + { + std::cout << "Invalid argument exception, STOPPING PROGRAM from rank " << rank << "\n"; + std::cout << e.what() << "\n"; + } + catch (std::ios_base::failure &e) + { + std::cout << "IO System base failure exception, STOPPING PROGRAM " + "from rank " + << rank << "\n"; + std::cout << e.what() << "\n"; + } + catch (std::exception &e) + { + std::cout << "Exception, STOPPING PROGRAM from rank " << rank << "\n"; + std::cout << e.what() << "\n"; + } + + // Add code to finalize MPI + + return 0; +} diff --git a/examples/hello/bpStepsWriteReadCuda/CMakeLists.txt b/examples/hello/bpStepsWriteReadCuda/CMakeLists.txt new file mode 100644 index 0000000000..590adb671a --- /dev/null +++ b/examples/hello/bpStepsWriteReadCuda/CMakeLists.txt @@ -0,0 +1,25 @@ +#------------------------------------------------------------------------------# +# Distributed under the OSI-approved Apache License, Version 2.0. See +# accompanying file Copyright.txt for details. +#------------------------------------------------------------------------------# + +cmake_minimum_required(VERSION 3.12) +project(ADIOS2HelloBPStepsWriteReadCudaExample) + +if(NOT TARGET adios2_core) + set(_components CXX) + + find_package(CUDAToolkit REQUIRED) + if(CUDAToolkit_FOUND) + enable_language(CUDA) + endif() + + find_package(ADIOS2 REQUIRED COMPONENTS ${_components}) +endif() + +if(ADIOS2_HAVE_CUDA OR ADIOS2_HAVE_Kokkos_CUDA) + add_executable(adios2_hello_bpStepsWriteReadCuda bpStepsWriteReadCuda.cu) + target_link_libraries(adios2_hello_bpStepsWriteReadCuda PUBLIC adios2::cxx11 CUDA::cudart) + set_target_properties(adios2_hello_bpStepsWriteReadCuda PROPERTIES CUDA_SEPARABLE_COMPILATION ON) + install(TARGETS adios2_hello_bpStepsWriteReadCuda RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) +endif() diff --git a/examples/hello/bpStepsWriteReadCuda/bpStepsWriteReadCuda.cu b/examples/hello/bpStepsWriteReadCuda/bpStepsWriteReadCuda.cu new file mode 100644 index 0000000000..5d911e64cf --- /dev/null +++ b/examples/hello/bpStepsWriteReadCuda/bpStepsWriteReadCuda.cu @@ -0,0 +1,142 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * bpStepsWriteReadCuda.cu Simple example of writing and reading data through ADIOS2 BP engine with + * multiple simulations steps for every IO step using CUDA + */ + +#include +#include +#include //std::invalid_argument std::exception +#include +#include + +#include + +#include + +__global__ void update_array(float *vect, int val) { vect[blockIdx.x] += val; } + +void writer(adios2::ADIOS &adios, const std::string &engine, const std::string &fname, + const size_t Nx, unsigned int nSteps) +{ + // Initialize the simulation data + float *gpuSimData; + cudaMalloc(&gpuSimData, Nx * sizeof(float)); + cudaMemset(gpuSimData, 0, Nx); + + // Set up the ADIOS structures + adios2::IO bpIO = adios.DeclareIO("WriteIO"); + bpIO.SetEngine(engine); + + // Declare an array for the ADIOS data of size (NumOfProcesses * Nx) + const adios2::Dims shape{static_cast(Nx)}; + const adios2::Dims start{static_cast(0)}; + const adios2::Dims count{Nx}; + auto bpFloats = bpIO.DefineVariable("bpFloats", shape, start, count); + auto bpStep = bpIO.DefineVariable("bpStep"); + + adios2::Engine bpWriter = bpIO.Open(fname, adios2::Mode::Write); + + // Simulation steps + for (unsigned int step = 0; step < nSteps; ++step) + { + // Make a 1D selection to describe the local dimensions of the + // variable we write and its offsets in the global spaces + const adios2::Box sel({0}, {Nx}); + bpFloats.SetSelection(sel); + + // Start IO step every write step + bpWriter.BeginStep(); + bpFloats.SetMemorySpace(adios2::MemorySpace::GPU); + bpWriter.Put(bpFloats, gpuSimData); + bpWriter.Put(bpStep, step); + bpWriter.EndStep(); + + // Update values in the simulation data + update_array<<>>(gpuSimData, 10); + } + + bpWriter.Close(); +} + +void reader(adios2::ADIOS &adios, const std::string &engine, const std::string &fname, + const size_t Nx, unsigned int /*nSteps*/) +{ + // Create ADIOS structures + adios2::IO bpIO = adios.DeclareIO("ReadIO"); + bpIO.SetEngine(engine); + + adios2::Engine bpReader = bpIO.Open(fname, adios2::Mode::Read); + + unsigned int inStep = 0; + float *gpuSimData; + cudaMalloc(&gpuSimData, Nx * sizeof(float)); + cudaMemset(gpuSimData, 0, Nx); + for (unsigned int step = 0; bpReader.BeginStep() == adios2::StepStatus::OK; ++step) + { + auto bpFloats = bpIO.InquireVariable("bpFloats"); + if (bpFloats) + { + const adios2::Dims start{0}; + const adios2::Dims count{Nx}; + const adios2::Box sel(start, count); + bpFloats.SetSelection(sel); + + bpFloats.SetMemorySpace(adios2::MemorySpace::GPU); + bpReader.Get(bpFloats, gpuSimData); //, adios2::Mode::Deferred); + } + auto bpStep = bpIO.InquireVariable("bpStep"); + if (bpStep) + { + bpReader.Get(bpStep, &inStep); + } + + bpReader.EndStep(); + if (inStep != step) + { + std::cout << "ERROR: step mismatch\n"; + return; + } + } + bpReader.Close(); +} + +int main(int argc, char **argv) +{ + const int device_id = 1; + cudaSetDevice(device_id); + + const std::string engine = argv[1] ? argv[1] : "BPFile"; + std::cout << "Using engine " << engine << std::endl; + + const std::string filename = engine + "StepsWriteReadCuda.bp"; + const unsigned int nSteps = 10; + const unsigned int Nx = 6000; + try + { + /** ADIOS class factory of IO class objects */ + adios2::ADIOS adios; + + writer(adios, engine, filename, Nx, nSteps); + reader(adios, engine, filename, Nx, nSteps); + } + catch (std::invalid_argument &e) + { + std::cout << "Invalid argument exception, STOPPING PROGRAM\n"; + std::cout << e.what() << "\n"; + } + catch (std::ios_base::failure &e) + { + std::cout << "IO System base failure exception, STOPPING PROGRAM\n"; + std::cout << e.what() << "\n"; + } + catch (std::exception &e) + { + std::cout << "Exception, STOPPING PROGRAM\n"; + std::cout << e.what() << "\n"; + } + + return 0; +} diff --git a/examples/hello/bpStepsWriteReadHip/CMakeLists.txt b/examples/hello/bpStepsWriteReadHip/CMakeLists.txt new file mode 100644 index 0000000000..3762c25b94 --- /dev/null +++ b/examples/hello/bpStepsWriteReadHip/CMakeLists.txt @@ -0,0 +1,21 @@ +#------------------------------------------------------------------------------# +# Distributed under the OSI-approved Apache License, Version 2.0. See +# accompanying file Copyright.txt for details. +#------------------------------------------------------------------------------# + +cmake_minimum_required(VERSION 3.12) +project(ADIOS2HelloBPStepsWriteReadHipExample) + +if(NOT TARGET adios2_core) + find_package(ADIOS2 REQUIRED COMPONENTS CXX) +endif() + +enable_language(HIP) + +# Needed for the hip cmake targets +find_package(hip REQUIRED) + +add_executable(adios2_hello_bpStepsWriteReadHip bpStepsWriteReadHip.cpp) +target_link_libraries(adios2_hello_bpStepsWriteReadHip adios2::cxx11 hip::device) +set_source_files_properties(bpStepsWriteReadHip.cpp PROPERTIES LANGUAGE HIP) +install(TARGETS adios2_hello_bpStepsWriteReadHip RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) diff --git a/examples/hello/bpStepsWriteReadHip/bpStepsWriteReadHip.cpp b/examples/hello/bpStepsWriteReadHip/bpStepsWriteReadHip.cpp new file mode 100644 index 0000000000..12fe720d51 --- /dev/null +++ b/examples/hello/bpStepsWriteReadHip/bpStepsWriteReadHip.cpp @@ -0,0 +1,161 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * bpStepsWriteReadHip.cpp Simple example of writing and reading bpFloats through ADIOS2 BP engine + * with multiple simulations steps for every IO step using HIP + */ +#include +#include +#include +#include //std::invalid_argument std::exception +#include + +#include + +#include + +__global__ void hip_initialize(float *vec) { vec[hipBlockIdx_x] = hipBlockIdx_x; } + +__global__ void hip_increment(float *vec, float val) { vec[hipBlockIdx_x] += val; } + +void writer(adios2::ADIOS &adios, const std::string &engine, const std::string &fname, + const size_t Nx, unsigned int nSteps) +{ + hipError_t hipExit; + float *gpuSimData; + hipExit = hipMalloc((void **)&gpuSimData, Nx * sizeof(float)); + if (hipExit != hipSuccess) + { + std::cout << "[BPWrite] error: " << hipGetErrorString(hipExit) << std::endl; + return; + } + hipLaunchKernelGGL(hip_initialize, dim3(Nx), dim3(1), 0, 0, gpuSimData); + hipExit = hipDeviceSynchronize(); + if (hipExit != hipSuccess) + { + std::cout << "[BPWrite] error: " << hipGetErrorString(hipExit) << std::endl; + return; + } + + adios2::IO bpIO = adios.DeclareIO("WriteIO"); + bpIO.SetEngine(engine); + + const adios2::Dims shape{static_cast(Nx)}; + const adios2::Dims start{static_cast(0)}; + const adios2::Dims count{Nx}; + auto bpFloats = bpIO.DefineVariable("bpFloats", shape, start, count); + auto bpStep = bpIO.DefineVariable("bpStep"); + + adios2::Engine bpWriter = bpIO.Open(fname, adios2::Mode::Write); + + for (unsigned int step = 0; step < nSteps; ++step) + { + const adios2::Box sel({0}, {Nx}); + bpFloats.SetSelection(sel); + + bpWriter.BeginStep(); + bpWriter.Put(bpFloats, gpuSimData); + bpWriter.Put(bpStep, step); + bpWriter.EndStep(); + + hipLaunchKernelGGL(hip_increment, dim3(Nx), dim3(1), 0, 0, gpuSimData, 10); + hipExit = hipDeviceSynchronize(); + if (hipExit != hipSuccess) + { + std::cout << "[BPWrite] error: " << hipGetErrorString(hipExit) << std::endl; + return; + } + } + + bpWriter.Close(); +} + +void reader(adios2::ADIOS &adios, const std::string &engine, const std::string &fname, + const size_t Nx, unsigned int /*nSteps*/) +{ + hipError_t hipExit; + adios2::IO bpIO = adios.DeclareIO("ReadIO"); + bpIO.SetEngine(engine); + + adios2::Engine bpReader = bpIO.Open(fname, adios2::Mode::Read); + + unsigned int inStep = 0; + float *gpuSimData; + hipExit = hipMalloc((void **)&gpuSimData, Nx * sizeof(float)); + if (hipExit != hipSuccess) + { + std::cout << "[BPWrite] error: " << hipGetErrorString(hipExit) << std::endl; + return; + } + for (unsigned int step = 0; bpReader.BeginStep() == adios2::StepStatus::OK; ++step) + { + auto bpFloats = bpIO.InquireVariable("bpFloats"); + if (bpFloats) + { + const adios2::Dims start{0}; + const adios2::Dims count{Nx}; + const adios2::Box sel(start, count); + bpFloats.SetSelection(sel); + bpFloats.SetMemorySpace(adios2::MemorySpace::GPU); + bpReader.Get(bpFloats, gpuSimData); + } + auto bpStep = bpIO.InquireVariable("bpStep"); + if (bpStep) + { + bpReader.Get(bpStep, &inStep); + } + + bpReader.EndStep(); + if (inStep != step) + { + std::cout << "ERROR: step mismatch\n"; + return; + } + } + bpReader.Close(); +} + +int main(int argc, char **argv) +{ + hipError_t hipExit; + const int device_id = 0; + hipExit = hipSetDevice(device_id); + if (hipExit != hipSuccess) + { + std::cout << "[BPWrite] error: " << hipGetErrorString(hipExit) << std::endl; + return 1; + } + + const std::string engine = argv[1] ? argv[1] : "BPFile"; + std::cout << "Using engine " << engine << std::endl; + + const std::string filename = engine + "StepsWriteReadHip.bp"; + const unsigned int nSteps = 10; + const unsigned int Nx = 6000; + try + { + /** ADIOS class factory of IO class objects */ + adios2::ADIOS adios; + + writer(adios, engine, filename, Nx, nSteps); + reader(adios, engine, filename, Nx, nSteps); + } + catch (std::invalid_argument &e) + { + std::cout << "Invalid argument exception, STOPPING PROGRAM\n"; + std::cout << e.what() << "\n"; + } + catch (std::ios_base::failure &e) + { + std::cout << "IO System base failure exception, STOPPING PROGRAM\n"; + std::cout << e.what() << "\n"; + } + catch (std::exception &e) + { + std::cout << "Exception, STOPPING PROGRAM\n"; + std::cout << e.what() << "\n"; + } + + return 0; +} diff --git a/examples/hello/bpStepsWriteReadKokkos/CMakeLists.txt b/examples/hello/bpStepsWriteReadKokkos/CMakeLists.txt new file mode 100644 index 0000000000..c420e6e762 --- /dev/null +++ b/examples/hello/bpStepsWriteReadKokkos/CMakeLists.txt @@ -0,0 +1,33 @@ +#------------------------------------------------------------------------------# +# Distributed under the OSI-approved Apache License, Version 2.0. See +# accompanying file Copyright.txt for details. +#------------------------------------------------------------------------------# + +cmake_minimum_required(VERSION 3.12) +project(ADIOS2HelloBPStepsWriteReadKokkosExample) + +# CXX Compiler settings only in for this example +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +if(NOT TARGET adios2_core) + set(_components CXX) + + find_package(Kokkos 3.7 QUIET) + if(Kokkos_FOUND AND DEFINED Kokkos_CXX_COMPILER) + set(CMAKE_CXX_COMPILER "${Kokkos_CXX_COMPILER}") + endif() + + find_package(ADIOS2 REQUIRED COMPONENTS ${_components}) +else() + if(DEFINED Kokkos_CXX_COMPILER) + set(CMAKE_CXX_COMPILER "${Kokkos_CXX_COMPILER}") + endif() +endif() + +if(ADIOS2_HAVE_Kokkos) + add_executable(adios2_hello_bpStepsWriteReadKokkos bpStepsWriteReadKokkos.cpp) + kokkos_compilation(SOURCE bpStepsWriteReadKokkos.cpp) + target_link_libraries(adios2_hello_bpStepsWriteReadKokkos adios2::cxx11 Kokkos::kokkos) + install(TARGETS adios2_hello_bpStepsWriteReadKokkos RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) +endif() diff --git a/examples/hello/bpStepsWriteReadKokkos/bpStepsWriteReadKokkos.cpp b/examples/hello/bpStepsWriteReadKokkos/bpStepsWriteReadKokkos.cpp new file mode 100644 index 0000000000..268d75adf3 --- /dev/null +++ b/examples/hello/bpStepsWriteReadKokkos/bpStepsWriteReadKokkos.cpp @@ -0,0 +1,146 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * bpStepsWriteReadKokkos.cpp Simple example of writing and reading bpFloats through ADIOS2 BP + * engine with multiple simulations steps for every IO step using Kokkos + */ +#include +#include +#include //std::invalid_argument std::exception +#include + +#include + +#include + +void writer(adios2::ADIOS &adios, const std::string &engine, const std::string &fname, + const size_t Nx, unsigned int nSteps) +{ + // Initialize the simulation bpFloats with the default memory space + using mem_space = Kokkos::DefaultExecutionSpace::memory_space; + Kokkos::View gpuSimData("simBuffer", Nx); + Kokkos::parallel_for( + "initBuffer", Kokkos::RangePolicy(0, Nx), + KOKKOS_LAMBDA(int i) { gpuSimData(i) = static_cast(i); }); + Kokkos::fence(); + + // Set up the ADIOS structures + adios2::IO bpIO = adios.DeclareIO("WriteIO"); + bpIO.SetEngine(engine); + + const adios2::Dims shape{static_cast(Nx)}; + const adios2::Dims start{static_cast(0)}; + const adios2::Dims count{Nx}; + auto bpFloats = bpIO.DefineVariable("bpFloats", shape, start, count); + auto bpStep = bpIO.DefineVariable("bpStep"); + + adios2::Engine bpWriter = bpIO.Open(fname, adios2::Mode::Write); + + // Simulation steps + for (unsigned int step = 0; step < nSteps; ++step) + { + // Make a 1D selection to describe the local dimensions of the + // variable we write and its offsets in the global spaces + adios2::Box sel({0}, {Nx}); + bpFloats.SetSelection(sel); + + // Start IO step every write step + bpWriter.BeginStep(); + bpWriter.Put(bpFloats, gpuSimData.data()); + bpWriter.Put(bpStep, step); + bpWriter.EndStep(); + + // Update values in the simulation bpFloats using the default + // execution space + Kokkos::parallel_for( + "updateBuffer", Kokkos::RangePolicy(0, Nx), + KOKKOS_LAMBDA(int i) { gpuSimData(i) += 10; }); + Kokkos::fence(); + } + + bpWriter.Close(); + Kokkos::DefaultExecutionSpace exe_space; + std::cout << "Done writing on memory space: " << exe_space.name() << std::endl; +} + +void reader(adios2::ADIOS &adios, const std::string &engine, const std::string &fname, + const size_t Nx, unsigned int /*nSteps*/) +{ + // Create ADIOS structures + adios2::IO bpIO = adios.DeclareIO("ReadIO"); + bpIO.SetEngine(engine); + + Kokkos::DefaultExecutionSpace exe_space; + std::cout << "Read on memory space: " << exe_space.name() << std::endl; + + adios2::Engine bpReader = bpIO.Open(fname, adios2::Mode::Read); + + using mem_space = Kokkos::DefaultExecutionSpace::memory_space; + Kokkos::View gpuSimData("simBuffer", Nx); + unsigned int inStep = 0; + for (unsigned int step = 0; bpReader.BeginStep() == adios2::StepStatus::OK; ++step) + { + auto bpFloats = bpIO.InquireVariable("bpFloats"); + if (bpFloats) + { + const adios2::Dims start{0}; + const adios2::Dims count{Nx}; + const adios2::Box sel(start, count); + bpFloats.SetSelection(sel); + + bpReader.Get(bpFloats, gpuSimData.data()); + } + auto bpStep = bpIO.InquireVariable("bpStep"); + if (bpStep) + { + bpReader.Get(bpStep, &inStep); + } + bpReader.EndStep(); + if (inStep != step) + { + std::cout << "ERROR: step mismatch\n"; + return; + } + } + + bpReader.Close(); +} + +int main(int argc, char **argv) +{ + Kokkos::initialize(argc, argv); + + const std::string engine = argv[1] ? argv[1] : "BPFile"; + std::cout << "Using engine " << engine << std::endl; + + const std::string filename = engine + "StepsWriteReadCuda.bp"; + const unsigned int nSteps = 10; + const unsigned int Nx = 6000; + try + { + /** ADIOS class factory of IO class objects */ + adios2::ADIOS adios; + + writer(adios, engine, filename, Nx, nSteps); + reader(adios, engine, filename, Nx, nSteps); + } + catch (std::invalid_argument &e) + { + std::cout << "Invalid argument exception, STOPPING PROGRAM\n"; + std::cout << e.what() << "\n"; + } + catch (std::ios_base::failure &e) + { + std::cout << "IO System base failure exception, STOPPING PROGRAM\n"; + std::cout << e.what() << "\n"; + } + catch (std::exception &e) + { + std::cout << "Exception, STOPPING PROGRAM\n"; + std::cout << e.what() << "\n"; + } + Kokkos::finalize(); + + return 0; +} diff --git a/examples/hello/bpThreadWrite/CMakeLists.txt b/examples/hello/bpThreadWrite/CMakeLists.txt new file mode 100644 index 0000000000..bc7fd8fb1b --- /dev/null +++ b/examples/hello/bpThreadWrite/CMakeLists.txt @@ -0,0 +1,21 @@ +#------------------------------------------------------------------------------# +# Distributed under the OSI-approved Apache License, Version 2.0. See +# accompanying file Copyright.txt for details. +#------------------------------------------------------------------------------# + +cmake_minimum_required(VERSION 3.12) +project(ADIOS2HelloThreadWriteExample) + +if(NOT TARGET adios2_core) + set(_components CXX) + + find_package(Threads QUIET) + + find_package(ADIOS2 REQUIRED COMPONENTS ${_components}) +endif() + +if(Threads_FOUND) + add_executable(adios2_hello_bpThreadWrite bpThreadWrite.cpp) + target_link_libraries(adios2_hello_bpThreadWrite adios2::cxx11 ${CMAKE_THREAD_LIBS_INIT}) + install(TARGETS adios2_hello_bpThreadWrite RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) +endif() diff --git a/examples/hello/bpThreadWrite/bpThreadWrite.cpp b/examples/hello/bpThreadWrite/bpThreadWrite.cpp new file mode 100644 index 0000000000..4badac3239 --- /dev/null +++ b/examples/hello/bpThreadWrite/bpThreadWrite.cpp @@ -0,0 +1,124 @@ + +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * bpThreadWrite.cpp : adios2 low-level API example to write in a threaded + * application using C++11 thread and having adios2 calls + * inside mutex regions adios2 API are not thread-safe: + * 1. launching MPI from a thread is not possible on many + * supercomputers + * 2. I/O is highly serialized (buffering and low-level I/O + * calls), therefore users must be aware that adios2 might introduce + * bottlenecks. To run: Do not use MPI, just run the executable + * ./adios2_hello_bpThreadWrite + * + * Created on: Nov 14, 2019 + * Author: William F Godoy godoywf@ornl.gov + */ + +#include + +#include //std::size_t +#include +#include +#include +#include +#include + +namespace +{ + +std::mutex mutex; + +// tasks that runs on thread, each section of the vector is covered +template +void ThreadTask(const std::size_t threadID, std::vector &data, const std::size_t startIndex, + const std::size_t localSize, const std::string &variableName, adios2::IO io, + adios2::Engine engine) +{ + (void)threadID; // unused variable + // populate vector data, but simply adding step to index + for (std::size_t i = 0; i < localSize; ++i) + { + const std::size_t index = startIndex + i; + data[index] = static_cast(index); + } + + // I/O write region in a locked mutex + { + mutex.lock(); + + adios2::Variable variable = io.InquireVariable(variableName); + variable.SetSelection({{startIndex}, {localSize}}); + + engine.Put(variable, &data[startIndex]); + // PerformPuts must be called to collect memory per buffer + engine.PerformPuts(); + + mutex.unlock(); + } +} + +} // end namespace + +int main(int argc, char *argv[]) +{ + try + { + constexpr std::size_t nx = 100; + // data to be populated and written per thread + std::vector data(nx); + + // initialize adios2 objects serially + adios2::ADIOS adios; + adios2::IO io = adios.DeclareIO("thread-write"); + // populate shape, leave start and count empty as + // they will come from each thread SetSelection + const std::string variableName = "data"; + io.DefineVariable(variableName, adios2::Dims{nx}, adios2::Dims(), adios2::Dims()); + + adios2::Engine engine = io.Open("thread-writes.bp", adios2::Mode::Write); + + // set up thread tasks + // just grab maximum number of threads to simplify things + const auto nthreads = static_cast(std::thread::hardware_concurrency()); + std::vector threadTasks; + threadTasks.reserve(nthreads); + + // launch threaded tasks (this is what OpenMP would simplify) + // elements per thread + const std::size_t stride = nx / nthreads; + // elements for last thread, add remainder + const std::size_t last = stride + nx % nthreads; + + engine.BeginStep(); + // launch threads + for (std::size_t t = 0; t < nthreads; ++t) + { + const std::size_t startIndex = stride * t; + // non-inclusive endIndex + const std::size_t localSize = (t == nthreads - 1) ? last : stride; + + // use std::ref to pass things by reference + // adios2 objects can be passed by value + + threadTasks.emplace_back(ThreadTask, t, std::ref(data), startIndex, localSize, + std::ref(variableName), io, engine); + } + + for (auto &threadTask : threadTasks) + { + threadTask.join(); + } + engine.EndStep(); + + engine.Close(); + } + catch (std::exception &e) + { + std::cout << "ERROR: ADIOS2 exception: " << e.what() << "\n"; + } + + return 0; +} diff --git a/examples/hello/bpTimeWriter/CMakeLists.txt b/examples/hello/bpTimeWriter/CMakeLists.txt deleted file mode 100644 index 5306bbd375..0000000000 --- a/examples/hello/bpTimeWriter/CMakeLists.txt +++ /dev/null @@ -1,12 +0,0 @@ -#------------------------------------------------------------------------------# -# Distributed under the OSI-approved Apache License, Version 2.0. See -# accompanying file Copyright.txt for details. -#------------------------------------------------------------------------------# - -add_executable(hello_bpTimeWriter helloBPTimeWriter_nompi.cpp) -target_link_libraries(hello_bpTimeWriter adios2::cxx11) - -if(ADIOS2_HAVE_MPI) - add_executable(hello_bpTimeWriter_mpi helloBPTimeWriter.cpp) - target_link_libraries(hello_bpTimeWriter_mpi adios2::cxx11_mpi MPI::MPI_C) -endif() diff --git a/examples/hello/bpTimeWriter/helloBPTimeWriter.cpp b/examples/hello/bpTimeWriter/helloBPTimeWriter.cpp deleted file mode 100644 index eab24b40e9..0000000000 --- a/examples/hello/bpTimeWriter/helloBPTimeWriter.cpp +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Distributed under the OSI-approved Apache License, Version 2.0. See - * accompanying file Copyright.txt for details. - * - * helloBPTimeWriter.cpp example for writing a variable using the Advance - * function for time aggregation. Time step is saved as an additional (global) - * single value variable, just for tracking purposes. - * - * Created on: Feb 16, 2017 - * Author: William F Godoy godoywf@ornl.gov - */ - -#include //std::for_each -#include //std::ios_base::failure -#include //std::cout -#include -#include //std::invalid_argument std::exception -#include - -#include - -int main(int argc, char *argv[]) -{ - int provided; - - // MPI_THREAD_MULTIPLE is only required if you enable the SST MPI_DP - MPI_Init_thread(&argc, &argv, MPI_THREAD_MULTIPLE, &provided); - int rank, size; - MPI_Comm_rank(MPI_COMM_WORLD, &rank); - MPI_Comm_size(MPI_COMM_WORLD, &size); - - // Application variable - std::vector myFloats = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; - const std::size_t Nx = myFloats.size(); - - try - { - /** ADIOS class factory of IO class objects */ - adios2::ADIOS adios(MPI_COMM_WORLD); - - /// 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 = 10; - std::vector> bpFloats(variablesSize); - - adios2::Variable bpString = bpIO.DefineVariable("bpString"); - - for (unsigned int v = 0; v < variablesSize; ++v) - { - std::string namev("bpFloats"); - if (v < 10) - { - namev += "00"; - } - else if (v < 100) - { - namev += "0"; - } - namev += std::to_string(v); - - bpFloats[v] = bpIO.DefineVariable(namev, {size * Nx}, {rank * Nx}, {Nx}, - adios2::ConstantDims); - } - - /** global single value variable: name */ - adios2::Variable bpTimeStep = - bpIO.DefineVariable("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) - { - bpWriter.BeginStep(); - if (rank == 0) // global single value, only saved by rank 0 - { - bpWriter.Put(bpTimeStep, timeStep); - } - - // template type is optional, but recommended - for (unsigned int v = 0; v < variablesSize; ++v) - { - myFloats[0] = static_cast(v + timeStep); - // Note: Put is deferred, so all variables will see v == 9 - // and myFloats[0] == 9, 10, or 11 - bpWriter.Put(bpFloats[v], myFloats.data()); - } - const std::string myString("Hello from rank: " + std::to_string(rank) + - " and timestep: " + std::to_string(timeStep)); - - if (rank == 0) - { - bpWriter.Put(bpString, myString); - } - - bpWriter.EndStep(); - } - - bpWriter.Close(); - } - // MPI_Barrier(MPI_COMM_WORLD); - - if (false) - { /////////////////////READ - // if (rank == 0) - // { - adios2::IO ioReader = adios.DeclareIO("bpReader"); - - adios2::Engine bpReader = ioReader.Open("myVector.bp", adios2::Mode::Read); - - adios2::Variable bpFloats000 = ioReader.InquireVariable("bpFloats000"); - - adios2::Variable bpString = - ioReader.InquireVariable("bpString"); - - if (bpFloats000) - { - bpFloats000.SetSelection({{rank * Nx}, {Nx}}); - bpFloats000.SetStepSelection({2, 1}); - - std::vector data(bpFloats000.SelectionSize()); - bpReader.Get(bpFloats000, data.data(), adios2::Mode::Sync); - - std::cout << "Data timestep " << bpFloats000.StepsStart() << " from rank " << rank - << ": "; - for (const auto datum : data) - { - std::cout << datum << " "; - } - std::cout << "\n"; - } - else - { - std::cout << "Variable bpFloats000 not found\n"; - } - - if (bpString) - { - bpString.SetStepSelection({3, 1}); - - std::string myString; - bpReader.Get(bpString, myString, adios2::Mode::Sync); - std::cout << myString << "\n"; - } - - bpReader.Close(); - } - } - catch (std::invalid_argument &e) - { - std::cout << "Invalid argument exception, STOPPING PROGRAM from rank " << rank << "\n"; - std::cout << e.what() << "\n"; - } - catch (std::ios_base::failure &e) - { - std::cout << "IO System base failure exception, STOPPING PROGRAM " - "from rank " - << rank << "\n"; - std::cout << e.what() << "\n"; - } - catch (std::exception &e) - { - std::cout << "Exception, STOPPING PROGRAM from rank " << rank << "\n"; - std::cout << e.what() << "\n"; - } - - MPI_Finalize(); - - return 0; -} diff --git a/examples/hello/bpTimeWriter/helloBPTimeWriter.py b/examples/hello/bpTimeWriter/helloBPTimeWriter.py deleted file mode 100644 index 4ddff5a1aa..0000000000 --- a/examples/hello/bpTimeWriter/helloBPTimeWriter.py +++ /dev/null @@ -1,50 +0,0 @@ -# -# Distributed under the OSI-approved Apache License, Version 2.0. See -# accompanying file Copyright.txt for details. -# -# test_hello.py -# Created on: Feb 2, 2017 -# Author: William F Godoy godoywf@ornl.gov - -from mpi4py import MPI -import adios2 -import numpy as np - - -# MPI -comm = MPI.COMM_WORLD -rank = comm.Get_rank() -size = comm.Get_size() - -# User data -myArray = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) -nx = myArray.size -time = np.array([0.0]) - -# ADIOS -adios = adios2.ADIOS(comm) - -# IO -bpIO = adios.DeclareIO("BPN2N") - -# Variables -bpArray = bpIO.DefineVariable("bpArray", myArray, [size * nx], [rank * nx], - [nx], adios2.ConstantDims) -bpTimeStep = bpIO.DefineVariable("bpTimeStep", time) - -# Engine -bpFileWriter = bpIO.Open("myArray.bp", adios2.Mode.Write) -# Doesn't work: bpFileWriter = bpIO.Open("myArray.bp", adios2.OpenModeWrite) -# Doesn't work: bpFileWriter = bpIO.Open("myArray.bp", adiosOpenModeWrite, -# MPI.COMM_WORLD) - - -for t in range(0, 10): - bpFileWriter.BeginStep() - if rank == 0: - time[0] = t - bpFileWriter.Put(bpTimeStep, time) - bpFileWriter.Put(bpArray, myArray) - bpFileWriter.EndStep() - -bpFileWriter.Close() diff --git a/examples/hello/bpTimeWriter/helloBPTimeWriter_nompi.cpp b/examples/hello/bpTimeWriter/helloBPTimeWriter_nompi.cpp deleted file mode 100644 index 9165189504..0000000000 --- a/examples/hello/bpTimeWriter/helloBPTimeWriter_nompi.cpp +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Distributed under the OSI-approved Apache License, Version 2.0. See - * accompanying file Copyright.txt for details. - * - * helloBPTimeWriter_nompi.cpp no mpi version of helloBPTimeWriter.cpp - * - * Created on: Feb 16, 2017 - * Author: William F Godoy godoywf@ornl.gov - */ - -#include //std::ios_base::failure -#include //std::cout -#include //std::invalid_argument std::exception -#include - -#include - -int main(int argc, char *argv[]) -{ - // Application variable - std::vector myFloats = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; - const std::size_t Nx = myFloats.size(); - - try - { - /** ADIOS class factory of IO class objects */ - adios2::ADIOS adios; - - /*** IO class object: settings and factory of Settings: Variables, - * Parameters, Transports, and Execution: Engines */ - adios2::IO bpIO = adios.DeclareIO("BPFile_N2N"); - - /** name, { shape (total dimensions) }, { start (local) }, { count - * {local} } */ - adios2::Variable bpFloats = - bpIO.DefineVariable("bpFloats", {}, {}, {Nx}, adios2::ConstantDims); - - adios2::Variable bpTimeStep = bpIO.DefineVariable("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 < 10; ++timeStep) - { - bpWriter.BeginStep(); - - // template type is optional but recommended - bpWriter.Put(bpTimeStep, timeStep); - - // modifying data - myFloats[0] = static_cast(timeStep); - bpWriter.Put(bpFloats, myFloats.data(), adios2::Mode::Sync); - - bpWriter.EndStep(); - } - - bpWriter.Close(); - } - catch (std::invalid_argument &e) - { - std::cout << "Invalid argument exception, STOPPING PROGRAM\n"; - std::cout << e.what() << "\n"; - } - catch (std::ios_base::failure &e) - { - std::cout << "IO System base failure exception, STOPPING PROGRAM\n"; - std::cout << e.what() << "\n"; - } - catch (std::exception &e) - { - std::cout << "Exception, STOPPING PROGRAM from rank\n"; - std::cout << e.what() << "\n"; - } - - return 0; -} diff --git a/examples/hello/bpWriter/CMakeLists.txt b/examples/hello/bpWriter/CMakeLists.txt index aad594f556..9eb0fbf91a 100644 --- a/examples/hello/bpWriter/CMakeLists.txt +++ b/examples/hello/bpWriter/CMakeLists.txt @@ -3,50 +3,75 @@ # accompanying file Copyright.txt for details. #------------------------------------------------------------------------------# -add_executable(hello_bpWriter helloBPWriter.cpp) -target_link_libraries(hello_bpWriter adios2::cxx11) +cmake_minimum_required(VERSION 3.12) +project(ADIOS2HelloBPWriterExample) -add_executable(hello_bpWriter_c helloBPWriter.c) -target_link_libraries(hello_bpWriter_c adios2::c) +if(NOT TARGET adios2_core) + set(_components C) -add_executable(hello_bpPutDeferred helloBPPutDeferred.cpp) -target_link_libraries(hello_bpPutDeferred adios2::cxx11) + include(CheckLanguage) + check_language(Fortran) + if(CMAKE_Fortran_COMPILER) + enable_language(Fortran) + endif() + if(CMAKE_Fortran_COMPILER_LOADED) + list(APPEND _components Fortran) + endif() -add_executable(hello_bpSubStreams helloBPSubStreams.cpp) -target_link_libraries(hello_bpSubStreams adios2::cxx11) + find_package(MPI COMPONENTS ${_components}) + if(MPI_FOUND) + # Workaround for various MPI implementations forcing the link of C++ bindings + add_definitions(-DOMPI_SKIP_MPICXX -DMPICH_SKIP_MPICXX) -if(ADIOS2_HAVE_SZ) - add_executable(hello_bpSZ helloBPSZ.cpp) - target_link_libraries(hello_bpSZ adios2::cxx11) + list(APPEND _components MPI) + endif() + list(APPEND _components CXX) + + find_package(ADIOS2 REQUIRED COMPONENTS ${_components}) endif() +add_executable(adios2_hello_bpWriter bpWriter.cpp) +target_link_libraries(adios2_hello_bpWriter adios2::cxx11) +install(TARGETS adios2_hello_bpWriter RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + +add_executable(adios2_hello_bpWriter_c bpWriter.c) +target_link_libraries(adios2_hello_bpWriter_c adios2::c) +install(TARGETS adios2_hello_bpWriter_c RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + +add_executable(adios2_hello_bpPutDeferred bpPutDeferred.cpp) +target_link_libraries(adios2_hello_bpPutDeferred adios2::cxx11) +install(TARGETS adios2_hello_bpPutDeferred RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + +add_executable(adios2_hello_bpSubStreams bpSubStreams.cpp) +target_link_libraries(adios2_hello_bpSubStreams adios2::cxx11) +install(TARGETS adios2_hello_bpSubStreams RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + if(ADIOS2_HAVE_Fortran) - add_executable(hello_bpWriter_f helloBPWriter.F90) - set_property(TARGET hello_bpWriter_f PROPERTY LINKER_LANGUAGE Fortran) - target_link_libraries(hello_bpWriter_f adios2::fortran) + add_executable(adios2_hello_bpWriter_f bpWriter.F90) + target_link_libraries(adios2_hello_bpWriter_f adios2::fortran) + install(TARGETS adios2_hello_bpWriter_f RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) endif() if(ADIOS2_HAVE_MPI) - add_executable(hello_bpWriter_mpi helloBPWriter.cpp) - target_link_libraries(hello_bpWriter_mpi adios2::cxx11_mpi MPI::MPI_C) + add_executable(adios2_hello_bpWriter_mpi bpWriter.cpp) + target_link_libraries(adios2_hello_bpWriter_mpi adios2::cxx11_mpi MPI::MPI_C) + install(TARGETS adios2_hello_bpWriter_mpi RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) - add_executable(hello_bpWriter_c_mpi helloBPWriter.c) - target_link_libraries(hello_bpWriter_c_mpi adios2::c_mpi MPI::MPI_C) + add_executable(adios2_hello_bpWriter_c_mpi bpWriter.c) + target_link_libraries(adios2_hello_bpWriter_c_mpi adios2::c_mpi MPI::MPI_C) + install(TARGETS adios2_hello_bpWriter_c_mpi RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) - add_executable(hello_bpPutDeferred_mpi helloBPPutDeferred.cpp) - target_link_libraries(hello_bpPutDeferred_mpi adios2::cxx11_mpi MPI::MPI_C) + add_executable(adios2_hello_bpPutDeferred_mpi bpPutDeferred.cpp) + target_link_libraries(adios2_hello_bpPutDeferred_mpi adios2::cxx11_mpi MPI::MPI_C) + install(TARGETS adios2_hello_bpPutDeferred_mpi RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) - add_executable(hello_bpSubStreams_mpi helloBPSubStreams.cpp) - target_link_libraries(hello_bpSubStreams_mpi adios2::cxx11_mpi MPI::MPI_C) - - if(ADIOS2_HAVE_SZ) - add_executable(hello_bpSZ_mpi helloBPSZ.cpp) - target_link_libraries(hello_bpSZ_mpi adios2::cxx11_mpi MPI::MPI_C) - endif() + add_executable(adios2_hello_bpSubStreams_mpi bpSubStreams.cpp) + target_link_libraries(adios2_hello_bpSubStreams_mpi adios2::cxx11_mpi MPI::MPI_C) + install(TARGETS adios2_hello_bpSubStreams_mpi RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) if(ADIOS2_HAVE_Fortran) - add_executable(hello_bpWriter_f_mpi helloBPWriter.F90) - set_property(TARGET hello_bpWriter_f_mpi PROPERTY LINKER_LANGUAGE Fortran) - target_link_libraries(hello_bpWriter_f_mpi adios2::fortran_mpi MPI::MPI_Fortran) + add_executable(adios2_hello_bpWriter_f_mpi bpWriter.F90) + target_link_libraries(adios2_hello_bpWriter_f_mpi adios2::fortran_mpi MPI::MPI_Fortran) + install(TARGETS adios2_hello_bpWriter_f_mpi RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) endif() endif() diff --git a/examples/hello/bpWriter/helloBPPutDeferred.cpp b/examples/hello/bpWriter/bpPutDeferred.cpp similarity index 91% rename from examples/hello/bpWriter/helloBPPutDeferred.cpp rename to examples/hello/bpWriter/bpPutDeferred.cpp index 209486496d..2c0371209e 100644 --- a/examples/hello/bpWriter/helloBPPutDeferred.cpp +++ b/examples/hello/bpWriter/bpPutDeferred.cpp @@ -2,17 +2,7 @@ * Distributed under the OSI-approved Apache License, Version 2.0. See * accompanying file Copyright.txt for details. * - * helloBPPutDeferred.cpp - * - * Created on: Oct 23, 2017 - * Author: William F Godoy godoywf@ornl.gov - */ - -/* - * Distributed under the OSI-approved Apache License, Version 2.0. See - * accompanying file Copyright.txt for details. - * - * helloBPPutDeferred.cpp: Simple self-descriptive example of how to write a + * bpPutDeferred.cpp: Simple self-descriptive example of how to write a * variable * to a BP File that lives in several MPI processes. * @@ -77,9 +67,11 @@ int main(int argc, char *argv[]) /** Engine derived class, spawned to start IO operations */ adios2::Engine bpFileWriter = bpIO.Open("myVectorDeferred.bp", adios2::Mode::Write); + bpFileWriter.BeginStep(); /** Put variables for buffering, template type is optional */ bpFileWriter.Put(bpFloats, myFloats.data()); bpFileWriter.Put(bpInts, myInts.data()); + bpFileWriter.EndStep(); /** Create bp file, engine becomes unreachable after this*/ bpFileWriter.Close(); diff --git a/examples/hello/bpWriter/helloBPSubStreams.cpp b/examples/hello/bpWriter/bpSubStreams.cpp similarity index 99% rename from examples/hello/bpWriter/helloBPSubStreams.cpp rename to examples/hello/bpWriter/bpSubStreams.cpp index 54db43007d..dad04e82b7 100644 --- a/examples/hello/bpWriter/helloBPSubStreams.cpp +++ b/examples/hello/bpWriter/bpSubStreams.cpp @@ -2,7 +2,7 @@ * Distributed under the OSI-approved Apache License, Version 2.0. See * accompanying file Copyright.txt for details. * - * helloBPSubStreams.cpp + * bpSubStreams.cpp * * Created on: Feb 21, 2018 * Author: William F Godoy godoywf@ornl.gov diff --git a/examples/hello/bpWriter/helloBPWriter.F90 b/examples/hello/bpWriter/bpWriter.F90 similarity index 97% rename from examples/hello/bpWriter/helloBPWriter.F90 rename to examples/hello/bpWriter/bpWriter.F90 index d1cea302ae..296cb290a1 100644 --- a/examples/hello/bpWriter/helloBPWriter.F90 +++ b/examples/hello/bpWriter/bpWriter.F90 @@ -1,4 +1,4 @@ -program helloBPWriter +program bpWriter #if ADIOS2_USE_MPI use mpi #endif @@ -72,4 +72,4 @@ program helloBPWriter call MPI_Finalize(ierr) #endif -end program helloBPWriter +end program bpWriter diff --git a/examples/hello/bpWriter/helloBPWriter.c b/examples/hello/bpWriter/bpWriter.c similarity index 93% rename from examples/hello/bpWriter/helloBPWriter.c rename to examples/hello/bpWriter/bpWriter.c index b88271347b..c304510493 100644 --- a/examples/hello/bpWriter/helloBPWriter.c +++ b/examples/hello/bpWriter/bpWriter.c @@ -2,7 +2,7 @@ * Distributed under the OSI-approved Apache License, Version 2.0. See * accompanying file Copyright.txt for details. * - * helloBPWriter.c : C bindings version of helloBPWriter.cpp + * bpWriter.c : C bindings version of bpWriter.cpp * * Created on: Aug 8, 2017 * Author: William F Godoy godoywf@ornl.gov @@ -68,6 +68,7 @@ int main(int argc, char *argv[]) adios2_adios *adios = adios2_init_serial(); #endif + adios2_step_status err; check_handler(adios, "adios"); adios2_io *io = adios2_declare_io(adios, "BPFile_Write"); @@ -90,9 +91,13 @@ int main(int argc, char *argv[]) adios2_engine *engine = adios2_open(io, "myVector_c.bp", adios2_mode_write); check_handler(engine, "engine"); + adios2_begin_step(engine, adios2_step_mode_append, 0.0f, &err); + errio = adios2_put(engine, variable, myFloats, adios2_mode_deferred); check_error(errio); + adios2_end_step(engine); + errio = adios2_close(engine); check_error(errio); diff --git a/examples/hello/bpWriter/helloBPWriter.cpp b/examples/hello/bpWriter/bpWriter.cpp similarity index 88% rename from examples/hello/bpWriter/helloBPWriter.cpp rename to examples/hello/bpWriter/bpWriter.cpp index 5a80cdbeb4..112feb21f5 100644 --- a/examples/hello/bpWriter/helloBPWriter.cpp +++ b/examples/hello/bpWriter/bpWriter.cpp @@ -2,7 +2,7 @@ * Distributed under the OSI-approved Apache License, Version 2.0. See * accompanying file Copyright.txt for details. * - * helloBPWriter.cpp: Simple self-descriptive example of how to write a variable + * bpWriter.cpp: Simple self-descriptive example of how to write a variable * to a BP File that lives in several MPI processes. * * Created on: Feb 16, 2017 @@ -69,20 +69,22 @@ int main(int argc, char *argv[]) std::string filename = "myVector_cpp.bp"; /** Engine derived class, spawned to start IO operations */ - adios2::Engine bpFileWriter = bpIO.Open(filename, adios2::Mode::Write); + adios2::Engine bpWriter = bpIO.Open(filename, adios2::Mode::Write); + bpWriter.BeginStep(); /** Put variables for buffering, template type is optional */ - bpFileWriter.Put(bpFloats, myFloats.data()); - bpFileWriter.Put(bpInts, myInts.data()); - // bpFileWriter.Put(bpString, myString); + bpWriter.Put(bpFloats, myFloats.data()); + bpWriter.Put(bpInts, myInts.data()); + // bpWriter.Put(bpString, myString); + bpWriter.EndStep(); /** Create bp file, engine becomes unreachable after this*/ - bpFileWriter.Close(); + bpWriter.Close(); if (rank == 0) { std::cout << "Wrote file " << filename << " to disk. It can now be read by running " - "./bin/hello_bpReader.\n"; + "./bin/adios2_hello_bpReader.\n"; } } catch (std::invalid_argument &e) diff --git a/examples/hello/bpWriter/helloBPWriter.py b/examples/hello/bpWriter/bpWriter.py similarity index 70% rename from examples/hello/bpWriter/helloBPWriter.py rename to examples/hello/bpWriter/bpWriter.py index ce29de2f0e..fe2272112b 100644 --- a/examples/hello/bpWriter/helloBPWriter.py +++ b/examples/hello/bpWriter/bpWriter.py @@ -2,7 +2,7 @@ # Distributed under the OSI-approved Apache License, Version 2.0. See # accompanying file Copyright.txt for details. # -# helloBPWriter_nompi.py : only works with non MPI version +# bpWriter.py : only works with MPI version # Created on: Feb 2, 2017 # Author: William F Godoy godoywf@ornl.gov from mpi4py import MPI @@ -15,7 +15,7 @@ size = comm.Get_size() # User data -myArray = numpy.array([0, 1., 2., 3., 4., 5., 6., 7., 8., 9.]) +myArray = numpy.array([0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]) Nx = myArray.size # ADIOS MPI Communicator @@ -23,22 +23,25 @@ # ADIOS IO bpIO = adios.DeclareIO("BPFile_N2N") -bpIO.SetEngine('bp3') +bpIO.SetEngine("BPFile") # bpIO.SetParameters( {"Threads" : "2", "ProfileUnits" : "Microseconds", # "InitialBufferSize" : "17Kb"} ) bpIOParams = {} -bpIOParams['Threads'] = '2' -bpIOParams['ProfileUnits'] = 'Microseconds' -bpIOParams['InitialBufferSize'] = '17Kb' +bpIOParams["Threads"] = "2" +bpIOParams["ProfileUnits"] = "Microseconds" +bpIOParams["InitialBufferSize"] = "17Kb" bpIO.SetParameters(bpIOParams) -fileID = bpIO.AddTransport('File', {'Library': 'fstream'}) +fileID = bpIO.AddTransport("File", {"Library": "fstream"}) # ADIOS Variable name, shape, start, offset, constant dims ioArray = bpIO.DefineVariable( - "bpArray", myArray, [size * Nx], [rank * Nx], [Nx], adios2.ConstantDims) + "bpArray", myArray, [size * Nx], [rank * Nx], [Nx], adios2.ConstantDims +) # ADIOS Engine bpFileWriter = bpIO.Open("npArray.bp", adios2.Mode.Write) +bpFileWriter.BeginStep() bpFileWriter.Put(ioArray, myArray, adios2.Mode.Sync) +bpFileWriter.EndStep() bpFileWriter.Close() diff --git a/examples/hello/bpWriter/bpWriter_tutorialSkeleton.cpp b/examples/hello/bpWriter/bpWriter_tutorialSkeleton.cpp new file mode 100644 index 0000000000..d24a7f9bfe --- /dev/null +++ b/examples/hello/bpWriter/bpWriter_tutorialSkeleton.cpp @@ -0,0 +1,61 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * bpWriter.cpp: Simple self-descriptive example of how to write a variable + * to a BP File that lives in several MPI processes. + * + * Created on: Feb 16, 2017 + * Author: William F Godoy godoywf@ornl.gov + */ + +#include //std::ios_base::failure +#include //std::cout +#include //std::invalid_argument std::exception +#include + +#include +#include + +int main(int argc, char *argv[]) +{ + int rank, size; + int provided; + // Add code to init MPI + + // Add code to create arrays + try + { + // Add code to create ADIOS object + + // Add code to create IO object + + // Add code to create variables + + // Add code to open file + + // Add code to write variables + + // Add code to close file + } + catch (std::invalid_argument &e) + { + std::cerr << "Invalid argument exception: " << e.what() << "\n"; + MPI_Abort(MPI_COMM_WORLD, 1); + } + catch (std::ios_base::failure &e) + { + std::cerr << "IO System base failure exception: " << e.what() << "\n"; + std::cerr << "STOPPING PROGRAM from rank " << rank << "\n"; + } + catch (std::exception &e) + { + std::cerr << "Exception: " << e.what() << "\n"; + std::cerr << "STOPPING PROGRAM from rank " << rank << "\n"; + MPI_Abort(MPI_COMM_WORLD, 1); + } + + // Add code to finalize MPI + + return 0; +} diff --git a/examples/hello/bpWriter/helloBPWriter_nompi.py b/examples/hello/bpWriter/helloBPWriter_nompi.py deleted file mode 100644 index 9428808fa0..0000000000 --- a/examples/hello/bpWriter/helloBPWriter_nompi.py +++ /dev/null @@ -1,29 +0,0 @@ -# -# Distributed under the OSI-approved Apache License, Version 2.0. See -# accompanying file Copyright.txt for details. -# -# helloBPWriter.py : only works with MPI version -# Created on: Feb 2, 2017 -# Author: William F Godoy godoywf@ornl.gov - -import numpy -import adios2 - -# User data -myArray = numpy.array([0, 1., 2., 3., 4., 5., 6., 7., 8., 9.]) -Nx = myArray.size - -# adios -adios = adios2.ADIOS() - -# ADIOS IO -bpIO = adios.DeclareIO("BPFile_N2N") - -# ADIOS Variable name, shape, start, offset, constant dims -ioArray = bpIO.DefineVariable( - "bpArray", myArray, [], [], [Nx], adios2.ConstantDims) - -# ADIOS Engine -bpFileWriter = bpIO.Open("npArray.bp", adios2.Mode.Write) -bpFileWriter.Put(ioArray, myArray, adios2.Mode.Sync) -bpFileWriter.Close() diff --git a/examples/hello/datamanReader/CMakeLists.txt b/examples/hello/datamanReader/CMakeLists.txt index 56a6139009..656bacefac 100644 --- a/examples/hello/datamanReader/CMakeLists.txt +++ b/examples/hello/datamanReader/CMakeLists.txt @@ -3,8 +3,28 @@ # accompanying file Copyright.txt for details. #------------------------------------------------------------------------------# -if(ADIOS2_HAVE_MPI) - add_executable(hello_datamanReader helloDataManReader.cpp) - target_link_libraries(hello_datamanReader adios2::cxx11_mpi MPI::MPI_C) +cmake_minimum_required(VERSION 3.12) +project(ADIOS2HelloDataManReaderExample) + +if(NOT TARGET adios2_core) + set(_components CXX) + + find_package(MPI COMPONENTS C) + if(MPI_FOUND) + # Workaround for various MPI implementations forcing the link of C++ bindings + add_definitions(-DOMPI_SKIP_MPICXX -DMPICH_SKIP_MPICXX) + + list(APPEND _components MPI) + endif() + + find_package(ZeroMQ 4.1 QUIET) + + find_package(ADIOS2 REQUIRED COMPONENTS ${_components}) +endif() + +if(ADIOS2_HAVE_MPI AND ADIOS2_HAVE_DataMan) + add_executable(adios2_hello_datamanReader dataManReader.cpp) + target_link_libraries(adios2_hello_datamanReader adios2::cxx11_mpi MPI::MPI_C) + install(TARGETS adios2_hello_datamanReader RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) endif() diff --git a/examples/hello/datamanReader/helloDataManReader.cpp b/examples/hello/datamanReader/dataManReader.cpp similarity index 98% rename from examples/hello/datamanReader/helloDataManReader.cpp rename to examples/hello/datamanReader/dataManReader.cpp index 8313a9a56d..2bc58495b2 100644 --- a/examples/hello/datamanReader/helloDataManReader.cpp +++ b/examples/hello/datamanReader/dataManReader.cpp @@ -2,7 +2,7 @@ * Distributed under the OSI-approved Apache License, Version 2.0. See * accompanying file Copyright.txt for details. * - * helloDataManReader.cpp + * dataManReader.cpp * * Created on: Jan 9, 2017 * Author: Jason Wang diff --git a/examples/hello/datamanReader/helloDataManReader.py b/examples/hello/datamanReader/dataManReader.py similarity index 92% rename from examples/hello/datamanReader/helloDataManReader.py rename to examples/hello/datamanReader/dataManReader.py index 87248b6a64..c773e84fb8 100644 --- a/examples/hello/datamanReader/helloDataManReader.py +++ b/examples/hello/datamanReader/dataManReader.py @@ -2,7 +2,7 @@ # Distributed under the OSI-approved Apache License, Version 2.0. See # accompanying file Copyright.txt for details. # -# helloDataManReader.py +# dataManReader.py # # Created on: Sept 5, 2019 # Author: Jason Wang @@ -21,7 +21,7 @@ io.SetEngine("DataMan") io.SetParameters({"IPAddress": "127.0.0.1", "Port": "12306", "Timeout": "5"}) -engine = io.Open('HelloDataMan', adios2.Mode.Read, comm) +engine = io.Open("HelloDataMan", adios2.Mode.Read, comm) while True: stepStatus = engine.BeginStep() diff --git a/examples/hello/datamanWriter/CMakeLists.txt b/examples/hello/datamanWriter/CMakeLists.txt index 7c500d6e12..0bc0789ac6 100644 --- a/examples/hello/datamanWriter/CMakeLists.txt +++ b/examples/hello/datamanWriter/CMakeLists.txt @@ -3,7 +3,27 @@ # accompanying file Copyright.txt for details. #------------------------------------------------------------------------------# -if(ADIOS2_HAVE_MPI) - add_executable(hello_datamanWriter helloDataManWriter.cpp) - target_link_libraries(hello_datamanWriter adios2::cxx11_mpi MPI::MPI_C) +cmake_minimum_required(VERSION 3.12) +project(ADIOS2HelloDataManWriterExample) + +if(NOT TARGET adios2_core) + set(_components CXX) + + find_package(MPI COMPONENTS C) + if(MPI_FOUND) + # Workaround for various MPI implementations forcing the link of C++ bindings + add_definitions(-DOMPI_SKIP_MPICXX -DMPICH_SKIP_MPICXX) + + list(APPEND _components MPI) + endif() + + find_package(ZeroMQ 4.1 QUIET) + + find_package(ADIOS2 REQUIRED COMPONENTS ${_components}) +endif() + +if(ADIOS2_HAVE_MPI AND ADIOS2_HAVE_DataMan) + add_executable(adios2_hello_datamanWriter dataManWriter.cpp) + target_link_libraries(adios2_hello_datamanWriter adios2::cxx11_mpi MPI::MPI_C) + install(TARGETS adios2_hello_datamanWriter RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) endif() diff --git a/examples/hello/datamanWriter/helloDataManWriter.cpp b/examples/hello/datamanWriter/dataManWriter.cpp similarity index 98% rename from examples/hello/datamanWriter/helloDataManWriter.cpp rename to examples/hello/datamanWriter/dataManWriter.cpp index bd29cb9c2b..fc106c2bb3 100644 --- a/examples/hello/datamanWriter/helloDataManWriter.cpp +++ b/examples/hello/datamanWriter/dataManWriter.cpp @@ -2,7 +2,7 @@ * Distributed under the OSI-approved Apache License, Version 2.0. See * accompanying file Copyright.txt for details. * - * helloDataManWriter.cpp + * dataManWriter.cpp * * Created on: Feb 16, 2017 * Author: Jason Wang diff --git a/examples/hello/datamanWriter/helloDataManWriter.py b/examples/hello/datamanWriter/dataManWriter.py similarity index 92% rename from examples/hello/datamanWriter/helloDataManWriter.py rename to examples/hello/datamanWriter/dataManWriter.py index e23774cb38..9035d0f42a 100644 --- a/examples/hello/datamanWriter/helloDataManWriter.py +++ b/examples/hello/datamanWriter/dataManWriter.py @@ -2,7 +2,7 @@ # Distributed under the OSI-approved Apache License, Version 2.0. See # accompanying file Copyright.txt for details. # -# helloDataManWriter.py +# dataManWriter.py # # Created on: Sept 5, 2019 # Author: Jason Wang @@ -36,9 +36,10 @@ io.SetParameters({"IPAddress": "127.0.0.1", "Port": "12306", "Timeout": "5"}) var = io.DefineVariable( - "FloatArray", floatArray, shape, start, count, adios2.ConstantDims) + "FloatArray", floatArray, shape, start, count, adios2.ConstantDims +) -engine = io.Open('HelloDataMan', adios2.Mode.Write) +engine = io.Open("HelloDataMan", adios2.Mode.Write) for i in range(steps): floatArray = floatArray + 1 diff --git a/examples/hello/dataspacesReader/CMakeLists.txt b/examples/hello/dataspacesReader/CMakeLists.txt index 7136868362..11e8e3ff13 100644 --- a/examples/hello/dataspacesReader/CMakeLists.txt +++ b/examples/hello/dataspacesReader/CMakeLists.txt @@ -3,10 +3,33 @@ # accompanying file Copyright.txt for details. #------------------------------------------------------------------------------# -add_executable(hello_dataSpacesReader helloDataSpacesReader.cpp) -target_link_libraries(hello_dataSpacesReader adios2::cxx11) +cmake_minimum_required(VERSION 3.12) +project(ADIOS2HelloDataSpacesReaderExample) -if(ADIOS2_HAVE_MPI) - add_executable(hello_dataSpacesReader_mpi helloDataSpacesReader.cpp) - target_link_libraries(hello_dataSpacesReader_mpi adios2::cxx11_mpi MPI::MPI_C) +if(NOT TARGET adios2_core) + set(_components CXX) + + find_package(MPI COMPONENTS C) + if(MPI_FOUND) + # Workaround for various MPI implementations forcing the link of C++ bindings + add_definitions(-DOMPI_SKIP_MPICXX -DMPICH_SKIP_MPICXX) + + list(APPEND _components MPI) + endif() + + find_package(DataSpaces 2.1.1 QUIET) + + find_package(ADIOS2 REQUIRED COMPONENTS ${_components}) +endif() + +if(ADIOS2_HAVE_DataSpaces) + add_executable(adios2_hello_dataSpacesReader dataSpacesReader.cpp) + target_link_libraries(adios2_hello_dataSpacesReader adios2::cxx11) + install(TARGETS adios2_hello_dataSpacesReader RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + + if(ADIOS2_HAVE_MPI) + add_executable(adios2_hello_dataSpacesReader_mpi dataSpacesReader.cpp) + target_link_libraries(adios2_hello_dataSpacesReader_mpi adios2::cxx11_mpi MPI::MPI_C) + install(TARGETS adios2_hello_dataSpacesReader_mpi RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + endif() endif() diff --git a/examples/hello/dataspacesReader/helloDataSpacesReader.cpp b/examples/hello/dataspacesReader/dataSpacesReader.cpp similarity index 98% rename from examples/hello/dataspacesReader/helloDataSpacesReader.cpp rename to examples/hello/dataspacesReader/dataSpacesReader.cpp index c2efd7ee1b..c6f6731432 100644 --- a/examples/hello/dataspacesReader/helloDataSpacesReader.cpp +++ b/examples/hello/dataspacesReader/dataSpacesReader.cpp @@ -2,7 +2,7 @@ * Distributed under the OSI-approved Apache License, Version 2.0. See * accompanying file Copyright.txt for details. * - * helloDataSpacesReader.cpp + * dataSpacesReader.cpp * * Created on: Feb 06, 2019 * Author: Pradeep Subedi diff --git a/examples/hello/dataspacesWriter/CMakeLists.txt b/examples/hello/dataspacesWriter/CMakeLists.txt index 6518c8c24b..32a1bb4673 100644 --- a/examples/hello/dataspacesWriter/CMakeLists.txt +++ b/examples/hello/dataspacesWriter/CMakeLists.txt @@ -3,10 +3,33 @@ # accompanying file Copyright.txt for details. #------------------------------------------------------------------------------# -add_executable(hello_dataSpacesWriter helloDataSpacesWriter.cpp) -target_link_libraries(hello_dataSpacesWriter adios2::cxx11) +cmake_minimum_required(VERSION 3.12) +project(ADIOS2HelloDataSpacesWriterExample) -if(ADIOS2_HAVE_MPI) - add_executable(hello_dataSpacesWriter_mpi helloDataSpacesWriter.cpp) - target_link_libraries(hello_dataSpacesWriter_mpi adios2::cxx11_mpi MPI::MPI_C) +if(NOT TARGET adios2_core) + set(_components CXX) + + find_package(MPI COMPONENTS C) + if(MPI_FOUND) + # Workaround for various MPI implementations forcing the link of C++ bindings + add_definitions(-DOMPI_SKIP_MPICXX -DMPICH_SKIP_MPICXX) + + list(APPEND _components MPI) + endif() + + find_package(DataSpaces 2.1.1 QUIET) + + find_package(ADIOS2 REQUIRED COMPONENTS ${_components}) +endif() + +if(ADIOS2_HAVE_DataSpaces) + add_executable(adios2_hello_dataSpacesWriter dataSpacesWriter.cpp) + target_link_libraries(adios2_hello_dataSpacesWriter adios2::cxx11) + install(TARGETS adios2_hello_dataSpacesWriter RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + + if(ADIOS2_HAVE_MPI) + add_executable(adios2_hello_dataSpacesWriter_mpi dataSpacesWriter.cpp) + target_link_libraries(adios2_hello_dataSpacesWriter_mpi adios2::cxx11_mpi MPI::MPI_C) + install(TARGETS adios2_hello_dataSpacesWriter_mpi RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + endif() endif() diff --git a/examples/hello/dataspacesWriter/helloDataSpacesWriter.cpp b/examples/hello/dataspacesWriter/dataSpacesWriter.cpp similarity index 98% rename from examples/hello/dataspacesWriter/helloDataSpacesWriter.cpp rename to examples/hello/dataspacesWriter/dataSpacesWriter.cpp index 103578c716..9c9e23b466 100644 --- a/examples/hello/dataspacesWriter/helloDataSpacesWriter.cpp +++ b/examples/hello/dataspacesWriter/dataSpacesWriter.cpp @@ -2,7 +2,7 @@ * Distributed under the OSI-approved Apache License, Version 2.0. See * accompanying file Copyright.txt for details. * - * helloDataSpacesWriter.cpp + * dataSpacesWriter.cpp * * Created on: Feb 06, 2019 * Author: Pradeep Subedi diff --git a/examples/hello/hdf5Reader/CMakeLists.txt b/examples/hello/hdf5Reader/CMakeLists.txt index 2dd4227cf9..ebfcb9ad7b 100644 --- a/examples/hello/hdf5Reader/CMakeLists.txt +++ b/examples/hello/hdf5Reader/CMakeLists.txt @@ -3,10 +3,33 @@ # accompanying file Copyright.txt for details. #------------------------------------------------------------------------------# -add_executable(hello_hdf5Reader helloHDF5Reader_nompi.cpp) -target_link_libraries(hello_hdf5Reader adios2::cxx11) +cmake_minimum_required(VERSION 3.12) +project(ADIOS2HelloHDF5ReaderExample) -if(ADIOS2_HAVE_MPI) - add_executable(hello_hdf5Reader_mpi helloHDF5Reader.cpp) - target_link_libraries(hello_hdf5Reader_mpi adios2::cxx11_mpi MPI::MPI_C) +if(NOT TARGET adios2_core) + set(_components CXX) + + find_package(MPI COMPONENTS C) + if(MPI_FOUND) + # Workaround for various MPI implementations forcing the link of C++ bindings + add_definitions(-DOMPI_SKIP_MPICXX -DMPICH_SKIP_MPICXX) + + list(APPEND _components MPI) + endif() + + find_package(HDF5 QUIET COMPONENTS C) + + find_package(ADIOS2 REQUIRED COMPONENTS ${_components}) +endif() + +if(ADIOS2_HAVE_HDF5) + add_executable(adios2_hello_hdf5Reader hdf5Reader_nompi.cpp) + target_link_libraries(adios2_hello_hdf5Reader adios2::cxx11) + install(TARGETS adios2_hello_hdf5Reader RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + + if(ADIOS2_HAVE_MPI) + add_executable(adios2_hello_hdf5Reader_mpi hdf5Reader.cpp) + target_link_libraries(adios2_hello_hdf5Reader_mpi adios2::cxx11_mpi MPI::MPI_C) + install(TARGETS adios2_hello_hdf5Reader_mpi RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + endif() endif() diff --git a/examples/hello/hdf5Reader/helloHDF5Reader.cpp b/examples/hello/hdf5Reader/hdf5Reader.cpp similarity index 97% rename from examples/hello/hdf5Reader/helloHDF5Reader.cpp rename to examples/hello/hdf5Reader/hdf5Reader.cpp index d5ade54e72..fd15a3d631 100644 --- a/examples/hello/hdf5Reader/helloHDF5Reader.cpp +++ b/examples/hello/hdf5Reader/hdf5Reader.cpp @@ -2,7 +2,7 @@ * Distributed under the OSI-approved Apache License, Version 2.0. See * accompanying file Copyright.txt for details. * - * helloHDF5Reader.cpp + * hdf5Reader.cpp * * Created on: Jan 24, 2018 * Author: Junmin Gu @@ -23,9 +23,9 @@ void ReadData(adios2::IO h5IO, adios2::Engine &h5Reader, const std::string &name if (var) { - int nDims = var.Shape().size(); + size_t nDims = var.Shape().size(); size_t totalSize = 1; - for (int i = 0; i < nDims; i++) + for (size_t i = 0; i < nDims; i++) { totalSize *= var.Shape()[i]; } @@ -99,6 +99,8 @@ int main(int argc, char *argv[]) /** Engine derived class, spawned to start IO operations */ adios2::Engine h5Reader = h5IO.Open(filename, adios2::Mode::Read); + h5Reader.BeginStep(); + const std::map variables = h5IO.AvailableVariables(); for (const auto &variablePair : variables) @@ -159,6 +161,7 @@ int main(int argc, char *argv[]) //... add more types if needed } } + h5Reader.EndStep(); h5Reader.Close(); } diff --git a/examples/hello/hdf5Reader/helloHDF5Reader_nompi.cpp b/examples/hello/hdf5Reader/hdf5Reader_nompi.cpp similarity index 96% rename from examples/hello/hdf5Reader/helloHDF5Reader_nompi.cpp rename to examples/hello/hdf5Reader/hdf5Reader_nompi.cpp index 120c12ebc5..967039a750 100644 --- a/examples/hello/hdf5Reader/helloHDF5Reader_nompi.cpp +++ b/examples/hello/hdf5Reader/hdf5Reader_nompi.cpp @@ -2,7 +2,7 @@ * Distributed under the OSI-approved Apache License, Version 2.0. See * accompanying file Copyright.txt for details. * - * helloHDF5Reader.cpp + * hdf5Reader.cpp * * Created on: Jan 24, 2018 * Author: Junmin Gu @@ -22,9 +22,9 @@ void ReadData(adios2::IO h5IO, adios2::Engine h5Reader, const std::string &name) if (var) { - int nDims = var.Shape().size(); + size_t nDims = var.Shape().size(); size_t totalSize = 1; - for (int i = 0; i < nDims; i++) + for (size_t i = 0; i < nDims; i++) { totalSize *= var.Shape()[i]; } @@ -90,6 +90,8 @@ int main(int argc, char *argv[]) /** Engine derived class, spawned to start IO operations */ adios2::Engine h5Reader = h5IO.Open(filename, adios2::Mode::Read); + h5Reader.BeginStep(); + const std::map variables = h5IO.AvailableVariables(); for (const auto &variablePair : variables) @@ -123,6 +125,8 @@ int main(int argc, char *argv[]) // ReadData(h5IO, h5Reader, "h5Floats"); // ReadData(h5IO, h5Reader, "h5Ints"); + h5Reader.EndStep(); + /** Close h5 file, engine becomes unreachable after this*/ h5Reader.Close(); } diff --git a/examples/hello/hdf5SubFile/CMakeLists.txt b/examples/hello/hdf5SubFile/CMakeLists.txt new file mode 100644 index 0000000000..81e494fa1b --- /dev/null +++ b/examples/hello/hdf5SubFile/CMakeLists.txt @@ -0,0 +1,30 @@ +#------------------------------------------------------------------------------# +# Distributed under the OSI-approved Apache License, Version 2.0. See +# accompanying file Copyright.txt for details. +#------------------------------------------------------------------------------# + +cmake_minimum_required(VERSION 3.12) +project(HelloHDF5SubFileExample) + +if(NOT TARGET adios2_core) + set(_components CXX) + + find_package(MPI COMPONENTS C) + if(MPI_FOUND) + # Workaround for various MPI implementations forcing the link of C++ bindings + add_definitions(-DOMPI_SKIP_MPICXX -DMPICH_SKIP_MPICXX) + + list(APPEND _components MPI) + endif() + + find_package(HDF5 QUIET COMPONENTS C) + + find_package(ADIOS2 REQUIRED COMPONENTS ${_components}) +endif() + +if(ADIOS2_HAVE_MPI AND ADIOS2_HAVE_HDF5 AND HDF5_VERSION VERSION_GREATER_EQUAL 1.14) + add_executable(adios2_hello_hdf5Subfile hdf5SubFile.cpp) + target_link_libraries(adios2_hello_hdf5Subfile adios2::cxx11_mpi MPI::MPI_C) + install(TARGETS adios2_hello_hdf5Subfile RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) +endif() + diff --git a/examples/h5subfile/h5_subfile.cpp b/examples/hello/hdf5SubFile/hdf5SubFile.cpp similarity index 99% rename from examples/h5subfile/h5_subfile.cpp rename to examples/hello/hdf5SubFile/hdf5SubFile.cpp index 09e3111ecf..a018267b1a 100644 --- a/examples/h5subfile/h5_subfile.cpp +++ b/examples/hello/hdf5SubFile/hdf5SubFile.cpp @@ -2,7 +2,7 @@ * Distributed under the OSI-approved Apache License, Version 2.0. See * accompanying file Copyright.txt for details. * - * helloHDF5Writer.cpp: Simple self-descriptive example of how to write a + * hdf5SubFile.cpp: Simple self-descriptive example of how to write a * variable to a parallel HDF5 File using MPI processes. * * Created on: March 6, 2023 diff --git a/examples/hello/hdf5Writer/CMakeLists.txt b/examples/hello/hdf5Writer/CMakeLists.txt index 934fbb4cfb..b1fd2bcdcf 100644 --- a/examples/hello/hdf5Writer/CMakeLists.txt +++ b/examples/hello/hdf5Writer/CMakeLists.txt @@ -3,10 +3,33 @@ # accompanying file Copyright.txt for details. #------------------------------------------------------------------------------# -add_executable(hello_hdf5Writer helloHDF5Writer_nompi.cpp) -target_link_libraries(hello_hdf5Writer adios2::cxx11) +cmake_minimum_required(VERSION 3.12) +project(ADIOS2HelloHDF5WriterExample) -if(ADIOS2_HAVE_MPI) - add_executable(hello_hdf5Writer_mpi helloHDF5Writer.cpp) - target_link_libraries(hello_hdf5Writer_mpi adios2::cxx11_mpi MPI::MPI_C) +if(NOT TARGET adios2_core) + set(_components CXX) + + find_package(MPI COMPONENTS C) + if(MPI_FOUND) + # Workaround for various MPI implementations forcing the link of C++ bindings + add_definitions(-DOMPI_SKIP_MPICXX -DMPICH_SKIP_MPICXX) + + list(APPEND _components MPI) + endif() + + find_package(HDF5 QUIET COMPONENTS C) + + find_package(ADIOS2 REQUIRED COMPONENTS ${_components}) +endif() + +if(ADIOS2_HAVE_HDF5) + add_executable(adios2_hello_hdf5Writer hdf5Writer_nompi.cpp) + target_link_libraries(adios2_hello_hdf5Writer adios2::cxx11) + install(TARGETS adios2_hello_hdf5Writer RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + + if(ADIOS2_HAVE_MPI) + add_executable(adios2_hello_hdf5Writer_mpi hdf5Writer.cpp) + target_link_libraries(adios2_hello_hdf5Writer_mpi adios2::cxx11_mpi MPI::MPI_C) + install(TARGETS adios2_hello_hdf5Writer_mpi RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + endif() endif() diff --git a/examples/hello/hdf5Writer/helloHDF5Writer.cpp b/examples/hello/hdf5Writer/hdf5Writer.cpp similarity index 98% rename from examples/hello/hdf5Writer/helloHDF5Writer.cpp rename to examples/hello/hdf5Writer/hdf5Writer.cpp index 7b5e001533..3e09334593 100644 --- a/examples/hello/hdf5Writer/helloHDF5Writer.cpp +++ b/examples/hello/hdf5Writer/hdf5Writer.cpp @@ -2,7 +2,7 @@ * Distributed under the OSI-approved Apache License, Version 2.0. See * accompanying file Copyright.txt for details. * - * helloHDF5Writer.cpp: Simple self-descriptive example of how to write a + * hdf5Writer.cpp: Simple self-descriptive example of how to write a * variable to a parallel HDF5 File using MPI processes. * * Created on: March 20, 2017 diff --git a/examples/hello/hdf5Writer/helloHDF5Writer_nompi.cpp b/examples/hello/hdf5Writer/hdf5Writer_nompi.cpp similarity index 93% rename from examples/hello/hdf5Writer/helloHDF5Writer_nompi.cpp rename to examples/hello/hdf5Writer/hdf5Writer_nompi.cpp index 436cde2194..a1fa27ef18 100644 --- a/examples/hello/hdf5Writer/helloHDF5Writer_nompi.cpp +++ b/examples/hello/hdf5Writer/hdf5Writer_nompi.cpp @@ -2,7 +2,7 @@ * Distributed under the OSI-approved Apache License, Version 2.0. See * accompanying file Copyright.txt for details. * - * helloHDF5Writer_nompi.cpp no mpi version of helloHDF5Writer.cpp + * hdf5Writer_nompi.cpp no mpi version of helloHDF5Writer.cpp * * Created on: March 20, 2017 * Author: Junmin @@ -39,9 +39,13 @@ int main(int argc, char *argv[]) /** Engine derived class, spawned to start IO operations */ adios2::Engine hdf5Writer = hdf5IO.Open("myVector.h5", adios2::Mode::Write); + hdf5Writer.BeginStep(); + /** Write variable for buffering */ hdf5Writer.Put(bpFloats, myFloats.data()); + hdf5Writer.EndStep(); + /** Create bp file, engine becomes unreachable after this*/ hdf5Writer.Close(); } diff --git a/examples/hello/helloWorld/CMakeLists.txt b/examples/hello/helloWorld/CMakeLists.txt new file mode 100644 index 0000000000..416d0d5b26 --- /dev/null +++ b/examples/hello/helloWorld/CMakeLists.txt @@ -0,0 +1,47 @@ +#------------------------------------------------------------------------------# +# Distributed under the OSI-approved Apache License, Version 2.0. See +# accompanying file Copyright.txt for details. +#------------------------------------------------------------------------------# + +cmake_minimum_required(VERSION 3.12) +project(ADIOS2HelloHelloWorldExample) + +if(NOT TARGET adios2_core) + set(_components C CXX) + + find_package(MPI COMPONENTS C) + if(MPI_FOUND) + # Workaround for various MPI implementations forcing the link of C++ bindings + add_definitions(-DOMPI_SKIP_MPICXX -DMPICH_SKIP_MPICXX) + + list(APPEND _components MPI) + endif() + + find_package(ADIOS2 REQUIRED COMPONENTS ${_components}) +endif() + +add_executable(adios2_hello_helloWorld_c hello-world.c) +target_link_libraries(adios2_hello_helloWorld_c adios2::c) +install(TARGETS adios2_hello_helloWorld_c RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + +add_executable(adios2_hello_helloWorld hello-world.cpp) +target_link_libraries(adios2_hello_helloWorld adios2::cxx11) +install(TARGETS adios2_hello_helloWorld RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + +add_executable(adios2_hello_helloWorld_hl hello-world-hl.cpp) +target_link_libraries(adios2_hello_helloWorld_hl adios2::cxx11) +install(TARGETS adios2_hello_helloWorld_hl RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + +if(ADIOS2_HAVE_MPI) + add_executable(adios2_hello_helloWorld_c_mpi hello-world.c) + target_link_libraries(adios2_hello_helloWorld_c_mpi adios2::c_mpi MPI::MPI_C) + install(TARGETS adios2_hello_helloWorld_c_mpi RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + + add_executable(adios2_hello_helloWorld_mpi hello-world.cpp) + target_link_libraries(adios2_hello_helloWorld_mpi adios2::cxx11_mpi MPI::MPI_C) + install(TARGETS adios2_hello_helloWorld_mpi RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + + add_executable(adios2_hello_helloWorld_hl_mpi hello-world-hl.cpp) + target_link_libraries(adios2_hello_helloWorld_hl_mpi adios2::cxx11_mpi MPI::MPI_C) + install(TARGETS adios2_hello_helloWorld_hl_mpi RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) +endif() diff --git a/examples/hello/helloWorld/hello-world-hl.cpp b/examples/hello/helloWorld/hello-world-hl.cpp new file mode 100644 index 0000000000..d1a4f2c05f --- /dev/null +++ b/examples/hello/helloWorld/hello-world-hl.cpp @@ -0,0 +1,75 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * hello-world-hl.cpp : adios2 high-level API example to write and read a + * std::string Variable with a greeting + * + * Created on: Nov 14, 2019 + * Author: William F Godoy godoywf@ornl.gov + */ + +#include +#include + +#include +#if ADIOS2_USE_MPI +#include +#endif + +void writer(const std::string &greeting) +{ +#if ADIOS2_USE_MPI + adios2::fstream out("hello-world-hl-cpp.bp", adios2::fstream::out, MPI_COMM_WORLD); +#else + adios2::fstream out("hello-world-hl-cpp.bp", adios2::fstream::out); +#endif + + out.write("Greeting", greeting); + out.close(); +} + +std::string reader() +{ +#if ADIOS2_USE_MPI + adios2::fstream in("hello-world-hl-cpp.bp", adios2::fstream::in, MPI_COMM_WORLD); +#else + adios2::fstream in("hello-world-hl-cpp.bp", adios2::fstream::in); +#endif + + for (adios2::fstep iStep; adios2::getstep(in, iStep);) + { + const std::vector greetings = in.read("Greeting"); + return greetings.front(); + } + return ""; +} + +int main(int argc, char *argv[]) +{ +#if ADIOS2_USE_MPI + MPI_Init(&argc, &argv); +#endif + + try + { + const std::string greeting = "Hello World from ADIOS2"; + writer(greeting); + + const std::string message = reader(); + std::cout << message << "\n"; + } + catch (std::exception &e) + { + std::cout << "ERROR: ADIOS2 exception: " << e.what() << "\n"; +#if ADIOS2_USE_MPI + MPI_Abort(MPI_COMM_WORLD, -1); +#endif + } + +#if ADIOS2_USE_MPI + MPI_Finalize(); +#endif + + return 0; +} diff --git a/examples/hello/helloWorld/hello-world-hl.py b/examples/hello/helloWorld/hello-world-hl.py new file mode 100644 index 0000000000..825fb5282e --- /dev/null +++ b/examples/hello/helloWorld/hello-world-hl.py @@ -0,0 +1,47 @@ +# +# Distributed under the OSI-approved Apache License, Version 2.0. See +# accompanying file Copyright.txt for details. +# +# hello-world.py : adios2 high-level API example to write and read a +# string Variable with a greeting +# +# Created on: 2/2/2021 +# Author: Dmitry Ganyushin ganyushindi@ornl.gov +# +import sys +from mpi4py import MPI +import adios2 + +DATA_FILENAME = "hello-world-hl-py.bp" +# MPI +comm = MPI.COMM_WORLD +rank = comm.Get_rank() +size = comm.Get_size() + + +def writer(greeting): + """write a string to a bp file""" + with adios2.open(DATA_FILENAME, "w", comm) as fh: + fh.write("Greeting", greeting, end_step=True) + return 0 + + +def reader(): + """read a string from to a bp file""" + with adios2.open(DATA_FILENAME, "r", comm) as fh: + for fstep in fh: + message = fstep.read_string("Greeting") + return message + + +def main(): + """driver function""" + greeting = "Hello World from ADIOS2" + writer(greeting) + message = reader() + print("{}".format(message)) + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/examples/hello/helloWorld/hello-world.c b/examples/hello/helloWorld/hello-world.c new file mode 100644 index 0000000000..d1ea152e5e --- /dev/null +++ b/examples/hello/helloWorld/hello-world.c @@ -0,0 +1,74 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * hello-world.c : adios2 C API example to write and read a + * char* Variable with a greeting + * + * Created on: Nov 14, 2019 + * Author: William F Godoy godoywf@ornl.gov + */ + +#include //printf +#include //malloc, free + +#include +#if ADIOS2_USE_MPI +#include +#endif + +void writer(adios2_adios *adios, const char *greeting) +{ + adios2_step_status status; + adios2_io *io = adios2_declare_io(adios, "hello-world-writer"); + adios2_variable *var_greeting = adios2_define_variable( + io, "Greeting", adios2_type_string, 0, NULL, NULL, NULL, adios2_constant_dims_true); + + adios2_engine *engine = adios2_open(io, "hello-world-c.bp", adios2_mode_write); + adios2_begin_step(engine, adios2_step_mode_append, -1., &status); + adios2_put(engine, var_greeting, greeting, adios2_mode_deferred); + adios2_end_step(engine); + adios2_close(engine); +} + +void reader(adios2_adios *adios, char *greeting) +{ + adios2_step_status status; + adios2_io *io = adios2_declare_io(adios, "hello-world-reader"); + adios2_engine *engine = adios2_open(io, "hello-world-c.bp", adios2_mode_read); + adios2_variable *var_greeting = adios2_inquire_variable(io, "Greeting"); + adios2_begin_step(engine, adios2_step_mode_read, -1., &status); + adios2_get(engine, var_greeting, greeting, adios2_mode_deferred); + adios2_end_step(engine); + adios2_close(engine); +} + +int main(int argc, char *argv[]) +{ +#if ADIOS2_USE_MPI + MPI_Init(&argc, &argv); +#endif + + { +#if ADIOS2_USE_MPI + adios2_adios *adios = adios2_init_mpi(MPI_COMM_WORLD); +#else + adios2_adios *adios = adios2_init(); +#endif + + const char greeting[] = "Hello World from ADIOS2"; + writer(adios, greeting); + + char *message = (char *)malloc(24); + reader(adios, message); + printf("%s\n", message); + + free(message); + } + +#if ADIOS2_USE_MPI + MPI_Finalize(); +#endif + + return 0; +} diff --git a/examples/hello/helloWorld/hello-world.cpp b/examples/hello/helloWorld/hello-world.cpp new file mode 100644 index 0000000000..722f70a868 --- /dev/null +++ b/examples/hello/helloWorld/hello-world.cpp @@ -0,0 +1,78 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * hello-world.cpp : adios2 low-level API example to write and read a + * std::string Variable with a greeting + * + * Created on: Nov 14, 2019 + * Author: William F Godoy godoywf@ornl.gov + */ + +#include +#include + +#include +#if ADIOS2_USE_MPI +#include +#endif + +void writer(adios2::ADIOS &adios, const std::string &greeting) +{ + adios2::IO io = adios.DeclareIO("hello-world-writer"); + adios2::Variable varGreeting = io.DefineVariable("Greeting"); + + adios2::Engine writer = io.Open("hello-world-cpp.bp", adios2::Mode::Write); + writer.BeginStep(); + writer.Put(varGreeting, greeting); + writer.EndStep(); + writer.Close(); +} + +std::string reader(adios2::ADIOS &adios) +{ + adios2::IO io = adios.DeclareIO("hello-world-reader"); + adios2::Engine reader = io.Open("hello-world-cpp.bp", adios2::Mode::Read); + reader.BeginStep(); + adios2::Variable varGreeting = io.InquireVariable("Greeting"); + std::string greeting; + reader.Get(varGreeting, greeting); + reader.EndStep(); + reader.Close(); + return greeting; +} + +int main(int argc, char *argv[]) +{ +#if ADIOS2_USE_MPI + MPI_Init(&argc, &argv); +#endif + + try + { +#if ADIOS2_USE_MPI + adios2::ADIOS adios(MPI_COMM_WORLD); +#else + adios2::ADIOS adios; +#endif + + const std::string greeting = "Hello World from ADIOS2"; + writer(adios, greeting); + + const std::string message = reader(adios); + std::cout << message << "\n"; + } + catch (std::exception &e) + { + std::cout << "ERROR: ADIOS2 exception: " << e.what() << "\n"; +#if ADIOS2_USE_MPI + MPI_Abort(MPI_COMM_WORLD, -1); +#endif + } + +#if ADIOS2_USE_MPI + MPI_Finalize(); +#endif + + return 0; +} diff --git a/examples/hello/helloWorld/hello-world.py b/examples/hello/helloWorld/hello-world.py new file mode 100644 index 0000000000..685d648597 --- /dev/null +++ b/examples/hello/helloWorld/hello-world.py @@ -0,0 +1,57 @@ +# +# Distributed under the OSI-approved Apache License, Version 2.0. See +# accompanying file Copyright.txt for details. +# +# hello-world.py : adios2 low-level API example to write and read a +# string Variable with a greeting +# +# Created on: 2/2/2021 +# Author: Dmitry Ganyushin ganyushindi@ornl.gov +# +import sys +from mpi4py import MPI +import adios2 + +DATA_FILENAME = "hello-world-py.bp" +# MPI +comm = MPI.COMM_WORLD +rank = comm.Get_rank() +size = comm.Get_size() + + +def writer(ad, greeting): + """write a string to a bp file""" + io = ad.DeclareIO("hello-world-writer") + var_greeting = io.DefineVariable("Greeting") + w = io.Open(DATA_FILENAME, adios2.Mode.Write) + w.BeginStep() + w.Put(var_greeting, greeting) + w.EndStep() + w.Close() + return 0 + + +def reader(ad): + """read a string from to a bp file""" + io = ad.DeclareIO("hello-world-reader") + r = io.Open(DATA_FILENAME, adios2.Mode.Read) + r.BeginStep() + var_greeting = io.InquireVariable("Greeting") + message = r.Get(var_greeting) + r.EndStep() + r.Close() + return message + + +def main(): + """driver function""" + ad = adios2.ADIOS(comm) + greeting = "Hello World from ADIOS2" + writer(ad, greeting) + message = reader(ad) + print("{}".format(message)) + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/examples/hello/helloWorld/hello-world_tutorialSkeleton.cpp b/examples/hello/helloWorld/hello-world_tutorialSkeleton.cpp new file mode 100644 index 0000000000..df89e385e3 --- /dev/null +++ b/examples/hello/helloWorld/hello-world_tutorialSkeleton.cpp @@ -0,0 +1,39 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * hello-world.cpp : adios2 low-level API example to write and read a + * std::string Variable with a greeting + * + * Created on: Nov 14, 2019 + * Author: William F Godoy godoywf@ornl.gov + */ + +#include +#include + +#include + +void writer(adios2::ADIOS &adios, const std::string &greeting) +{ + // Add code +} + +std::string reader(adios2::ADIOS &adios) +{ + // Add code +} + +int main(int argc, char *argv[]) +{ + try + { + // Add code + } + catch (std::exception &e) + { + std::cout << "ERROR: ADIOS2 exception: " << e.what() << "\n"; + } + + return 0; +} diff --git a/examples/hello/inlineFWriteCppRead/CMakeLists.txt b/examples/hello/inlineFWriteCppRead/CMakeLists.txt index 64b99b539d..ad5cfbd537 100644 --- a/examples/hello/inlineFWriteCppRead/CMakeLists.txt +++ b/examples/hello/inlineFWriteCppRead/CMakeLists.txt @@ -3,17 +3,36 @@ # accompanying file Copyright.txt for details. #------------------------------------------------------------------------------# -include(FortranCInterface) -FortranCInterface_HEADER(InlineExampleFC.h MACRO_NAMESPACE "FC_") -FortranCInterface_VERIFY(CXX QUIET) +cmake_minimum_required(VERSION 3.12) +project(ADIOS2HelloFWriteCppReadExample) -add_library(InlineMixedLangCPP inlineMixedLang.cpp) -target_link_libraries(InlineMixedLangCPP adios2::cxx11) -target_include_directories(InlineMixedLangCPP - PRIVATE - ${CMAKE_CURRENT_BINARY_DIR} - ) +if(NOT TARGET adios2_core) + set(_components CXX) -add_executable(InlineMixedLangF inlineMixedLang.f90) -target_link_libraries(InlineMixedLangF adios2::fortran InlineMixedLangCPP) -set_target_properties(InlineMixedLangF PROPERTIES LINKER_LANGUAGE Fortran) + include(CheckLanguage) + check_language(Fortran) + if(CMAKE_Fortran_COMPILER) + enable_language(Fortran) + endif() + if(CMAKE_Fortran_COMPILER_LOADED) + list(APPEND _components Fortran) + endif() + + find_package(ADIOS2 REQUIRED COMPONENTS ${_components}) +endif() + +if(ADIOS2_HAVE_Fortran) + include(FortranCInterface) + FortranCInterface_HEADER(InlineExampleFC.h MACRO_NAMESPACE "FC_") + FortranCInterface_VERIFY(CXX QUIET) + + add_library(adios2_hello_inlineMixedLang inlineMixedLang.cpp) + target_link_libraries(adios2_hello_inlineMixedLang adios2::cxx11) + target_include_directories(adios2_hello_inlineMixedLang PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) + install(TARGETS adios2_hello_inlineMixedLang RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + + add_executable(adios2_hello_inlineMixedLang_f inlineMixedLang.f90) + target_link_libraries(adios2_hello_inlineMixedLang_f adios2_hello_inlineMixedLang adios2::fortran) + set_target_properties(adios2_hello_inlineMixedLang_f PROPERTIES LINKER_LANGUAGE Fortran) + install(TARGETS adios2_hello_inlineMixedLang_f RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) +endif() diff --git a/examples/hello/inlineFWriteCppRead/inlineMixedLang.cpp b/examples/hello/inlineFWriteCppRead/inlineMixedLang.cpp index 45765a1503..c7dc5f75b5 100644 --- a/examples/hello/inlineFWriteCppRead/inlineMixedLang.cpp +++ b/examples/hello/inlineFWriteCppRead/inlineMixedLang.cpp @@ -28,6 +28,9 @@ void FC_GLOBAL(open_reader, OPEN_READER)(adios2::IO *io) void FC_GLOBAL(analyze_data, ANALYZE_DATA)() { + // begin step on the reader + reader.BeginStep(); + // grab the desired variable auto u = adiosIO->InquireVariable("data2D"); if (!u) @@ -37,9 +40,6 @@ void FC_GLOBAL(analyze_data, ANALYZE_DATA)() } auto shape = u.Shape(); - // begin step on the reader - reader.BeginStep(); - // get the data pointer and do some stuff with it float *data = nullptr; reader.Get(u, &data); diff --git a/examples/hello/inlineMWE/CMakeLists.txt b/examples/hello/inlineMWE/CMakeLists.txt new file mode 100644 index 0000000000..98ac7fcc70 --- /dev/null +++ b/examples/hello/inlineMWE/CMakeLists.txt @@ -0,0 +1,17 @@ +#------------------------------------------------------------------------------# +# Distributed under the OSI-approved Apache License, Version 2.0. See +# accompanying file Copyright.txt for details. +#------------------------------------------------------------------------------# + +cmake_minimum_required(VERSION 3.12) +project(ADIOS2HelloInlineMWEExample) + +if(NOT TARGET adios2_core) + set(_components CXX) + + find_package(ADIOS2 REQUIRED COMPONENTS ${_components}) +endif() + +add_executable(adios2_hello_inlineMWE inlineMWE.cpp) +target_link_libraries(adios2_hello_inlineMWE adios2::cxx11) +install(TARGETS adios2_hello_inlineMWE RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) diff --git a/examples/inlineMWE/inlineMWE.cpp b/examples/hello/inlineMWE/inlineMWE.cpp similarity index 84% rename from examples/inlineMWE/inlineMWE.cpp rename to examples/hello/inlineMWE/inlineMWE.cpp index 41d4ba37a6..cb12a3642b 100644 --- a/examples/inlineMWE/inlineMWE.cpp +++ b/examples/hello/inlineMWE/inlineMWE.cpp @@ -1,3 +1,8 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + */ + #include #include @@ -26,5 +31,7 @@ int main(int argc, char *argv[]) std::cout << "Getting data from address " << data << " via inline reader\n"; reader.EndStep(); } + writer.Close(); + reader.Close(); return 0; } diff --git a/examples/hello/inlineReaderWriter/CMakeLists.txt b/examples/hello/inlineReaderWriter/CMakeLists.txt index 25a8334140..cf76d4d0e6 100644 --- a/examples/hello/inlineReaderWriter/CMakeLists.txt +++ b/examples/hello/inlineReaderWriter/CMakeLists.txt @@ -3,10 +3,29 @@ # accompanying file Copyright.txt for details. #------------------------------------------------------------------------------# -add_executable(hello_inlineReaderWriter helloInlineReaderWriter.cpp) -target_link_libraries(hello_inlineReaderWriter adios2::cxx11) +cmake_minimum_required(VERSION 3.12) +project(ADIOS2HelloInlineReaderWriterExample) + +if(NOT TARGET adios2_core) + set(_components CXX) + + find_package(MPI COMPONENTS C) + if(MPI_FOUND) + # Workaround for various MPI implementations forcing the link of C++ bindings + add_definitions(-DOMPI_SKIP_MPICXX -DMPICH_SKIP_MPICXX) + + list(APPEND _components MPI) + endif() + + find_package(ADIOS2 REQUIRED COMPONENTS ${_components}) +endif() + +add_executable(adios2_hello_inlineReaderWriter inlineReaderWriter.cpp) +target_link_libraries(adios2_hello_inlineReaderWriter adios2::cxx11) +install(TARGETS adios2_hello_inlineReaderWriter RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) if(ADIOS2_HAVE_MPI) - add_executable(hello_inlineReaderWriter_mpi helloInlineReaderWriter.cpp) - target_link_libraries(hello_inlineReaderWriter_mpi adios2::cxx11_mpi MPI::MPI_C) + add_executable(adios2_hello_inlineReaderWriter_mpi inlineReaderWriter.cpp) + target_link_libraries(adios2_hello_inlineReaderWriter_mpi adios2::cxx11_mpi MPI::MPI_C) + install(TARGETS adios2_hello_inlineReaderWriter_mpi RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) endif() diff --git a/examples/hello/inlineReaderWriter/helloInlineReaderWriter.cpp b/examples/hello/inlineReaderWriter/inlineReaderWriter.cpp similarity index 98% rename from examples/hello/inlineReaderWriter/helloInlineReaderWriter.cpp rename to examples/hello/inlineReaderWriter/inlineReaderWriter.cpp index 3fe9674924..f7ca536bfc 100644 --- a/examples/hello/inlineReaderWriter/helloInlineReaderWriter.cpp +++ b/examples/hello/inlineReaderWriter/inlineReaderWriter.cpp @@ -2,7 +2,7 @@ * Distributed under the OSI-approved Apache License, Version 2.0. See * accompanying file Copyright.txt for details. * - * helloInlineReaderWriter.cpp example borrowed from helloBPTimeWriter, using + * inlineReaderWriter.cpp example borrowed from bpTimeWriter, using * the inline engine. Writes a variable using the Advance function for time * aggregation. Time step is saved as an additional (global) single value * variable, just for tracking purposes. diff --git a/examples/hello/skeleton/CMakeLists.txt b/examples/hello/skeleton/CMakeLists.txt index 5e5a35007c..4c6ead50ab 100644 --- a/examples/hello/skeleton/CMakeLists.txt +++ b/examples/hello/skeleton/CMakeLists.txt @@ -3,16 +3,37 @@ # accompanying file Copyright.txt for details. #------------------------------------------------------------------------------# -add_executable(hello_skeletonWriter helloSkeletonWriter.cpp HelloSkeletonArgs.cpp) -target_link_libraries(hello_skeletonWriter adios2::cxx11) +cmake_minimum_required(VERSION 3.12) +project(ADIOS2HelloSkeletonExample) -add_executable(hello_skeletonReader helloSkeletonReader.cpp HelloSkeletonArgs.cpp) -target_link_libraries(hello_skeletonReader adios2::cxx11) +if(NOT TARGET adios2_core) + set(_components CXX) + + find_package(MPI COMPONENTS C) + if(MPI_FOUND) + # Workaround for various MPI implementations forcing the link of C++ bindings + add_definitions(-DOMPI_SKIP_MPICXX -DMPICH_SKIP_MPICXX) + + list(APPEND _components MPI) + endif() + + find_package(ADIOS2 REQUIRED COMPONENTS ${_components}) +endif() + +add_executable(adios2_hello_skeletonWriter skeletonWriter.cpp SkeletonArgs.cpp) +target_link_libraries(adios2_hello_skeletonWriter adios2::cxx11) +install(TARGETS adios2_hello_skeletonWriter RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + +add_executable(adios2_hello_skeletonReader skeletonReader.cpp SkeletonArgs.cpp) +target_link_libraries(adios2_hello_skeletonReader adios2::cxx11) +install(TARGETS adios2_hello_skeletonReader RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) if(ADIOS2_HAVE_MPI) - add_executable(hello_skeletonWriter_mpi helloSkeletonWriter.cpp HelloSkeletonArgs.cpp) - target_link_libraries(hello_skeletonWriter_mpi adios2::cxx11_mpi MPI::MPI_C) + add_executable(adios2_hello_skeletonWriter_mpi skeletonWriter.cpp SkeletonArgs.cpp) + target_link_libraries(adios2_hello_skeletonWriter_mpi adios2::cxx11_mpi MPI::MPI_C) + install(TARGETS adios2_hello_skeletonWriter_mpi RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) - add_executable(hello_skeletonReader_mpi helloSkeletonReader.cpp HelloSkeletonArgs.cpp) - target_link_libraries(hello_skeletonReader_mpi adios2::cxx11_mpi MPI::MPI_C) + add_executable(adios2_hello_skeletonReader_mpi skeletonReader.cpp SkeletonArgs.cpp) + target_link_libraries(adios2_hello_skeletonReader_mpi adios2::cxx11_mpi MPI::MPI_C) + install(TARGETS adios2_hello_skeletonReader_mpi RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) endif() diff --git a/examples/hello/skeleton/HelloSkeletonArgs.cpp b/examples/hello/skeleton/SkeletonArgs.cpp similarity index 92% rename from examples/hello/skeleton/HelloSkeletonArgs.cpp rename to examples/hello/skeleton/SkeletonArgs.cpp index 2ee3b8ff64..109ca5388d 100644 --- a/examples/hello/skeleton/HelloSkeletonArgs.cpp +++ b/examples/hello/skeleton/SkeletonArgs.cpp @@ -6,7 +6,7 @@ * Author: Norbert Podhorszki */ -#include "HelloSkeletonArgs.h" +#include "SkeletonArgs.h" #include @@ -42,7 +42,7 @@ static void printUsage(bool isWriter) static unsigned int convertToUint(std::string varName, char *arg) { char *end; - unsigned int retval = std::strtoul(arg, &end, 10); + const auto retval = static_cast(std::strtoul(arg, &end, 10)); if (end[0] || errno == ERANGE) { throw std::invalid_argument("Invalid value given for " + varName + ": " + std::string(arg)); @@ -50,8 +50,7 @@ static unsigned int convertToUint(std::string varName, char *arg) return retval; } -HelloSkeletonArgs::HelloSkeletonArgs(bool isWriter, int argc, char *argv[], int rank, int nproc) -: rank{rank} +SkeletonArgs::SkeletonArgs(bool isWriter, int argc, char *argv[], int rank, int nproc) : rank{rank} { npx = npy = ndx = ndy = steps = sleeptime = 0; gndx = gndy = posx = posy = offsx = offsy = 0; @@ -98,7 +97,7 @@ HelloSkeletonArgs::HelloSkeletonArgs(bool isWriter, int argc, char *argv[], int } } -void HelloSkeletonArgs::DecomposeArray(size_t NX, size_t NY) +void SkeletonArgs::DecomposeArray(size_t NX, size_t NY) { gndx = static_cast(NX); gndy = static_cast(NY); diff --git a/examples/hello/skeleton/HelloSkeletonArgs.h b/examples/hello/skeleton/SkeletonArgs.h similarity index 93% rename from examples/hello/skeleton/HelloSkeletonArgs.h rename to examples/hello/skeleton/SkeletonArgs.h index 7ae34366f0..0433e83950 100644 --- a/examples/hello/skeleton/HelloSkeletonArgs.h +++ b/examples/hello/skeleton/SkeletonArgs.h @@ -11,7 +11,7 @@ #include -class HelloSkeletonArgs +class SkeletonArgs { public: @@ -41,7 +41,7 @@ class HelloSkeletonArgs int rank; // MPI rank unsigned int nproc; // number of processors - HelloSkeletonArgs(bool isWriter, int argc, char *argv[], int rank, int nproc); + SkeletonArgs(bool isWriter, int argc, char *argv[], int rank, int nproc); void DecomposeArray(size_t NX, size_t NY); }; diff --git a/examples/hello/skeleton/HelloSkeletonPrint.h b/examples/hello/skeleton/SkeletonPrint.h similarity index 100% rename from examples/hello/skeleton/HelloSkeletonPrint.h rename to examples/hello/skeleton/SkeletonPrint.h diff --git a/examples/hello/skeleton/hello_bpfile.xml b/examples/hello/skeleton/bpfile.xml similarity index 97% rename from examples/hello/skeleton/hello_bpfile.xml rename to examples/hello/skeleton/bpfile.xml index aeb255fd93..f46b17d38b 100644 --- a/examples/hello/skeleton/hello_bpfile.xml +++ b/examples/hello/skeleton/bpfile.xml @@ -1,6 +1,6 @@ diff --git a/examples/hello/skeleton/hello_skeleton.xml b/examples/hello/skeleton/skeleton.xml similarity index 96% rename from examples/hello/skeleton/hello_skeleton.xml rename to examples/hello/skeleton/skeleton.xml index bbca561454..ed9ad58b9c 100644 --- a/examples/hello/skeleton/hello_skeleton.xml +++ b/examples/hello/skeleton/skeleton.xml @@ -1,6 +1,6 @@ diff --git a/examples/hello/skeleton/helloSkeletonReader.cpp b/examples/hello/skeleton/skeletonReader.cpp similarity index 89% rename from examples/hello/skeleton/helloSkeletonReader.cpp rename to examples/hello/skeleton/skeletonReader.cpp index 5744647b2a..84ad636345 100644 --- a/examples/hello/skeleton/helloSkeletonReader.cpp +++ b/examples/hello/skeleton/skeletonReader.cpp @@ -1,3 +1,8 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + */ + #include #include //std::ios_base::failure #include //std::cout @@ -6,8 +11,8 @@ #include -#include "HelloSkeletonArgs.h" -#include "HelloSkeletonPrint.h" +#include "SkeletonArgs.h" +#include "SkeletonPrint.h" int main(int argc, char *argv[]) { @@ -32,7 +37,7 @@ int main(int argc, char *argv[]) try { - HelloSkeletonArgs settings(false, argc, argv, rank, nproc); + SkeletonArgs settings(false, argc, argv, rank, nproc); /** ADIOS class factory of IO class objects, Debug is ON by default */ #if ADIOS2_USE_MPI @@ -48,14 +53,8 @@ int main(int argc, char *argv[]) adios2::Dims count, start; std::vector myArray; - while (true) + while (reader.BeginStep(adios2::StepMode::Read, 60.0f) == adios2::StepStatus::OK) { - adios2::StepStatus status = reader.BeginStep(adios2::StepMode::Read, 60.0f); - if (status != adios2::StepStatus::OK) - { - break; - } - if (step == 0) { // this just discovers in the metadata file that the variable @@ -83,7 +82,7 @@ int main(int argc, char *argv[]) start.push_back(settings.offsy); vMyArray.SetSelection({start, count}); - size_t elementsSize = count[0] * count[1]; + const size_t elementsSize = count[0] * count[1]; myArray.resize(elementsSize); } } diff --git a/examples/hello/skeleton/helloSkeletonWriter.cpp b/examples/hello/skeleton/skeletonWriter.cpp similarity index 93% rename from examples/hello/skeleton/helloSkeletonWriter.cpp rename to examples/hello/skeleton/skeletonWriter.cpp index 407fe967dc..0eb1d43638 100644 --- a/examples/hello/skeleton/helloSkeletonWriter.cpp +++ b/examples/hello/skeleton/skeletonWriter.cpp @@ -13,7 +13,7 @@ #include #include -#include "HelloSkeletonArgs.h" +#include "SkeletonArgs.h" #include @@ -40,7 +40,7 @@ int main(int argc, char *argv[]) try { - HelloSkeletonArgs settings(true, argc, argv, rank, nproc); + SkeletonArgs settings(true, argc, argv, rank, nproc); std::vector myArray(settings.ndx * settings.ndy); @@ -65,7 +65,7 @@ int main(int argc, char *argv[]) { for (size_t i = 0; i < settings.ndx; ++i) { - myArray[idx] = rank + (step / 100.0f); + myArray[idx] = static_cast(rank) + (static_cast(step) / 100.0f); ++idx; } } diff --git a/examples/hello/sstKokkos/CMakeLists.txt b/examples/hello/sstKokkos/CMakeLists.txt new file mode 100644 index 0000000000..4074583bb7 --- /dev/null +++ b/examples/hello/sstKokkos/CMakeLists.txt @@ -0,0 +1,37 @@ +#-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- # +#Distributed under the OSI - approved Apache License, Version 2.0. See +#accompanying file Copyright.txt for details. +#-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- # + +cmake_minimum_required(VERSION 3.12) +project(ADIOS2HelloSSTKokkosExample) + +#CXX Compiler settings only in for this example +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +if (NOT TARGET adios2_core) + set(_components CXX) + + find_package(Kokkos 3.7 QUIET) + if (Kokkos_FOUND AND DEFINED Kokkos_CXX_COMPILER) + set(CMAKE_CXX_COMPILER "${Kokkos_CXX_COMPILER}") + endif() + + find_package(ADIOS2 REQUIRED COMPONENTS ${_components}) +else() + if (DEFINED Kokkos_CXX_COMPILER) + set(CMAKE_CXX_COMPILER "${Kokkos_CXX_COMPILER}") + endif() +endif() + +if (ADIOS2_HAVE_Kokkos) + add_executable(adios2_hello_sstWriterKokkos sstWriterKokkos.cpp) + add_executable(adios2_hello_sstReaderKokkos sstReaderKokkos.cpp) + kokkos_compilation(SOURCE sstWriterKokkos.cpp) + kokkos_compilation(SOURCE sstReaderKokkos.cpp) + target_link_libraries(adios2_hello_sstWriterKokkos adios2::cxx11 Kokkos::kokkos) + install(TARGETS adios2_hello_sstWriterKokkos RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + target_link_libraries(adios2_hello_sstReaderKokkos adios2::cxx11 Kokkos::kokkos) + install(TARGETS adios2_hello_sstReaderKokkos RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) +endif() diff --git a/examples/hello/sstKokkos/sstReaderKokkos.cpp b/examples/hello/sstKokkos/sstReaderKokkos.cpp new file mode 100644 index 0000000000..6dd6f9eed8 --- /dev/null +++ b/examples/hello/sstKokkos/sstReaderKokkos.cpp @@ -0,0 +1,88 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * sstReaderKokkos.cpp Simple example of reading bpFloats through ADIOS2 SST + * engine with multiple simulations steps for every IO step using Kokkos + */ +#include +#include +#include + +#include +#include + +#include + +template +int BPRead(adios2::ADIOS &adios, const std::string fname, const size_t Nx, const size_t Ny, + const size_t nSteps, const std::string engine) +{ + adios2::IO io = adios.DeclareIO("ReadIO"); + io.SetEngine(engine); + + ExecSpace exe_space; + std::cout << "Read on memory space: " << exe_space.name() << std::endl; + + adios2::Engine bpReader = io.Open(fname, adios2::Mode::Read); + + unsigned int step = 0; + bool correctValues = true; + Kokkos::View gpuSimData("simBuffer", Nx, Ny); + for (; bpReader.BeginStep() == adios2::StepStatus::OK; ++step) + { + auto data = io.InquireVariable("bpFloats"); + const adios2::Dims start{0, 0}; + const adios2::Dims count{Nx, Ny}; + const adios2::Box sel(start, count); + data.SetSelection(sel); + + // var.SetMemorySpace(adios2::MemorySpace::GPU); + bpReader.Get(data, gpuSimData); + bpReader.EndStep(); + + auto cpuData = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace{}, gpuSimData); + if (cpuData(0, 0) != step * 10) + { + std::cout << "Value mismatch at step " << step << std::endl; + correctValues = false; + break; + } + } + if (correctValues) + std::cout << "Read " << step << " steps successfully" << std::endl; + + bpReader.Close(); + return 0; +} + +int main(int argc, char **argv) +{ + const std::string engine = argv[1] ? argv[1] : "SST"; + std::cout << "Using engine " << engine << std::endl; + const size_t Nx = 600, Ny = 100, nSteps = 2; + const std::string memorySpace = "Device"; + + const std::string filename = engine + "StepsWriteReadKokkos"; + Kokkos::initialize(argc, argv); + { + adios2::ADIOS adios; + + std::cout << "Using engine " << engine << std::endl; + if (memorySpace == "Device") + { + using mem_space = Kokkos::DefaultExecutionSpace::memory_space; + std::cout << "Memory space: DefaultMemorySpace" << std::endl; + BPRead(adios, filename + "_DD.bp", Nx, Ny, + nSteps, engine); + } + else + { + std::cout << "Memory space: HostSpace" << std::endl; + BPRead(adios, filename + "_HH.bp", Nx, Ny, nSteps, + engine); + } + } + Kokkos::finalize(); + return 0; +} diff --git a/examples/hello/sstKokkos/sstWriterKokkos.cpp b/examples/hello/sstKokkos/sstWriterKokkos.cpp new file mode 100644 index 0000000000..5354d7e228 --- /dev/null +++ b/examples/hello/sstKokkos/sstWriterKokkos.cpp @@ -0,0 +1,96 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * sstWriterKokkos.cpp Simple example of writing bpFloats through ADIOS2 SST + * engine with multiple simulations steps for every IO step using Kokkos + */ +#include +#include +#include + +#include +#include + +#include + +template +int BPWrite(adios2::ADIOS &adios, const std::string fname, const size_t Nx, const size_t Ny, + const size_t nSteps, const std::string engine) +{ + // Initialize the simulation data + Kokkos::View gpuSimData("simBuffer", Nx, Ny); + static_assert(Kokkos::SpaceAccessibility::accessible, ""); + Kokkos::parallel_for( + "initBuffer", Kokkos::RangePolicy(0, Nx), KOKKOS_LAMBDA(int i) { + for (int j = 0; j < Ny; j++) + gpuSimData(i, j) = static_cast(i); + }); + Kokkos::fence(); + + adios2::IO io = adios.DeclareIO("WriteIO"); + io.SetEngine(engine); + + const adios2::Dims shape{Nx, Ny}; + const adios2::Dims start{0, 0}; + const adios2::Dims count{Nx, Ny}; + auto data = io.DefineVariable("bpFloats", shape, start, count); + + adios2::Engine bpWriter = io.Open(fname, adios2::Mode::Write); + + // Simulation steps + for (int step = 0; step < nSteps; ++step) + { + adios2::Box sel({0, 0}, {Nx, Ny}); + data.SetSelection(sel); + + bpWriter.BeginStep(); + // var.SetMemorySpace(adios2::MemorySpace::GPU); + bpWriter.Put(data, gpuSimData); + bpWriter.EndStep(); + + // Update values in the simulation data + Kokkos::parallel_for( + "updateBuffer", Kokkos::RangePolicy(0, Nx), KOKKOS_LAMBDA(int i) { + for (int j = 0; j < Ny; j++) + gpuSimData(i, j) += 10; + }); + Kokkos::fence(); + } + + bpWriter.Close(); + ExecSpace exe_space; + std::cout << "Done writing on memory space: " << exe_space.name() << std::endl; + return 0; +} + +int main(int argc, char **argv) +{ + const std::string engine = argv[1] ? argv[1] : "SST"; + std::cout << "Using engine " << engine << std::endl; + const size_t Nx = 600, Ny = 100, nSteps = 2; + const std::string memorySpace = "Device"; + + const std::string filename = engine + "StepsWriteReadKokkos"; + Kokkos::initialize(argc, argv); + { + adios2::ADIOS adios; + + std::cout << "Using engine " << engine << std::endl; + if (memorySpace == "Device") + { + using mem_space = Kokkos::DefaultExecutionSpace::memory_space; + std::cout << "Memory space: DefaultMemorySpace" << std::endl; + BPWrite(adios, filename + "_DD.bp", Nx, Ny, + nSteps, engine); + } + else + { + std::cout << "Memory space: HostSpace" << std::endl; + BPWrite(adios, filename + "_HH.bp", Nx, Ny, nSteps, + engine); + } + } + Kokkos::finalize(); + return 0; +} diff --git a/examples/hello/sstReader/CMakeLists.txt b/examples/hello/sstReader/CMakeLists.txt index eff30267d5..39a0b615c0 100644 --- a/examples/hello/sstReader/CMakeLists.txt +++ b/examples/hello/sstReader/CMakeLists.txt @@ -3,10 +3,35 @@ # accompanying file Copyright.txt for details. #------------------------------------------------------------------------------# -add_executable(hello_sstReader helloSstReader.cpp) -target_link_libraries(hello_sstReader adios2::cxx11) +cmake_minimum_required(VERSION 3.12) +project(ADIOS2HelloSstReaderExample) -if(ADIOS2_HAVE_MPI) - add_executable(hello_sstReader_mpi helloSstReader.cpp) - target_link_libraries(hello_sstReader_mpi adios2::cxx11_mpi MPI::MPI_C) +if(NOT TARGET adios2_core) + set(_components CXX) + + find_package(MPI COMPONENTS C) + if(MPI_FOUND) + # Workaround for various MPI implementations forcing the link of C++ bindings + add_definitions(-DOMPI_SKIP_MPICXX -DMPICH_SKIP_MPICXX) + + list(APPEND _components MPI) + endif() + + if(NOT WIN32) + find_package(LIBFABRIC 1.6 QUIET) + endif() + + find_package(ADIOS2 REQUIRED COMPONENTS ${_components}) +endif() + +if(ADIOS2_HAVE_SST) + add_executable(adios2_hello_sstReader sstReader.cpp) + target_link_libraries(adios2_hello_sstReader adios2::cxx11) + install(TARGETS adios2_hello_sstReader RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + + if(ADIOS2_HAVE_MPI) + add_executable(adios2_hello_sstReader_mpi sstReader.cpp) + target_link_libraries(adios2_hello_sstReader_mpi adios2::cxx11_mpi MPI::MPI_C) + install(TARGETS adios2_hello_sstReader_mpi RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + endif() endif() diff --git a/examples/hello/sstReader/helloSstReader.cpp b/examples/hello/sstReader/sstReader.cpp similarity index 97% rename from examples/hello/sstReader/helloSstReader.cpp rename to examples/hello/sstReader/sstReader.cpp index 8dfcb1ba0c..56630b3eea 100644 --- a/examples/hello/sstReader/helloSstReader.cpp +++ b/examples/hello/sstReader/sstReader.cpp @@ -2,10 +2,10 @@ * Distributed under the OSI-approved Apache License, Version 2.0. See * accompanying file Copyright.txt for details. * - * helloSstReader.cpp + * sstReader.cpp * * Created on: Aug 17, 2017 -v * Author: Greg Eisenhauer + * Author: Greg Eisenhauer */ #include diff --git a/examples/hello/sstWriter/CMakeLists.txt b/examples/hello/sstWriter/CMakeLists.txt index 637e00bfd4..f5adca3e58 100644 --- a/examples/hello/sstWriter/CMakeLists.txt +++ b/examples/hello/sstWriter/CMakeLists.txt @@ -3,10 +3,35 @@ # accompanying file Copyright.txt for details. #------------------------------------------------------------------------------# -add_executable(hello_sstWriter helloSstWriter.cpp) -target_link_libraries(hello_sstWriter adios2::cxx11) +cmake_minimum_required(VERSION 3.12) +project(ADIOS2HelloSstWriterExample) -if(ADIOS2_HAVE_MPI) - add_executable(hello_sstWriter_mpi helloSstWriter.cpp) - target_link_libraries(hello_sstWriter_mpi adios2::cxx11_mpi MPI::MPI_C) +if(NOT TARGET adios2_core) + set(_components CXX) + + find_package(MPI COMPONENTS C) + if(MPI_FOUND) + # Workaround for various MPI implementations forcing the link of C++ bindings + add_definitions(-DOMPI_SKIP_MPICXX -DMPICH_SKIP_MPICXX) + + list(APPEND _components MPI) + endif() + + if (NOT WIN32) + find_package(LIBFABRIC 1.6 QUIET) + endif () + + find_package(ADIOS2 REQUIRED COMPONENTS ${_components}) +endif() + +if(ADIOS2_HAVE_SST) + add_executable(adios2_hello_sstWriter sstWriter.cpp) + target_link_libraries(adios2_hello_sstWriter adios2::cxx11) + install(TARGETS adios2_hello_sstWriter RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + + if(ADIOS2_HAVE_MPI) + add_executable(adios2_hello_sstWriter_mpi sstWriter.cpp) + target_link_libraries(adios2_hello_sstWriter_mpi adios2::cxx11_mpi MPI::MPI_C) + install(TARGETS adios2_hello_sstWriter_mpi RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + endif() endif() diff --git a/examples/hello/sstWriter/helloSstWriter.cpp b/examples/hello/sstWriter/sstWriter.cpp similarity index 81% rename from examples/hello/sstWriter/helloSstWriter.cpp rename to examples/hello/sstWriter/sstWriter.cpp index e4c58b1b17..02d4981171 100644 --- a/examples/hello/sstWriter/helloSstWriter.cpp +++ b/examples/hello/sstWriter/sstWriter.cpp @@ -2,7 +2,7 @@ * Distributed under the OSI-approved Apache License, Version 2.0. See * accompanying file Copyright.txt for details. * - * helloSstWriter.cpp + * sstWriter.cpp * * Created on: Aug 17, 2017 * Author: Greg Eisenhauer @@ -35,11 +35,12 @@ int main(int argc, char *argv[]) size = 1; #endif - std::vector myFloats = {(float)10.0 * rank + 0, (float)10.0 * rank + 1, - (float)10.0 * rank + 2, (float)10.0 * rank + 3, - (float)10.0 * rank + 4, (float)10.0 * rank + 5, - (float)10.0 * rank + 6, (float)10.0 * rank + 7, - (float)10.0 * rank + 8, (float)10.0 * rank + 9}; + std::vector myFloats = { + static_cast(10.0 * rank + 0), static_cast(10.0 * rank + 1), + static_cast(10.0 * rank + 2), static_cast(10.0 * rank + 3), + static_cast(10.0 * rank + 4), static_cast(10.0 * rank + 5), + static_cast(10.0 * rank + 6), static_cast(10.0 * rank + 7), + static_cast(10.0 * rank + 8), static_cast(10.0 * rank + 9)}; const std::size_t Nx = myFloats.size(); try diff --git a/examples/hello/sstWriter/helloSstWriter.py b/examples/hello/sstWriter/sstWriter.py similarity index 72% rename from examples/hello/sstWriter/helloSstWriter.py rename to examples/hello/sstWriter/sstWriter.py index 99508627ad..08a7a8270a 100644 --- a/examples/hello/sstWriter/helloSstWriter.py +++ b/examples/hello/sstWriter/sstWriter.py @@ -12,13 +12,13 @@ # ADIOS IO sstIO = adios.DeclareIO("myIO") -sstIO.SetEngine('Sst') -myArray = np.array([0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0], - dtype='f') +sstIO.SetEngine("Sst") +myArray = np.array([0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0], dtype="f") myArray = 10.0 * rank + myArray nx = len(myArray) -ioArray = sstIO.DefineVariable("bpFloats", myArray, [size * nx], - [rank * nx], [nx], adios2.ConstantDims) +ioArray = sstIO.DefineVariable( + "bpFloats", myArray, [size * nx], [rank * nx], [nx], adios2.ConstantDims +) sstFileWriter = sstIO.Open("helloSst", adios2.Mode.Write) sstFileWriter.BeginStep() sstFileWriter.Put(ioArray, myArray, adios2.Mode.Sync) diff --git a/examples/inlineMWE/CMakeLists.txt b/examples/inlineMWE/CMakeLists.txt deleted file mode 100644 index 3773d2d3f7..0000000000 --- a/examples/inlineMWE/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ -#------------------------------------------------------------------------------# -# Distributed under the OSI-approved Apache License, Version 2.0. See -# accompanying file Copyright.txt for details. -#------------------------------------------------------------------------------# - -add_executable(inlineMWE inlineMWE.cpp) -target_link_libraries(inlineMWE adios2::cxx11) diff --git a/examples/plugins/CMakeLists.txt b/examples/plugins/CMakeLists.txt index 5fed9662d6..013d696b17 100644 --- a/examples/plugins/CMakeLists.txt +++ b/examples/plugins/CMakeLists.txt @@ -4,4 +4,6 @@ #------------------------------------------------------------------------------# add_subdirectory(engine) -add_subdirectory(operator) +if(ADIOS2_HAVE_Sodium) + add_subdirectory(operator) +endif() diff --git a/examples/plugins/ReadMe.md b/examples/plugins/ReadMe.md new file mode 100644 index 0000000000..3fbfdaa0c6 --- /dev/null +++ b/examples/plugins/ReadMe.md @@ -0,0 +1,13 @@ +## ADIOS2 plugins examples + +The _plugins_ examples are meant to introduce you to the plugin capabilities of ADIOS2, such as +how to develop your own engine or operators. + +They can be found in the following subdirectories, and they should be explored in the order that they are listed: + +1. [engine](engine): The _engine_ example demonstrates how to develop the read/write capabilities of your ADIOS2 engine + and use it to read and write variables. + * Languages: C++ +2. [operator](operator): The _operator_ example demonstrates how to read and write variables using the + ADIOS2/plugins/operators/EncryptionOperator and ADIOS2's BP engine. + * Languages: C++ diff --git a/examples/plugins/engine/CMakeLists.txt b/examples/plugins/engine/CMakeLists.txt index a611c0b8b7..d902043a83 100644 --- a/examples/plugins/engine/CMakeLists.txt +++ b/examples/plugins/engine/CMakeLists.txt @@ -3,33 +3,39 @@ # accompanying file Copyright.txt for details. #------------------------------------------------------------------------------# +cmake_minimum_required(VERSION 3.12) +project(ADIOS2PluginsEngineExample) + +if(NOT TARGET adios2_core) + set(_components CXX) + + find_package(ADIOS2 REQUIRED COMPONENTS ${_components}) +endif() + include(GenerateExportHeader) -add_library(PluginEngineWrite - ExampleWritePlugin.cpp -) -target_link_libraries(PluginEngineWrite adios2::cxx11 adios2_core) -generate_export_header(PluginEngineWrite BASE_NAME plugin_engine_write) -target_include_directories(PluginEngineWrite PUBLIC + +add_library(adios2_plugins_exampleWritePlugin ExampleWritePlugin.cpp) +target_link_libraries(adios2_plugins_exampleWritePlugin adios2::cxx11 adios2_core) +generate_export_header(adios2_plugins_exampleWritePlugin BASE_NAME plugin_engine_write) +target_include_directories(adios2_plugins_exampleWritePlugin PUBLIC $ $ ) +install(TARGETS adios2_plugins_exampleWritePlugin RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) -add_library(PluginEngineRead - ExampleReadPlugin.cpp -) -target_link_libraries(PluginEngineRead adios2::cxx11 adios2_core) -generate_export_header(PluginEngineRead BASE_NAME plugin_engine_read) -target_include_directories(PluginEngineRead PUBLIC +add_library(adios2_plugins_exampleReadPlugin ExampleReadPlugin.cpp) +target_link_libraries(adios2_plugins_exampleReadPlugin adios2::cxx11 adios2_core) +generate_export_header(adios2_plugins_exampleReadPlugin BASE_NAME plugin_engine_read) +target_include_directories(adios2_plugins_exampleReadPlugin PUBLIC $ $ ) +install(TARGETS adios2_plugins_exampleReadPlugin RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) -add_executable(examplePluginEngine_write - examplePluginEngine_write.cpp -) -target_link_libraries(examplePluginEngine_write adios2::cxx11) +add_executable(adios2_plugins_examplePluginEngineWrite examplePluginEngineWrite.cpp) +target_link_libraries(adios2_plugins_examplePluginEngineWrite adios2::cxx11) +install(TARGETS adios2_plugins_examplePluginEngineWrite RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) -add_executable(examplePluginEngine_read - examplePluginEngine_read.cpp -) -target_link_libraries(examplePluginEngine_read adios2::cxx11) +add_executable(adios2_plugins_examplePluginEngineRead examplePluginEngineRead.cpp) +target_link_libraries(adios2_plugins_examplePluginEngineRead adios2::cxx11) +install(TARGETS adios2_plugins_examplePluginEngineRead RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) diff --git a/examples/plugins/engine/examplePluginEngine_read.cpp b/examples/plugins/engine/examplePluginEngineRead.cpp similarity index 60% rename from examples/plugins/engine/examplePluginEngine_read.cpp rename to examples/plugins/engine/examplePluginEngineRead.cpp index 17042868dc..02241e4291 100644 --- a/examples/plugins/engine/examplePluginEngine_read.cpp +++ b/examples/plugins/engine/examplePluginEngineRead.cpp @@ -2,7 +2,7 @@ * Distributed under the OSI-approved Apache License, Version 2.0. See * accompanying file Copyright.txt for details. * - * examplePluginEngine_read.cpp example showing how to use ExampleReadPlugin + * examplePluginEngineRead.cpp example showing how to use ExampleReadPlugin * engine * * Created on: July 5, 2021 @@ -16,35 +16,6 @@ #include "adios2.h" -void testStreaming(adios2::Engine &reader, std::vector &myFloats, - adios2::Variable &var) -{ - for (int i = 0; i < 2; i++) - { - if (i == 1) - { - for (auto &num : myFloats) - { - num *= 2; - } - } - - reader.BeginStep(); - std::vector readFloats; - reader.Get(var, readFloats); - reader.EndStep(); - - if (readFloats == myFloats) - { - std::cout << "data was read correctly!" << std::endl; - } - else - { - std::cout << "data was not read correctly!" << std::endl; - } - } -} - int main(int argc, char *argv[]) { std::string config; @@ -53,12 +24,6 @@ int main(int argc, char *argv[]) config = std::string(argv[1]); } - bool streaming = false; - if (argc > 2) - { - streaming = std::atoi(argv[2]) == 1; - } - std::vector myFloats = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; bool success = false; @@ -82,30 +47,38 @@ int main(int argc, char *argv[]) } adios2::Engine reader = io.Open("TestPlugin", adios2::Mode::Read); - auto var = io.InquireVariable("data"); - if (!var) - { - std::cout << "variable does not exist" << std::endl; - } - - if (streaming) - { - testStreaming(reader, myFloats, var); - } - else + // test streaming + for (int i = 0; i < 2; i++) { - std::vector readFloats; - reader.Get(var, readFloats); - reader.PerformGets(); + if (i == 1) + { + for (auto &num : myFloats) + { + num *= 2; + } + } - if (readFloats == myFloats) + reader.BeginStep(); + auto var = io.InquireVariable("data"); + if (!var) { - std::cout << "data was read correctly!" << std::endl; + std::cout << "variable does not exist" << std::endl; } else { - std::cout << "data was not read correctly!" << std::endl; + std::vector readFloats; + reader.Get(var, readFloats); + + if (readFloats == myFloats) + { + std::cout << "data was read correctly!" << std::endl; + } + else + { + std::cout << "data was not read correctly!" << std::endl; + } } + reader.EndStep(); } /** Engine becomes unreachable after this*/ diff --git a/examples/plugins/engine/examplePluginEngine_write.cpp b/examples/plugins/engine/examplePluginEngineWrite.cpp similarity index 77% rename from examples/plugins/engine/examplePluginEngine_write.cpp rename to examples/plugins/engine/examplePluginEngineWrite.cpp index bb6f6f51b9..75b51c660d 100644 --- a/examples/plugins/engine/examplePluginEngine_write.cpp +++ b/examples/plugins/engine/examplePluginEngineWrite.cpp @@ -2,7 +2,7 @@ * Distributed under the OSI-approved Apache License, Version 2.0. See * accompanying file Copyright.txt for details. * - * examplePluginEngine_write.cpp example showing how to use ExampleWritePlugin + * examplePluginEngineWrite.cpp example showing how to use ExampleWritePlugin * engine * * Created on: July 5, 2021 @@ -16,24 +16,6 @@ #include "adios2.h" -void testStreaming(adios2::Engine &writer, std::vector &myFloats, - adios2::Variable &var) -{ - for (int i = 0; i < 2; i++) - { - if (i == 1) - { - for (auto &num : myFloats) - { - num *= 2; - } - } - writer.BeginStep(); - writer.Put(var, myFloats.data()); - writer.EndStep(); - } -} - int main(int argc, char *argv[]) { std::string config; @@ -42,12 +24,6 @@ int main(int argc, char *argv[]) config = std::string(argv[1]); } - bool streaming = false; - if (argc > 2) - { - streaming = std::atoi(argv[2]) == 1; - } - /** Application variable */ std::vector myFloats = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; const std::size_t Nx = myFloats.size(); @@ -78,14 +54,19 @@ int main(int argc, char *argv[]) } adios2::Engine writer = io.Open("TestPlugin", adios2::Mode::Write); - if (streaming) - { - testStreaming(writer, myFloats, var); - } - else + // test streaming + for (int i = 0; i < 2; i++) { + if (i == 1) + { + for (auto &num : myFloats) + { + num *= 2; + } + } + writer.BeginStep(); writer.Put(var, myFloats.data()); - writer.PerformPuts(); + writer.EndStep(); } /** Engine becomes unreachable after this*/ diff --git a/examples/plugins/engine/example_engine.xml b/examples/plugins/engine/example_engine.xml index 412c1a9684..46393a70d7 100644 --- a/examples/plugins/engine/example_engine.xml +++ b/examples/plugins/engine/example_engine.xml @@ -10,7 +10,7 @@ - + @@ -22,7 +22,7 @@ - + diff --git a/examples/plugins/operator/CMakeLists.txt b/examples/plugins/operator/CMakeLists.txt index 8881bb8f16..f71e6dca20 100644 --- a/examples/plugins/operator/CMakeLists.txt +++ b/examples/plugins/operator/CMakeLists.txt @@ -2,12 +2,24 @@ # Distributed under the OSI-approved Apache License, Version 2.0. See # accompanying file Copyright.txt for details. #------------------------------------------------------------------------------# -add_executable(exampleOperatorPlugin_write - examplePluginOperator_write.cpp -) -target_link_libraries(exampleOperatorPlugin_write adios2::cxx11) - -add_executable(exampleOperatorPlugin_read - examplePluginOperator_read.cpp -) -target_link_libraries(exampleOperatorPlugin_read adios2::cxx11) + +cmake_minimum_required(VERSION 3.12) +project(ADIOS2PluginsOperatorExample) + +if(NOT TARGET adios2_core) + set(_components CXX) + + find_package(Sodium QUIET) + + find_package(ADIOS2 REQUIRED COMPONENTS ${_components}) +endif() + +if(ADIOS2_HAVE_Sodium) + add_executable(adios2_plugins_exampleOperatorPluginWrite examplePluginOperatorWrite.cpp) + target_link_libraries(adios2_plugins_exampleOperatorPluginWrite adios2::cxx11) + install(TARGETS adios2_plugins_exampleOperatorPluginWrite RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + + add_executable(adios2_plugins_exampleOperatorPluginRead examplePluginOperatorRead.cpp) + target_link_libraries(adios2_plugins_exampleOperatorPluginRead adios2::cxx11) + install(TARGETS adios2_plugins_exampleOperatorPluginRead RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) +endif() \ No newline at end of file diff --git a/examples/plugins/operator/examplePluginOperator_read.cpp b/examples/plugins/operator/examplePluginOperatorRead.cpp similarity index 95% rename from examples/plugins/operator/examplePluginOperator_read.cpp rename to examples/plugins/operator/examplePluginOperatorRead.cpp index 01e47e92a5..1430b7cd96 100644 --- a/examples/plugins/operator/examplePluginOperator_read.cpp +++ b/examples/plugins/operator/examplePluginOperatorRead.cpp @@ -2,7 +2,7 @@ * Distributed under the OSI-approved Apache License, Version 2.0. See * accompanying file Copyright.txt for details. * - * examplePluginOperator_read.cpp example showing how to use EncryptionOperator + * examplePluginOperatorRead.cpp example showing how to use EncryptionOperator * plugin * * Created on: July 5, 2021 @@ -51,6 +51,7 @@ int main(int argc, char *argv[]) /** global array: name, { shape (total dimensions) }, { start (local) }, * { count (local) }, all are constant dimensions */ adios2::Engine reader = io.Open("testOperator.bp", adios2::Mode::Read); + reader.BeginStep(); auto var = io.InquireVariable("data"); if (!var) { @@ -59,7 +60,7 @@ int main(int argc, char *argv[]) if (config.empty()) { - io.SetEngine("BP4"); + io.SetEngine("BPFile"); /* PluginName -> is required. If your operator needs * other parameters, they can be passed in here as well. */ adios2::Params params; @@ -81,6 +82,7 @@ int main(int argc, char *argv[]) { std::cout << "data was not read correctly!" << std::endl; } + reader.EndStep(); /** Engine becomes unreachable after this*/ reader.Close(); diff --git a/examples/plugins/operator/examplePluginOperator_write.cpp b/examples/plugins/operator/examplePluginOperatorWrite.cpp similarity index 97% rename from examples/plugins/operator/examplePluginOperator_write.cpp rename to examples/plugins/operator/examplePluginOperatorWrite.cpp index 28dfe33f4b..2909b28bf7 100644 --- a/examples/plugins/operator/examplePluginOperator_write.cpp +++ b/examples/plugins/operator/examplePluginOperatorWrite.cpp @@ -56,7 +56,7 @@ int main(int argc, char *argv[]) if (config.empty()) { - io.SetEngine("BP4"); + io.SetEngine("BPFile"); /* PluginName -> is required. If your operator needs * other parameters, they can be passed in here as well. */ adios2::Params params; @@ -68,7 +68,9 @@ int main(int argc, char *argv[]) adios2::Engine writer = io.Open("testOperator.bp", adios2::Mode::Write); + writer.BeginStep(); writer.Put(var, myDoubles.data()); + writer.EndStep(); /** Engine becomes unreachable after this*/ writer.Close(); diff --git a/examples/query/CMakeLists.txt b/examples/query/CMakeLists.txt deleted file mode 100644 index 444dda6fef..0000000000 --- a/examples/query/CMakeLists.txt +++ /dev/null @@ -1,10 +0,0 @@ -#------------------------------------------------------------------------------# -# Distributed under the OSI-approved Apache License, Version 2.0. See -# accompanying file Copyright.txt for details. -#------------------------------------------------------------------------------# - -if(ADIOS2_HAVE_MPI) - add_executable(queryTest test.cpp) - target_link_libraries(queryTest adios2::cxx11_mpi MPI::MPI_C) -endif() - diff --git a/examples/query/READ.ME b/examples/query/READ.ME deleted file mode 100644 index 65b8042d3e..0000000000 --- a/examples/query/READ.ME +++ /dev/null @@ -1,8 +0,0 @@ -q1.json is a json query file for one var - -q2.json is a composite query - -The bp*xml are the from heat transfer example with bp4 engine. -and tag is added at the end for xml query spec - -JSON query file option should be used with ADIOS2_HAVE_DATAMAN \ No newline at end of file diff --git a/examples/query/test.cpp b/examples/query/test.cpp deleted file mode 100644 index 94da39a0dc..0000000000 --- a/examples/query/test.cpp +++ /dev/null @@ -1,136 +0,0 @@ -#include "adios2.h" -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -// #include "adios2/toolkit/query/Worker.h" - -int main(int argc, char *argv[]) -{ - int provided; - - // MPI_THREAD_MULTIPLE is only required if you enable the SST MPI_DP - MPI_Init_thread(&argc, &argv, MPI_THREAD_MULTIPLE, &provided); - int rank, size; - MPI_Comm_rank(MPI_COMM_WORLD, &rank); - MPI_Comm_size(MPI_COMM_WORLD, &size); - - try - { - std::string configFileName = "query.xml"; - std::string dataFileName = "/tmp/heatbp4.bp"; - if (argc <= 2) - { - std::cout << "Usage: " << argv[0] << " configFileName dataFilePath (queryFile)" - << std::endl; - std::cout << " e.g. " << argv[0] << " bp4io.xml heat_bp4.bp/ " << std::endl; - std::cout << " or " << argv[0] << " bp4io.xml heat_bp4.bp/ q1.json" << std::endl; - return 0; - } - - configFileName = argv[1]; - dataFileName = argv[2]; - - if (rank == 0) - { - std::cout << " using config file = " << configFileName << std::endl; - std::cout << " data file = " << dataFileName << std::endl; - } - - adios2::ADIOS ad = adios2::ADIOS(configFileName, MPI_COMM_WORLD); - - adios2::IO queryIO = ad.DeclareIO("query"); - adios2::Engine reader = queryIO.Open(dataFileName, adios2::Mode::Read, MPI_COMM_WORLD); -#ifdef NEVER - adios2::QueryWorker w = adios2::QueryWorker(configFileName, reader); -#else - std::string queryFile = configFileName; - if (argc > 3) - { - queryFile = argv[3]; - } - std::cout << "Testing query file ..." << queryFile << std::endl; - adios2::QueryWorker w = adios2::QueryWorker(queryFile, reader); -#endif - std::vector> touched_blocks; - - while (reader.BeginStep() == adios2::StepStatus::OK) - { - adios2::Box empty; - w.GetResultCoverage(empty, touched_blocks); - // adios2::Box tt({10,10}, {12,12}); - // w.GetResultCoverage(tt, touched_blocks); - std::cout << " ... now can read out touched blocks ... size=" << touched_blocks.size() - << std::endl; - for (auto n : touched_blocks) - { - std::ostringstream startStr; - std::ostringstream countStr; - for (size_t k = 0; k < n.first.size(); k++) - { - startStr << n.first[k] << " "; - countStr << n.second[k] << " "; - } - std::cout << "\t[" << startStr.str() << "] [" << countStr.str() << "]" - << std::endl; - } - reader.EndStep(); - } - reader.Close(); - return 0; - } - catch (std::exception &e) - { - std::cout << "Exception, STOPPING PROGRAM from rank " << rank << "\n"; - std::cout << e.what() << "\n"; - } - - MPI_Finalize(); - - return 0; -} - -bool testMe(std::string &queryConfigFile, std::string const &doubleVarName, MPI_Comm comm) -{ - adios2::ADIOS ad(queryConfigFile, comm); - std::string dataFileName = "test.file"; - - // adios2::query::Worker w(queryConfigFile, comm); - - // w.SetSource(inIO, reader); - - { - // the config file should have info on idx method to use - - /* - // if wanting to build customized minmax idx - // instead of using the existing block stats or bp4 minmax arrays - bool overwrite = false; - size_t recommendedSize = 20000; - - if (!w.PrepareIdx(overwrite, recommendedSize, doubleVarName)) - return false; - */ - } - - adios2::IO inIO = ad.DeclareIO("query"); - adios2::Engine reader = inIO.Open(dataFileName, adios2::Mode::Read, comm); - - // to be continued - if (!reader) - return false; - // std::vector dataOutput; - // std::vector coordinateOutput; - - return true; -} - -/* - */ diff --git a/examples/simulations/CMakeLists.txt b/examples/simulations/CMakeLists.txt new file mode 100644 index 0000000000..d6b6434beb --- /dev/null +++ b/examples/simulations/CMakeLists.txt @@ -0,0 +1,13 @@ +if(ADIOS2_HAVE_MPI) + add_subdirectory(gray-scott) + add_subdirectory(gray-scott-struct) + + if(ADIOS2_HAVE_Kokkos) + add_subdirectory(gray-scott-kokkos) + endif() + + add_subdirectory(heatTransfer) +endif() + +add_subdirectory(korteweg-de-vries) +add_subdirectory(lorenz_ode) diff --git a/examples/simulations/GrayScott.jl/.JuliaFormatter.toml b/examples/simulations/GrayScott.jl/.JuliaFormatter.toml new file mode 100644 index 0000000000..00db94693b --- /dev/null +++ b/examples/simulations/GrayScott.jl/.JuliaFormatter.toml @@ -0,0 +1,4 @@ +margin = 80 +join_lines_based_on_source = true +style = "sciml" +format_doctrings = true diff --git a/examples/simulations/GrayScott.jl/Project.toml b/examples/simulations/GrayScott.jl/Project.toml new file mode 100644 index 0000000000..a295ba3546 --- /dev/null +++ b/examples/simulations/GrayScott.jl/Project.toml @@ -0,0 +1,19 @@ +name = "GrayScott" +uuid = "089a57ea-382b-4fd7-9f05-24902db6ec52" +authors = ["William F Godoy "] +version = "0.1.0" + +[deps] +ADIOS2 = "e0ce9d3b-0dbd-416f-8264-ccca772f60ec" +AMDGPU = "21141c5a-9bdb-4563-92ae-f87d6854732e" +ArgParse = "c7e460c6-2fb9-53a9-8c5b-16f535851c63" +CUDA = "052768ef-5323-5732-b1bb-66c8b64840ba" +Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f" +JSON = "682c06a0-de6a-54ab-a142-c8b1cf79cde6" +MPI = "da04e1cc-30fd-572f-bb4f-1f8673147195" +MPIPreferences = "3da0fdf6-3ccc-4f1b-acd9-58baa6c99267" +PProf = "e4faabce-9ead-11e9-39d9-4379958e3056" +Profile = "9abbd945-dff8-562f-b5e8-e1ebf5ef1b79" + +[compat] +julia = "1.8" diff --git a/examples/simulations/GrayScott.jl/ReadMe.md b/examples/simulations/GrayScott.jl/ReadMe.md new file mode 100644 index 0000000000..2e12adb5d8 --- /dev/null +++ b/examples/simulations/GrayScott.jl/ReadMe.md @@ -0,0 +1,154 @@ +### ADIOS2 GrayScott.jl example + +Julia version +of [the gray-scott C++ and Python](https://github.com/ornladios/ADIOS2/blob/master/examples/simulations/gray-scott/) +example. + +This is a 3D 7-point stencil code to simulate the following [Gray-Scott +reaction diffusion model](https://doi.org/10.1126/science.261.5118.189): + +``` +u_t = Du * (u_xx + u_yy + u_zz) - u * v^2 + F * (1 - u) + noise * randn(-1,1) +v_t = Dv * (v_xx + v_yy + v_zz) + u * v^2 - (F + k) * v +``` + +This version contains: + +- CPU threaded solver using Julia's [multithreading]](https://docs.julialang.org/en/v1/manual/multi-threading/) +- GPU solvers using [CUDA.jl](https://github.com/JuliaGPU/CUDA.jl), [AMDGPU.jl](https://github.com/JuliaGPU/AMDGPU.jl) +- Parallel I/O using the [ADIOS2.jl](https://github.com/eschnett/ADIOS2.jl) Julia bindings + to [ADIOS2](https://github.com/ornladios/ADIOS2) +- Message passing interface (MPI) using [MPI.jl](https://github.com/JuliaParallel/MPI.jl) Julia bindings to MPI +- Easily switch between float- (Float32) and double- (Float64) precision in the configuration file + +#### How to run + +Currently only the simulation part is ported from C++, the data analysis is work-in-progress. + +Pre-requisites: + +- A recent Julia version: v1.8.5 or v1.9.0-beta3 as of January 2023 + from [julialang.org/downloads](https://julialang.org/downloads/) + +##### Run locally + +1. **Set up dependencies** + +From the `GrayScott.jl` directory instantiate and use MPI artifact jll (preferred method). +To use a system provided MPI, see [here](https://juliaparallel.org/MPI.jl/latest/configuration/#using_system_mpi) + +```julia + +$ julia --project + +Julia REPL + +julia> ] + +(GrayScott.jl)> instantiate +... +(GrayScott.jl)> <- +julia> using MPIPreferences +julia> MPIPreferences.use_jll_binary() +julia> exit() +``` + +Julia manages its own packages using [Pkg.jl](https://pkgdocs.julialang.org/v1/), the above would create +platform-specific `LocalPreferences.toml` and `Manifest.toml` files. + +2. **Set up the examples/settings-files.json configuration file** + +``` +{ + "L": 64, + "Du": 0.2, + "Dv": 0.1, + "F": 0.02, + "k": 0.048, + "dt": 1.0, + "plotgap": 10, + "steps": 10000, + "noise": 0.1, + "output": "gs-julia-1MPI-64L-F32.bp", + "checkpoint": false, + "checkpoint_freq": 700, + "checkpoint_output": "ckpt.bp", + "restart": false, + "restart_input": "ckpt.bp", + "adios_config": "adios2.xml", + "adios_span": false, + "adios_memory_selection": false, + "mesh_type": "image", + "precision": "Float32", + "backend": "CPU" +} + +``` + +The file is nearly identical to the C++ original example. +Not all options are currently supported, but two Julia-only options are added: + + - "precision": either Float32 or Float64 in the array simulation (including GPUs) + - "backend": "CPU", "CUDA" or "AMDGPU" + +3. **Running the simulation** + +- `CPU threads`: launch julia assigning a number of threads (e.g. -t 8): + + ``` + $ julia --project -t 8 gray-scott.jl examples/settings-files.json + ``` + +- `CUDA/AMDGPU`: set the "backend" option in examples/settings-files.json to either "CUDA" or "AMDGPU" + + ``` + $ julia --project gray-scott.jl examples/settings-files.json + ``` + +This would generate an adios2 file from the output entry in the configuration file (e.g. `gs-julia-1MPI-64L-F32.bp`) +that can be visualized with ParaView with either the VTX or the FIDES readers. +**Important**: the AMDGPU.jl implementation of `randn` is currently work in progress. +See related issue [here](https://github.com/JuliaGPU/AMDGPU.jl/issues/378) + +4. **Running on OLCF Summit and Crusher systems** + The code was tested on the Oak Ridge National Laboratory Leadership Computing Facilities ( + OLCF): [Summit](https://docs.olcf.ornl.gov/systems/summit_user_guide.html) + and [Crusher](https://docs.olcf.ornl.gov/systems/crusher_quick_start_guide.html). Both are used testing a recent + version of Julia [v1.9.0-beta3](https://julialang.org/downloads/#upcoming_release) and a `JULIA_DEPOT_PATH` is + required to install packages and artifacts. **DO NOT USE your home directory**. We are providing configuration + scripts in `scripts/config_XXX.sh` showing the plumming required for these systems. They need to be executed only + once per session from the login nodes. + +To reuse these file the first 3 entries must be modified and run on login-nodes and the PATH poiting at a downloaded +Julia binary for the corresponding PowerPC (Summit) and x86-64 (Crusher) architectures. Only "CPU" and "CUDA" backends +are supported on Summit, while "CPU" and "AMDGPU" backends are supported on Crusher. + + ``` + ### Replace these 3 entries + PROJ_DIR=/gpfs/alpine/proj-shared/csc383 + export JULIA_DEPOT_PATH=$PROJ_DIR/etc/summit/julia_depot + GS_DIR=$PROJ_DIR/wgodoy/ADIOS2/examples/simulations/GrayScott.jl + ... + ### and the path + export PATH=$PROJ_DIR/opt/summit/julia-1.9.0-beta3/bin:$PATH + ``` + +#### To-do list + +1. Add support including random number on device kernel code on `AMDGPU.jl` +2. Set the domain size `L` in the configuration file as a multiple of 6 for Summit, and a multiple of 4 on Crusher +3. Add data analysis: PDF for u and v and Julia 2D plotting capabilities: Plots.jl, Makie.jl +4. Add interactive computing with Pluto.jl notebooks + +#### Acknowledgements + +This research was supported by the Exascale Computing Project (17-SC-20-SC), a joint project of the U.S. Department of +Energy’s Office of Science and National Nuclear Security Administration, responsible for delivering a capable exascale +ecosystem, including software, applications, and hardware technology, to support the nation’s exascale computing +imperative. + +This research used resources of the Oak Ridge Leadership Computing Facility at the Oak Ridge National Laboratory, which +is supported by the Office of Science of the U.S. Department of Energy under Contract No. DE-AC05-00OR22725. + +Thanks to the Exascale Computing Project PROTEAS-TUNE and ADIOS subprojects, and the ASCR Bluestone. +Thanks to all the Julia community members, packages developers and maintainers for their great work. \ No newline at end of file diff --git a/examples/simulations/GrayScott.jl/examples/settings-files.json b/examples/simulations/GrayScott.jl/examples/settings-files.json new file mode 100644 index 0000000000..ab6b9cc9d4 --- /dev/null +++ b/examples/simulations/GrayScott.jl/examples/settings-files.json @@ -0,0 +1,23 @@ +{ + "L": 64, + "Du": 0.2, + "Dv": 0.1, + "F": 0.02, + "k": 0.048, + "dt": 1.0, + "plotgap": 10, + "steps": 10000, + "noise": 0.1, + "output": "gs-julia-1MPI-64L-F32.bp", + "checkpoint": false, + "checkpoint_freq": 700, + "checkpoint_output": "ckpt.bp", + "restart": false, + "restart_input": "ckpt.bp", + "adios_config": "adios2.xml", + "adios_span": false, + "adios_memory_selection": false, + "mesh_type": "image", + "precision": "Float32", + "backend": "CPU" +} \ No newline at end of file diff --git a/examples/simulations/GrayScott.jl/gray-scott.jl b/examples/simulations/GrayScott.jl/gray-scott.jl new file mode 100644 index 0000000000..2c1196beb9 --- /dev/null +++ b/examples/simulations/GrayScott.jl/gray-scott.jl @@ -0,0 +1,15 @@ +import GrayScott + +# using Profile +# using PProf + +function julia_main()::Cint + GrayScott.main(ARGS) + return 0 +end + +if !isdefined(Base, :active_repl) + @time julia_main() + # @profile julia_main() + # pprof() +end \ No newline at end of file diff --git a/examples/simulations/GrayScott.jl/scripts/config_crusher.sh b/examples/simulations/GrayScott.jl/scripts/config_crusher.sh new file mode 100644 index 0000000000..3820dd297b --- /dev/null +++ b/examples/simulations/GrayScott.jl/scripts/config_crusher.sh @@ -0,0 +1,43 @@ +#!/bin/bash + +PROJ_DIR=/gpfs/alpine/proj-shared/csc383 +export JULIA_DEPOT_PATH=$PROJ_DIR/etc/crusher/julia_depot +GS_DIR=$PROJ_DIR/wgodoy/ADIOS2/examples/simulations/GrayScott.jl + +# remove existing generated Manifest.toml +rm -f $GS_DIR/Manifest.toml +rm -f $GS_DIR/LocalPreferences.toml + +# good practice to avoid conflicts with existing default modules +module purge + +# load required modules +module load PrgEnv-cray/8.3.3 # has required gcc +module load cray-mpich +module load rocm/5.4.0 +module load adios2 # only works with PrgEnv-cray + +# existing julia 1.6 module is outdated +export PATH=$PROJ_DIR/opt/crusher/julia-1.9.0-beta3/bin:$PATH + +# Required to point at underlying modules above +export JULIA_AMDGPU_DISABLE_ARTIFACTS=1 +# Required to enable underlying ADIOS2 library from loaded module +export JULIA_ADIOS2_PATH=$OLCF_ADIOS2_ROOT + +# MPIPreferences to use spectrum-mpi +julia --project=$GS_DIR -e 'using Pkg; Pkg.add("MPIPreferences")' +julia --project=$GS_DIR -e 'using MPIPreferences; MPIPreferences.use_system_binary(; library_names=["libmpi_cray"], mpiexec="srun")' + +# Regression being fixed with CUDA v4.0.0. CUDA.jl does lazy loading for portability to systems without NVIDIA GPUs +julia --project=$GS_DIR -e 'using Pkg; Pkg.add(name="CUDA", version="v3.13.1")' + +# Instantiate the project by installing packages in Project.toml +julia --project=$GS_DIR -e 'using Pkg; Pkg.instantiate()' + +# Adds a custom branch in case the development version is needed (for devs to test new features) +julia --project=$GS_DIR -e 'using Pkg; Pkg.add(url="https://github.com/eschnett/ADIOS2.jl.git", rev="main")' + +# Build the new ADIOS2 +julia --project=$GS_DIR -e 'using Pkg; Pkg.build()' +julia --project=$GS_DIR -e 'using Pkg; Pkg.precompile()' diff --git a/examples/simulations/GrayScott.jl/scripts/config_summit.sh b/examples/simulations/GrayScott.jl/scripts/config_summit.sh new file mode 100644 index 0000000000..d5f616ee31 --- /dev/null +++ b/examples/simulations/GrayScott.jl/scripts/config_summit.sh @@ -0,0 +1,43 @@ +#!/bin/bash + +# Replace these 3 entries +PROJ_DIR=/gpfs/alpine/proj-shared/csc383 +export JULIA_DEPOT_PATH=$PROJ_DIR/etc/summit/julia_depot +GS_DIR=$PROJ_DIR/wgodoy/ADIOS2/examples/simulations/GrayScott.jl + +# remove existing generated Manifest.toml +rm -f $GS_DIR/Manifest.toml +rm -f $GS_DIR/LocalPreferences.toml + +# good practice to avoid conflicts with existing default modules +# needed to avoid seg fault with MPI +module purge + +# load required modules +module load spectrum-mpi +module load gcc/12.1.0 # needed by julia libraries +module load cuda/11.0.3 # failure with 11.5.2 +module load adios2/2.8.1 +# module load julia/1.8.2 not working with CUDA.jl as it's missing libLLVM-13jl.so +export PATH=$PROJ_DIR/opt/summit/julia-1.9.0-beta3/bin:$PATH + +# Required to enable underlying ADIOS2 library from loaded module +export JULIA_ADIOS2_PATH=$OLCF_ADIOS2_ROOT + +# MPIPreferences to use spectrum-mpi +julia --project=$GS_DIR -e 'using Pkg; Pkg.add("MPIPreferences")' +julia --project=$GS_DIR -e 'using MPIPreferences; MPIPreferences.use_system_binary(; library_names=["libmpi_ibm"], mpiexec="jsrun")' + +# Instantiate the project by installing packages in Project.toml +julia --project=$GS_DIR -e 'using Pkg; Pkg.instantiate()' + +# Adds to LocalPreferences.toml to use underlying system CUDA since CUDA.jl v4.0.0 +# https://cuda.juliagpu.org/stable/installation/overview/#Using-a-local-CUDA +julia --project=$GS_DIR -e 'using CUDA; CUDA.set_runtime_version!("local")' + +# Adds a custom branch in case the development version is needed (for devs to test new features) +julia --project=$GS_DIR -e 'using Pkg; Pkg.add(url="https://github.com/eschnett/ADIOS2.jl.git", rev="main")' + +# Build the new ADIOS2 +julia --project=$GS_DIR -e 'using Pkg; Pkg.build()' +julia --project=$GS_DIR -e 'using Pkg; Pkg.precompile()' diff --git a/examples/simulations/GrayScott.jl/scripts/job_crusher.sh b/examples/simulations/GrayScott.jl/scripts/job_crusher.sh new file mode 100644 index 0000000000..ee4953f6d1 --- /dev/null +++ b/examples/simulations/GrayScott.jl/scripts/job_crusher.sh @@ -0,0 +1,17 @@ +#!/bin/bash +#SBATCH -A CSC383_crusher +#SBATCH -J gs-julia-1MPI-1GPU +#SBATCH -o %x-%j.out +#SBATCH -e %x-%j.err +#SBATCH -t 0:02:00 +#SBATCH -p batch +#SBATCH -N 1 + +date + +GS_DIR=/gpfs/alpine/proj-shared/csc383/wgodoy/ADIOS2/examples/simulations/GrayScott.jl +GS_EXE=$GS_DIR/gray-scott.jl + +srun -n 1 --gpus=1 julia --project=$GS_DIR $GS_EXE settings-files.json + +# launch this file with sbatch `$ sbatch job_crusher.sh` diff --git a/examples/simulations/GrayScott.jl/scripts/job_summit.sh b/examples/simulations/GrayScott.jl/scripts/job_summit.sh new file mode 100644 index 0000000000..9beffc157f --- /dev/null +++ b/examples/simulations/GrayScott.jl/scripts/job_summit.sh @@ -0,0 +1,18 @@ +#!/bin/bash +# Begin LSF directives +#BSUB -P csc383 +#BSUB -W 00:02 +#BSUB -nnodes 1 +#BSUB -J gs-julia +#BSUB -o output.%J +#BSUB -e output.%J +#BSUB -N godoywf@ornl.gov +# End BSUB directives and begin shell commands + +date +GS_DIR=/gpfs/alpine/proj-shared/csc383/wgodoy/ADIOS2/examples/simulations/GrayScott.jl +GS_EXE=$GS_DIR/gray-scott.jl + +jsrun -n 1 -g 1 julia --project=$GS_DIR $GS_EXE settings-files.json + +# launch this file with bsub `$ bsub job_summit.sh` diff --git a/examples/simulations/GrayScott.jl/src/GrayScott.jl b/examples/simulations/GrayScott.jl/src/GrayScott.jl new file mode 100644 index 0000000000..d50c1abb09 --- /dev/null +++ b/examples/simulations/GrayScott.jl/src/GrayScott.jl @@ -0,0 +1,91 @@ +""" +GrayScott.jl is a Simulation and Analysis parallel framework for solving the +Gray-Scott 3D diffusion reaction system of equations of two variables U and V on +a regular Cartesian mesh. + +The bp output files can be visualized with ParaView. +""" +module GrayScott + +import MPI, ADIOS2 + +# contains relevant data containers "structs" for Input, Domain and Fields +include(joinpath("simulation", "Structs.jl")) + +# contains helper functions for general use +include(joinpath("helper", "Helper.jl")) +import .Helper + +# initializes inputs from configuration file +include(joinpath("simulation", "Inputs.jl")) +import .Inputs + +# manages the simulation computation +include(joinpath("simulation", "Simulation.jl")) +import .Simulation + +# manages the I/O +include(joinpath("simulation", "IO.jl")) +import .IO + +function julia_main()::Cint + try + main(ARGS) + catch + Base.invokelatest(Base.display_error, Base.catch_stack()) + return 1 + end + return 0 +end + +function main(args::Vector{String})::Int32 + MPI.Init() + comm = MPI.COMM_WORLD + rank = MPI.Comm_rank(comm) + size = MPI.Comm_size(comm) + + # a data struct that holds settings data from config_file in args + # example config file: ../examples/settings-files.json + settings = Inputs.get_settings(args, comm) + + # initialize MPI Cartesian Domain and Communicator + mpi_cart_domain = Simulation.init_domain(settings, comm) + + # initialize fields + fields = Simulation.init_fields(settings, + mpi_cart_domain, + Helper.get_type(settings.precision)) + + # initialize IOStream struct holding ADIOS-2 components for parallel I/O + stream = IO.init(settings, mpi_cart_domain, fields) + + restart_step::Int32 = 0 + # @TODO: checkpoint-restart + step::Int32 = restart_step + + while step < settings.steps + Simulation.iterate!(fields, settings, mpi_cart_domain) + step += 1 + + if step % settings.plotgap == 0 + if rank == 0 + println("Simulation at step ", step, " writing output step ", + step / settings.plotgap) + end + + IO.write_step!(stream, step, fields) + end + end + + IO.close!(stream) + + # Debugging session or Julia REPL session, not needed overall as it would be + # called when the program ends + if !isinteractive() + MPI.Finalize() + end + + return 0 +end + +end # module GrayScott diff --git a/examples/simulations/GrayScott.jl/src/analysis/pdfcalc.jl b/examples/simulations/GrayScott.jl/src/analysis/pdfcalc.jl new file mode 100644 index 0000000000..f7fb0bb33f --- /dev/null +++ b/examples/simulations/GrayScott.jl/src/analysis/pdfcalc.jl @@ -0,0 +1,160 @@ + +import MPI +import ArgParse +import ADIOS2 + +function _epsilon(d::T)::Bool where {T <: Number} + return (d < 1.0e-20) +end + +""" +Return 2 arrays pdf and bins of a 2D slice +""" +function _compute_pdf(data::Array{T, 3}, shape, count, nbins, min::T, + max::T) where {T} + pdf = Array{T, 2}(undef, nbins, count) + bins = Array{T, 1}(undef, nbins) + bin_width = (max - min) / nbins + + for i in 1:nbins + bins[i] = min + (i - 1) * bin_width + end + + slice_size = shape[2] * shape[3] + # special case: only one bin or small window + if nbins == 1 || _epsilon(max - min) || _epsilon(bin_width) + fill!(pdf, slice_size) + return pdf, bins + end + + # Calculate a PDF for 'nbins' bins for values between 'min' and 'max' + + for c in 1:count + for j in 1:shape[2] + for k in 1:shape[3] + value = data[k, j, c] + + if value > max || value < min + @show value, " is outside [", min, max "]" + end + bin = floor((value - min) / bin_width) + + if bin == nbins + bin = nbins - 1 + end + pdf[bin, c] += 1 + end + end + end +end + +function _parse_arguments(args) + s = ArgParse.ArgParseSettings(description = "gray-scott workflow pdf generator, Julia version") + + # @add_arg_table! s begin + # "--opt1" # an option (will take an argument) + # "--opt2", "-o" # another option, with short form + # "arg1" # a positional argument + # end + + ArgParse.@add_arg_table! s begin + "input" + help = "Name of the input file handle for reading data" + arg_type = String + required = true + "output" + help = "Name of the output file to which data must be written" + arg_type = String + required = true + "N" + help = "Number of bins for the PDF calculation, default = 1000" + arg_type = Int64 + required = false + default = 1000 + "output_inputdata" + help = "YES will write the original variables besides the analysis results" + arg_type = Bool + required = false + default = false + end + + # parse_args return a dictionary with key/value for arguments + parsed_arguments = ArgParse.parse_args(args, s) + return parsed_arguments +end + +function _read_data_write_pdf(inputs, comm) + in_filename = inputs["input"] + out_filename = inputs["output"] + nbins = inputs["N"] + write_inputvars = inputs["output_inputdata"] + + adios = ADIOS2.adios_init_mpi("adios2.xml", comm) + + reader_io = ADIOS2.declare_io(adios, "SimulationOutput") + writer_io = ADIOS2.declare_io(adios, "PDFAnalysisOutput") + + rank = MPI.Comm_rank(comm) + size = MPI.Comm_size(comm) + + if rank == 0 + println("PDF analysis reads from Simulation using engine type: ", + ADIOS2.engine_type(reader_io)) + println("PDF analysis writes using engine type: ", + ADIOS2.engine_type(writer_io)) + end + + # Engines for reading and writing + reader = ADIOS2.open(reader_io, inputs["input"], ADIOS2.mode_read) + writer = ADIOS2.open(writer_io, inputs["output"], ADIOS2.mode_write) + + # break inside if needed + while true + + # timeout is 10 seconds + read_status = ADIOS2.begin_step(reader, ADIOS2.step_mode_read, 10) + + if read_status == ADIOS2.step_status_not_ready + # sleep in seconds, minimum is one milisecond = 0.001 + sleep(1) + continue + else if read_status != ADIOS2.step_status_ok + break + end + + step_sim_out = ADIOS2.current_step(reader) + var_U = ADIOS2.inquire_variable(reader_io, "U") + var_V = ADIOS2.inquire_variable(reader_io, "V") + var_step = ADIOS2.inquire_variable(reader_io, "step") + + shape = ADIOS2.shape(var_U) + + # Split in the slowest dimension + count_z = shape[3] / size + start_z = count_z * rank + + # Last process needs to read all the rest + if rank == size-1 + count_z = shape[3] - count_z * (size-1) + end + + # missing set_selection + start = ( 0,0,start_z) + count = (shape[1], shape[2], count_z) + ADIOS2.set_selection(var_U, start, count) + ADIOS2.set_selection(var_V, start, count) + + # Calculate + + end +end + +function main(args) + MPI.Init() + + inputs = _parse_arguments(args) + comm = MPI.COMM_WORLD + _read_data_write_pdf(inputs, comm) + + MPI.Finalize() +end diff --git a/examples/simulations/GrayScott.jl/src/helper/Helper.jl b/examples/simulations/GrayScott.jl/src/helper/Helper.jl new file mode 100644 index 0000000000..757c571714 --- /dev/null +++ b/examples/simulations/GrayScott.jl/src/helper/Helper.jl @@ -0,0 +1,7 @@ + +module Helper + +include("helperMPI.jl") +include("helperString.jl") + +end \ No newline at end of file diff --git a/examples/simulations/GrayScott.jl/src/helper/helperMPI.jl b/examples/simulations/GrayScott.jl/src/helper/helperMPI.jl new file mode 100644 index 0000000000..529d7e0420 --- /dev/null +++ b/examples/simulations/GrayScott.jl/src/helper/helperMPI.jl @@ -0,0 +1,15 @@ + +import MPI + +export bcase_file + +function bcast_file_contents(file_name::String, comm, root = 0)::String + size::UInt32 = 0 + data::Vector{UInt8} = [] + if MPI.Comm_rank(comm) == root + data = read(open(file_name, "r")) + end + + data = MPI.bcast(data, comm) + return String(data) +end diff --git a/examples/simulations/GrayScott.jl/src/helper/helperString.jl b/examples/simulations/GrayScott.jl/src/helper/helperString.jl new file mode 100644 index 0000000000..596a2f0b94 --- /dev/null +++ b/examples/simulations/GrayScott.jl/src/helper/helperString.jl @@ -0,0 +1,14 @@ + +export get_type + +function get_type(input::String) + if input == "Float64" + return Float64 + elseif input == "Float32" + return Float32 + elseif input == "Float16" + return Float16 + end + + return nothing +end \ No newline at end of file diff --git a/examples/simulations/GrayScott.jl/src/simulation/IO.jl b/examples/simulations/GrayScott.jl/src/simulation/IO.jl new file mode 100644 index 0000000000..deb3a24ae8 --- /dev/null +++ b/examples/simulations/GrayScott.jl/src/simulation/IO.jl @@ -0,0 +1,106 @@ +module IO + +export init, write_step! + +# import external module +import ADIOS2 + +# internal submodule +import ..Simulation +# types from parent module types in Structs.jl +import ..Settings, ..MPICartDomain, ..Fields, ..IOStream + +function init(settings::Settings, mcd::MPICartDomain, + fields::Fields{T}) where {T} + + # initialize adios MPI using the cartesian communicator + adios = ADIOS2.adios_init_mpi(mcd.cart_comm) + io = ADIOS2.declare_io(adios, "SimulationOutput") + # @TODO: implement ADIOS2.set_engine in ADIOS2.jl + engine = ADIOS2.open(io, settings.output, ADIOS2.mode_write) + + # store simulation run provenance as attributes + ADIOS2.define_attribute(io, "F", settings.F) + ADIOS2.define_attribute(io, "k", settings.k) + ADIOS2.define_attribute(io, "dt", settings.dt) + ADIOS2.define_attribute(io, "Du", settings.Du) + ADIOS2.define_attribute(io, "Dv", settings.Dv) + ADIOS2.define_attribute(io, "noise", settings.noise) + + _add_visualization_schemas(io, settings.L) + + # ADIOS2 requires tuples for the dimensions + # define global variables u and v + shape = (settings.L, settings.L, settings.L) + start = Tuple(mcd.proc_offsets) + count = Tuple(mcd.proc_sizes) + + var_step = ADIOS2.define_variable(io, "step", Int32) + var_U = ADIOS2.define_variable(io, "U", T, shape, start, count) + var_V = ADIOS2.define_variable(io, "V", T, shape, start, count) + + return IOStream(adios, io, engine, var_step, var_U, var_V) +end + +function write_step!(stream::IOStream, step::Int32, fields::Fields{T}) where {T} + + # this creates temporaries similar to Fortran + u_no_ghost, v_no_ghost = Simulation.get_fields(fields) + + # writer engine + w = stream.engine + + ADIOS2.begin_step(w) + ADIOS2.put!(w, stream.var_step, step) + ADIOS2.put!(w, stream.var_U, u_no_ghost) + ADIOS2.put!(w, stream.var_V, v_no_ghost) + ADIOS2.end_step(w) +end + +function close!(stream::IOStream) + ADIOS2.close(stream.engine) + ADIOS2.adios_finalize(stream.adios) +end + +function _add_visualization_schemas(io, length) + + # Fides schema + ADIOS2.define_attribute(io, "Fides_Data_Model", "uniform") + ADIOS2.define_attribute_array(io, "Fides_Origin", [0.0, 0.0, 0.0]) + ADIOS2.define_attribute_array(io, "Fides_Spacing", [0.1, 0.1, 0.1]) + ADIOS2.define_attribute(io, "Fides_Dimension_Variable", "U") + ADIOS2.define_attribute_array(io, "Fides_Variable_List", ["U", "V"]) + ADIOS2.define_attribute_array(io, "Fides_Variable_Associations", + ["points", "points"]) + + # VTX schema + # string concatenation uses *, ^ is for repetition + # if length = 64 + # extent = "0 64 0 64 0 64 " + extent = ("0 " * string(length) * " ")^3 + extent = rstrip(extent) + + # deactive code formatting using JuliaFormatter.jl + # raw strings: " must be escaped with \" + #! format: off + vtx_schema = raw" + + + + + + + + + step + + + + + " + #! format: on + # reactive code formatting using JuliaFormatter.jl + ADIOS2.define_attribute(io, "vtk.xml", vtx_schema) +end + +end diff --git a/examples/simulations/GrayScott.jl/src/simulation/Inputs.jl b/examples/simulations/GrayScott.jl/src/simulation/Inputs.jl new file mode 100644 index 0000000000..a4160ce1d8 --- /dev/null +++ b/examples/simulations/GrayScott.jl/src/simulation/Inputs.jl @@ -0,0 +1,78 @@ + +""" +Submodule used by GrayScott to handle inputs +""" +module Inputs + +export get_settings + +import ArgParse +import JSON + +import ..Helper +# import directly from parent module (GrayScott) +import ..Settings, ..SettingsKeys + +# public facing function +function get_settings(args::Vector{String}, comm)::Settings + config_file = _parse_args(args) + + # check format extension + if !endswith(config_file, ".json") && + !(endswith(config_file, ".yaml") || endswith(config_file, ".yml")) + throw(ArgumentError("config file must be json, yaml format. Extension not recognized.\n")) + end + + config_file_contents::String = Helper.bcast_file_contents(config_file, comm) + + if endswith(config_file, ".json") + return _parse_settings_json(config_file_contents) + end + + return nothing +end + +# local scope functions +function _parse_args(args::Vector{String}; + error_handler = ArgParse.default_handler)::String + s = ArgParse.ArgParseSettings(description = "gray-scott workflow simulation example configuration file, Julia version, GrayScott.jl", + exc_handler = error_handler) + + # @add_arg_table! s begin + # "--opt1" # an option (will take an argument) + # "--opt2", "-o" # another option, with short form + # "arg1" # a positional argument + # end + + ArgParse.@add_arg_table! s begin + "config_file" + help = "configuration file" + arg_type = String + required = true + end + + # parse_args return a dictionary with key/value for arguments + parsed_arguments = ArgParse.parse_args(args, s) + + # key is mandatory, so it's safe to retrieve + config_file::String = parsed_arguments["config_file"] + + return config_file +end + +function _parse_settings_json(json_contents::String)::Settings + json = JSON.parse(json_contents) + settings = Settings() + + # Iterate through dictionary pairs + for (key, value) in json + # Iterate through predefined keys, else ignore (no error if unrecognized) + if key in SettingsKeys + setproperty!(settings, Symbol(key), value) + end + end + + return settings +end + +end # module \ No newline at end of file diff --git a/examples/simulations/GrayScott.jl/src/simulation/Simulation.jl b/examples/simulations/GrayScott.jl/src/simulation/Simulation.jl new file mode 100644 index 0000000000..f3cbf3325c --- /dev/null +++ b/examples/simulations/GrayScott.jl/src/simulation/Simulation.jl @@ -0,0 +1,281 @@ +""" +The present file contains runtime backend for using CPU Threads, and optionally +CUDA.jl and AMDGPU.jl +""" +module Simulation + +export init_domain, init_fields + +import MPI +import Distributions + +# from parent module +import ..Settings, ..MPICartDomain, ..Fields + +# include functions for NVIDIA GPUs using CUDA.jl +include("Simulation_CUDA.jl") +# include functions for AMD GPUs using AMDGPU.jl +include("Simulation_AMDGPU.jl") + +function init_domain(settings::Settings, comm::MPI.Comm)::MPICartDomain + mcd = MPICartDomain() + + # set dims and Cartesian communicator + mcd.dims = MPI.Dims_create(MPI.Comm_size(comm), mcd.dims) + mcd.cart_comm = MPI.Cart_create(comm, mcd.dims) + + # set proc local coordinates in Cartesian communicator + rank = MPI.Comm_rank(comm) + mcd.coords = MPI.Cart_coords(mcd.cart_comm, rank) + + # set proc local mesh sizes + mcd.proc_sizes = settings.L ./ mcd.dims + + for (i, coord) in enumerate(mcd.coords) + if coord < settings.L % mcd.dims[i] + mcd.proc_sizes[i] += 1 + end + end + + # set proc local offsets + for i in 1:3 + mcd.proc_offsets[i] = settings.L / mcd.dims[i] * + mcd.coords[i] + +min(settings.L % mcd.dims[i], mcd.coords[i]) + end + + # get neighbors ranks + mcd.proc_neighbors["west"], + mcd.proc_neighbors["east"] = MPI.Cart_shift(mcd.cart_comm, 0, 1) + mcd.proc_neighbors["down"], + mcd.proc_neighbors["up"] = MPI.Cart_shift(mcd.cart_comm, 1, 1) + mcd.proc_neighbors["south"], + mcd.proc_neighbors["north"] = MPI.Cart_shift(mcd.cart_comm, 2, 1) + + return mcd +end + +""" +Create and Initialize fields for either CPU, CUDA.jl, AMDGPU.jl backends +Multiple dispatch would direct to the appropriate overleaded function +""" +function init_fields(settings::Settings, + mcd::MPICartDomain, T)::Fields{T} + lowercase_backend = lowercase(settings.backend) + if lowercase_backend == "cuda" + return _init_fields_cuda(settings, mcd, T) + elseif lowercase_backend == "amdgpu" + return _init_fields_amdgpu(settings, mcd, T) + end + # everything else would trigger the CPU threads backend + return _init_fields_cpu(settings, mcd, T) +end + +function _init_fields_cpu(settings::Settings, + mcd::MPICartDomain, T)::Fields{T} + size_x = mcd.proc_sizes[1] + size_y = mcd.proc_sizes[2] + size_z = mcd.proc_sizes[3] + + # should be ones + u = ones(T, size_x + 2, size_y + 2, size_z + 2) + v = zeros(T, size_x + 2, size_y + 2, size_z + 2) + + u_temp = zeros(T, size_x + 2, size_y + 2, size_z + 2) + v_temp = zeros(T, size_x + 2, size_y + 2, size_z + 2) + + function is_inside(x, y, z, offsets, sizes)::Bool + if x < offsets[1] || x >= offsets[1] + sizes[1] + return false + end + if y < offsets[2] || y >= offsets[2] + sizes[2] + return false + end + if z < offsets[3] || z >= offsets[3] + sizes[3] + return false + end + + return true + end + + d::Int64 = 6 + + # global locations + minL = Int64(settings.L / 2 - d) + maxL = Int64(settings.L / 2 + d) + + xoff = mcd.proc_offsets[1] + yoff = mcd.proc_offsets[2] + zoff = mcd.proc_offsets[3] + + Threads.@threads for z in minL:maxL + for y in minL:maxL + for x in minL:maxL + if !is_inside(x, y, z, mcd.proc_offsets, mcd.proc_sizes) + continue + end + + # Julia is 1-index, like Fortran :) + u[x - xoff + 2, y - yoff + 2, z - zoff + 2] = 0.25 + v[x - xoff + 2, y - yoff + 2, z - zoff + 2] = 0.33 + end + end + end + + xy_face_t, xz_face_t, yz_face_t = _get_mpi_faces(size_x, size_y, size_z, T) + + fields = Fields(u, v, u_temp, v_temp, xy_face_t, xz_face_t, yz_face_t) + return fields +end + +function iterate!(fields::Fields{T, N, Array{T, N}}, settings::Settings, + mcd::MPICartDomain) where {T, N} + _exchange!(fields, mcd) + # this function is the bottleneck + _calculate!(fields, settings, mcd) + + # swap the names + fields.u, fields.u_temp = fields.u_temp, fields.u + fields.v, fields.v_temp = fields.v_temp, fields.v +end + +function _get_mpi_faces(size_x, size_y, size_z, T) + + ## create a new type taking: count, block length, stride + ## to interoperate with MPI for ghost cell exchange + xy_face_t = MPI.Types.create_vector(size_y + 2, size_x, size_x + 2, + MPI.Datatype(T)) + xz_face_t = MPI.Types.create_vector(size_z, size_x, + (size_x + 2) * (size_y + 2), + MPI.Datatype(T)) + yz_face_t = MPI.Types.create_vector((size_y + 2) * (size_z + 2), 1, + size_x + 2, MPI.Datatype(T)) + MPI.Types.commit!(xy_face_t) + MPI.Types.commit!(xz_face_t) + MPI.Types.commit!(yz_face_t) + + return xy_face_t, xz_face_t, yz_face_t +end + +function _exchange!(fields, mcd) + """ + Send XY face z=size_z+1 to north and receive z=1 from south + """ + function _exchange_xy!(var, size_z, data_type, rank1, rank2, comm) + # to north + send_buf = MPI.Buffer(@view(var[2, 1, size_z + 1]), 1, data_type) + recv_buf = MPI.Buffer(@view(var[2, 1, 1]), 1, data_type) + MPI.Sendrecv!(send_buf, recv_buf, comm, dest = rank1, source = rank2) + + # to south + send_buf = MPI.Buffer(@view(var[2, 1, 2]), 1, data_type) + recv_buf = MPI.Buffer(@view(var[2, 1, size_z + 2]), 1, data_type) + MPI.Sendrecv!(send_buf, recv_buf, comm, dest = rank2, source = rank1) + end + + """ + Send XZ face y=size_y+1 to up and receive y=1 from down + """ + function _exchange_xz!(var, size_y, data_type, rank1, rank2, comm) + # to up + send_buf = MPI.Buffer(@view(var[2, size_y + 1, 2]), 1, data_type) + recv_buf = MPI.Buffer(@view(var[2, 1, 2]), 1, data_type) + MPI.Sendrecv!(send_buf, recv_buf, comm, dest = rank1, source = rank2) + + # to down + send_buf = MPI.Buffer(@view(var[2, 2, 2]), 1, data_type) + recv_buf = MPI.Buffer(@view(var[2, size_y + 2, 2]), 1, data_type) + MPI.Sendrecv!(send_buf, recv_buf, comm, dest = rank2, source = rank1) + end + + """ + Send YZ face x=size_x+2 to east and receive x=2 from west + """ + function _exchange_yz!(var, size_x, data_type, rank1, rank2, comm) + # to east + send_buf = MPI.Buffer(@view(var[size_x + 1, 1, 1]), 1, data_type) + recv_buf = MPI.Buffer(@view(var[1, 1, 1]), 1, data_type) + MPI.Sendrecv!(send_buf, recv_buf, comm, dest = rank1, source = rank2) + + # to west + send_buf = MPI.Buffer(@view(var[2, 1, 1]), 1, data_type) + recv_buf = MPI.Buffer(@view(var[size_x + 2, 1, 1]), 1, data_type) + MPI.Sendrecv!(send_buf, recv_buf, comm, dest = rank2, source = rank1) + end + + # if already a CPU array, no need to copy, + # otherwise (device) copy to host. + u = typeof(fields.u) <: Array ? fields.u : Array(fields.u) + v = typeof(fields.v) <: Array ? fields.v : Array(fields.v) + + for var in [u, v] + _exchange_xy!(var, mcd.proc_sizes[3], fields.xy_face_t, + mcd.proc_neighbors["north"], mcd.proc_neighbors["south"], + mcd.cart_comm) + + _exchange_xz!(var, mcd.proc_sizes[2], fields.xz_face_t, + mcd.proc_neighbors["up"], mcd.proc_neighbors["down"], + mcd.cart_comm) + + _exchange_yz!(var, mcd.proc_sizes[1], fields.yz_face_t, + mcd.proc_neighbors["east"], mcd.proc_neighbors["west"], + mcd.cart_comm) + end +end + +function _calculate!(fields::Fields{T, N, Array{T, N}}, settings::Settings, + mcd::MPICartDomain) where {T, N} + Du = convert(T, settings.Du) + Dv = convert(T, settings.Dv) + F = convert(T, settings.F) + K = convert(T, settings.k) + noise = convert(T, settings.noise) + dt = convert(T, settings.dt) + + # loop through non-ghost cells, bounds are inclusive + # @TODO: load balancing? option: a big linear loop + # use @inbounds at the right for-loop level, avoid putting it at the top level + Threads.@threads for k in 2:(mcd.proc_sizes[3] + 1) + for j in 2:(mcd.proc_sizes[2] + 1) + @inbounds for i in 2:(mcd.proc_sizes[1] + 1) + u = fields.u[i, j, k] + v = fields.v[i, j, k] + + # introduce a random disturbance on du + du = Du * _laplacian(i, j, k, fields.u) - u * v^2 + + F * (1.0 - u) + + noise * rand(Distributions.Uniform(-1, 1)) + + dv = Dv * _laplacian(i, j, k, fields.v) + u * v^2 - + (F + K) * v + + # advance the next step + fields.u_temp[i, j, k] = u + du * dt + fields.v_temp[i, j, k] = v + dv * dt + end + end + end +end + +""" + 7-point stencil around the cell, + this is equally a host and a device function! +""" +function _laplacian(i, j, k, var) + @inbounds l = var[i - 1, j, k] + var[i + 1, j, k] + var[i, j - 1, k] + + var[i, j + 1, k] + var[i, j, k - 1] + var[i, j, k + 1] - + 6.0 * var[i, j, k] + return l / 6.0 +end + +function get_fields(fields::Fields{T, N, Array{T, N}}) where {T, N} + @inbounds begin + u_no_ghost = fields.u[(begin + 1):(end - 1), (begin + 1):(end - 1), + (begin + 1):(end - 1)] + v_no_ghost = fields.v[(begin + 1):(end - 1), (begin + 1):(end - 1), + (begin + 1):(end - 1)] + end + return u_no_ghost, v_no_ghost +end + +end # module diff --git a/examples/simulations/GrayScott.jl/src/simulation/Simulation_AMDGPU.jl b/examples/simulations/GrayScott.jl/src/simulation/Simulation_AMDGPU.jl new file mode 100644 index 0000000000..8920167779 --- /dev/null +++ b/examples/simulations/GrayScott.jl/src/simulation/Simulation_AMDGPU.jl @@ -0,0 +1,168 @@ + +import AMDGPU + +function _init_fields_amdgpu(settings::Settings, mcd::MPICartDomain, + T)::Fields{T, 3, <:AMDGPU.ROCArray{T, 3}} + size_x = mcd.proc_sizes[1] + size_y = mcd.proc_sizes[2] + size_z = mcd.proc_sizes[3] + + # should be ones + u = AMDGPU.ones(T, size_x + 2, size_y + 2, size_z + 2) + v = AMDGPU.zeros(T, size_x + 2, size_y + 2, size_z + 2) + + u_temp = AMDGPU.zeros(T, size_x + 2, size_y + 2, size_z + 2) + v_temp = AMDGPU.zeros(T, size_x + 2, size_y + 2, size_z + 2) + + roc_offsets = AMDGPU.ROCArray(mcd.proc_offsets) + roc_sizes = AMDGPU.ROCArray(mcd.proc_sizes) + + d::Int64 = 6 + minL = Int64(settings.L / 2 - d) + maxL = Int64(settings.L / 2 + d) + + # @TODO: get ideal grid size and threads + threads = (16, 16) + # grid size must be the total number of threads of each direction + grid = (settings.L, settings.L) + + AMDGPU.wait(AMDGPU.@roc groupsize=threads gridsize=grid _populate_amdgpu!(u, + v, + roc_offsets, + roc_sizes, + minL, + maxL)) + + xy_face_t, xz_face_t, yz_face_t = _get_mpi_faces(size_x, size_y, size_z, T) + + fields = Fields(u, v, u_temp, v_temp, xy_face_t, xz_face_t, yz_face_t) + return fields +end + +function iterate!(fields::Fields{T, N, <:AMDGPU.ROCArray{T, N}}, + settings::Settings, + mcd::MPICartDomain) where {T, N} + _exchange!(fields, mcd) + # this function is the bottleneck + _calculate!(fields, settings, mcd) + + # swap the names + fields.u, fields.u_temp = fields.u_temp, fields.u + fields.v, fields.v_temp = fields.v_temp, fields.v +end + +function _populate_amdgpu!(u, v, offsets, sizes, minL, maxL) + function is_inside(x, y, z, offsets, sizes)::Bool + if x < offsets[1] || x >= offsets[1] + sizes[1] + return false + end + if y < offsets[2] || y >= offsets[2] + sizes[2] + return false + end + if z < offsets[3] || z >= offsets[3] + sizes[3] + return false + end + + return true + end + + # local coordinates (this are 1-index already) + lz = (AMDGPU.workgroupIdx().x - Int32(1)) * AMDGPU.workgroupDim().x + + AMDGPU.workitemIdx().x + ly = (AMDGPU.workgroupIdx().y - Int32(1)) * AMDGPU.workgroupDim().y + + AMDGPU.workitemIdx().y + + # This check might not be needed + if lz <= size(u, 3) && ly <= size(u, 2) + + # get global coordinates + z = lz + offsets[3] - 1 + y = ly + offsets[2] - 1 + + if z >= minL && z <= maxL && y >= minL && y <= maxL + xoff = offsets[1] + + for x in minL:maxL + # check if global coordinates for initialization are inside the region + if !is_inside(x, y, z, offsets, sizes) + continue + end + + # Julia is 1-index, like Fortran :) + u[x - xoff + 2, ly + 1, lz + 1] = 0.25 + v[x - xoff + 2, ly + 1, lz + 1] = 0.33 + end + end + end +end + +function _calculate!(fields::Fields{T, N, <:AMDGPU.ROCArray{T, N}}, + settings::Settings, + mcd::MPICartDomain) where {T, N} + Du = convert(T, settings.Du) + Dv = convert(T, settings.Dv) + F = convert(T, settings.F) + K = convert(T, settings.k) + noise = convert(T, settings.noise) + dt = convert(T, settings.dt) + + roc_sizes = AMDGPU.ROCArray(mcd.proc_sizes) + + threads = (16, 16) + blocks = (settings.L, settings.L) + + AMDGPU.wait(AMDGPU.@roc groupsize=threads gridsize=grid _calculate_kernel_amdgpu!(fields.u, + fields.v, + fields.u_temp, + fields.v_temp, + roc_sizes, + Du, + Dv, + F, + K, + noise, + dt)) +end + +function _calculate_kernel_amdgpu!(u, v, u_temp, v_temp, sizes, Du, Dv, F, K, + noise, dt) + + # local coordinates (this are 1-index already) + k = (AMDGPU.workgroupIdx().x - Int32(1)) * AMDGPU.workgroupDim().x + + AMDGPU.workitemIdx().x + j = (AMDGPU.workgroupIdx().y - Int32(1)) * AMDGPU.workgroupDim().y + + AMDGPU.workitemIdx().y + + # loop through non-ghost cells + if k >= 2 && k <= sizes[3] + 1 && j >= 2 && j <= sizes[2] + 1 + # bounds are inclusive + for i in 2:(sizes[1] + 1) + u_ijk = u[i, j, k] + v_ijk = v[i, j, k] + + du = Du * _laplacian(i, j, k, u) - u_ijk * v_ijk^2 + + F * (1.0 - u_ijk) + # + noise * AMDGPU.rand(eltype(u)) + # WIP in AMDGPU.jl, works with CUDA.jl + # + rand(Distributions.Uniform(-1, 1)) + + dv = Dv * _laplacian(i, j, k, v) + u_ijk * v_ijk^2 - + (F + K) * v_ijk + + # advance the next step + u_temp[i, j, k] = u_ijk + du * dt + v_temp[i, j, k] = v_ijk + dv * dt + end + end +end + +function get_fields(fields::Fields{T, N, <:AMDGPU.ROCArray{T, N}}) where {T, N} + u = Array(fields.u) + u_no_ghost = u[(begin + 1):(end - 1), (begin + 1):(end - 1), + (begin + 1):(end - 1)] + + v = Array(fields.v) + v_no_ghost = v[(begin + 1):(end - 1), (begin + 1):(end - 1), + (begin + 1):(end - 1)] + return u_no_ghost, v_no_ghost +end diff --git a/examples/simulations/GrayScott.jl/src/simulation/Simulation_CUDA.jl b/examples/simulations/GrayScott.jl/src/simulation/Simulation_CUDA.jl new file mode 100644 index 0000000000..ee470f00ec --- /dev/null +++ b/examples/simulations/GrayScott.jl/src/simulation/Simulation_CUDA.jl @@ -0,0 +1,160 @@ + +import CUDA + +function _init_fields_cuda(settings::Settings, mcd::MPICartDomain, + T)::Fields{T, 3, <:CUDA.CuArray{T, 3}} + size_x = mcd.proc_sizes[1] + size_y = mcd.proc_sizes[2] + size_z = mcd.proc_sizes[3] + + # should be ones + u = CUDA.ones(T, size_x + 2, size_y + 2, size_z + 2) + v = CUDA.zeros(T, size_x + 2, size_y + 2, size_z + 2) + + u_temp = CUDA.zeros(T, size_x + 2, size_y + 2, size_z + 2) + v_temp = CUDA.zeros(T, size_x + 2, size_y + 2, size_z + 2) + + cu_offsets = CUDA.CuArray(mcd.proc_offsets) + cu_sizes = CUDA.CuArray(mcd.proc_sizes) + + d::Int64 = 6 + minL = Int64(settings.L / 2 - d) + maxL = Int64(settings.L / 2 + d) + + # @TODO: get ideal blocks and threads + threads = (16, 16) + blocks = (settings.L, settings.L) + + CUDA.@cuda threads=threads blocks=blocks _populate_cuda!(u, v, + cu_offsets, + cu_sizes, + minL, maxL) + CUDA.synchronize() + + xy_face_t, xz_face_t, yz_face_t = _get_mpi_faces(size_x, size_y, size_z, T) + + fields = Fields(u, v, u_temp, v_temp, xy_face_t, xz_face_t, yz_face_t) + return fields +end + +function iterate!(fields::Fields{T, N, <:CUDA.CuArray{T, N}}, + settings::Settings, + mcd::MPICartDomain) where {T, N} + _exchange!(fields, mcd) + # this function is the bottleneck + _calculate!(fields, settings, mcd) + + # swap the names + fields.u, fields.u_temp = fields.u_temp, fields.u + fields.v, fields.v_temp = fields.v_temp, fields.v +end + +function _populate_cuda!(u, v, offsets, sizes, minL, maxL) + function is_inside(x, y, z, offsets, sizes)::Bool + if x < offsets[1] || x >= offsets[1] + sizes[1] + return false + end + if y < offsets[2] || y >= offsets[2] + sizes[2] + return false + end + if z < offsets[3] || z >= offsets[3] + sizes[3] + return false + end + + return true + end + + # local coordinates (this are 1-index already) + lz = (CUDA.blockIdx().x - Int32(1)) * CUDA.blockDim().x + + CUDA.threadIdx().x + ly = (CUDA.blockIdx().y - Int32(1)) * CUDA.blockDim().y + + CUDA.threadIdx().y + + if lz <= size(u, 3) && ly <= size(u, 2) + + # get global coordinates + z = lz + offsets[3] - 1 + y = ly + offsets[2] - 1 + + if z >= minL && z <= maxL && y >= minL && y <= maxL + xoff = offsets[1] + + for x in minL:maxL + # check if global coordinates for initialization are inside the region + if !is_inside(x, y, z, offsets, sizes) + continue + end + + # Julia is 1-index, like Fortran :) + u[x - xoff + 2, ly + 1, lz + 1] = 0.25 + v[x - xoff + 2, ly + 1, lz + 1] = 0.33 + end + end + end +end + +function _calculate!(fields::Fields{T, N, <:CUDA.CuArray{T, N}}, + settings::Settings, + mcd::MPICartDomain) where {T, N} + function _calculate_kernel!(u, v, u_temp, v_temp, sizes, Du, Dv, F, K, + noise, dt) + + # local coordinates (this are 1-index already) + k = (CUDA.blockIdx().x - Int32(1)) * CUDA.blockDim().x + + CUDA.threadIdx().x + j = (CUDA.blockIdx().y - Int32(1)) * CUDA.blockDim().y + + CUDA.threadIdx().y + + # loop through non-ghost cells + if k >= 2 && k <= sizes[3] + 1 && j >= 2 && j <= sizes[2] + 1 + # bounds are inclusive + for i in 2:(sizes[1] + 1) + u_ijk = u[i, j, k] + v_ijk = v[i, j, k] + + du = Du * _laplacian(i, j, k, u) - u_ijk * v_ijk^2 + + F * (1.0 - u_ijk) + + noise * rand(Distributions.Uniform(-1, 1)) + + dv = Dv * _laplacian(i, j, k, v) + u_ijk * v_ijk^2 - + (F + K) * v_ijk + + # advance the next step + u_temp[i, j, k] = u_ijk + du * dt + v_temp[i, j, k] = v_ijk + dv * dt + end + end + end + + Du = convert(T, settings.Du) + Dv = convert(T, settings.Dv) + F = convert(T, settings.F) + K = convert(T, settings.k) + noise = convert(T, settings.noise) + dt = convert(T, settings.dt) + + cu_sizes = CUDA.CuArray(mcd.proc_sizes) + + threads = (16, 16) + blocks = (settings.L, settings.L) + + CUDA.@cuda threads=threads blocks=blocks _calculate_kernel!(fields.u, + fields.v, + fields.u_temp, + fields.v_temp, + cu_sizes, + Du, Dv, F, K, + noise, dt) + CUDA.synchronize() +end + +function get_fields(fields::Fields{T, N, <:CUDA.CuArray{T, N}}) where {T, N} + u = Array(fields.u) + u_no_ghost = u[(begin + 1):(end - 1), (begin + 1):(end - 1), + (begin + 1):(end - 1)] + + v = Array(fields.v) + v_no_ghost = v[(begin + 1):(end - 1), (begin + 1):(end - 1), + (begin + 1):(end - 1)] + return u_no_ghost, v_no_ghost +end diff --git a/examples/simulations/GrayScott.jl/src/simulation/Structs.jl b/examples/simulations/GrayScott.jl/src/simulation/Structs.jl new file mode 100644 index 0000000000..ca35fb5611 --- /dev/null +++ b/examples/simulations/GrayScott.jl/src/simulation/Structs.jl @@ -0,0 +1,102 @@ + +""" +Settings carry the settings from the simulation config file (json or yaml formats) + +Using Base.@kwdef macro for easy defaults and enable keyword arguments +Settings(Du = 0.2, noise = 0.2) +See: +https://discourse.julialang.org/t/default-value-of-some-fields-in-a-mutable-struct/33408/24?u=williamfgc +""" +Base.@kwdef mutable struct Settings + L::Int64 = 128 + steps::Int32 = 20000 + plotgap::Int32 = 200 + F::Float64 = 0.04 + k::Float64 = 0 + dt::Float64 = 0.2 + Du::Float64 = 0.05 + Dv::Float64 = 0.1 + noise::Float64 = 0.0 + output::String = "foo.bp" + checkpoint::Bool = false + checkpoint_freq::Int32 = 2000 + checkpoint_output::String = "ckpt.bp" + restart::Bool = false + restart_input::String = "ckpt.bp" + adios_config::String = "adios2.yaml" + adios_span::Bool = false + adios_memory_selection::Bool = false + mesh_type::String = "image" + precision::String = "Float64" + backend::String = "CPU" +end + +SettingsKeys = Set{String}([ + "L", + "steps", + "plotgap", + "F", + "k", + "dt", + "Du", + "Dv", + "noise", + "output", + "checkpoint", + "checkpoint_freq", + "checkpoint_output", + "restart", + "restart_input", + "adios_config", + "adios_span", + "adios_memory_selection", + "mesh_type", + "precision", + "backend", + ]) + +Base.@kwdef mutable struct MPICartDomain + cart_comm::MPI.Comm = MPI.COMM_NULL + + # Cartesian communicator info + # Could used StaticArrays.jl? + # start dims with zeros + dims::Vector{Int32} = zeros(Int32, 3) + coords::Vector{Int32} = zeros(Int32, 3) + + # local process mesh sizes and offsets in Cartesian domain info, using defaults + proc_sizes::Vector{Int64} = [128, 128, 128] + proc_offsets::Vector{Int64} = [1, 1, 1] + + # couldn't use NamedTuples as struct is mutable + proc_neighbors = Dict{String, Int32}("west" => -1, "east" => -1, "up" => -1, + "down" => -1, "north" => -1, + "south" => -1) +end + +""" +Carry the physical field outputs: u and v +Using AbstractArray to allow for Array, CuArray and ROCArray +""" +mutable struct Fields{T, N, A <: AbstractArray{T, N}} + u::A + v::A + u_temp::A + v_temp::A + # MPI Datatypes for halo exchange MPI.Datatype(T) + xy_face_t::MPI.Datatype + xz_face_t::MPI.Datatype + yz_face_t::MPI.Datatype +end + +""" +Carry the I/O information for outputs +""" +struct IOStream + adios::ADIOS2.Adios + io::ADIOS2.AIO + engine::ADIOS2.Engine + var_step::ADIOS2.Variable + var_U::ADIOS2.Variable + var_V::ADIOS2.Variable +end diff --git a/examples/simulations/GrayScott.jl/test/Project.toml b/examples/simulations/GrayScott.jl/test/Project.toml new file mode 100644 index 0000000000..c60df76b67 --- /dev/null +++ b/examples/simulations/GrayScott.jl/test/Project.toml @@ -0,0 +1,3 @@ +[deps] +MPI = "da04e1cc-30fd-572f-bb4f-1f8673147195" +Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" diff --git a/examples/simulations/GrayScott.jl/test/functional/functional-GrayScott.jl b/examples/simulations/GrayScott.jl/test/functional/functional-GrayScott.jl new file mode 100644 index 0000000000..46a844a037 --- /dev/null +++ b/examples/simulations/GrayScott.jl/test/functional/functional-GrayScott.jl @@ -0,0 +1,12 @@ + +import GrayScott +import Test: @testset, @test + +@testset "GrayScott" begin MPI.mpiexec() do runcmd + config_file = joinpath(dirname(Base.active_project()), "examples", + "settings-files.json") + + juliacmd = `julia --project gray-scott.jl $config_file` + + @test run(`mpirun -n 4 $juliacmd`).exitcode == 0 +end end \ No newline at end of file diff --git a/examples/simulations/GrayScott.jl/test/runtests.jl b/examples/simulations/GrayScott.jl/test/runtests.jl new file mode 100644 index 0000000000..e795c94ca9 --- /dev/null +++ b/examples/simulations/GrayScott.jl/test/runtests.jl @@ -0,0 +1,26 @@ + +import MPI + +# Run all lightweight unit tests within a single MPI session +MPI.Init() + +verbose = false + +# unit tests for module GrayScott +include(joinpath("unit", "helper", "unit-helperMPI.jl")) + +include(joinpath("unit", "simulation", "unit-Inputs.jl")) +include(joinpath("unit", "simulation", "unit-Simulation.jl")) +include(joinpath("unit", "simulation", "unit-Simulation_CUDA.jl")) +include(joinpath("unit", "simulation", "unit-IO.jl")) + +# unit tests for analysis scripts +include(joinpath("unit", "analysis", "unit-pdfcalc.jl")) + +MPI.Finalize() + +# Command line tests. These are heavier tests launched as separate processes. +# The downside is that only global success can be tested and not internal states. + +# functional tests +# include(joinpath("functional", "functional-GrayScott.jl")) diff --git a/examples/simulations/GrayScott.jl/test/unit/analysis/unit-pdfcalc.jl b/examples/simulations/GrayScott.jl/test/unit/analysis/unit-pdfcalc.jl new file mode 100644 index 0000000000..87ea9b8478 --- /dev/null +++ b/examples/simulations/GrayScott.jl/test/unit/analysis/unit-pdfcalc.jl @@ -0,0 +1,19 @@ + +import Test: @testset, @test, @test_throws + +include(joinpath(dirname(Base.active_project()), "src", "analysis", + "pdfcalc.jl")) + +@testset "unit-analysis.pdfcalc._parse_args" begin + inputs = _parse_arguments(["foo.bp", "bar.bp", "1500"]) + @test inputs["input"] == "foo.bp" + @test inputs["output"] == "bar.bp" + @test inputs["N"] == 1500 + @test inputs["output_inputdata"] == false + + inputs = _parse_arguments(["input.bp", "output.bp", "1000", "true"]) + @test inputs["input"] == "input.bp" + @test inputs["output"] == "output.bp" + @test inputs["N"] == 1000 + @test inputs["output_inputdata"] == true +end diff --git a/examples/simulations/GrayScott.jl/test/unit/helper/unit-helperMPI.jl b/examples/simulations/GrayScott.jl/test/unit/helper/unit-helperMPI.jl new file mode 100644 index 0000000000..33d9f2202f --- /dev/null +++ b/examples/simulations/GrayScott.jl/test/unit/helper/unit-helperMPI.jl @@ -0,0 +1,12 @@ + +import Test: @testset, @test, @test_throws +import GrayScott: Helper + +@testset "unit-Helper.bcast_file_contents" begin + config_file = joinpath(dirname(Base.active_project()), "examples", + "settings-files.json") + + file_contents = Helper.bcast_file_contents(config_file, MPI.COMM_WORLD) + file_contents_expected = String(read(open(config_file, "r"))) + @test file_contents == file_contents_expected +end \ No newline at end of file diff --git a/examples/simulations/GrayScott.jl/test/unit/simulation/unit-IO.jl b/examples/simulations/GrayScott.jl/test/unit/simulation/unit-IO.jl new file mode 100644 index 0000000000..5a33f90ed9 --- /dev/null +++ b/examples/simulations/GrayScott.jl/test/unit/simulation/unit-IO.jl @@ -0,0 +1,36 @@ + +import Test: @testset, @test, @test_throws + +import ADIOS2 + +# import submodule +import GrayScott: IO +# import types +import GrayScott: Settings, MPICartDomain, Fields + +@testset "unit-IO.init" begin + settings = Settings() + mpi_cart_domain = MPICartDomain() + fields = Simulation.init_fields(settings, mpi_cart_domain, Float32) + + @test eltype(fields.u) == Float32 + @test eltype(fields.v) == Float32 + + stream = IO.init(settings, mpi_cart_domain, fields) + + @test ADIOS2.name(stream.engine) == "foo.bp" + IO.close!(stream) + + # @TODO: needs to be done from rank==0 only + # Base.Filesystem.rm("foo.bp", force = true, recursive = true) +end + +@testset "unit-IO.write" begin + settings = Settings() + settings.L = 6 + mpi_cart_domain = Simulation.init_domain(settings, MPI.COMM_WORLD) + fields = Simulation.init_fields(settings, mpi_cart_domain, Float32) + stream = IO.init(settings, mpi_cart_domain, fields) + IO.write_step!(stream, Int32(0), fields) + IO.close!(stream) +end diff --git a/examples/simulations/GrayScott.jl/test/unit/simulation/unit-Inputs.jl b/examples/simulations/GrayScott.jl/test/unit/simulation/unit-Inputs.jl new file mode 100644 index 0000000000..fb77325de5 --- /dev/null +++ b/examples/simulations/GrayScott.jl/test/unit/simulation/unit-Inputs.jl @@ -0,0 +1,15 @@ + +import Test: @testset, @test, @test_throws +import GrayScott: Inputs + +# Unfortunately due to MPI being a Singleton, single MPI.Init() +# these unit tests don't run as independent files + +@testset "unit-Inputs.get_settings" begin + config_file = joinpath(dirname(Base.active_project()), "examples", + "settings-files.json") + Inputs.get_settings([config_file], MPI.COMM_WORLD) + + @test_throws(ArgumentError, + Inputs.get_settings(["hello.nojson"], MPI.COMM_WORLD)) +end diff --git a/examples/simulations/GrayScott.jl/test/unit/simulation/unit-Simulation.jl b/examples/simulations/GrayScott.jl/test/unit/simulation/unit-Simulation.jl new file mode 100644 index 0000000000..ad43a8b49f --- /dev/null +++ b/examples/simulations/GrayScott.jl/test/unit/simulation/unit-Simulation.jl @@ -0,0 +1,34 @@ + +import Test: @testset, @test, @test_throws +# import submodule +import GrayScott: Simulation +# import types +import GrayScott: Settings, MPICartDomain, Fields + +# Unfortunately due to MPI being a Singleton, single MPI.Init() +# these unit tests don't run as independent files + +@testset "unit-Simulation.init" begin + settings = Settings() + mpi_cart_domain = Simulation.init_domain(settings, MPI.COMM_WORLD) + fields = Simulation.init_fields(settings, mpi_cart_domain, Float32) + + @test typeof(fields) == Fields{Float32, 3, Array{Float32, 3}} +end + +@testset "unit-Simulation.iterate" begin + settings = Settings() + settings.L = 2 + mpi_cart_domain = Simulation.init_domain(settings, MPI.COMM_WORLD) + fields = Simulation.init_fields(settings, mpi_cart_domain, Float32) + + Simulation.iterate!(fields, settings, mpi_cart_domain) + + if verbose + sleep(0.01) + rank = MPI.Comm_rank(MPI.COMM_WORLD) + @show rank, fields.v + end +end + +#end diff --git a/examples/simulations/GrayScott.jl/test/unit/simulation/unit-Simulation_CUDA.jl b/examples/simulations/GrayScott.jl/test/unit/simulation/unit-Simulation_CUDA.jl new file mode 100644 index 0000000000..e3c3a6fc07 --- /dev/null +++ b/examples/simulations/GrayScott.jl/test/unit/simulation/unit-Simulation_CUDA.jl @@ -0,0 +1,28 @@ + +import Test: @testset, @test, @test_throws +# import submodule +import GrayScott: Simulation +# import types +import GrayScott: Settings, MPICartDomain, Fields + +@testset "unit-Simulation.init_fields-cuda" begin + function test_init_cuda(L) + settings = Settings() + settings.L = L + mpi_cart_domain = Simulation.init_domain(settings, MPI.COMM_WORLD) + + fields = Simulation.init_fields(settings, mpi_cart_domain, Float32) + + settings.backend = "CUDA" + fields_cuda = Simulation.init_fields(settings, mpi_cart_domain, Float32) + + @test fields.u ≈ Array(fields_cuda.u) + @test fields.v ≈ Array(fields_cuda.v) + end + + test_init_cuda(8) + test_init_cuda(16) + test_init_cuda(32) + test_init_cuda(64) + test_init_cuda(128) +end \ No newline at end of file diff --git a/examples/simulations/ReadMe.md b/examples/simulations/ReadMe.md new file mode 100644 index 0000000000..d3b72b36a6 --- /dev/null +++ b/examples/simulations/ReadMe.md @@ -0,0 +1,30 @@ +## ADIOS2 simulations examples + +The _simulations_ examples are meant to demonstrate how to integrate ADIOS2 within your +simulation code to read, write and/or stream your simulation data. + +They can be found in the following subdirectories, and they should be explored in the order that they are listed: + +1. [korteweg-de-vries](korteweg-de-vries): The _korteweg-de-vries_ example demonstrates how to solve the initial value + problem for the Korteweg de-Vries equation via the Zabusky and Krustal scheme and integrate ADIOS2 for its IO + capabilities. + * Languages: C++, Python +2. [lorenz_ode](lorenz_ode): The _lorenz_ode_ example demonstrates how to solve the Lorenz system of ordinary + differential equations and integrate ADIOS2 for its IO capabilities. + * Languages: C++ +3. [gray-scott](gray-scott): The _gray-scott_ example demonstrates how to perform simulation with the Gray-Scott + reaction diffusion model and integrate ADIOS2 for its IO capabilities. + * Languages: C++ +4. [gray-scott-struct](gray-scott-struct): The _gray-scott-struct_ example demonstrates how to perform a simulation with + the Gray-Scott reaction diffusion model using a struct that defines user defined data types and integrate ADIOS2 for + its IO capabilities. + * Languages: C++ +5. [gray-scott-kokkos](gray-scott-kokkos): The _gray-scott-kokkos_ example demonstrates how to perform a simulation with + the Gray-Scott reaction diffusion model using Kokkos and integrate ADIOS2 for its IO capabilities. + * Languages: C++ +6. [GrayScott.jl](GrayScott.jl): The _GrayScott.jl_ example demonstrates how to perform a simulation with the Gray-Scott + reaction diffusion model and integrate ADIOS2 for its IO capabilities. + * Languages: Julia +7. [heatTransfer](heatTransfer): The _heatTransfer_ example demonstrates how to solve a 2D Poisson equation for + temperature in homogeneous media using finite differences and integrate ADIOS2 for its IO capabilities. + * Languages: C++ diff --git a/examples/simulations/gray-scott-kokkos/CMakeLists.txt b/examples/simulations/gray-scott-kokkos/CMakeLists.txt new file mode 100644 index 0000000000..b43362cf3f --- /dev/null +++ b/examples/simulations/gray-scott-kokkos/CMakeLists.txt @@ -0,0 +1,47 @@ +#------------------------------------------------------------------------------# +# Distributed under the OSI-approved Apache License, Version 2.0. See +# accompanying file Copyright.txt for details. +#------------------------------------------------------------------------------# + +cmake_minimum_required(VERSION 3.12) +project(ADIOS2SimulationsGrayScottKokkosExample) + +# CXX Compiler settings only in for this example +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +if(NOT TARGET adios2_core) + set(_components CXX) + + find_package(MPI COMPONENTS C) + if(MPI_FOUND) + # Workaround for various MPI implementations forcing the link of C++ bindings + add_definitions(-DOMPI_SKIP_MPICXX -DMPICH_SKIP_MPICXX) + + list(APPEND _components MPI) + endif() + + find_package(Kokkos 3.7 QUIET) + if(Kokkos_FOUND AND DEFINED Kokkos_CXX_COMPILER) + set(CMAKE_CXX_COMPILER "${Kokkos_CXX_COMPILER}") + endif() + + find_package(ADIOS2 REQUIRED COMPONENTS ${_components}) +else() + if(DEFINED Kokkos_CXX_COMPILER) + set(CMAKE_CXX_COMPILER "${Kokkos_CXX_COMPILER}") + endif() +endif() + +if(ADIOS2_HAVE_MPI AND ADIOS2_HAVE_Kokkos) + add_executable(adios2_simulations_gray-scott-kokkos + main.cpp + gray-scott.cpp + settings.cpp + writer.cpp + restart.cpp + ) + kokkos_compilation(SOURCE gray-scott.cpp) + target_link_libraries(adios2_simulations_gray-scott-kokkos adios2::cxx11_mpi MPI::MPI_C Kokkos::kokkos) + install(TARGETS adios2_simulations_gray-scott-kokkos RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) +endif() diff --git a/examples/simulations/gray-scott-kokkos/ReadMe.md b/examples/simulations/gray-scott-kokkos/ReadMe.md new file mode 100644 index 0000000000..86790505d0 --- /dev/null +++ b/examples/simulations/gray-scott-kokkos/ReadMe.md @@ -0,0 +1,9 @@ +### ADIOS2 gray-scott-kokkos example + +This is a 3D 7-point stencil code to simulate the following [Gray-Scott +reaction diffusion model](https://doi.org/10.1126/science.261.5118.189): + +#### Differences from the gray-scott example + +It uses Kokkos to run the simulation on GPU. +Please use the installed Gray-Scott example directory but run adios2_simulations_gray-scott-kokkos binary. diff --git a/examples/simulations/gray-scott-kokkos/gray-scott.cpp b/examples/simulations/gray-scott-kokkos/gray-scott.cpp new file mode 100644 index 0000000000..b6f6cd4b7c --- /dev/null +++ b/examples/simulations/gray-scott-kokkos/gray-scott.cpp @@ -0,0 +1,330 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * The solver is based on Hiroshi Watanabe's 2D Gray-Scott reaction diffusion + * code available at: https://github.com/kaityo256/sevendayshpc/tree/master/day5 + */ + +#include "gray-scott.h" + +#include +#include // runtime_error +#include + +GrayScott::GrayScott(const Settings &settings, MPI_Comm comm) +: settings(settings), comm(comm), rand_pool(5374857) +{ +} + +GrayScott::~GrayScott() {} + +void GrayScott::init() +{ + init_mpi(); + init_field(); +} + +void GrayScott::iterate() +{ + auto temp_u = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace{}, u); + auto temp_v = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace{}, v); + exchange(temp_u, temp_v); + Kokkos::deep_copy(u, temp_u); + Kokkos::deep_copy(v, temp_v); + + calc(); + + std::swap(u, u2); + std::swap(v, v2); +} + +void GrayScott::restart(Kokkos::View &u_in, + Kokkos::View &v_in) +{ + auto const expected_len = (size_x + 2) * (size_y + 2) * (size_z + 2); + if (u_in.size() == expected_len) + { + u = u_in; + v = v_in; + } + else + { + throw std::runtime_error("Restart with incompatible array size, expected " + + std::to_string(expected_len) + " got " + + std::to_string(u_in.size()) + " elements"); + } +} + +const Kokkos::View GrayScott::u_ghost() const { return u; } + +const Kokkos::View GrayScott::v_ghost() const { return v; } + +Kokkos::View GrayScott::u_noghost() const +{ + return data_noghost(u); +} + +Kokkos::View GrayScott::v_noghost() const +{ + return data_noghost(v); +} + +void GrayScott::u_noghost(Kokkos::View u_no_ghost) const +{ + data_noghost(u, u_no_ghost); +} + +void GrayScott::v_noghost(Kokkos::View v_no_ghost) const +{ + data_noghost(v, v_no_ghost); +} + +Kokkos::View +GrayScott::data_noghost(const Kokkos::View &data) const +{ + Kokkos::View buf("noghost_temp", size_x, size_y, size_z); + data_no_ghost_common(data, buf); + return buf; +} + +void GrayScott::data_noghost(const Kokkos::View &data, + Kokkos::View data_no_ghost) const +{ + data_no_ghost_common(data, data_no_ghost); +} + +void GrayScott::init_field() +{ + Kokkos::resize(u, size_x + 2, size_y + 2, size_z + 2); + Kokkos::deep_copy(u, 1.0); + Kokkos::resize(v, size_x + 2, size_y + 2, size_z + 2); + Kokkos::deep_copy(v, 0.0); + Kokkos::resize(u2, size_x + 2, size_y + 2, size_z + 2); + Kokkos::deep_copy(u2, 0.0); + Kokkos::resize(v2, size_x + 2, size_y + 2, size_z + 2); + Kokkos::deep_copy(v2, 0.0); + + const int d = 6; + auto const L = settings.L; + auto const settingsL = static_cast(settings.L); + auto const temp_u = u; + auto const temp_v = v; + size_t const ox = offset_x, oy = offset_y, oz = offset_z; + size_t const sx = size_x, sy = size_y; + auto const min_z = std::max(L / 2 - d, offset_z); + auto const max_z = std::min(L / 2 + d, offset_z + size_z); + Kokkos::parallel_for( + "init_buffers", Kokkos::RangePolicy<>(min_z, max_z), KOKKOS_LAMBDA(int z) { + for (int y = settingsL / 2 - d; y < settingsL / 2 + d; y++) + { + if (y < static_cast(oy)) + continue; + if (y >= static_cast(oy + sy)) + continue; + for (int x = settingsL / 2 - d; x < settingsL / 2 + d; x++) + { + if (x < static_cast(ox)) + continue; + if (x >= static_cast(ox + sx)) + continue; + temp_u(x - ox + 1, y - oy + 1, z - oz + 1) = 0.25; + temp_v(x - ox + 1, y - oy + 1, z - oz + 1) = 0.33; + } + } + }); +} + +void GrayScott::calc() +{ + auto const temp_u = u; + auto const temp_v = v; + auto const temp_u2 = u2; + auto const temp_v2 = v2; + auto const Du = settings.Du; + auto const Dv = settings.Dv; + auto const dt = settings.dt; + auto const F = settings.F; + auto const k = settings.k; + auto const noise = settings.noise; + size_t const sx = size_x, sy = size_y, sz = size_z; + auto const random_pool = rand_pool; + Kokkos::parallel_for( + "calc_gray_scott", Kokkos::RangePolicy<>(1, sz + 1), KOKKOS_LAMBDA(int z) { + RandomPool::generator_type generator = random_pool.get_state(); + double ts; + for (int y = 1; y < static_cast(sy) + 1; y++) + { + for (int x = 1; x < static_cast(sx) + 1; x++) + { + double du, dv; + // laplacian for u + ts = 0; + ts += temp_u(x - 1, y, z); + ts += temp_u(x + 1, y, z); + ts += temp_u(x, y - 1, z); + ts += temp_u(x, y + 1, z); + ts += temp_u(x, y, z - 1); + ts += temp_u(x, y, z + 1); + ts += -6.0 * temp_u(x, y, z); + ts /= 6.0; + du = Du * ts; + + // laplacian for v + ts = 0; + ts += temp_v(x - 1, y, z); + ts += temp_v(x + 1, y, z); + ts += temp_v(x, y - 1, z); + ts += temp_v(x, y + 1, z); + ts += temp_v(x, y, z - 1); + ts += temp_v(x, y, z + 1); + ts += -6.0 * temp_v(x, y, z); + ts /= 6.0; + dv = Dv * ts; + + du += (-temp_u(x, y, z) * temp_v(x, y, z) * temp_v(x, y, z) + + F * (1.0 - temp_u(x, y, z))); + dv += (temp_u(x, y, z) * temp_v(x, y, z) * temp_v(x, y, z) - + (F + k) * temp_v(x, y, z)); + du += noise * generator.frand(-1.f, 1.f); + temp_u2(x, y, z) = temp_u(x, y, z) + du * dt; + temp_v2(x, y, z) = temp_v(x, y, z) + dv * dt; + } + } + random_pool.free_state(generator); + }); +} + +void GrayScott::init_mpi() +{ + int dims[3] = {}; + const int periods[3] = {1, 1, 1}; + int coords[3] = {}; + + MPI_Comm_rank(comm, &rank); + MPI_Comm_size(comm, &procs); + + MPI_Dims_create(procs, 3, dims); + npx = dims[0]; + npy = dims[1]; + npz = dims[2]; + + MPI_Cart_create(comm, 3, dims, periods, 0, &cart_comm); + MPI_Cart_coords(cart_comm, rank, 3, coords); + px = coords[0]; + py = coords[1]; + pz = coords[2]; + + size_x = settings.L / npx; + size_y = settings.L / npy; + size_z = settings.L / npz; + + if (px < settings.L % npx) + { + size_x++; + } + if (py < settings.L % npy) + { + size_y++; + } + if (pz < settings.L % npz) + { + size_z++; + } + + offset_x = (settings.L / npx * px) + std::min(settings.L % npx, px); + offset_y = (settings.L / npy * py) + std::min(settings.L % npy, py); + offset_z = (settings.L / npz * pz) + std::min(settings.L % npz, pz); + + MPI_Cart_shift(cart_comm, 0, 1, &west, &east); + MPI_Cart_shift(cart_comm, 1, 1, &down, &up); + MPI_Cart_shift(cart_comm, 2, 1, &south, &north); + + // XY faces: size_x * (size_y + 2) + MPI_Type_vector(static_cast(size_y + 2), static_cast(size_x), + static_cast(size_x + 2), MPI_DOUBLE, &xy_face_type); + MPI_Type_commit(&xy_face_type); + + // XZ faces: size_x * size_z + MPI_Type_vector(static_cast(size_z), static_cast(size_x), + static_cast((size_x + 2) * (size_y + 2)), MPI_DOUBLE, &xz_face_type); + MPI_Type_commit(&xz_face_type); + + // YZ faces: (size_y + 2) * (size_z + 2) + MPI_Type_vector(static_cast((size_y + 2) * (size_z + 2)), 1, static_cast(size_x + 2), + MPI_DOUBLE, &yz_face_type); + MPI_Type_commit(&yz_face_type); +} + +void GrayScott::exchange_xy( + Kokkos::View local_data) const +{ + MPI_Status st; + + // Send XY face z=size_z to north and receive z=0 from south + MPI_Sendrecv(&local_data.data()[l2i(1, 0, static_cast(size_z))], 1, xy_face_type, north, 1, + &local_data.data()[l2i(1, 0, 0)], 1, xy_face_type, south, 1, cart_comm, &st); + // Send XY face z=1 to south and receive z=size_z+1 from north + MPI_Sendrecv(&local_data.data()[l2i(1, 0, 1)], 1, xy_face_type, south, 1, + &local_data.data()[l2i(1, 0, static_cast(size_z + 1))], 1, xy_face_type, + north, 1, cart_comm, &st); +} + +void GrayScott::exchange_xz( + Kokkos::View local_data) const +{ + MPI_Status st; + + // Send XZ face y=size_y to up and receive y=0 from down + MPI_Sendrecv(&local_data.data()[l2i(1, static_cast(size_y), 1)], 1, xz_face_type, up, 2, + &local_data.data()[l2i(1, 0, 1)], 1, xz_face_type, down, 2, cart_comm, &st); + // Send XZ face y=1 to down and receive y=size_y+1 from up + MPI_Sendrecv(&local_data.data()[l2i(1, 1, 1)], 1, xz_face_type, down, 2, + &local_data.data()[l2i(1, static_cast(size_y + 1), 1)], 1, xz_face_type, up, + 2, cart_comm, &st); +} + +void GrayScott::exchange_yz( + Kokkos::View local_data) const +{ + MPI_Status st; + + // Send YZ face x=size_x to east and receive x=0 from west + MPI_Sendrecv(&local_data.data()[l2i(static_cast(size_x), 0, 0)], 1, yz_face_type, east, 3, + &local_data.data()[l2i(0, 0, 0)], 1, yz_face_type, west, 3, cart_comm, &st); + // Send YZ face x=1 to west and receive x=size_x+1 from east + MPI_Sendrecv(&local_data.data()[l2i(1, 0, 0)], 1, yz_face_type, west, 3, + &local_data.data()[l2i(static_cast(size_x + 1), 0, 0)], 1, yz_face_type, east, + 3, cart_comm, &st); +} + +void GrayScott::exchange(Kokkos::View u, + Kokkos::View v) const +{ + exchange_xy(u); + exchange_xz(u); + exchange_yz(u); + + exchange_xy(v); + exchange_xz(v); + exchange_yz(v); +} + +void GrayScott::data_no_ghost_common( + const Kokkos::View &data, + Kokkos::View data_no_ghost) const +{ + auto const sx = size_x; + auto const sy = size_y; + auto const sz = size_z; + Kokkos::parallel_for( + "updateBuffer", Kokkos::RangePolicy<>(1, sz + 1), KOKKOS_LAMBDA(int z) { + for (int y = 1; y < static_cast(sy) + 1; y++) + { + for (int x = 1; x < static_cast(sx) + 1; x++) + { + data_no_ghost(x - 1, y - 1, z - 1) = data(x, y, z); + } + } + }); +} diff --git a/examples/simulations/gray-scott-kokkos/gray-scott.h b/examples/simulations/gray-scott-kokkos/gray-scott.h new file mode 100644 index 0000000000..26553c8c07 --- /dev/null +++ b/examples/simulations/gray-scott-kokkos/gray-scott.h @@ -0,0 +1,102 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + */ + +#ifndef __GRAY_SCOTT_H__ +#define __GRAY_SCOTT_H__ + +#include + +#include +#include +#include + +#include "settings.h" + +class GrayScott +{ +public: + // Dimension of process grid + size_t npx, npy, npz; + // Coordinate of this rank in process grid + size_t px, py, pz; + // Dimension of local array + size_t size_x, size_y, size_z; + // Offset of local array in the global array + size_t offset_x, offset_y, offset_z; + + GrayScott(const Settings &settings, MPI_Comm comm); + ~GrayScott(); + + void init(); + void iterate(); + void restart(Kokkos::View &u, + Kokkos::View &v); + + const Kokkos::View u_ghost() const; + const Kokkos::View v_ghost() const; + + Kokkos::View u_noghost() const; + Kokkos::View v_noghost() const; + + void u_noghost(Kokkos::View u_no_ghost) const; + void v_noghost(Kokkos::View v_no_ghost) const; + + Settings settings; + + Kokkos::View u, v, u2, v2; + + int rank, procs; + int west, east, up, down, north, south; + MPI_Comm comm; + MPI_Comm cart_comm; + + // MPI datatypes for halo exchange + MPI_Datatype xy_face_type; + MPI_Datatype xz_face_type; + MPI_Datatype yz_face_type; + + using RandomPool = Kokkos::Random_XorShift64_Pool; + RandomPool rand_pool; + + // Setup cartesian communicator data types + void init_mpi(); + // Setup initial conditions + void init_field(); + + // Process simulation for one timestep + void calc(); + + // Exchange faces with neighbors + void exchange(Kokkos::View u, + Kokkos::View v) const; + // Exchange XY faces with north/south + void + exchange_xy(Kokkos::View local_data) const; + // Exchange XZ faces with up/down + void + exchange_xz(Kokkos::View local_data) const; + // Exchange YZ faces with west/east + void + exchange_yz(Kokkos::View local_data) const; + + // Return a copy of data with ghosts removed + Kokkos::View + data_noghost(const Kokkos::View &data) const; + + // pointer version + void data_noghost(const Kokkos::View &data, + Kokkos::View no_ghost) const; + + // Convert local coordinate to local index + KOKKOS_FUNCTION int l2i(int x, int y, int z) const + { + return static_cast(x + y * (size_x + 2) + z * (size_x + 2) * (size_y + 2)); + } + + void data_no_ghost_common(const Kokkos::View &data, + Kokkos::View data_no_ghost) const; +}; + +#endif diff --git a/examples/simulations/gray-scott-kokkos/json.hpp b/examples/simulations/gray-scott-kokkos/json.hpp new file mode 100644 index 0000000000..1e7cf51e0a --- /dev/null +++ b/examples/simulations/gray-scott-kokkos/json.hpp @@ -0,0 +1,20274 @@ +/* + __ _____ _____ _____ + __| | __| | | | JSON for Modern C++ +| | |__ | | | | | | version 3.4.0 +|_____|_____|_____|_|___| https://github.com/nlohmann/json + +Licensed under the MIT License . +SPDX-License-Identifier: MIT +Copyright (c) 2013-2018 Niels Lohmann . + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +#ifndef NLOHMANN_JSON_HPP +#define NLOHMANN_JSON_HPP + +#define NLOHMANN_JSON_VERSION_MAJOR 3 +#define NLOHMANN_JSON_VERSION_MINOR 4 +#define NLOHMANN_JSON_VERSION_PATCH 0 + +#include // all_of, find, for_each +#include // assert +#include // and, not, or +#include // nullptr_t, ptrdiff_t, size_t +#include // hash, less +#include // initializer_list +#include // istream, ostream +#include // iterator_traits, random_access_iterator_tag +#include // accumulate +#include // string, stoi, to_string +#include // declval, forward, move, pair, swap + +// #include +#ifndef NLOHMANN_JSON_FWD_HPP +#define NLOHMANN_JSON_FWD_HPP + +#include // int64_t, uint64_t +#include // map +#include // allocator +#include // string +#include // vector + +/*! +@brief namespace for Niels Lohmann +@see https://github.com/nlohmann +@since version 1.0.0 +*/ +namespace nlohmann +{ +/*! +@brief default JSONSerializer template argument + +This serializer ignores the template arguments and uses ADL +([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl)) +for serialization. +*/ +template +struct adl_serializer; + +template class ObjectType = + std::map, + template class ArrayType = std::vector, + class StringType = std::string, class BooleanType = bool, + class NumberIntegerType = std::int64_t, + class NumberUnsignedType = std::uint64_t, + class NumberFloatType = double, + template class AllocatorType = std::allocator, + template class JSONSerializer = + adl_serializer> +class basic_json; + +/*! +@brief JSON Pointer + +A JSON pointer defines a string syntax for identifying a specific value +within a JSON document. It can be used with functions `at` and +`operator[]`. Furthermore, JSON pointers are the base for JSON patches. + +@sa [RFC 6901](https://tools.ietf.org/html/rfc6901) + +@since version 2.0.0 +*/ +template +class json_pointer; + +/*! +@brief default JSON class + +This type is the default specialization of the @ref basic_json class which +uses the standard template types. + +@since version 1.0.0 +*/ +using json = basic_json<>; +} // namespace nlohmann + +#endif + +// #include + + +// This file contains all internal macro definitions +// You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them + +// exclude unsupported compilers +#if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK) + #if defined(__clang__) + #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400 + #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers" + #endif + #elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER)) + #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800 + #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers" + #endif + #endif +#endif + +// disable float-equal warnings on GCC/clang +#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wfloat-equal" +#endif + +// disable documentation warnings on clang +#if defined(__clang__) + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdocumentation" +#endif + +// allow for portable deprecation warnings +#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) + #define JSON_DEPRECATED __attribute__((deprecated)) +#elif defined(_MSC_VER) + #define JSON_DEPRECATED __declspec(deprecated) +#else + #define JSON_DEPRECATED +#endif + +// allow to disable exceptions +#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION) + #define JSON_THROW(exception) throw exception + #define JSON_TRY try + #define JSON_CATCH(exception) catch(exception) + #define JSON_INTERNAL_CATCH(exception) catch(exception) +#else + #define JSON_THROW(exception) std::abort() + #define JSON_TRY if(true) + #define JSON_CATCH(exception) if(false) + #define JSON_INTERNAL_CATCH(exception) if(false) +#endif + +// override exception macros +#if defined(JSON_THROW_USER) + #undef JSON_THROW + #define JSON_THROW JSON_THROW_USER +#endif +#if defined(JSON_TRY_USER) + #undef JSON_TRY + #define JSON_TRY JSON_TRY_USER +#endif +#if defined(JSON_CATCH_USER) + #undef JSON_CATCH + #define JSON_CATCH JSON_CATCH_USER + #undef JSON_INTERNAL_CATCH + #define JSON_INTERNAL_CATCH JSON_CATCH_USER +#endif +#if defined(JSON_INTERNAL_CATCH_USER) + #undef JSON_INTERNAL_CATCH + #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER +#endif + +// manual branch prediction +#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) + #define JSON_LIKELY(x) __builtin_expect(!!(x), 1) + #define JSON_UNLIKELY(x) __builtin_expect(!!(x), 0) +#else + #define JSON_LIKELY(x) x + #define JSON_UNLIKELY(x) x +#endif + +// C++ language standard detection +#if (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464 + #define JSON_HAS_CPP_17 + #define JSON_HAS_CPP_14 +#elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1) + #define JSON_HAS_CPP_14 +#endif + +/*! +@brief macro to briefly define a mapping between an enum and JSON +@def NLOHMANN_JSON_SERIALIZE_ENUM +@since version 3.4.0 +*/ +#define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \ + template \ + inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \ + { \ + static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ + static const std::pair m[] = __VA_ARGS__; \ + auto it = std::find_if(std::begin(m), std::end(m), \ + [e](const std::pair& ej_pair) -> bool \ + { \ + return ej_pair.first == e; \ + }); \ + j = ((it != std::end(m)) ? it : std::begin(m))->second; \ + } \ + template \ + inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \ + { \ + static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ + static const std::pair m[] = __VA_ARGS__; \ + auto it = std::find_if(std::begin(m), std::end(m), \ + [j](const std::pair& ej_pair) -> bool \ + { \ + return ej_pair.second == j; \ + }); \ + e = ((it != std::end(m)) ? it : std::begin(m))->first; \ + } + +// Ugly macros to avoid uglier copy-paste when specializing basic_json. They +// may be removed in the future once the class is split. + +#define NLOHMANN_BASIC_JSON_TPL_DECLARATION \ + template class ObjectType, \ + template class ArrayType, \ + class StringType, class BooleanType, class NumberIntegerType, \ + class NumberUnsignedType, class NumberFloatType, \ + template class AllocatorType, \ + template class JSONSerializer> + +#define NLOHMANN_BASIC_JSON_TPL \ + basic_json + +// #include + + +#include // not +#include // size_t +#include // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type + +namespace nlohmann +{ +namespace detail +{ +// alias templates to reduce boilerplate +template +using enable_if_t = typename std::enable_if::type; + +template +using uncvref_t = typename std::remove_cv::type>::type; + +// implementation of C++14 index_sequence and affiliates +// source: https://stackoverflow.com/a/32223343 +template +struct index_sequence +{ + using type = index_sequence; + using value_type = std::size_t; + static constexpr std::size_t size() noexcept + { + return sizeof...(Ints); + } +}; + +template +struct merge_and_renumber; + +template +struct merge_and_renumber, index_sequence> + : index_sequence < I1..., (sizeof...(I1) + I2)... > {}; + +template +struct make_index_sequence + : merge_and_renumber < typename make_index_sequence < N / 2 >::type, + typename make_index_sequence < N - N / 2 >::type > {}; + +template<> struct make_index_sequence<0> : index_sequence<> {}; +template<> struct make_index_sequence<1> : index_sequence<0> {}; + +template +using index_sequence_for = make_index_sequence; + +// dispatch utility (taken from ranges-v3) +template struct priority_tag : priority_tag < N - 1 > {}; +template<> struct priority_tag<0> {}; + +// taken from ranges-v3 +template +struct static_const +{ + static constexpr T value{}; +}; + +template +constexpr T static_const::value; +} // namespace detail +} // namespace nlohmann + +// #include + + +#include // not +#include // numeric_limits +#include // false_type, is_constructible, is_integral, is_same, true_type +#include // declval + +// #include + +// #include + +// #include + + +#include + +// #include + + +namespace nlohmann +{ +namespace detail +{ +template struct make_void +{ + using type = void; +}; +template using void_t = typename make_void::type; +} // namespace detail +} // namespace nlohmann + + +// http://en.cppreference.com/w/cpp/experimental/is_detected +namespace nlohmann +{ +namespace detail +{ +struct nonesuch +{ + nonesuch() = delete; + ~nonesuch() = delete; + nonesuch(nonesuch const&) = delete; + void operator=(nonesuch const&) = delete; +}; + +template class Op, + class... Args> +struct detector +{ + using value_t = std::false_type; + using type = Default; +}; + +template class Op, class... Args> +struct detector>, Op, Args...> +{ + using value_t = std::true_type; + using type = Op; +}; + +template