docs(discretization/quadrature): added doxygen docs throughout

This commit is contained in:
2026-10-05 13:51:47 -04:00
parent 36585a9682
commit 4b742bcaf5
8 changed files with 451 additions and 115 deletions

View File

@@ -1,23 +1,42 @@
#pragma once
/**
* @file concepts.hpp
* @author Emily M. Boudreaux
*
* @brief File containing concepts for the quadrature backend module. These concepts are used to constrain template parameters in the quadrature backend module.
*/
#include "mfem/fem/intrules.hpp"
namespace serif::discretization::quadrature::backend::mfem {
/**
* @brief A HasReferenceSetIntegrationRule is an integrator that can be configured with a reference to an integration rule.
*/
template <typename IntegratorT>
concept HasReferenceSetIntegrationRule = requires (IntegratorT &integrator, const ::mfem::IntegrationRule &integration_rule) {
integrator.SetIntegrationRule(integration_rule);
};
/**
* @brief A HasPointerSetIntegrationRule is an integrator that can be configured with a pointer to an integration rule.
*/
template <typename IntegratorT>
concept HasPointerSetIntegrationRule = requires (IntegratorT &integrator, const ::mfem::IntegrationRule &integration_rule) {
integrator.SetIntRule(&integration_rule);
};
/**
* @brief A HasSetIntRule is an integrator that can be configured with an integration rule by value.
*/
template <typename IntegratorT>
concept HasSetIntRule = requires (IntegratorT &integrator, const ::mfem::IntegrationRule &integration_rule) {
integrator.SetIntRule(integration_rule);
};
/**
* @brief A ConfigurableIntegrator is an integrator that can be configured with an integration rule in some way (either by reference, by pointer, or by value).
*/
template <typename IntegratorT>
concept ConfigurableIntegrator = HasReferenceSetIntegrationRule<IntegratorT> ||
HasPointerSetIntegrationRule<IntegratorT> ||

View File

@@ -1,18 +1,32 @@
#pragma once
/**
* @file configure.hpp
* @author Emily M. Boudreaux
*
* @brief File containing utility functions for configuring MFEM integrators with integration rules.
*/
#include "mfem/fem/intrules.hpp"
#include "serif/discretization/quadrature/backend/mfem/concepts.hpp"
namespace serif::discretization::quadrature::backend::mfem {
/**
* @brief Configure an MFEM integrator with an integration rule. This function will call the appropriate SetIntegrationRule method on the integrator based on its capabilities.
* @tparam IntegratorT The type of the integrator to configure.
* @param integrator The integrator to configure.
* @param integration_rule The integration rule to use for configuration.
*/
template <ConfigurableIntegrator IntegratorT>
void set_integration_rule(IntegratorT &integrator, const ::mfem::IntegrationRule &integration_rule) {
if constexpr (HasReferenceSetIntegrationRule<IntegratorT>) {
integrator.SetIntegrationRule(integration_rule);
} else if constexpr (HasPointerSetIntegrationRule<IntegratorT>) {
integrator.SetIntegrationRule(&integration_rule);
} else {
integrator.SetIntRule(&integration_rule);
} else {
integrator.SetIntRule(integration_rule);
}
}
}

View File

@@ -1,4 +1,20 @@
#pragma once
/**
* @file mfem_resolver.hpp
* @author Emily M. Boudreaux
*
* @brief File containing the MFEMResolver class. This class is used to resolve the appropriate MFEM integration rule for a given quadrature context.
*
* @note We may want to consider renaming this file to runtime to stick to convention. The reason I did not initially is that this is more specific than pure runtime
* projection of compile time invariants (which is what most of the other files named runtime.hpp do). Something to think about.
*
* @note You will see ::mfem throughout. This is an important syntax to use here since MFEM's code lives in the mfem namespace; however, we also have code living in an
* mfem namespace. Outside of translation units that include using namespace serif::discretization::quadrature::backend and outside of the
* serif::discretization::quadrature::backend::mfem namespace itself these two things do not conflict. However, in those two cases there is a degeneracy the compiler
* cannot resolve between mfem:: and mfem::. Using ::mfem explicitly tells the compiler that we are looking from the root of the namespace tree not the current namespace.
*/
#include <span>
#include <format>
#include <unordered_map>
@@ -15,46 +31,62 @@
#include "serif/discretization/quadrature/query.hpp"
#include "serif/discretization/quadrature/backend/mfem/concepts.hpp"
#include "serif/discretization/quadrature/backend/mfem/configure.hpp"
#include "serif/discretization/quadrature/backend/mfem/mfem_static_order.hpp"
#include "serif/utils/format/strings.hpp"
// We may want to consider renaming this file to runtime to stick to convention. The reason
// I did not initially is that this is more specific than pure runtime projection of compile
// time invariants (which is what most of the other files named runtime.hpp do). Something to think
// about
// Note also that you will see ::mfem throughout. This is an important syntax to use here since MFEM's
// code lives in the mfem namespace; however, we also have code living in an mfem namespace.
// Outside of translation units that include using namespace serif::discretization::quadrature::backend
// and outside of the serif::discretization::quadrature::backend::mfem namespace itself these two things
// do not conflict. However, in those two cases there is a degeneracy the compiler cannot
// resolve between mfem:: and mfem:: (see what I did there?) Using ::mfem explicitly tells the compiler
// that we are looking from the root of the namespace tree not the current namespace. This is important to avoid ambiguity and compiler errors.
namespace serif::discretization::quadrature::backend::mfem {
/**
* @brief The MFEMQuadratureContext struct is used to describe the context in which we are trying to resolve an MFEM integration rule. This includes the geometry type, the order of the geometry weight, any dynamic orders, the domain or set of domains, and the mapping kind.
*
* The idea here is that there is some information we can know at compile time (e.g. the role the particular integration is playing) and some we can only know
* at runtime (e.g. a manual quadrature boost requested by the user) so QuadratureContext contains all of that information which can then be turned into
* a single quadrature order. This is born out of the recognition that there is really not one good choice for quadrature order; rather,
* different systems have different accuracy requirements and should generally use the lowest order that is sufficient for their needs.
*/
struct MFEMQuadratureContext final {
QuadratureRole role = QuadratureRole::discretization;
QuadratureRole role = QuadratureRole::discretization; ///< The role of the quadrature rule.
::mfem::Geometry::Type geometry = ::mfem::Geometry::INVALID;
int geometry_weight_order = 0;
::mfem::Geometry::Type geometry = ::mfem::Geometry::INVALID; ///< The geometry type of the element for which we are trying to resolve an MFEM integration rule.
int geometry_weight_order = 0; ///< The order of the geometry weight.
std::span<const int> dynamic_orders{};
domain::DomainOrSet domain = domain::AllDomains{};
std::span<const int> dynamic_orders{}; ///< The dynamic orders of the quadrature rule. Dynamics orders come from runtime information.
domain::DomainOrSet domain = domain::AllDomains{}; ///< The domain or set of domains for which we are trying to resolve an MFEM integration rule.
MappingKind mapping = MappingKind::none;
MappingKind mapping = MappingKind::none; ///< The mapping kind of the quadrature rule.
};
/**
* @brief The MFEMRule struct is used to describe the result of resolving an MFEM integration rule. This includes the resolution (which contains the order and any other relevant information) and a pointer to the integration rule itself.
*/
struct MFEMRule final {
Resolution resolution{};
const ::mfem::IntegrationRule *integration_rule = nullptr;
Resolution resolution{}; ///< The resolution of the MFEM integration rule, which contains the order and any other relevant information.
const ::mfem::IntegrationRule *integration_rule = nullptr; ///< A pointer to the MFEM integration rule itself.
};
/**
* @brief The MFEMResolver class is used to resolve the appropriate MFEM integration rule for a given quadrature context. It uses a policy to determine the appropriate order and other relevant information for the integration rule.
*/
class MFEMResolver final {
public:
/**
* @brief Constructs an MFEMResolver with the given policy.
*
* @param policy The policy used to determine the appropriate order and other relevant information for the integration rule.
*/
explicit MFEMResolver (Policy policy) noexcept : m_policy(std::move(policy)) {} // Do we actually want to use move rvalue semantics here?
/**
* @brief Resolves the appropriate MFEM integration rule for a given quadrature context and form type.
*
* @tparam FormT The form type for which we are trying to resolve an MFEM integration rule.
*
* @param context The quadrature context describing the situation in which we are trying to resolve an MFEM integration rule.
*
* @return An MFEMRule struct containing the resolution and a pointer to the MFEM integration rule itself.
*/
template <forms::Form FormT>
[[nodiscard]] MFEMRule resolve(const MFEMQuadratureContext& context) const {
if (context.geometry_weight_order < 0) {
@@ -78,6 +110,17 @@ namespace serif::discretization::quadrature::backend::mfem {
return MFEMRule{.resolution = resolution, .integration_rule = &integration_rule};
}
/**
* @brief Configures an MFEM integrator with the appropriate integration rule for a given quadrature context and form type. This function will call the appropriate SetIntegrationRule method on the integrator based on its capabilities.
*
* @tparam FormT The form type for which we are trying to configure the integrator.
* @tparam IntegratorT The type of the integrator to configure.
*
* @param integrator The integrator to configure.
* @param context The quadrature context describing the situation in which we are trying to configure the integrator.
*
* @return The resolution of the MFEM integration rule used to configure the integrator.
*/
template <forms::Form FormT, ConfigurableIntegrator IntegratorT>
Resolution configure(IntegratorT &integrator, const MFEMQuadratureContext& context) const {
const MFEMRule rule = resolve<FormT>(context);
@@ -86,10 +129,13 @@ namespace serif::discretization::quadrature::backend::mfem {
}
private:
Policy m_policy;
Policy m_policy; ///< The policy used to determine the appropriate order and other relevant information for the integration rule.
};
}
/**
* @brief Specialization of std::formatter for MFEMQuadratureContext. This allows for easy formatting of MFEMQuadratureContext objects using std::format.
*/
template <>
struct std::formatter<serif::discretization::quadrature::backend::mfem::MFEMQuadratureContext> : std::formatter<std::string> {
template <typename FormatContext>

View File

@@ -1,19 +1,39 @@
#pragma once
/**
* @file mfem_static_order.hpp
* @author Emily M. Boudreaux
*
* @brief File containing the mfem_form_static_order trait. This trait is used to determine the static order of an MFEM integrator for a given form type.
*/
#include "serif/discretization/blocks/concepts.hpp"
#include "serif/discretization/forms/operands.hpp"
#include "serif/discretization/forms/concept.hpp"
#include "serif/utils/types/type_list.hpp"
#include "serif/discretization/quadrature/backend/order.hpp"
namespace serif::discretization::quadrature::backend::mfem {
/**
* @brief A helper struct to compute the static order of an MFEM integrator for a given list of operands.
* @tparam OperandListT The list of operand types.
*/
template <typename OperandListT>
struct MFEMOperandListOrder;
/**
* @brief A specialization of the MFEMOperandListOrder struct for a list of operand types. This struct is used to compute the static order of an MFEM integrator for a given list of operands.
* @tparam OperandTs The operand types that make up the list.
*/
template <forms::IsOperand... OperandTs>
struct MFEMOperandListOrder<utils::types::TypeList<OperandTs...>> final {
static constexpr int value = (resolve_operand_order<OperandTs>() + ... + 0);
static constexpr int value = (resolve_operand_order<OperandTs>() + ... + 0); ///< The static order of the MFEM integrator for the given list of operands. This is computed by summing the static orders of each operand in the list.
};
/**
* @brief A trait to determine the static order of an MFEM integrator for a given form type.
* @tparam FormT The form type to check.
*/
template <forms::Form FormT>
inline constexpr int mfem_form_static_order = MFEMOperandListOrder<typename FormT::operand_types>::value;
}

View File

@@ -1,5 +1,12 @@
#pragma once
/**
* @file order.hpp
* @author Emily M. Boudreaux
*
* @brief File containing the resolve_operand_order function and related utilities. These are used to determine the static order of an integrator for a given operand or form type.
*/
#include <type_traits>
#include "serif/discretization/functional_space/space.hpp"
@@ -7,20 +14,48 @@
#include "serif/discretization/forms/operands.hpp"
#include "serif/utils/error/errors.hpp"
namespace serif::discretization::quadrature::backend::mfem {
/**
* @brief A helper struct to extract the functional space traits from a DiscreteFunctionalSpace.
* @tparam FunctionalSpaceT The functional space type to extract traits from.
*/
template <typename FunctionalSpaceT>
struct DiscreteFunctionalSpaceTraits;
/**
* @brief A specialization of the DiscreteFunctionalSpaceTraits struct for a DiscreteFunctionalSpace. This struct is used to extract the functional space traits from a DiscreteFunctionalSpace.
*
* @tparam SpaceV The functional space family.
* @tparam OrderV The order of the functional space.
* @tparam RankV The rank of the functional space.
*
* @todo Could we remove this?
*/
template <auto SpaceV, auto OrderV, auto RankV>
struct DiscreteFunctionalSpaceTraits<functional_space::DiscreteFunctionalSpace<SpaceV, OrderV, RankV>> final {
static constexpr auto space = SpaceV;
static constexpr auto order = static_cast<int>(OrderV);
static constexpr std::size_t rank = static_cast<std::size_t>(RankV);
static constexpr auto space = SpaceV; ///< The functional space family.
static constexpr auto order = static_cast<int>(OrderV); ///< The order of the functional space.
static constexpr std::size_t rank = static_cast<std::size_t>(RankV); ///< The rank of the functional space.
};
/**
* @brief A helper alias to extract the functional space traits from a DiscreteFunctionalSpace.
* @tparam FunctionalSpaceT The functional space type to extract traits from.
*/
template <blocks::HasFunctionalSpace TermT>
using FunctionalSpaceTraits = DiscreteFunctionalSpaceTraits<typename TermT::FunctionalSpace>;
/**
* @brief A function to resolve the static order of an MFEM integrator for a given operand type.
*
* @tparam OperandT The operand type to resolve the static order for.
*
* @return The static order of the MFEM integrator for the given operand type.
*
* @todo We already have some of this information in the form_traits file, we should probably extract the order boost from there.
*/
template <forms::IsOperand OperandT>
[[nodiscard]] consteval int resolve_operand_order() noexcept {
using Operand = std::remove_cvref_t<OperandT>;
@@ -28,7 +63,7 @@ namespace serif::discretization::quadrature::backend::mfem {
using Operation = Operand::operation_type;
if constexpr (!blocks::HasFunctionalSpace<Term>) {
static_assert(std::same_as<forms::Operation, forms::Operation::Value>, "Non-Spatial terms only support the value operation at the moment.");
static_assert(std::same_as<Operation, forms::Operation::Value>, "Non-Spatial terms only support the value operation at the moment.");
return 0;
} else {
using Space = FunctionalSpaceTraits<Term>;
@@ -47,9 +82,13 @@ namespace serif::discretization::quadrature::backend::mfem {
return order > 0 ? order - 1 : 0;
} else if constexpr (std::same_as<Operation, forms::Operation::Divergence>) {
static_assert(family == functional_space::Family::hdiv, "Only H(div) spaces support the divergence operation at the moment.");
static_assert(Space::rank == 1 && (family == functional_space::Family::hdiv || family == functional_space::Family::h1), "Divergence requires a vector H1 or H(div) term.");
return order;
if constexpr (family == functional_space::Family::hdiv) {
return order;
} else {
return order > 0 ? order - 1 : 0;
}
} else if constexpr (std::same_as<Operation, forms::Operation::Curl>) {
static_assert(family == functional_space::Family::hcurl, "Only H(curl) spaces support the curl operation at the moment.");
@@ -65,6 +104,11 @@ namespace serif::discretization::quadrature::backend::mfem {
}
}
/**
* @brief Sums the dynamic orders in a span of integers.
* @param dynamic_orders The span of dynamic orders to sum.
* @return The sum of the dynamic orders.
*/
[[nodiscard]] inline int sum_dynamic_orders(const std::span<const int> dynamic_orders) {
int total = 0;
for (const int order : dynamic_orders) {

View File

@@ -1,20 +1,57 @@
#pragma once
/**
* @file policy.hpp
* @author Emily M. Boudreaux
*
* @brief File containing the Policy class. This class is used to determine the appropriate order and other relevant information for the integration rule based on a given quadrature query.
*/
#include "serif/discretization/quadrature/query.hpp"
#include "serif/discretization/quadrature/rules.hpp"
namespace serif::discretization::quadrature {
/**
* @brief The Policy class is used to determine the appropriate order and other relevant information for the integration rule based on a given quadrature query. It uses a RuleSet to determine the appropriate order and other relevant information for the integration rule.
*/
class Policy final {
public:
/**
* @brief Constructs a Policy with the given RuleSet.
*
* @param ruleSet The RuleSet used to determine the appropriate order and other relevant information for the integration rule.
*/
explicit Policy(RuleSet ruleSet);
/**
* @brief Resolves the appropriate order and other relevant information for the integration rule based on the given quadrature query.
*
* @param query The quadrature query used to determine the appropriate order and other relevant information for the integration rule.
* @return The resolution containing the appropriate order and other relevant information for the integration rule.
*/
[[nodiscard]] Resolution resolve(const Query &query) const;
private:
/**
* @brief Computes the base order for the given quadrature query. This is used to determine the appropriate order for the integration rule.
*
* @param query The quadrature query used to determine the base order.
* @return The base order for the given quadrature query.
*/
[[nodiscard]] static int compute_base_order(const Query &query);
/**
* @brief Retrieves the RuleControl for the given quadrature role. This is used to determine the appropriate order and other relevant information for the integration rule.
*
* @param role The quadrature role used to retrieve the RuleControl.
* @return The RuleControl for the given quadrature role.
*/
[[nodiscard]] const RuleControl &get_role_control(QuadratureRole role) const;
private:
RuleSet m_ruleSet;
RuleSet m_ruleSet; ///< The RuleSet used to determine the appropriate order and other relevant information for the integration rule.
};
}

View File

@@ -1,5 +1,12 @@
#pragma once
/**
* @file query.hpp
* @author Emily M. Boudreaux
*
* @brief File containing the Query struct. This struct is used to represent a quadrature query, which contains all the information needed to determine the appropriate order and other relevant information for the integration rule.
*/
#include <format>
#include <string>
@@ -9,23 +16,42 @@
#include "serif/discretization/forms/runtime.hpp"
namespace serif::discretization::quadrature {
/**
* @brief The Query struct is used to represent a quadrature query, which contains all the information needed to determine the appropriate order and other relevant information for the integration rule.
*/
struct Query final {
forms::FormDescriptor form;
forms::FormDescriptor form; ///< The form descriptor for the form being queried.
QuadratureRole role = QuadratureRole::discretization;
domain::DomainOrSet domain = domain::AllDomains{};
MappingKind mapping = MappingKind::none;
QuadratureRole role = QuadratureRole::discretization; ///< The role of the quadrature rule.
domain::DomainOrSet domain = domain::AllDomains{}; ///< The domain or set of domains for which we are trying to resolve an MFEM integration rule.
MappingKind mapping = MappingKind::none; ///< The mapping kind of the quadrature rule.
int trial_order = 0;
int test_order = 0;
int coefficient_order = 0;
int geometry_weight_order = 0;
int trial_order_reduction = 0;
int test_order_reduction = 0;
int trial_order = 0; ///< The order of the trial space.
int test_order = 0; ///< The order of the test space.
int coefficient_order = 0; ///< The order of the coefficient space.
int geometry_weight_order = 0; ///< The order of the geometry weight.
int trial_order_reduction = 0; ///< The reduction in the order of the trial space.
int test_order_reduction = 0; ///< The reduction in the order of the test space.
std::optional<int> base_order;
std::optional<int> base_order; ///< The base order for the quadrature rule.
};
/**
* @brief A helper function to create a Query object for a given form type. This function is used to simplify the creation of Query objects by automatically filling in the form descriptor and other relevant information.
*
* @tparam FormT The form type for which we are creating the query.
*
* @param role The role of the quadrature rule.
* @param domain The domain or set of domains for which we are trying to resolve an MFEM integration rule.
* @param mapping The mapping kind of the quadrature rule.
* @param trialOrder The order of the trial space.
* @param testOrder The order of the test space.
* @param coefficientOrder The order of the coefficient space.
* @param geometryWeightOrder The order of the geometry weight.
* @param baseOrder An optional base order for the quadrature rule.
*
* @return A Query object containing all the relevant information for the quadrature query.
*/
template <forms::Form FormT>
[[nodiscard]] constexpr Query make_query(
const QuadratureRole role,
@@ -53,6 +79,9 @@ namespace serif::discretization::quadrature {
}
}
/**
* @brief A specialization of the std::formatter for the Query struct. This allows for easy formatting of Query objects using std::format.
*/
template <>
struct std::formatter<serif::discretization::quadrature::Query> : std::formatter<std::string> {
template <typename FormatContext>

View File

@@ -1,4 +1,12 @@
#pragma once
/**
* @file rules.hpp
* @author Emily M. Boudreaux
*
* @brief File containing the RuleSet class and related types. The RuleSet class is used to determine the appropriate order and other relevant information for the integration rule based on a given quadrature query.
*/
#include <optional>
#include <string>
#include <vector>
@@ -8,39 +16,74 @@
#include "serif/discretization/forms/runtime.hpp"
namespace serif::discretization::quadrature {
/**
* @brief An enumeration of the different roles that a quadrature rule can play.
*
* The idea here is that different roles might require or allow different levels of accuracy. For example, integrating for a preconditioner
* generally need not be as accurate as integrating for the discretization itself.
*/
enum class QuadratureRole {
discretization,
preconditioner,
diagnostic,
projection
discretization, ///< The quadrature rule is being used for discretization.
preconditioner, ///< The quadrature rule is being used for preconditioning.
diagnostic, ///< The quadrature rule is being used for diagnostics.
projection ///< The quadrature rule is being used for projection.
};
/**
* @brief An enumeration of the different mapping kinds that a quadrature rule can have.
*
* The idea here is that different mapping kinds might require or allow different levels of accuracy. For example, an affine mapping
* generally requires less accuracy than a general mapping.
*/
enum class MappingKind {
none,
affine,
general,
kelvin
none, ///< The quadrature rule has no mapping.
affine, ///< The quadrature rule has an affine mapping.
general, ///< The quadrature rule has a general mapping.
kelvin ///< The quadrature rule has a Kelvin mapping (compactified).
};
/**
* @brief An enumeration of the different modes that the quadrature system can operate in.
*
* The idea here is that different modes might require or allow different levels of accuracy. For example, a fast mode might prioritize speed over accuracy,
* while a production mode might prioritize accuracy over speed.
*/
enum class Mode {
fast,
production,
reference,
convergence
fast, ///< The quadrature system is operating in fast mode.
production, ///< The quadrature system is operating in production mode.
reference, ///< The quadrature system is operating in reference mode.
convergence ///< The quadrature system is operating in convergence mode. (note in convergence mode the system may inject additional loops to test convergence of the quadrature rule). Convergence should only ever be used for testing and validation, not in production.
};
/**
* @brief A struct to control the behavior of a quadrature rule for a given form or role. Rule control always
* contains boost (default to 0) and may contain some fixed order (think of this as an override). If the fixed order is empty
* then the quadrature system will determine the order based on the form and role + boost.
*/
struct RuleControl {
std::optional<int> fixed_order;
int boost = 0;
std::optional<int> fixed_order; ///< An optional fixed order for the quadrature rule. If this is set, it will override the default order determined by the form and role.
int boost = 0; ///< An additional boost to the order of the quadrature rule. This is added to the default order determined by the form and role.
};
/**
* @brief A struct to represent a form rule, which contains a form descriptor and a rule control. Used to tie some form to a specific quadrature rule control.
*/
struct FormRule final {
forms::FormDescriptor form;
RuleControl control;
forms::FormDescriptor form; ///< The form descriptor for the form being queried.
RuleControl control; ///< The rule control for the form being queried. This contains the fixed order and boost for the quadrature rule.
};
/**
* @brief The RuleSet class is used to determine the appropriate order and other relevant information for the integration rule based on a given quadrature query. It contains a set of form rules and role controls, as well as a fallback control.
*/
class RuleSet {
public:
/**
* @brief Sets the rule control for a given form type. This allows for specifying a fixed order or boost for a specific form.
* @tparam FormT The form type for which to set the rule control.
* @param control The rule control to set for the given form type.
*/
template <forms::Form FormT>
void set_form_control(
const RuleControl control
@@ -48,6 +91,14 @@ namespace serif::discretization::quadrature {
set_form_control(forms::form_descriptor<FormT>, control);
}
/**
* @brief Sets the rule control for a given form descriptor. This allows for specifying a fixed order or boost for a specific form.
*
* @param form The form descriptor for which to set the rule control.
* @param control The rule control to set for the given form descriptor.
*
* This works by searching through all the form rules in the Rule set and comparing their runtime descriptors. If the correct form is found then the control is updated. If the form is not found then a new form rule is added to the RuleSet.
*/
void set_form_control(
const forms::FormDescriptor &form,
const RuleControl control
@@ -62,6 +113,14 @@ namespace serif::discretization::quadrature {
m_formRules.push_back(FormRule{.form = form, .control = control});
}
/**
* @brief Finds the rule control for a given form descriptor. This allows for retrieving the fixed order or boost for a specific form.
*
* @param form The form descriptor for which to find the rule control.
* @return A pointer to the rule control for the given form descriptor, or nullptr if no rule control is found.
*
* This works by searching through all the form rules in the Rule set and comparing their runtime descriptors. If the correct form is found then a pointer to its rule control is returned. If the form is not found then nullptr is returned.
*/
[[nodiscard]] const RuleControl *find_form_control(
const forms::FormDescriptor &form
) const noexcept {
@@ -74,6 +133,7 @@ namespace serif::discretization::quadrature {
return nullptr;
}
/
void set_role_control(
const QuadratureRole role,
const RuleControl control
@@ -97,6 +157,11 @@ namespace serif::discretization::quadrature {
}
}
/**
* @brief Get the rule control for a given quadrature role. This allows for retrieving the fixed order or boost for a specific role.
* @param role The quadrature role for which to get the rule control.
* @return The rule control for the given quadrature role.
*/
[[nodiscard]] const RuleControl &role_control(
const QuadratureRole role
) const noexcept {
@@ -117,118 +182,165 @@ namespace serif::discretization::quadrature {
std::unreachable();
}
/**
* @brief Set the fallback rule control for the RuleSet. This is used when no specific form or role control is found.
* @param control The fallback rule control to set.
*/
void set_fallback_control(
const RuleControl control
) noexcept {
m_fallbackControl = control;
}
/**
* @brief Get the fallback rule control for the RuleSet. This is used when no specific form or role control is found.
* @return The fallback rule control for the RuleSet.
*/
[[nodiscard]] const RuleControl &fallback_control() const noexcept {
return m_fallbackControl;
}
/**
* @brief Get the begin iterator for the form rules in the RuleSet.
* @return An iterator to the beginning of the form rules in the RuleSet.
*/
auto begin() {
return m_formRules.begin();
}
/**
* @brief Get the end iterator for the form rules in the RuleSet.
* @return An iterator to the end of the form rules in the RuleSet.
*/
auto end() {
return m_formRules.end();
}
/**
* @brief Get the const begin iterator for the form rules in the RuleSet.
* @return An iterator to the beginning of the form rules in the RuleSet.
*/
auto begin() const {
return m_formRules.begin();
}
/**
* @brief Get the const end iterator for the form rules in the RuleSet.
* @return An iterator to the end of the form rules in the RuleSet.
*/
auto end() const {
return m_formRules.end();
}
private:
std::vector<FormRule> m_formRules;
std::vector<FormRule> m_formRules; ///< The form rules in the RuleSet. Each form rule contains a form descriptor and a rule control.
RuleControl m_discretizationControl;
RuleControl m_preconditionerControl;
RuleControl m_diagnosticControl;
RuleControl m_projectionControl;
RuleControl m_discretizationControl; ///< The rule control for the discretization role.
RuleControl m_preconditionerControl; ///< The rule control for the preconditioner role.
RuleControl m_diagnosticControl; ///< The rule control for the diagnostic role.
RuleControl m_projectionControl; ///< The rule control for the projection role.
RuleControl m_fallbackControl;
RuleControl m_fallbackControl; ///< The fallback rule control for the RuleSet. This is used when no specific form or role control is found.
};
/**
* @brief A struct to hold the rule controls for each quadrature role. This is used to group the rule controls together for convenience.
*/
struct RoleControls {
RuleControl discretization;
RuleControl preconditioner;
RuleControl diagnostic;
RuleControl projection;
RuleControl discretization; ///< The rule control for the discretization role.
RuleControl preconditioner; ///< The rule control for the preconditioner role.
RuleControl diagnostic; ///< The rule control for the diagnostic role.
RuleControl projection; ///< The rule control for the projection role.
};
/**
* @brief A struct to hold the resolution of a quadrature query. This contains the base order, boost, and final order of the quadrature rule, as well as a flag indicating whether a fixed order was used.
*/
struct Resolution {
int base_order;
int boost;
int order;
bool used_fixed_order;
int base_order; ///< The base order of the quadrature rule, which is determined by the form and role.
int boost; ///< The boost to the order of the quadrature rule, generally manually set
int order; ///< The final order of the quadrature rule, which is the sum of the base order and boost.
bool used_fixed_order; ///< A flag indicating whether a fixed order was used.
};
/**
* @brief A struct to hold the options for a quadrature term. This contains an optional fixed order and an additional boost to the order of the quadrature rule.
*/
struct QuadratureTermOptions {
std::optional<int> fixed_order;
int additional_boost = 0;
std::optional<int> fixed_order; ///< An optional fixed order for the quadrature rule. If this is set, it will override the default order determined by the form and role.
int additional_boost = 0; ///< An additional boost to the order of the quadrature rule. This is added to the default order determined by the form and role.
};
/**
* @brief A struct to hold the options for the quadrature manifest. This contains flags for enabling the manifest, including repeated queries, and an optional output file.
*/
struct QuadratureManifestOptions {
bool enabled = false;
bool include_repeated_queries = false;
std::optional<std::string> output_file;
bool enabled = false; ///< A flag indicating whether the quadrature manifest is enabled.
bool include_repeated_queries = false; ///< A flag indicating whether to include repeated queries in the quadrature manifest.
std::optional<std::string> output_file; ///< An optional output file for the quadrature manifest. If this is set, the manifest will be written to the specified file.
};
/**
* @brief A struct to hold the options for quadrature validation. This contains flags for requiring explicit base orders and MFEM rules, rejecting negative boosts, and reporting unused overrides.
*/
struct QuadratureValidationOptions {
bool require_explicit_base_order = false;
bool require_explicit_mfem_rule = false;
bool reject_negative_boosts = true;
bool report_unused_overrides = true;
bool require_explicit_base_order = false; ///< A flag indicating whether explicit base orders are required.
bool require_explicit_mfem_rule = false; ///< A flag indicating whether explicit MFEM rules are required.
bool reject_negative_boosts = true; ///< A flag indicating whether negative boosts should be rejected.
bool report_unused_overrides = true; ///< A flag indicating whether unused overrides should be reported.
};
/**
* @brief A struct to hold the options for quadrature roles. This contains the quadrature term options for each role.
*/
struct QuadratureRoleOptions {
QuadratureTermOptions discretization;
QuadratureTermOptions preconditioner;
QuadratureTermOptions diagnostic;
QuadratureTermOptions projection;
QuadratureTermOptions discretization; ///< The quadrature term options for the discretization role.
QuadratureTermOptions preconditioner; ///< The quadrature term options for the preconditioner role.
QuadratureTermOptions diagnostic; ///< The quadrature term options for the diagnostic role.
QuadratureTermOptions projection; ///< The quadrature term options for the projection role.
};
/**
* @brief A struct to hold the options for the quadrature system. This contains the mode, global boost, fallback fixed order, quadrature term options for each term, quadrature role options, convergence boosts, quadrature manifest options, and quadrature validation options.
*/
struct QuadratureOptions {
Mode mode = Mode::production;
int global_boost = 0;
std::optional<int> fallback_fixed_order;
Mode mode = Mode::production; ///< The mode of the quadrature system. This determines the level of accuracy and speed of the quadrature system.
int global_boost = 0; ///< The global boost to the order of the quadrature rule. This is added to the default order determined by the form and role. Note that different systems have different accuracy requirements and should generally use the lowest order that is sufficient for their needs.
std::optional<int> fallback_fixed_order; ///< The fallback fixed order for the quadrature rule. This is used if no other order is specified.
QuadratureTermOptions gravity_hdiv_mass;
QuadratureTermOptions gravity_divergence;
QuadratureTermOptions gravity_source;
QuadratureTermOptions gravity_force;
QuadratureTermOptions gravity_boundary;
QuadratureTermOptions centrifugal;
QuadratureTermOptions density_projection;
QuadratureTermOptions eos_closure;
QuadratureTermOptions hydrostatic_equilibrium;
QuadratureTermOptions isobaric_surface;
QuadratureTermOptions mesh_extension;
QuadratureTermOptions mass_conservation;
QuadratureTermOptions mass_normalization;
QuadratureTermOptions center_of_mass;
QuadratureTermOptions quadrupole;
QuadratureTermOptions gravitational_energy;
QuadratureTermOptions pressure_integral;
QuadratureTermOptions pressure_force;
QuadratureTermOptions virial;
QuadratureTermOptions error_norm;
QuadratureTermOptions gravity_hdiv_mass; ///< The quadrature term options for the gravity H(div) mass term.
QuadratureTermOptions gravity_divergence; ///< The quadrature term options for the gravity divergence term.
QuadratureTermOptions gravity_source; ///< The quadrature term options for the gravity source term.
QuadratureTermOptions gravity_force; ///< The quadrature term options for the gravity force term.
QuadratureTermOptions gravity_boundary; ///< The quadrature term options for the gravity boundary term.
QuadratureTermOptions centrifugal; ///< The quadrature term options for the centrifugal term.
QuadratureTermOptions density_projection; ///< The quadrature term options for the density projection term.
QuadratureTermOptions eos_closure; ///< The quadrature term options for the EOS closure term.
QuadratureTermOptions hydrostatic_equilibrium; ///< The quadrature term options for the hydrostatic equilibrium term.
QuadratureTermOptions isobaric_surface; ///< The quadrature term options for the isobaric surface term.
QuadratureTermOptions mesh_extension; ///< The quadrature term options for the mesh extension term.
QuadratureTermOptions mass_conservation; ///< The quadrature term options for the mass conservation term.
QuadratureTermOptions mass_normalization; ///< The quadrature term options for the mass normalization term.
QuadratureTermOptions center_of_mass; ///< The quadrature term options for the center of mass term.
QuadratureTermOptions quadrupole; ///< The quadrature term options for the quadrupole term.
QuadratureTermOptions gravitational_energy; ///< The quadrature term options for the gravitational energy term.
QuadratureTermOptions pressure_integral; ///< The quadrature term options for the pressure integral term.
QuadratureTermOptions pressure_force; ///< The quadrature term options for the pressure force term.
QuadratureTermOptions virial; ///< The quadrature term options for the virial term.
QuadratureTermOptions error_norm; ///< The quadrature term options for the error norm term.
QuadratureRoleOptions roles;
QuadratureRoleOptions roles; ///< The quadrature role options for each quadrature role.
std::vector<int> convergence_boosts = {0, 2, 4};
QuadratureManifestOptions manifest;
QuadratureValidationOptions validation;
std::vector<int> convergence_boosts = {0, 2, 4}; ///< The set of convergence boosts used for a tests (only used when the quadrature system is in convergence mode).
QuadratureManifestOptions manifest; ///< The quadrature manifest options for the quadrature system. This contains flags for enabling the manifest, including repeated queries, and an optional output file.
QuadratureValidationOptions validation; ///< The quadrature validation options for the quadrature system. This contains flags for requiring explicit base orders and MFEM rules, rejecting negative boosts, and reporting unused overrides.
};
}
/**
* @brief Specializations of the std::formatter for the QuadratureRole, MappingKind, Mode, RuleControl, FormRule, and RuleSet types. This allows for easy formatting of these types using std::format.
*/
template <>
struct std::formatter<serif::discretization::quadrature::QuadratureRole> : std::formatter<std::string_view> {
template <typename FormatContext>
@@ -252,6 +364,9 @@ struct std::formatter<serif::discretization::quadrature::QuadratureRole> : std::
}
};
/**
* @brief Specializations of the std::formatter for the MappingKind type. This allows for easy formatting of the MappingKind type using std::format.
*/
template <>
struct std::formatter<serif::discretization::quadrature::MappingKind> : std::formatter<std::string_view> {
template <typename FormatContext>
@@ -278,6 +393,9 @@ struct std::formatter<serif::discretization::quadrature::MappingKind> : std::for
}
};
/**
* @brief A specialization of the std::formatter for the Mode type. This allows for easy formatting of the Mode type using std::format.
*/
template <>
struct std::formatter<serif::discretization::quadrature::Mode> : std::formatter<std::string_view> {
template <typename FormatContext>
@@ -304,6 +422,9 @@ struct std::formatter<serif::discretization::quadrature::Mode> : std::formatter<
}
};
/**
* @brief A specialization of the std::formatter for the RuleControl type. This allows for easy formatting of the RuleControl type using std::format.
*/
template <>
struct std::formatter<serif::discretization::quadrature::RuleControl> : std::formatter<std::string_view> {
template <typename FormatContext>
@@ -314,6 +435,9 @@ struct std::formatter<serif::discretization::quadrature::RuleControl> : std::for
}
};
/**
* @brief A specialization of the std::formatter for the FormRule type. This allows for easy formatting of the FormRule type using std::format.
*/
template <>
struct std::formatter<serif::discretization::quadrature::FormRule> : std::formatter<std::string_view> {
template <typename FormatContext>
@@ -324,6 +448,9 @@ struct std::formatter<serif::discretization::quadrature::FormRule> : std::format
}
};
/**
* @brief A specialization of the std::formatter for the RuleSet type. This allows for easy formatting of the RuleSet type using std::format.
*/
template <>
struct std::formatter<serif::discretization::quadrature::RuleSet> : std::formatter<std::string_view> {
template <typename FormatContext>