diff --git a/src/include/serif/equations/point.hpp b/src/include/serif/equations/point.hpp new file mode 100644 index 00000000..b6a236b1 --- /dev/null +++ b/src/include/serif/equations/point.hpp @@ -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 +#include +#include +#include +#include + +#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 + 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 + struct OperandValues, 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 + using Entry = std::conditional_t, discretization::forms::OperandValue, discretization::forms::PartialDerivative>>; + + /** + * @brief The storage type for the operand values or local derivatives. If all entries are of type double, this is a std::array; otherwise, it is a std::tuple...>. + */ + using Storage = std::conditional_t<(std::same_as, double> && ...), std::array, std::tuple...>>; + 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 when a term has multiple sampled operations. + */ + template + static consteval std::size_t index() { + constexpr std::array matches{([] { + if constexpr (discretization::forms::IsOperand) { + return std::same_as; + } else { + return std::same_as; + } + }())...}; + + 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 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 + decltype(auto) get() { + return std::get()>(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 + decltype(auto) get() const { + return std::get()>(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 + struct EquationPoint { + OperandValues fields; ///< The values of the operands at the given point in space. + std::array 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 + 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 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 position_derivative{}; ///< The local derivative of the test operand value with respect to position, which is a 3D vector. + }; +} // namespace serif::equations diff --git a/src/include/serif/equations/sum.hpp b/src/include/serif/equations/sum.hpp deleted file mode 100644 index e69de29b..00000000