Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Non-spatial meshes #1534

Open
wants to merge 22 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,7 @@ set(CORE_SOURCE
src/Record.cpp
src/RecordComponent.cpp
src/Series.cpp
src/UnitDimension.cpp
src/version.cpp
src/WriteIterations.cpp
src/auxiliary/Date.cpp
Expand Down
59 changes: 26 additions & 33 deletions include/openPMD/IO/AbstractIOHandler.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include "openPMD/IO/IOTask.hpp"
#include "openPMD/IterationEncoding.hpp"
#include "openPMD/config.hpp"
#include "openPMD/version.hpp"

#if openPMD_HAVE_MPI
#include <mpi.h>
Expand Down Expand Up @@ -75,6 +76,20 @@ enum class FlushLevel
CreateOrOpenFiles
};

enum class OpenpmdStandard
{
v_1_0_0,
v_1_0_1,
v_1_1_0,
v_2_0_0
};

namespace auxiliary
{
auto parseStandard(std::string const &) -> OpenpmdStandard;
auto formatStandard(OpenpmdStandard) -> char const *;
} // namespace auxiliary

namespace internal
{
/**
Expand Down Expand Up @@ -189,38 +204,7 @@ class AbstractIOHandler
friend class detail::ADIOS2File;

private:
IterationEncoding m_encoding = IterationEncoding::groupBased;

void setIterationEncoding(IterationEncoding encoding)
{
/*
* In file-based iteration encoding, the APPEND mode is handled entirely
* by the frontend, the backend should just treat it as CREATE mode.
* Similar for READ_LINEAR which should be treated as READ_RANDOM_ACCESS
* in the backend.
*/
if (encoding == IterationEncoding::fileBased)
{
switch (m_backendAccess)
{

case Access::READ_LINEAR:
// do we really want to have those as const members..?
*const_cast<Access *>(&m_backendAccess) =
Access::READ_RANDOM_ACCESS;
break;
case Access::APPEND:
*const_cast<Access *>(&m_backendAccess) = Access::CREATE;
break;
case Access::READ_RANDOM_ACCESS:
case Access::READ_WRITE:
case Access::CREATE:
break;
}
}

m_encoding = encoding;
}
void setIterationEncoding(IterationEncoding encoding);

public:
#if openPMD_HAVE_MPI
Expand Down Expand Up @@ -284,8 +268,14 @@ class AbstractIOHandler
*/
Access m_backendAccess;
Access m_frontendAccess;
internal::SeriesStatus m_seriesStatus = internal::SeriesStatus::Default;
std::queue<IOTask> m_work;

/**************************************************************************
* Since the AbstractIOHandler is linked to every object of the frontend, *
* it stores a number of members that are needed by methods traversing *
* the object hierarchy. Those members are found below. *
**************************************************************************/

/**
* This is to avoid that the destructor tries flushing again if an error
* happened. Otherwise, this would lead to confusing error messages.
Expand All @@ -294,6 +284,9 @@ class AbstractIOHandler
* The destructor will only attempt flushing again if this is true.
*/
bool m_lastFlushSuccessful = false;
internal::SeriesStatus m_seriesStatus = internal::SeriesStatus::Default;
IterationEncoding m_encoding = IterationEncoding::groupBased;
OpenpmdStandard m_standard = auxiliary::parseStandard(getStandardDefault());
}; // AbstractIOHandler

} // namespace openPMD
105 changes: 101 additions & 4 deletions include/openPMD/Mesh.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@
*/
#pragma once

#include "openPMD/UnitDimension.hpp"
#include "openPMD/backend/Attributable.hpp"
#include "openPMD/backend/BaseRecord.hpp"
#include "openPMD/backend/MeshRecordComponent.hpp"

#include <array>
#include <ostream>
#include <string>
#include <type_traits>
Expand Down Expand Up @@ -155,7 +155,7 @@ class Mesh : public BaseRecord<MeshRecordComponent>
*/
template <
typename T,
typename = std::enable_if_t<std::is_floating_point<T>::value> >
typename = std::enable_if_t<std::is_floating_point<T>::value>>
Mesh &setGridSpacing(std::vector<T> const &gridSpacing);

/**
Expand Down Expand Up @@ -184,22 +184,119 @@ class Mesh : public BaseRecord<MeshRecordComponent>
* Mesh::gridSpacing and Mesh::gridGlobalOffset, in order to convert from
* simulation units to SI units.
*
* Valid for openPMD version 1.*.
* In order to specify the gridUnitSI per dimension (openPMD 2.*),
* use the vector overload or `setGridUnitSIPerDimension()`.
*
* @param gridUnitSI unit-conversion factor to multiply each value in
* Mesh::gridSpacing and Mesh::gridGlobalOffset, in order to convert from
* simulation units to SI units.
* @return Reference to modified mesh.
*/
Mesh &setGridUnitSI(double gridUnitSI);

