3030#include " openPMD/IterationEncoding.hpp"
3131#include " openPMD/auxiliary/Environment.hpp"
3232#include " openPMD/auxiliary/Filesystem.hpp"
33+ #include " openPMD/auxiliary/JSON_internal.hpp"
3334#include " openPMD/auxiliary/Mpi.hpp"
3435#include " openPMD/auxiliary/StringManip.hpp"
3536#include " openPMD/auxiliary/TypeTraits.hpp"
@@ -213,7 +214,8 @@ void ADIOS2IOHandlerImpl::init(
213214 {
214215 "adios2": {
215216 "dataset": {
216- "operators": null
217+ "operators": null,
218+ "shape": null
217219 }
218220 }
219221 })" ;
@@ -739,6 +741,12 @@ void ADIOS2IOHandlerImpl::createPath(
739741 }
740742}
741743
744+ enum class Shape
745+ {
746+ GlobalArray,
747+ LocalValue
748+ };
749+
742750void ADIOS2IOHandlerImpl::createDataset (
743751 Writable *writable, const Parameter<Operation::CREATE_DATASET> ¶meters)
744752{
@@ -798,15 +806,52 @@ void ADIOS2IOHandlerImpl::createDataset(
798806 }();
799807
800808 std::vector<ParameterizedOperator> operators;
801- if (config.json ().contains (" adios2" ))
802- {
803- json::TracingJSON datasetConfig (config[" adios2" ]);
804- auto datasetOperators = getOperators (datasetConfig);
809+
810+ Shape arrayShape = Shape::GlobalArray;
811+ [&]() {
812+ if (!config.json ().contains (" adios2" ))
813+ {
814+ return ;
815+ };
816+ json::TracingJSON adios2Config (config[" adios2" ]);
817+ auto datasetOperators = getOperators (adios2Config);
805818 if (datasetOperators.has_value ())
806819 {
807820 operators = std::move (*datasetOperators);
808821 }
809- }
822+ if (!adios2Config.json ().contains (" dataset" ))
823+ {
824+ return ;
825+ }
826+ auto datasetConfig = adios2Config[" dataset" ];
827+ if (!datasetConfig.json ().contains (" shape" ))
828+ {
829+ return ;
830+ }
831+ auto maybe_shape =
832+ json::asLowerCaseStringDynamic (datasetConfig[" shape" ].json ());
833+ if (!maybe_shape.has_value ())
834+ {
835+ throw error::BackendConfigSchema (
836+ {" adios2" , " dataset" , " shape" },
837+ " Must be convertible to string type." );
838+ }
839+ auto const &shape = *maybe_shape;
840+ if (shape == " global_array" )
841+ {
842+ arrayShape = Shape::GlobalArray;
843+ }
844+ else if (shape == " local_value" )
845+ {
846+ arrayShape = Shape::LocalValue;
847+ }
848+ else
849+ {
850+ throw error::BackendConfigSchema (
851+ {" adios2" , " dataset" , " shape" },
852+ " Unknown value: '" + shape + " '." );
853+ }
854+ }();
810855
811856#if 0
812857 std::cout << "Operations for '" << varName << "':";
@@ -823,12 +868,41 @@ void ADIOS2IOHandlerImpl::createDataset(
823868 " Warning: parts of the backend configuration for ADIOS2 dataset '" +
824869 varName + " ' remain unused:\n " );
825870
826- // cast from openPMD::Extent to adios2::Dims
827- adios2::Dims shape (parameters.extent .begin (), parameters.extent .end ());
828- if (auto jd = parameters.joinedDimension ; jd.has_value ())
829- {
830- shape[jd.value ()] = adios2::JoinedDim;
831- }
871+ adios2::Dims shape = [&]() {
872+ switch (arrayShape)
873+ {
874+
875+ case Shape::GlobalArray: {
876+ // cast from openPMD::Extent to adios2::Dims
877+ adios2::Dims res (
878+ parameters.extent .begin (), parameters.extent .end ());
879+ if (auto jd = parameters.joinedDimension ; jd.has_value ())
880+ {
881+ res[jd.value ()] = adios2::JoinedDim;
882+ }
883+ return res;
884+ }
885+ case Shape::LocalValue: {
886+ int required_size = 1 ;
887+ #if openPMD_HAVE_MPI
888+ if (m_communicator.has_value ())
889+ {
890+ MPI_Comm_size (*m_communicator, &required_size);
891+ }
892+ #endif
893+ if (parameters.extent !=
894+ Extent{Extent::value_type (required_size)})
895+ {
896+ throw error::OperationUnsupportedInBackend (
897+ " ADIOS2" ,
898+ " Shape for local value array must be a 1D array "
899+ " equivalent to the MPI size." );
900+ }
901+ return adios2::Dims{adios2::LocalValueDim};
902+ }
903+ }
904+ throw std::runtime_error (" Unreachable!" );
905+ }();
832906
833907 auto &fileData = getFileData (file, IfFileNotOpen::ThrowError);
834908
@@ -1125,6 +1199,10 @@ namespace detail
11251199 auto &engine = ba.getEngine ();
11261200 adios2::Variable<T> variable = impl->verifyDataset <T>(
11271201 params.offset , params.extent , IO, varName);
1202+ if (variable.Shape () == adios2::Dims{adios2::LocalValueDim})
1203+ {
1204+ params.out ->backendManagedBuffer = false ;
1205+ }
11281206 adios2::Dims offset (params.offset .begin (), params.offset .end ());
11291207 adios2::Dims extent (params.extent .begin (), params.extent .end ());
11301208 variable.SetSelection ({std::move (offset), std::move (extent)});
0 commit comments