Skip to content

Commit

Permalink
Simplified configuration and changed class to namespace.
Browse files Browse the repository at this point in the history
  • Loading branch information
odlomax committed Aug 12, 2024
1 parent bbc59b6 commit 2179506
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 141 deletions.
104 changes: 43 additions & 61 deletions src/atlas/util/PackVectorFields.cc
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "atlas/util/PackVectorFields.h"

#include <map>
#include <string>
#include <type_traits>
#include <vector>
Expand All @@ -18,23 +19,11 @@ namespace util {

namespace {

template <int I>
using Integer = std::integral_constant<int, I>;
template <int N>
using IntegerSequence = std::make_integer_sequence<int, N>;
using eckit::LocalConfiguration;

using array::DataType;
using array::helpers::arrayForEachDim;

template <typename T>
T getT(const Config& config, const std::string& key) {
auto value = T{};
const auto success = config.get(key, value);
ATLAS_ASSERT_MSG(success,
"\"" + key + "\" entry missing from configuration.");
return value;
}

void addOrReplaceField(FieldSet& fieldSet, const Field& field) {
const auto fieldName = field.name();
if (fieldSet.has(fieldName)) {
Expand Down Expand Up @@ -102,17 +91,17 @@ void copyFields(ComponentField& componentField, VectorField& vectorField,
// Iterate over fields.
auto vectorView = array::make_view<Value, Rank>(vectorField);
auto componentView = array::make_view<Value, Rank - 1>(componentField);
constexpr auto Dims = IntegerSequence<Rank - 1>{};
constexpr auto Dims = std::make_integer_sequence<int, Rank - 1>{};
arrayForEachDim(Dims, execution::par, std::tie(componentView, vectorView),
copier);
};

const auto selectRank = [&](auto value) {
switch (vectorField.rank()) {
case 2:
return copyData(value, Integer<2>{});
return copyData(value, std::integral_constant<int, 2>{});
case 3:
return copyData(value, Integer<3>{});
return copyData(value, std::integral_constant<int, 3>{});
default:
ATLAS_THROW_EXCEPTION("Unsupported vector field rank: " +
std::to_string(vectorField.rank()));
Expand Down Expand Up @@ -140,37 +129,23 @@ void copyFields(ComponentField& componentField, VectorField& vectorField,

} // namespace

PackVectorFields::PackVectorFields(const LocalConfiguration& config) {
const auto vectorFieldList =
getT<LocalConfigurations>(config, "vector fields");

for (const auto& vectorField : vectorFieldList) {
const auto vectorName = vectorField.getString("name");
const auto componentNameList = vectorField.getStringVector("components");

// Vector information for each component field.
auto componentIndex = idx_t{0};
const auto vectorSize = componentNameList.size();
for (const auto& componentName : componentNameList) {
const auto vectorFieldConfig =
Config("component index", componentIndex++) |
option::name(vectorName) | option::variables(vectorSize);
componentToVectorMap_.set(componentName, vectorFieldConfig);
}
namespace pack_vector_fields {

// Component information for each vector field.
auto componentFieldConfigs = std::vector<Config>{};
for (const auto& componentName : componentNameList) {
componentFieldConfigs.push_back(option::name(componentName));
FieldSet pack(const FieldSet& fields, FieldSet packedFields) {
// Get the number of variables for each vector field.
auto vectorSizeMap = std::map<std::string, idx_t>{};
for (const auto& field : fields) {
auto vectorFieldName = std::string{};
if (field.metadata().get("vector field name", vectorFieldName)) {
++vectorSizeMap[vectorFieldName];
}
vectorToComponentMap_.set(vectorName, componentFieldConfigs);
}
}
auto vectorIndexMap = std::map<std::string, idx_t>{};

FieldSet PackVectorFields::pack(const FieldSet& fields,
FieldSet packedFields) const {
// Pack vector fields.
for (const auto& field : fields) {
if (!componentToVectorMap_.has(field.name())) {
auto vectorFieldName = std::string{};
if (!field.metadata().get("vector field name", vectorFieldName)) {
// Not a vector component field.
addOrReplaceField(packedFields, field);
continue;
Expand All @@ -181,32 +156,37 @@ FieldSet PackVectorFields::pack(const FieldSet& fields,

// Get or create vector field.
const auto vectorFieldConfig =
getT<Config>(componentToVectorMap_, componentField.name()) |
option::name(vectorFieldName) |
option::levels(componentField.levels()) |
option::variables(vectorSizeMap[vectorFieldName]) |
option::datatype(componentField.datatype());
auto& vectorField = getOrCreateField(
packedFields, componentField.functionspace(), vectorFieldConfig);

// Copy field data.
const auto componentIndex =
getT<idx_t>(vectorFieldConfig, "component index");
const auto vectorIndex = vectorIndexMap[vectorFieldName]++;
const auto copier = [&](auto&& componentElem, auto&& vectorElem) {
vectorElem(componentIndex) = componentElem;
vectorElem(vectorIndex) = componentElem;
};
copyFields(componentField, vectorField, copier);

// Copy metadata.
const auto componentMetadata = componentField.metadata();
vectorField.metadata().set(componentField.name() + " metadata",
componentMetadata);
const auto componentFieldMetadata = componentField.metadata();
auto componentFieldMetadataVector = std::vector<LocalConfiguration>{};
vectorField.metadata().get("component field metadata",
componentFieldMetadataVector);
componentFieldMetadataVector.push_back(componentFieldMetadata);
vectorField.metadata().set("component field metadata",
componentFieldMetadataVector);
}
return packedFields;
}

FieldSet PackVectorFields::unpack(const FieldSet& fields,
FieldSet unpackedFields) const {
FieldSet unpack(const FieldSet& fields, FieldSet unpackedFields) {
for (const auto& field : fields) {
if (!vectorToComponentMap_.has(field.name())) {
auto componentFieldMetadataVector = std::vector<LocalConfiguration>{};
if (!field.metadata().get("component field metadata",
componentFieldMetadataVector)) {
// Not a vector field.
addOrReplaceField(unpackedFields, field);
continue;
Expand All @@ -215,33 +195,35 @@ FieldSet PackVectorFields::unpack(const FieldSet& fields,
// Field is vector.
const auto& vectorField = field;

const auto componentFieldConfigs =
getT<std::vector<Config>>(vectorToComponentMap_, vectorField.name());
auto vectorIndex = 0;
for (const auto& componentFieldMetadata : componentFieldMetadataVector) {
std::cout << componentFieldMetadata << std::endl;

for (auto componentIndex = size_t{0};
componentIndex < componentFieldConfigs.size();
++componentIndex) {
// Get or create field.
auto componentFieldName = std::string{};
componentFieldMetadata.get("name", componentFieldName);
const auto componentFieldConfig =
componentFieldConfigs[componentIndex] |
option::name(componentFieldName) |
option::levels(vectorField.levels()) |
option::datatype(vectorField.datatype());
auto& componentField = getOrCreateField(
unpackedFields, vectorField.functionspace(), componentFieldConfig);

// Copy field data.
const auto copier = [&](auto&& componentElem, auto&& vectorElem) {
componentElem = vectorElem(componentIndex);
componentElem = vectorElem(vectorIndex);
};
copyFields(componentField, vectorField, copier);

// Copy metadata.
componentField.metadata() = vectorField.metadata().get<Config>(
componentField.name() + " metadata");
componentField.metadata() = componentFieldMetadata;

++vectorIndex;
}
}
return unpackedFields;
}

} // namespace pack_vector_fields
} // namespace util
} // namespace atlas
39 changes: 20 additions & 19 deletions src/atlas/util/PackVectorFields.h
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
#pragma once

#include <string>
#include <vector>

#include "atlas/field.h"
#include "atlas/util/Config.h"

namespace eckit {
class LocalConfiguration;
Expand All @@ -13,21 +9,26 @@ class LocalConfiguration;
namespace atlas {
namespace util {

using eckit::LocalConfiguration;
using LocalConfigurations = std::vector<LocalConfiguration>;

class PackVectorFields {
public:
PackVectorFields(const LocalConfiguration& config);
FieldSet pack(const FieldSet& fields,
FieldSet packedFields = FieldSet{}) const;
FieldSet unpack(const FieldSet& fields,
FieldSet unpackedFields = FieldSet{}) const;

private:
Config componentToVectorMap_{};
Config vectorToComponentMap_{};
};
namespace pack_vector_fields {

/// @brief Packs vector field components into vector fields
///
/// @details Iterates through @param fields and creates vector fields from any
/// component field with the "vector name" string metadata. These, as
/// well as any present scalar fields are added to the return-value
/// field set.
/// Note, a mutable @param packedFields field set can be supplied if
/// one needs to guarantee the order of the packed fields
FieldSet pack(const FieldSet& fields, FieldSet packedFields = FieldSet{});

/// @brief Unpacks vector field into vector field components.
///
/// @details Undoes "pack" operation when a set of packed fields are supplied
/// as @param fields. A mutable @param unpackedFields field set can be
/// supplied if one needs to guarantee the order of the unpacked
/// fields.
FieldSet unpack(const FieldSet& fields, FieldSet unpackedFields = FieldSet{});
}; // namespace pack_vector_fields

} // namespace util
} // namespace atlas
Loading

0 comments on commit 2179506

Please sign in to comment.