feat(quadrature): quadrature system brought over

Ported and dramatically cleaned up the quadrature system. This includes centralizing all field definitions
This commit is contained in:
2026-09-19 07:35:57 -04:00
parent 7b4f30d945
commit c44584c1e7
75 changed files with 8936 additions and 172 deletions

View File

@@ -0,0 +1,10 @@
#pragma once
#include "serif/discretization/forms/forms.hpp"
namespace serif::discretization::forms {
template <typename FormCandidate>
concept Form = std::derived_from<std::remove_cvref_t<FormCandidate>, form> && // A form must derive from form
requires {
typename std::remove_cvref_t<FormCandidate>::operand_types; // a form must define a type list of operand types for the trial and test terms
}; // We could consider strengthening this to enforce that the type list (operand_types) contains only operand types and that there is an entry for TrialT and TestT
}

View File

@@ -0,0 +1,48 @@
#pragma once
#include "serif/discretization/forms/concept.hpp"
#include "serif/discretization/forms/forms.hpp"
namespace serif::discretization::forms {
template <Form FormT>
struct FormTraits {
static constexpr int trial_order_reduction = 0;
static constexpr int test_order_reduction = 0;
};
template <blocks::Term TrialT, blocks::Term TestT>
struct FormTraits<mass<TrialT, TestT>> {
static constexpr int trial_order_reduction = 0;
static constexpr int test_order_reduction = 0;
};
template <blocks::Term TrialT, blocks::Term TestT>
struct FormTraits<divergence<TrialT, TestT>> {
static constexpr int trial_order_reduction = 1;
static constexpr int test_order_reduction = 0;
};
template <blocks::Term TrialT, blocks::Term TestT>
struct FormTraits<source<TrialT, TestT>> {
static constexpr int trial_order_reduction = 0;
static constexpr int test_order_reduction = 0;
};
template <blocks::Term TrialT, blocks::Term TestT>
struct FormTraits<force<TrialT, TestT>> {
static constexpr int trial_order_reduction = 0;
static constexpr int test_order_reduction = 0;
};
template <blocks::Term TrialT, blocks::Term TestT>
struct FormTraits<boundary_flux<TrialT, TestT>> {
static constexpr int trial_order_reduction = 0;
static constexpr int test_order_reduction = 0;
};
template <blocks::Term TrialT, blocks::Term TestT>
struct FormTraits<projection<TrialT, TestT>> {
static constexpr int trial_order_reduction = 0;
static constexpr int test_order_reduction = 0;
};
}

View File

@@ -0,0 +1,73 @@
#pragma once
#include <concepts>
#include <type_traits>
#include "serif/discretization/blocks/concepts.hpp"
#include "serif/discretization/forms/operands.hpp"
#include "serif/utils/types/type_list.hpp"
#include "serif/meta/names.hpp"
namespace serif::discretization::forms {
struct form {};
template <blocks::Term TrialT, blocks::Term TestT>
struct mass final : form {
static constexpr std::string_view name = meta::template_name<mass>();
using trial_type = TrialT;
using test_type = TestT;
using operand_types = utils::types::TypeList<Operand<TrialT>, Operand<TestT>>;
};
template <blocks::Term TrialT, blocks::Term TestT>
struct divergence final : form {
static constexpr std::string_view name = meta::template_name<divergence>();
using trial_type = TrialT;
using test_type = TestT;
using operand_types = utils::types::TypeList<Operand<TrialT, Operation::Divergence>, Operand<TestT>>;
};
template <blocks::Term TrialT, blocks::Term TestT>
struct source final : form {
static constexpr std::string_view name = meta::template_name<source>();
using trial_type = TrialT;
using test_type = TestT;
using operand_types = utils::types::TypeList<Operand<TrialT>, Operand<TestT>>;
};
template <blocks::Term TrialT, blocks::Term TestT>
struct force final : form {
static constexpr std::string_view name = meta::template_name<force>();
using trial_type = TrialT;
using test_type = TestT;
using operand_types = utils::types::TypeList<Operand<TrialT>, Operand<TestT>>;
};
template <blocks::Term TrialT, blocks::Term TestT>
struct boundary_flux final : form {
static constexpr std::string_view name = meta::template_name<boundary_flux>();
using trial_type = TrialT;
using test_type = TestT;
using operand_types = utils::types::TypeList<Operand<TrialT, Operation::NormalTrace>, Operand<TestT, Operation::NormalTrace>>;
};
template <blocks::Term TrialT, blocks::Term TestT>
struct projection final : form {
static constexpr std::string_view name = meta::template_name<projection>();
using trial_type = TrialT;
using test_type = TestT;
using operand_types = utils::types::TypeList<Operand<TrialT>, Operand<TestT>>;
};
}

View File

@@ -0,0 +1,38 @@
#pragma once
#include <concepts>
#include <type_traits>
#include "serif/discretization/blocks/concepts.hpp"
namespace serif::discretization::forms {
struct Operation {
struct Value {};
struct Gradient {};
struct Divergence {};
struct Curl {};
struct NormalTrace {};
};
template <typename OperationCandidate>
concept IsOperation =
std::same_as<std::remove_cvref_t<OperationCandidate>, Operation::Value> ||
std::same_as<std::remove_cvref_t<OperationCandidate>, Operation::Gradient> ||
std::same_as<std::remove_cvref_t<OperationCandidate>, Operation::Divergence> ||
std::same_as<std::remove_cvref_t<OperationCandidate>, Operation::Curl> ||
std::same_as<std::remove_cvref_t<OperationCandidate>, Operation::NormalTrace>;
template <blocks::Term TermT, IsOperation OperationT = Operation::Value> // We choose to default to the value operation because it is the most common.
struct Operand final {
using term_type = TermT;
using operation_type = OperationT;
};
template <typename OperandCandidate>
concept IsOperand = requires { // Recall that requires expressions are not evaluated. What this checks is that it is valid syntax given the type to requires the term type and operation type. It does not check that the term type is a valid term or that the operation type is a valid operation.
typename std::remove_cvref_t<OperandCandidate>::term_type;
typename std::remove_cvref_t<OperandCandidate>::operation_type; } &&
blocks::Term<typename std::remove_cvref_t<OperandCandidate>::term_type> && // Then here, now that we know we can safely ask for the term type we validate it is actually a valid term
IsOperation<typename std::remove_cvref_t<OperandCandidate>::operation_type>; // And here we validate that the operation type is actually a valid operation
};

View File

@@ -0,0 +1,34 @@
#pragma once
#include <string_view>
#include <format>
#include "serif/discretization/blocks/runtime.hpp"
#include "serif/discretization/forms/concept.hpp"
namespace serif::discretization::forms {
struct FormDescriptor final {
std::string_view name;
blocks::TermDescriptor trial;
blocks::TermDescriptor test;
[[nodiscard]] friend constexpr bool operator==(const FormDescriptor&, const FormDescriptor&) noexcept = default;
};
template <Form FormT>
inline constexpr FormDescriptor form_descriptor{
.name = FormT::name,
.trial = blocks::term_descriptor<typename FormT::trial_type>,
.test = blocks::term_descriptor<typename FormT::test_type>
};
}
template <>
struct std::formatter<serif::discretization::forms::FormDescriptor> : std::formatter<std::string> {
template <typename FormatContext>
auto format(const serif::discretization::forms::FormDescriptor& fd, FormatContext& ctx) const {
return std::formatter<std::string>::format(std::format("FormDescriptor(name={}, trial={}, test={})", fd.name, fd.trial, fd.test), ctx);
}
};