/** Alias for `setGridUnitSIPerDimension(std::vector<double>)`.
*
* Set the unit-conversion factors per axis to multiply each value in
* Mesh::gridSpacing and Mesh::gridGlobalOffset, in order to convert from
* simulation units to SI units.
*
* Valid for openPMD 2.*.
* The legacy behavior (openPMD 1.*, a scalar gridUnitSI) is implemented
* by `setGridUnitSI(double)`.
*
* @param gridUnitSI unit-conversion factor to multiply each value in
* Mesh::gridSpacing and Mesh::gridGlobalOffset, in order to convert from
* simulation units to SI units.
*
* @return Reference to modified mesh.
*/
Mesh &setGridUnitSI(std::vector<double> const &gridUnitSI);

/**
* @return A vector of the gridUnitSI per grid axis in the order of
* the axisLabels. If the gridUnitSI is defined as a scalar
* (legacy openPMD), the dimensionality is determined and a vector of
* `dimensionality` times the scalar vector is returned.
*/
std::vector<double> gridUnitSIPerDimension() const;

/* Set the unit-conversion factors per axis to multiply each value in
* Mesh::gridSpacing and Mesh::gridGlobalOffset, in order to convert from
* simulation units to SI units.
*
* Valid for openPMD 2.*.
* The legacy behavior (openPMD 1.*, a scalar gridUnitSI) is implemented
* by `setGridUnitSI(double)`.
*
* @param gridUnitSI unit-conversion factor to multiply each value in
* Mesh::gridSpacing and Mesh::gridGlobalOffset, in order to convert from
* simulation units to SI units.
*
* @return Reference to modified mesh.
*/
Mesh &setGridUnitSIPerDimension(std::vector<double> const &gridUnitSI);

/** Set the powers of the 7 base measures characterizing the record's unit
* in SI.
*
* @param unitDimension map containing pairs of (UnitDimension, double)
* that represent the power of the particular base.
* @return Reference to modified mesh.
*/
Mesh &setUnitDimension(unit_representations::AsMap const &unitDimension);

/** Set the powers of the 7 base measures characterizing the record's unit
* in SI.
*
* @param unitDimension array containing seven doubles, each
* representing the power of the particular base in order.
* @return Reference to modified mesh.
*/
Mesh &setUnitDimension(unit_representations::AsArray const &unitDimension);

/**
* @brief Set the unitDimension for each axis of the current grid.
*
* @param gridUnitDimension A vector of the unitDimensions for each
* axis of the grid in the order of the axisLabels, in dict representation.

* Behavior note: This is an updating method, meaning that an SI unit that
* has been defined before and is in the next call not explicitly set
* in the `std::map<UnitDimension, double>` will keep its previous value.
*
* @return Reference to modified mesh.
*/
Mesh &
setUnitDimension(std::map<UnitDimension, double> const &unitDimension);
setGridUnitDimension(unit_representations::AsMaps const &gridUnitDimension);

/**
* @brief Set the unitDimension for each axis of the current grid.
*
* @param gridUnitDimension A vector of the unitDimensions for each
* axis of the grid in the order of the axisLabels, in array representation.

* Behavior note: This is an updating method, meaning that an SI unit that
* has been defined before and is in the next call not explicitly set
* in the `std::map<UnitDimension, double>` will keep its previous value.
*
* @return Reference to modified mesh.
*/
Mesh &setGridUnitDimension(
unit_representations::AsArrays const &gridUnitDimension);

/**
* @brief Return the physical dimensions of the mesh axes.

* If the attribute is not defined, the axes are assumed to be spatial
* and the return value will be according to this assumption.
* If the attribute is defined, the dimensionality of the return value is
* not checked against the dimensionality of the mesh.
*
* @return A vector of arrays, each array representing the SI unit of one
* mesh axis.
*/
unit_representations::AsArrays gridUnitDimension() const;

/**
* @tparam T Floating point type of user-selected precision (e.g. float,
Expand All @@ -222,7 +319,7 @@ class Mesh : public BaseRecord<MeshRecordComponent>
*/
template <
typename T,
typename = std::enable_if_t<std::is_floating_point<T>::value> >
typename = std::enable_if_t<std::is_floating_point<T>::value>>
Mesh &setTimeOffset(T timeOffset);

private:
Expand Down
5 changes: 3 additions & 2 deletions include/openPMD/Record.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@
#pragma once

#include "openPMD/RecordComponent.hpp"
#include "openPMD/UnitDimension.hpp"
#include "openPMD/backend/BaseRecord.hpp"

