From 78c78f6bd4db393c21e84d79f51d7ac3094885f0 Mon Sep 17 00:00:00 2001 From: Emily Boudreaux Date: Thu, 8 Oct 2026 11:16:42 -0400 Subject: [PATCH] feat(equations): added compile time concepts and types These help constrain what are valid equations at compile time thereby preventing invalid equations from causing runtime crashes due to missing methods and members (this does not validate anythinng about the physics of an equation, only that the form of the equation is right). Note that this is done at compile time rather than with runtime polymorphism to avoid both indirection cost but more imporantly to allow the compiler to more easily inline functions and preform other optimizations that indirection can hide. --- src/include/serif/equations/concepts.hpp | 90 ++++++++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 src/include/serif/equations/concepts.hpp diff --git a/src/include/serif/equations/concepts.hpp b/src/include/serif/equations/concepts.hpp new file mode 100644 index 00000000..c9294133 --- /dev/null +++ b/src/include/serif/equations/concepts.hpp @@ -0,0 +1,90 @@ +#pragma once + +/** + * @file concepts.hpp + * @author Emily M. Boudreaux + * @brief Concepts for equations, contributions, and pointwise evaluation. + */ + +#include +#include +#include "serif/equations/contributions.hpp" +#include "serif/equations/point.hpp" + +namespace serif::equations { + + /** + * @concept PointEquation + * + * @brief A concept that defines the requirements for a pointwise equation. + * + * @requires The equation must have a test type (::Test) and an operand type (::Operands). + * @requires The test type (::Test) must be either a spatial term or a global scalar term. + * @requires The test type must have a residual block. + * @requires The operand type must be a valid operand + * @requires The operant term type (::term_type) must be the same as the test type (::Test). + * @requires The equation must have a method called ::evaluate() that takes an EquationPoint of the operand type and returns a PointLinearization of the operand type and the operand value of the test operand. + * + */ + template + concept PointEquation = + requires { + typename T::Test; + typename T::Operands; + } && + (discretization::blocks::SpatialTerm || discretization::blocks::GlobalScalarTerm) && + discretization::blocks::HasResidualBlock && + discretization::forms::IsOperand> && + std::same_as::term_type, typename T::Test> && + requires(const T& equation, const EquationPoint& point) { + { + equation.evaluate(point) + } -> std::same_as>>>; + }; + + /** + * @struct ValidContributions + * + * @brief A compile-time check to ensure that a tuple of contributions is valid for a given residual row type. This is the default false specialization. + * + * @tparam RowT The type of the residual row that the contributions must share. + * @tparam TupleT A tuple of contributions to validate. + */ + template + struct ValidContributions : std::false_type {}; + + /** + * @struct ValidContributions + * + * @brief A compile-time check to ensure that a tuple of contributions is valid for a given residual row type. This is the specialization for a non-empty tuple of contributions. + * + * @tparam RowT The type of the residual row that the contributions must share. + * @tparam C The first contribution type in the tuple. + * @tparam RestCs The remaining contribution types in the tuple. + * + * @true_if The size of C (contributions) is not zero + * @true_if Each contribution satisfies the PointEquation concept + * @true_if Each contribution's test type is the same as RowT + */ + template + struct ValidContributions> : std::bool_constant< + sizeof...(C) != 0 && (requires { + requires PointEquation; + requires std::same_as; } && ...)> {}; + + + /** + * @concept Equation + * + * @brief A concept that defines the requirements for a valid SERiF equation. + * + * @requires The equation must have a test type (::Test) and a name (::name). + * @requires The name must be convertible to a std::string_view. + * @requires The contributions of the equation must be valid for the test type, as defined by the ValidContributions struct. + */ + template + concept Equation = requires { + typename T::Test; + { T::name } -> std::convertible_to; + } && ValidContributions>::value; +} // namespace serif::equations