feat(equations): Added point-wise datastructurs which equations return to the operator backend

These include all the information needed to integrate the global residual over the domain
This commit is contained in:
2026-10-12 10:55:58 -04:00
parent 0875831525
commit eb521f3f01
2 changed files with 149 additions and 0 deletions

View File

@@ -0,0 +1,149 @@
#pragma once
/**
* @file point.hpp
* @author Emily M. Boudreaux
*
* @brief File containing the definitions of the EquationPoint and PointLinearization structs, which are used to represent the values and derivatives of operands at a given point in space.
*
* Effectively every equation returns a PointLinearization from evaluate. Generally, you likely do not need to touch this file if
* you are trying to just add new physics.
*/
#include <array>
#include <concepts>
#include <cstddef>
#include <tuple>
#include <type_traits>
#include "serif/discretization/forms/value.hpp"
#include "serif/utils/types/type_list.hpp"
namespace serif::equations {
/**
* @struct OperandValues
*
* @brief A helper struct to store the values of operands. There is some convention here,
* specifically if OutputT is void then this struct represents the values of the operands, otherwise
* it represents the local derivatives of the operands with respect to OutputT.
*
* @tparam OperandsT The list of operands to store values for, which must be a TypeList of valid operands.
* @tparam OutputT The type of the output with respect to which local derivatives are computed. If void, this struct stores operand values.
*/
template <typename OperandsT, typename OutputT = void>
struct OperandValues;
/**
* @struct OperandValues
*
* @brief A specialization of the OperandValues struct for a non-empty list of operands. This struct stores the values of the operands or their local derivatives with respect to OutputT.
*
* @tparam OutputT The type of the output with respect to which local derivatives are computed. If void, this struct stores operand values.
* @tparam Operands The list of operands to store values for, which must be a non-empty pack of valid operands.
*/
template <typename OutputT, discretization::forms::IsOperand... Operands>
struct OperandValues<utils::types::TypeList<Operands...>, OutputT> {
static constexpr std::size_t count = sizeof...(Operands); ///< The number of operands in the list, which is the size of the pack of operands.
/**
* @brief The type of the entry in the storage for a given operand. If OutputT is void, this is the value of the operand; otherwise, it is the local derivative of OutputT with respect to the operand value.
*
* @tparam OperandT The operand type for which to determine the entry type.
*/
template <typename OperandT>
using Entry = std::conditional_t<std::is_void_v<OutputT>, discretization::forms::OperandValue<OperandT>, discretization::forms::PartialDerivative<OutputT, discretization::forms::OperandValue<OperandT>>>;
/**
* @brief The storage type for the operand values or local derivatives. If all entries are of type double, this is a std::array<double, count>; otherwise, it is a std::tuple<Entry<Operands>...>.
*/
using Storage = std::conditional_t<(std::same_as<Entry<Operands>, double> && ...), std::array<double, count>, std::tuple<Entry<Operands>...>>;
Storage values{};
/**
* @brief Get the index of a uniquely identified operand in the storage. If the operand is not uniquely identified, this will trigger a static assertion.
*
* @tparam KeyT The operand type for which to get the index.
* @return The index of the operand in the storage.
*
* @requires The operand must occur exactly once in the list of operands, otherwise a static assertion will be triggered. Use Operand<Term, Operation> when a term has multiple sampled operations.
*/
template <typename KeyT>
static consteval std::size_t index() {
constexpr std::array<bool, count> matches{([] {
if constexpr (discretization::forms::IsOperand<KeyT>) {
return std::same_as<KeyT, Operands>;
} else {
return std::same_as<KeyT, typename Operands::term_type>;
}
}())...};
constexpr auto count_matches = [&] {
int n = 0;
for (const bool match : matches) {
n += match;
}
return n;
}();
static_assert(count_matches == 1, "The requested operand must occur exactly once; use Operand<Term, Operation> when a term has multiple sampled operations.");
for (std::size_t i = 0; i < count; ++i) {
if (matches[i]) {
return i;
}
}
return count;
}
/**
* @brief Get the value or local partial for a uniquely identified operand
*
* @tparam KeyT The operand type for which to get the value or local partial.
* @return A reference to the value or local partial of the operand in the storage.
*/
template <typename KeyT>
decltype(auto) get() {
return std::get<index<KeyT>()>(values);
}
/**
* @brief Get the value or local partial for a uniquely identified operand
*
* @tparam KeyT The operand type for which to get the value or local partial.
* @return A const reference to the value or local partial of the operand in the storage.
*/
template <typename KeyT>
decltype(auto) get() const {
return std::get<index<KeyT>()>(values);
}
};
/**
* @struct EquationPoint
*
* @brief A struct to represent the values of operands at a given point in space.
*
* @tparam OperandsT The list of operands to store values for, which must be a TypeList of valid operands.
*/
template <typename OperandsT>
struct EquationPoint {
OperandValues<OperandsT> fields; ///< The values of the operands at the given point in space.
std::array<double, 3> position{}; ///< The physical position of the point in space, which is a 3D vector.
};
/**
* @struct PointLinearization
*
* @brief A struct to represent the linearization of a pointwise equation at a given point in space. This includes the residual and the local derivatives of the operands with respect to the test operand value, as well as the local derivative of the test operand value with respect to position.
*
* @tparam OperandsT The list of operands to store values for, which must be a TypeList of valid operands.
* @tparam ResultT The type of the output with respect to which local derivatives are computed. If void, this struct stores operand values.
*/
template <typename OperandsT, typename ResultT = double>
struct PointLinearization {
ResultT residual{}; ///< The residual of the pointwise equation at the given point in space, which is of type ResultT. Note the inner product of these with some operation on a test function will be integrated over the domain by the operator backend to produce the global residual.
OperandValues<OperandsT, ResultT> field_derivatives; ///< The local derivatives of the operands with respect to the test operand value, which are stored in an OperandValues struct.
discretization::forms::PartialDerivative<ResultT, discretization::forms::VectorValue> position_derivative{}; ///< The local derivative of the test operand value with respect to position, which is a 3D vector.
};
} // namespace serif::equations