#include <map>
#include <string>
#include <type_traits>

Expand All @@ -40,7 +40,8 @@ class Record : public BaseRecord<RecordComponent>
Record &operator=(Record const &) = default;
~Record() override = default;

Record &setUnitDimension(std::map<UnitDimension, double> const &);
Record &setUnitDimension(unit_representations::AsMap const &);
Record &setUnitDimension(unit_representations::AsArray const &);

template <typename T>
T timeOffset() const;
Expand Down
27 changes: 27 additions & 0 deletions include/openPMD/UnitDimension.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,16 @@
*/
#pragma once

#include <array>
#include <cstdint>
#include <map>
#include <vector>

namespace openPMD
{

using UnitDimensionExponent = double;

/** Physical dimension of a record
*
* Dimensional base quantities of the international system of quantities
Expand All @@ -38,4 +44,25 @@ enum class UnitDimension : uint8_t
N, //!< amount of substance
J //!< luminous intensity
};

namespace unit_representations
{
using AsMap = std::map<UnitDimension, UnitDimensionExponent>;
using AsArray = std::array<UnitDimensionExponent, 7>;

using AsMaps = std::vector<AsMap>;
using AsArrays = std::vector<AsArray>;

auto asArray(AsMap const &) -> AsArray;
auto asMap(AsArray const &, bool skip_zeros = true) -> AsMap;

auto asArrays(AsMaps const &) -> AsArrays;
auto asMaps(AsArrays const &, bool skip_zeros = true) -> AsMaps;

namespace auxiliary
{
void fromMapOfUnitDimension(
double *cursor, std::map<UnitDimension, double> const &udim);
} // namespace auxiliary
} // namespace unit_representations
} // namespace openPMD
2 changes: 2 additions & 0 deletions include/openPMD/backend/Attributable.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,8 @@ class Attributable
*/
void touch();

[[nodiscard]] OpenpmdStandard openPMDStandard() const;

// clang-format off
OPENPMD_protected
// clang-format on
Expand Down
4 changes: 2 additions & 2 deletions include/openPMD/backend/BaseRecord.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -474,7 +474,7 @@ class BaseRecord
*
* @return powers of the 7 base measures in the order specified above
*/
std::array<double, 7> unitDimension() const;
unit_representations::AsArray unitDimension() const;

void setDatasetDefined(BaseRecordComponent::Data_t &data) override
{
Expand Down Expand Up @@ -928,7 +928,7 @@ auto BaseRecord<T_elem>::emplace(Args &&...args) -> std::pair<iterator, bool>
}

template <typename T_elem>
inline std::array<double, 7> BaseRecord<T_elem>::unitDimension() const
inline unit_representations::AsArray BaseRecord<T_elem>::unitDimension() const
{
return this->getAttribute("unitDimension")
.template get<std::array<double, 7>>();
Expand Down
26 changes: 24 additions & 2 deletions include/openPMD/binding/python/UnitDimension.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ namespace openPMD
{
namespace python
{
constexpr auto doc_unit_dimension = R"docstr(
constexpr auto doc_unit_dimension = &R"docstr(
Return the physical dimension (quantity) of a record

Annotating the physical dimension of a record allows us to read data
Expand All @@ -40,7 +40,29 @@ See https://en.wikipedia.org/wiki/International_System_of_Quantities#Base_quanti
See https://github.com/openPMD/openPMD-standard/blob/1.1.0/STANDARD.md#required-for-each-record

Returns the powers of the 7 base measures in the order specified above.
)docstr";
)docstr"[1];

constexpr auto doc_mesh_unit_dimension = &R"docstr(
Return the physical dimension (quantity) of the record axes

Annotating the physical dimension of the record axes allows us to read data
sets with arbitrary names and understand their purpose simply by
dimensional analysis. The dimensional base quantities in openPMD are
in order: length (L), mass (M), time (T), electric current (I),
thermodynamic temperature (theta), amount of substance (N),
luminous intensity (J) after the international system of quantities
(ISQ).
This attribute may be left out, the axes will then be interpreted as spatial.

See https://en.wikipedia.org/wiki/Dimensional_analysis
See https://en.wikipedia.org/wiki/International_System_of_Quantities#Base_quantities
See https://github.com/openPMD/openPMD-standard/blob/1.1.0/STANDARD.md#required-for-each-record

Returns the powers of the 7 base measures in the order specified above, listed
for each axis in the order of the axisLabels.
This attribute has been introduced as part of openPMD 2.0.0 in:
Ref.: https://github.com/openPMD/openPMD-standard/pull/193
)docstr"[1];

} // namespace python
} // namespace openPMD
Loading
Loading