diff --git a/include/openPMD/IO/IOTask.hpp b/include/openPMD/IO/IOTask.hpp index d2fc05f379..51dfac4268 100644 --- a/include/openPMD/IO/IOTask.hpp +++ b/include/openPMD/IO/IOTask.hpp @@ -125,6 +125,7 @@ struct OPENPMDAPI_EXPORT Parameter } std::string name = ""; + std::string openPMDversion; // @todo: Maybe move this to AbstractIOHandler }; template <> diff --git a/include/openPMD/RecordComponent.tpp b/include/openPMD/RecordComponent.tpp index e8ba6006ab..7a1f466561 100644 --- a/include/openPMD/RecordComponent.tpp +++ b/include/openPMD/RecordComponent.tpp @@ -21,6 +21,8 @@ #pragma once +#include "openPMD/Datatype.hpp" +#include "openPMD/Error.hpp" #include "openPMD/RecordComponent.hpp" #include "openPMD/Span.hpp" #include "openPMD/auxiliary/Memory.hpp" @@ -93,12 +95,38 @@ inline std::shared_ptr RecordComponent::loadChunk(Offset o, Extent e) #endif } +namespace detail +{ + template + struct do_convert + { + template + static std::optional call(Attribute &attr) + { + if constexpr (std::is_convertible_v) + { + return std::make_optional(attr.get()); + } + else + { + return std::nullopt; + } + } + + static constexpr char const *errorMsg = "is_conversible"; + }; +} // namespace detail + template inline void RecordComponent::loadChunk(std::shared_ptr data, Offset o, Extent e) { Datatype dtype = determineDatatype(data); - if (dtype != getDatatype()) + /* + * For constant components, we implement type conversion, so there is + * a separate check further below. + */ + if (dtype != getDatatype() && !constant()) if (!isSameInteger(getDatatype()) && !isSameFloatingPoint(getDatatype()) && !isSameComplexFloatingPoint(getDatatype()) && @@ -160,10 +188,25 @@ RecordComponent::loadChunk(std::shared_ptr data, Offset o, Extent e) for (auto const &dimensionSize : extent) numPoints *= dimensionSize; - T value = rc.m_constantValue.get(); + std::optional val = + switchNonVectorType>( + /* from = */ getDatatype(), rc.m_constantValue); - T *raw_ptr = data.get(); - std::fill(raw_ptr, raw_ptr + numPoints, value); + if (val.has_value()) + { + T *raw_ptr = data.get(); + std::fill(raw_ptr, raw_ptr + numPoints, *val); + } + else + { + std::string const data_type_str = datatypeToString(getDatatype()); + std::string const requ_type_str = + datatypeToString(determineDatatype()); + std::string err_msg = + "Type conversion during chunk loading not possible! "; + err_msg += "Data: " + data_type_str + "; Load as: " + requ_type_str; + throw error::WrongAPIUsage(err_msg); + } } else { diff --git a/src/IO/JSON/JSONIOHandlerImpl.cpp b/src/IO/JSON/JSONIOHandlerImpl.cpp index 02c9e0710e..c1fd9095a2 100644 --- a/src/IO/JSON/JSONIOHandlerImpl.cpp +++ b/src/IO/JSON/JSONIOHandlerImpl.cpp @@ -455,6 +455,13 @@ void JSONIOHandlerImpl::createFile( access::write(m_handler->m_backendAccess), "[JSON] Creating a file in read-only mode is not possible."); + if (m_attributeModeSpecificationVia == SpecificationVia::DefaultValue) + { + m_attributeMode = parameters.openPMDversion >= "2." + ? AttributeMode::Short + : AttributeMode::Long; + } + if (!writable->written) { std::string name = parameters.name + m_originalExtension; diff --git a/src/Iteration.cpp b/src/Iteration.cpp index 593e38066f..7bb87ff8f3 100644 --- a/src/Iteration.cpp +++ b/src/Iteration.cpp @@ -206,6 +206,7 @@ void Iteration::flushFileBased( /* create file */ Parameter fCreate; fCreate.name = filename; + fCreate.openPMDversion = s.openPMD(); IOHandler()->enqueue(IOTask(&s.writable(), fCreate)); /* create basePath */ diff --git a/src/Series.cpp b/src/Series.cpp index b2c5fc5667..496ae20be4 100644 --- a/src/Series.cpp +++ b/src/Series.cpp @@ -925,6 +925,7 @@ void Series::flushGorVBased( } Parameter fCreate; fCreate.name = series.m_name; + fCreate.openPMDversion = openPMD(); IOHandler()->enqueue(IOTask(this, fCreate)); }