24#include "openPMD/Error.hpp"
25#include "openPMD/IO/ADIOS/ADIOS2Auxiliary.hpp"
26#include "openPMD/IO/ADIOS/ADIOS2FilePosition.hpp"
27#include "openPMD/IO/ADIOS/ADIOS2PreloadAttributes.hpp"
28#include "openPMD/IO/ADIOS/ADIOS2PreloadVariables.hpp"
29#include "openPMD/IO/ADIOS/macros.hpp"
30#include "openPMD/IO/AbstractIOHandler.hpp"
31#include "openPMD/IO/AbstractIOHandlerImpl.hpp"
32#include "openPMD/IO/AbstractIOHandlerImplCommon.hpp"
33#include "openPMD/IO/FlushParametersInternal.hpp"
34#include "openPMD/IO/IOTask.hpp"
35#include "openPMD/IO/InvalidatableFile.hpp"
36#include "openPMD/IterationEncoding.hpp"
37#include "openPMD/ThrowError.hpp"
38#include "openPMD/auxiliary/JSON_internal.hpp"
39#include "openPMD/auxiliary/StringManip.hpp"
40#include "openPMD/backend/Variant_internal.hpp"
41#include "openPMD/backend/Writable.hpp"
42#include "openPMD/config.hpp"
45#if openPMD_HAVE_ADIOS2
51#include <nlohmann/json.hpp>
61#include <unordered_map>
67#if openPMD_HAVE_ADIOS2
69std::optional<size_t> joinedDimension(adios2::Dims
const &dims);
75 template <
typename,
typename>
93 struct BufferedAttributeRead;
94 struct BufferedAttributeWrite;
98class ADIOS2IOHandlerImpl
99 :
public AbstractIOHandlerImplCommon<ADIOS2FilePosition>
101 template <
typename,
typename>
117 friend struct detail::BufferedAttributeRead;
120 using UseGroupTable = adios_defs::UseGroupTable;
121 using FlushTarget = adios_defs::FlushTarget;
129 std::string engineType,
130 std::string specifiedExtension);
134 explicit ADIOS2IOHandlerImpl(
136 std::string engineType,
137 std::string specifiedExtension);
139 ~ADIOS2IOHandlerImpl()
override;
149 bool checkFile(std::string fullFilePath)
const;
225 FlushTarget m_flushTarget = FlushTarget::Disk;
228 adios2::ADIOS m_ADIOS;
230 std::optional<MPI_Comm> m_communicator;
235 std::string m_engineType;
236 std::optional<std::string> m_realEngineType;
238 inline std::string
const &realEngineType()
const
240 if (m_realEngineType.has_value())
242 return *m_realEngineType;
249 inline std::string &realEngineType()
251 return const_cast<std::string &
>(
252 static_cast<ADIOS2IOHandlerImpl
const *
>(
this)->realEngineType());
254 inline void pretendEngine(std::string facade_engine)
256 if (!m_realEngineType.has_value())
258 m_realEngineType = std::move(m_engineType);
260 m_engineType = std::move(facade_engine);
265 std::string m_userSpecifiedExtension;
271 std::optional<UseGroupTable> m_useGroupTable;
273 enum class UseSpan :
char
280 UseSpan m_useSpanBasedPutByDefault = UseSpan::Auto;
282 enum class ModifiableAttributes :
char
289 ModifiableAttributes m_modifiableAttributes =
290 ModifiableAttributes::Unspecified;
292 inline UseGroupTable useGroupTable()
const
294 if (!m_useGroupTable.has_value())
296 return UseGroupTable::No;
298 return m_useGroupTable.value();
301 bool m_writeAttributesFromThisRank =
true;
303 struct ParameterizedOperator
306 adios2::Params params;
309 std::vector<ParameterizedOperator> defaultOperators;
314 template <
typename Callback>
318 template <
typename Key>
321 if (cfg.
json().is_object() && cfg.
json().contains(key))
331 template <
typename Key>
334 return config<Key>(std::forward<Key>(key), m_config);
344 std::optional<std::vector<ParameterizedOperator>>
348 std::optional<std::vector<ParameterizedOperator>> getOperators();
350 template <
typename Parameter>
351 std::vector<ParameterizedOperator> getDatasetOperators(
354 std::string fileSuffix(
bool verbose =
true)
const;
376 std::unordered_map<InvalidatableFile, std::unique_ptr<detail::ADIOS2File>>
379 std::map<std::string, adios2::Operator> m_operators;
384 filePositionToString(std::shared_ptr<ADIOS2FilePosition>)
override;
386 std::shared_ptr<ADIOS2FilePosition> extendFilePosition(
387 std::shared_ptr<ADIOS2FilePosition>
const &pos,
388 std::string extend)
override;
392 std::optional<adios2::Operator>
393 getCompressionOperator(std::string
const &compression);
399 std::string nameOfVariable(
Writable *writable);
410 std::string nameOfAttribute(
Writable *writable, std::string attribute);
416 GroupOrDataset groupOrDataset(
Writable *);
418 enum class IfFileNotOpen :
char
423 ReopenFileThatWeCreated,
424 ReopenFileFoundOnDisk = OpenImplicitly,
432 template <
typename T>
433 static void setStepSelectionForVariable(
434 adios2::Variable<T> var,
435 std::string
const &varName,
436 size_t step_selection,
440 auto var_steps = var.Steps();
441 if (var_steps == 1 && step_selection == 0)
446 if (file_steps != var_steps)
448 if (!av.m_preparsed.has_value())
451 error::AffectedObject::Dataset,
452 error::Reason::UnexpectedContent,
454 "The opened file contains different data per step, but "
455 "variable data was not preparsed. ERROR: Variable " +
456 varName +
"' has " + std::to_string(var_steps) +
457 " step(s), but the file has " +
458 std::to_string(file_steps) +
" step(s).");
460 auto preparsed = av.m_preparsed->m_partialVariables.find(varName);
461 if (preparsed == av.m_preparsed->m_partialVariables.end())
464 error::AffectedObject::Dataset,
465 error::Reason::UnexpectedContent,
467 "The opened file contains different data per step, but "
468 "variable data contains no preparsing info on '" +
469 varName +
"'. Has " + std::to_string(var_steps) +
470 " step(s), but the file has " +
471 std::to_string(file_steps) +
" step(s).");
473 auto step_index = std::find(
474 preparsed->second.begin(),
475 preparsed->second.end(),
477 if (step_index == preparsed->second.end())
480 error::AffectedObject::Dataset,
481 error::Reason::UnexpectedContent,
483 "Tried selecting global step " +
484 std::to_string(step_selection) +
" for variable '" +
486 "', but variable is not defined for that step (only "
488 auxiliary::vec_as_string(preparsed->second) +
489 "). Has " + std::to_string(var_steps) +
490 " step(s), but the file has " +
491 std::to_string(file_steps) +
" step(s).");
495 step_selection = step_index - preparsed->second.begin();
497 var.SetStepSelection({step_selection, 1});
508 template <
typename T>
509 adios2::Variable<T> verifyDataset(
510 Offset
const &offset,
511 Extent
const &extent,
513 adios2::Engine &engine,
514 std::string
const &varName,
515 std::optional<size_t> stepSelection,
519 auto requiredType = adios2::GetType<T>();
520 auto actualType = IO.VariableType(varName);
522 if (requiredType != actualType)
524 std::stringstream errorMessage;
525 errorMessage <<
"Trying to access a dataset with wrong type "
526 "(trying to access dataset with type '"
527 << requiredType <<
"', but has type '"
528 << actualType <<
"')";
530 error::AffectedObject::Dataset,
531 error::Reason::UnexpectedContent,
536 adios2::Variable<T> var = IO.InquireVariable<
T>(varName);
537 if (!var.operator
bool())
540 throw std::runtime_error(
541 "[ADIOS2] Internal error: Failed opening ADIOS2 variable.");
543 if (stepSelection.has_value())
545 auto file_steps = engine.Steps();
546 setStepSelectionForVariable(
547 var, varName, *stepSelection, file_steps, av);
550 adios2::Dims shape = var.Shape();
551 auto actualDim = shape.size();
553 auto requiredDim = extent.size();
554 if (requiredDim != actualDim)
557 error::AffectedObject::Dataset,
558 error::Reason::UnexpectedContent,
560 "Trying to access a dataset with wrong dimensionality "
561 "(trying to access dataset with dimensionality " +
562 std::to_string(requiredDim) +
563 ", but has dimensionality " +
564 std::to_string(actualDim) +
")");
567 auto joinedDim = joinedDimension(shape);
568 auto make_runtime_error = [&](
char const *message) {
570 s <<
"[ADIOS2IOHandlerImpl::verifyDataset()] " << message;
571 s <<
"\nNote: Variable '" << varName <<
"' has shape ";
572 auxiliary::write_vec_to_stream(s, shape)
573 <<
", is accessed from offset ";
574 auxiliary::write_vec_to_stream(s, offset) <<
" with extent ";
575 auxiliary::write_vec_to_stream(s, extent);
576 if (joinedDim.has_value())
578 s <<
" (joined dimension on index " << *joinedDim <<
").";
582 s <<
" (no joined dimension).";
584 return std::runtime_error(s.str());
586 if (joinedDim.has_value() ||
587 var.ShapeID() == adios2::ShapeID::JoinedArray)
591 throw make_runtime_error(
592 "Offset must be an empty vector in case of joined array.");
594 if (!joinedDim.has_value())
596 throw make_runtime_error(
597 "Trying to access a dataset as a non-joined array, but it "
598 "has previously been array.");
600 for (
unsigned int i = 0; i < actualDim; i++)
602 if (*joinedDim != i && extent[i] != shape[i])
604 throw make_runtime_error(
605 "store_chunk extent of non-joined dimensions "
606 "must be equivalent to the total extent.");
612 for (
unsigned int i = 0; i < actualDim; i++)
614 if (!(joinedDim.has_value() && *joinedDim == i) &&
615 offset[i] + extent[i] > shape[i])
617 throw make_runtime_error(
"Dataset access out of bounds.");
623 {adios2::Dims(offset.begin(), offset.end()),
624 adios2::Dims(extent.begin(), extent.end())});
630 bool noGroupBased =
false;
631 bool blosc2bp5 =
false;
632 } printedWarningsAlready;
639 template <
typename T>
640 inline constexpr bool IsUnsupportedComplex_v =
641 std::is_same_v<T, std::complex<long double>> ||
642 std::is_same_v<T, std::vector<std::complex<long double>>>;
651 template <
typename AdiosType>
652 auto call(std::string
const &name)
const
655 return attributes.getAttribute<AdiosType>(step, IO, name);
659 template <
typename T>
667 template <
int n,
typename... Params>
673 template <
typename T>
679 template <
int n,
typename... Params>
680 static void call(Params &&...);
685 template <
typename T>
689 std::string
const &varName,
691 std::optional<size_t> stepSelection,
692 std::vector<ADIOS2IOHandlerImpl::ParameterizedOperator>
const
696 static constexpr char const *errorMsg =
"ADIOS2: openDataset()";
716 template <
typename T>
719 std::string
const &name,
720 std::vector<ADIOS2IOHandlerImpl::ParameterizedOperator>
const
722 adios2::Dims
const &shape = adios2::Dims(),
723 adios2::Dims
const &start = adios2::Dims(),
724 adios2::Dims
const &count = adios2::Dims(),
725 bool const constantDims =
false);
727 static constexpr char const *errorMsg =
"ADIOS2: defineVariable()";
732 template <
typename T>
736 adios2::Engine &engine,
737 std::string
const &varName,
740 template <
int n,
typename... Params>
741 static void call(Params &&...);
752 template <
typename T>
761 auto attr = IO.InquireAttribute<
T>(name);
766 std::vector<T> data = attr.Data();
767 if (data.size() != 1)
771 return data[0] == val;
781 throw std::runtime_error(
782 "[ADIOS2] Internal error: no support for long double complex "
791 adios2::IO &, std::string, std::vector<std::complex<long double>>)
793 throw std::runtime_error(
794 "[ADIOS2] Internal error: no support for long double complex "
795 "vector attribute types");
799 template <
typename T>
805 auto attr = IO.InquireAttribute<
T>(name);
810 std::vector<T> data = attr.Data();
811 if (data.size() != val.size())
815 for (
size_t i = 0; i < val.size(); ++i)
817 if (data[i] != val[i])
830 adios2::IO &IO, std::string name, std::vector<std::string> val)
832 auto attr = IO.InquireAttribute<std::string>(name);
837 std::vector<std::string> data = attr.Data();
838 if (data.size() != val.size())
842 for (
size_t i = 0; i < val.size(); ++i)
844 if (data[i] != val[i])
853 template <
typename T,
size_t n>
857 adios2::IO &IO, std::string name, std::array<T, n> val)
859 auto attr = IO.InquireAttribute<
T>(name);
864 std::vector<T> data = attr.Data();
865 if (data.size() != n)
869 for (
size_t i = 0; i < n; ++i)
871 if (data[i] != val[i])
882 using rep = detail::bool_representation;
884 static constexpr rep toRep(
bool b)
889 static constexpr bool fromRep(rep r)
898 using rep = detail::bool_representation;
900 static constexpr rep toRep(
bool b)
905 static constexpr bool fromRep(rep r)
913 auto attr = IO.InquireAttribute<rep>(name);
918 std::vector<rep> data = attr.Data();
919 if (data.size() != 1)
923 return data[0] == toRep(val);
929class ADIOS2IOHandler :
public AbstractIOHandler
931#if openPMD_HAVE_ADIOS2
933 friend class ADIOS2IOHandlerImpl;
936 ADIOS2IOHandlerImpl m_impl;
939 ~ADIOS2IOHandler()
override
944 auto params = internal::defaultParsedFlushParams;
947 catch (std::exception
const &ex)
949 std::cerr <<
"[~ADIOS2IOHandler] An error occurred: " << ex.what()
954 std::cerr <<
"[~ADIOS2IOHandler] An error occurred." << std::endl;
965 std::optional<std::unique_ptr<AbstractIOHandler>> initialize_from,
970 std::string engineType,
971 std::string specifiedExtension);
976 std::optional<std::unique_ptr<AbstractIOHandler>> initialize_from,
980 std::string engineType,
981 std::string specifiedExtension);
988 bool fullSupportForVariableBasedEncoding()
const override
993 std::future<void>
flush(internal::ParsedFlushParams &)
override;
Definition ADIOS2IOHandler.hpp:930
std::future< void > flush(internal::ParsedFlushParams &) override
Process operations in queue according to FIFO.
Definition ADIOS2IOHandler.cpp:2615
std::string backendName() const override
The currently used backend.
Definition ADIOS2IOHandler.hpp:983
Definition ADIOS2IOHandler.hpp:100
adios2::Mode adios2AccessMode(std::string const &fullPath, adios_defs::OpenFileAs)
The ADIOS2 access type to chose for Engines opened within this instance.
Definition ADIOS2IOHandler.cpp:2014
void readDataset(Writable *, Parameter< Operation::READ_DATASET > &) override
Read a chunk of data from an existing dataset.
Definition ADIOS2IOHandler.cpp:1202
void openFile(Writable *, Parameter< Operation::OPEN_FILE > &) override
Open an existing file assuming it conforms to openPMD.
Definition ADIOS2IOHandler.cpp:1018
void touch(Writable *, Parameter< Operation::TOUCH > const &) override
Treat this writable's file as open/active/dirty.
Definition ADIOS2IOHandler.cpp:1999
void writeAttribute(Writable *, Parameter< Operation::WRITE_ATT > const &) override
Create a single attribute and fill the value, possibly overwriting an existing attribute.
Definition ADIOS2IOHandler.cpp:1191
void createFile(Writable *, Parameter< Operation::CREATE_FILE > const &) override
Create a new file in physical storage, possibly overriding an existing file.
Definition ADIOS2IOHandler.cpp:676
void deletePath(Writable *, Parameter< Operation::DELETE_PATH > const &) override
Delete all objects within an existing path.
Definition ADIOS2IOHandler.cpp:1154
void deleteDataset(Writable *, Parameter< Operation::DELETE_DATASET > const &) override
Delete an existing dataset.
Definition ADIOS2IOHandler.cpp:1160
void listDatasets(Writable *, Parameter< Operation::LIST_DATASETS > &) override
List all datasets inside a group, non-recursively.
Definition ADIOS2IOHandler.cpp:1855
void closePath(Writable *, Parameter< Operation::CLOSE_PATH > const &) override
Close an openPMD group.
Definition ADIOS2IOHandler.cpp:1941
void advance(Writable *, Parameter< Operation::ADVANCE > &) override
Advance the file/stream that this writable belongs to.
Definition ADIOS2IOHandler.cpp:1926
void deleteFile(Writable *, Parameter< Operation::DELETE_FILE > const &) override
Delete an existing file from physical storage.
Definition ADIOS2IOHandler.cpp:1148
void listAttributes(Writable *, Parameter< Operation::LIST_ATTS > ¶meters) override
List all attributes associated with an object.
Definition ADIOS2IOHandler.cpp:1897
void openDataset(Writable *, Parameter< Operation::OPEN_DATASET > &) override
Open an existing dataset and determine its datatype and extent.
Definition ADIOS2IOHandler.cpp:1114
void extendDataset(Writable *, Parameter< Operation::EXTEND_DATASET > const &) override
Increase the extent of an existing dataset.
Definition ADIOS2IOHandler.cpp:997
void availableChunks(Writable *, Parameter< Operation::AVAILABLE_CHUNKS > &) override
Report chunks that are available for loading from the dataset represented by this writable.
Definition ADIOS2IOHandler.cpp:1973
void closeFile(Writable *, Parameter< Operation::CLOSE_FILE > const &) override
Close the file corresponding with the writable and release file handles.
Definition ADIOS2IOHandler.cpp:1059
void readAttributeAllsteps(Writable *, Parameter< Operation::READ_ATT_ALLSTEPS > &) override
Collective task to read modifiable attributes over steps.
Definition ADIOS2IOHandler.cpp:1607
void createDataset(Writable *, Parameter< Operation::CREATE_DATASET > const &) override
Create a new dataset of given type, extent and storage properties.
Definition ADIOS2IOHandler.cpp:827
void checkFile(Writable *, Parameter< Operation::CHECK_FILE > &) override
Check if the file specified by the parameter is already present on disk.
Definition ADIOS2IOHandler.cpp:739
void writeDataset(Writable *, Parameter< Operation::WRITE_DATASET > &) override
Write a chunk of data into an existing dataset.
Definition ADIOS2IOHandler.cpp:1174
void listPaths(Writable *, Parameter< Operation::LIST_PATHS > &) override
List all paths/sub-groups inside a group, non-recursively.
Definition ADIOS2IOHandler.cpp:1715
void createPath(Writable *, Parameter< Operation::CREATE_PATH > const &) override
Create all necessary groups for a path, possibly recursively.
Definition ADIOS2IOHandler.cpp:793
void getBufferView(Writable *, Parameter< Operation::GET_BUFFER_VIEW > &) override
Get a view into a dataset buffer that can be filled by a user.
Definition ADIOS2IOHandler.cpp:1290
void readAttribute(Writable *, Parameter< Operation::READ_ATT > &) override
Read the value of an existing attribute.
Definition ADIOS2IOHandler.cpp:1382
void openPath(Writable *, Parameter< Operation::OPEN_PATH > const &) override
Open all contained groups in a path, possibly recursively.
Definition ADIOS2IOHandler.cpp:1086
void deregister(Writable *, Parameter< Operation::DEREGISTER > const &) override
Notify the backend that the Writable has been / will be deallocated.
Definition ADIOS2IOHandler.cpp:1993
void deleteAttribute(Writable *, Parameter< Operation::DELETE_ATT > const &) override
Delete an existing attribute.
Definition ADIOS2IOHandler.cpp:1167
Interface for communicating between logical and physically persistent data.
Definition AbstractIOHandler.hpp:206
std::string fullPath(InvalidatableFile)
Definition AbstractIOHandlerImplCommon.hpp:179
Layer to mirror structure of logical data and persistent data in file.
Definition Writable.hpp:76
Definition ADIOS2File.hpp:143
Extend nlohmann::json with tracing of which keys have been accessed by operator[]().
Definition JSON_internal.hpp:69
nlohmann::json & json()
Access the underlying JSON value.
Definition JSON.cpp:65
Public definitions of openPMD-api.
Definition Date.cpp:29
Access
File access mode to use during IO.
Definition Access.hpp:58
@ T
time
Definition UnitDimension.hpp:41
Datatype
Concrete datatype of an object available at runtime.
Definition Datatype.hpp:51
Wrapper around a shared pointer to:
Definition InvalidatableFile.hpp:44
Typesafe description of all required arguments for a specified Operation.
Definition IOTask.hpp:148
Definition ADIOS2PreloadAttributes.hpp:152
Definition ADIOS2PreloadVariables.hpp:36
Definition ADIOS2IOHandler.hpp:647
Definition ADIOS2IOHandler.hpp:645
Definition ADIOS2IOHandler.hpp:754
static bool attributeUnchanged(adios2::IO &IO, std::string name, T val)
Is the attribute given by parameters name and val already defined exactly in that way within the give...
Definition ADIOS2IOHandler.hpp:759
Definition ADIOS2PreloadAttributes.hpp:132
Definition ADIOS2IOHandler.hpp:672
Definition ADIOS2File.hpp:70
Definition ADIOS2File.hpp:94
Definition ADIOS2IOHandler.hpp:76
Definition ADIOS2IOHandler.hpp:684
Definition ADIOS2File.hpp:79
Definition ADIOS2IOHandler.hpp:88
Definition ADIOS2IOHandler.cpp:1221
Definition ADIOS2IOHandler.hpp:731
Definition ADIOS2File.cpp:163
Definition ADIOS2IOHandler.hpp:700
static void call(adios2::IO &IO, std::string const &name, std::vector< ADIOS2IOHandlerImpl::ParameterizedOperator > const &compressions, adios2::Dims const &shape=adios2::Dims(), adios2::Dims const &start=adios2::Dims(), adios2::Dims const &count=adios2::Dims(), bool const constantDims=false)
Define a Variable of type T within the passed IO.
Definition ADIOS2IOHandler.cpp:2477
Definition ADIOS2File.hpp:102
Definition FlushParametersInternal.hpp:32