Program Listing for File field.h¶
↰ Return to documentation for file (include/immersx/core/field.h)
// ---------------------------------------------------------------------
//
// Copyright (C) 2026 by Luca Heltai
//
// This file is part of the ImmersX application, based on
// the deal.II library.
//
// The ImmersX application is free software; you can use
// it, redistribute it, and/or modify it under the terms of the Apache-2.0
// License WITH LLVM-exception (the "License"); either version 3.0 of the
// License, or (at your option) any later version. The full text of the
// license can be found in the LICENSE.md file at the top level of the
// ImmersX distribution.
//
// ---------------------------------------------------------------------
#ifndef immersx_field_h
#define immersx_field_h
#include <deal.II/base/exceptions.h>
#include <deal.II/base/index_set.h>
#include <cstddef>
#include <limits>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>
namespace ImmersX
{
class FieldId
{
public:
inline static constexpr std::size_t invalid_value =
std::numeric_limits<std::size_t>::max();
constexpr FieldId() = default;
explicit constexpr FieldId(const std::size_t value)
: value_(value)
{}
constexpr std::size_t
value() const
{
return value_;
}
constexpr bool
is_valid() const
{
return value_ != invalid_value;
}
friend constexpr bool
operator==(const FieldId left, const FieldId right)
{
return left.value_ == right.value_;
}
friend constexpr bool
operator!=(const FieldId left, const FieldId right)
{
return !(left == right);
}
friend constexpr bool
operator<(const FieldId left, const FieldId right)
{
return left.value_ < right.value_;
}
private:
std::size_t value_ = invalid_value;
};
class HistoryGroupId
{
public:
inline static constexpr std::size_t invalid_value =
std::numeric_limits<std::size_t>::max();
constexpr HistoryGroupId() = default;
explicit constexpr HistoryGroupId(const std::size_t value)
: value_(value)
{}
constexpr std::size_t
value() const
{
return value_;
}
constexpr bool
is_valid() const
{
return value_ != invalid_value;
}
friend constexpr bool
operator==(const HistoryGroupId left, const HistoryGroupId right)
{
return left.value_ == right.value_;
}
friend constexpr bool
operator!=(const HistoryGroupId left, const HistoryGroupId right)
{
return !(left == right);
}
friend constexpr bool
operator<(const HistoryGroupId left, const HistoryGroupId right)
{
return left.value_ < right.value_;
}
private:
std::size_t value_ = invalid_value;
};
struct FieldDescriptor
{
std::string name;
HistoryGroupId history_group;
dealii::IndexSet locally_owned;
dealii::IndexSet locally_relevant;
dealii::IndexSet differential_components;
};
class StateLayout
{
public:
FieldId
add_field(FieldDescriptor descriptor)
{
AssertThrow(!descriptor.name.empty(),
dealii::ExcMessage("A field must have a name."));
AssertThrow(!has_field(descriptor.name),
dealii::ExcMessage("Duplicate field name '" +
descriptor.name + "'."));
AssertThrow(descriptor.differential_components.size() == 0 ||
descriptor.differential_components.size() ==
descriptor.locally_owned.size(),
dealii::ExcMessage(
"Differential components must have the same global size "
"as the field vector."));
if (descriptor.differential_components.size() == 0)
descriptor.differential_components =
dealii::IndexSet(descriptor.locally_owned.size());
const FieldId id(fields_.size());
field_names_.emplace(descriptor.name, id);
fields_.push_back(std::move(descriptor));
return id;
}
bool
has_field(const std::string &name) const
{
return field_names_.find(name) != field_names_.end();
}
FieldId
field_id(const std::string &name) const
{
const auto it = field_names_.find(name);
AssertThrow(it != field_names_.end(),
dealii::ExcMessage("Unknown field name '" + name + "'."));
return it->second;
}
bool
contains(const FieldId id) const
{
return id.is_valid() && id.value() < fields_.size();
}
const FieldDescriptor &
field(const FieldId id) const
{
AssertThrow(contains(id),
dealii::ExcMessage("Field identifier is not in the state "
"layout."));
return fields_[id.value()];
}
std::size_t
n_fields() const
{
return fields_.size();
}
private:
std::vector<FieldDescriptor> fields_;
std::unordered_map<std::string, FieldId> field_names_;
};
} // namespace ImmersX
#endif // immersx_field_h