docs(functional_space): added doxygen comments throughout

This commit is contained in:
2026-10-02 07:28:34 -04:00
parent 05df03b1c1
commit 80e15b60b5

View File

@@ -1,61 +1,104 @@
#pragma once
/**
* @file space.hpp
* @author Emily M. Boudreaux
* @brief This file defines the functional space types used in the discretization framework, including compile-time descriptors and runtime descriptors.
*/
#include <type_traits>
#include <format>
#include "serif/meta/enums.hpp"
namespace serif::discretization::functional_space {
/**
* @brief Compile-time descriptor for the rank of a functional space.
* @tparam R The rank of the functional space.
*/
template <std::size_t R>
struct Rank {
constexpr static std::size_t value = R;
constexpr static std::size_t value = R; ///< The rank of the functional space.
};
/**
* @brief Compile-time descriptor for the family, continuity, trace, and mapping of a functional space.
*
* @note These are almost all of the functional spaces that MFEM supports, if in the future MFEM adds some other space and
* you wish to extend SERiF to support it (or you introduce some non MFEM backend with another space) then one early
* place you will need to modify is this enum.
*
* @note We do not support mfem::ceed::ParAlgebraicCoarseSpace
*/
enum class Family {
l2,
h1,
hdiv,
hcurl
l2, ///< L2 space, typically used for discontinuous functions.
h1, ///< H1 space, typically used for continuous functions.
hdiv, ///< H(div) space, typically used for vector fields with normal continuity.
hcurl ///< H(curl) space, typically used for vector fields with tangential continuity.
};
inline static auto Family2StringMap = meta::enum_to_enum_string_map<Family>();
inline static auto String2FamilyMap = meta::enum_to_string_enum_map<Family>();
inline static auto Family2StringMap = meta::enum_to_enum_string_map<Family>(); ///< Mapping from Family enum values to their string representations.
inline static auto String2FamilyMap = meta::enum_to_string_enum_map<Family>(); ///< Mapping from string representations to Family enum values.
/**
* @brief Compile-time descriptor for the continuity of a functional space. This enum is parallel to the @ref Family enum.
*
* @todo There may be a better way to store these relations that forces them to be parallel rather than just relying on the programmer to keep them in sync.
*/
enum class Continuity {
discontinuous,
continuous,
normal_continuous,
tangential_continuous
discontinuous, ///< Discontinuous functions, typically used for L2 spaces.
continuous, ///< C0 continuous functions, typically used for H1 spaces.
normal_continuous, ///< Functions with normal continuity, typically used for H(div) spaces.
tangential_continuous ///< Functions with tangential continuity, typically used for H(curl) spaces.
};
inline static auto Continuity2StringMap = meta::enum_to_enum_string_map<Continuity>();
inline static auto String2ContinuityMap = meta::enum_to_string_enum_map<Continuity>();
inline static auto Continuity2StringMap = meta::enum_to_enum_string_map<Continuity>(); ///< Mapping from Continuity enum values to their string representations.
inline static auto String2ContinuityMap = meta::enum_to_string_enum_map<Continuity>(); ///< Mapping from string representations to Continuity enum values.
/**
* @brief Compile-time descriptor for the trace of a functional space. This enum is parallel to the @ref Family enum.
*/
enum class Trace {
none,
value,
normal,
tangential
none, ///< No trace, typically used for L2 spaces.
value, ///< Value trace, typically used for H1 spaces.
normal, ///< Normal trace, typically used for H(div) spaces.
tangential ///< Tangential trace, typically used for H(curl) spaces.
};
inline static auto Trace2StringMap = meta::enum_to_enum_string_map<Trace>();
inline static auto String2TraceMap = meta::enum_to_string_enum_map<Trace>();
inline static auto Trace2StringMap = meta::enum_to_enum_string_map<Trace>(); ///< Mapping from Trace enum values to their string representations.
inline static auto String2TraceMap = meta::enum_to_string_enum_map<Trace>(); ///< Mapping from string representations to Trace enum values.
/**
* @brief Compile-time descriptor for the mapping of a functional space. This tells the DomainMapper which piola transformations to use when moving between reference and physical spaces.
*/
enum class Mapping {
identity,
contravariant_piola,
covariant_piola
identity, ///< Identity mapping, typically used for L2 and H1 spaces.
contravariant_piola, ///< Contravariant Piola mapping, preserving the normal trace, typically used for H(div) spaces. (\f$ \frac{1}{\text{det(J)}}J\hat{\phi}(F^{-1}(x)) \f$ transforming some vector field \f$\phi(x)\f$ for some transformation \f$ F \f$ with Jacobian \f$ J \f$)
covariant_piola ///< Covariant Piola mapping, preserving the tangential trace, typically used for H(curl) spaces. (\f$ J^{-T}\hat{\phi}(F^{-1}(x)) \f$ transforming some vector field \f$\phi(x)\f$ for some transformation \f$ F \f$ with Jacobian \f$ J \f$)
};
inline static auto Mapping2StringMap = meta::enum_to_enum_string_map<Mapping>();
inline static auto String2MappingMap = meta::enum_to_string_enum_map<Mapping>();
inline static auto Mapping2StringMap = meta::enum_to_enum_string_map<Mapping>(); ///< Mapping from Mapping enum values to their string representations.
inline static auto String2MappingMap = meta::enum_to_string_enum_map<Mapping>(); ///< Mapping from string representations to Mapping enum values.
/**
* @brief Compile-time descriptor for a functional space. This struct is used to describe the family, continuity, trace, and mapping of a functional space at compile time.
*/
struct SpaceDescriptor final {
const Family family;
const Continuity continuity;
const Trace trace;
const Mapping mapping;
const Family family; ///< The family of the functional space (e.g. L2, H1, H(div), H(curl)).
const Continuity continuity; ///< The continuity of the functional space (e.g. discontinuous, continuous, normal continuous, tangential continuous).
const Trace trace; ///< The trace of the functional space (e.g. none, value, normal, tangential).
const Mapping mapping; ///< The mapping of the functional space (e.g. identity, contravariant_piola, covariant_piola).
};
/**
* @brief Compile-time descriptor for an L2 functional space. This is a convenience descriptor that allows you to easily create an L2 functional space descriptor without having to specify all the parameters.
* The specifications are
* - family = Family::l2
* - continuity = Continuity::discontinuous
* - trace = Trace::none
* - mapping = Mapping::identity
*/
inline static constexpr SpaceDescriptor L2{
.family = Family::l2,
.continuity = Continuity::discontinuous,
@@ -63,6 +106,14 @@ namespace serif::discretization::functional_space {
.mapping = Mapping::identity
};
/**
* @brief Compile-time descriptor for an H1 functional space. This is a convenience descriptor that allows you to easily create an H1 functional space descriptor without having to specify all the parameters.
* The specifications are
* - family = Family::h1
* - continuity = Continuity::continuous
* - trace = Trace::value
* - mapping = Mapping::identity
*/
inline static constexpr SpaceDescriptor H1{
.family = Family::h1,
.continuity = Continuity::continuous,
@@ -70,6 +121,14 @@ namespace serif::discretization::functional_space {
.mapping = Mapping::identity
};
/**
* @brief Compile-time descriptor for an H(div) functional space. This is a convenience descriptor that allows you to easily create an H(div) functional space descriptor without having to specify all the parameters.
* The specifications are
* - family = Family::hdiv
* - continuity = Continuity::normal_continuous
* - trace = Trace::normal
* - mapping = Mapping::contravariant_piola
*/
inline static constexpr SpaceDescriptor Hdiv{
.family = Family::hdiv,
.continuity = Continuity::normal_continuous,
@@ -77,6 +136,14 @@ namespace serif::discretization::functional_space {
.mapping = Mapping::contravariant_piola
};
/**
* @brief Compile-time descriptor for an H(curl) functional space. This is a convenience descriptor that allows you to easily create an H(curl) functional space descriptor without having to specify all the parameters.
* The specifications are
* - family = Family::hcurl
* - continuity = Continuity::tangential_continuous
* - trace = Trace::tangential
* - mapping = Mapping::covariant_piola
*/
inline static constexpr SpaceDescriptor Hcurl{
.family = Family::hcurl,
.continuity = Continuity::tangential_continuous,
@@ -84,17 +151,35 @@ namespace serif::discretization::functional_space {
.mapping = Mapping::covariant_piola
};
/**
* @brief Concept to validate a valid space descriptor. A space descriptor is valid if it is of type SpaceDescriptor. This is a very simple concept that just checks that the type is exactly SpaceDescriptor.
*/
template <typename SpaceDescriptorCandidate>
concept IsSpaceDescriptor = std::is_same_v<SpaceDescriptor, SpaceDescriptorCandidate>;
/**
* @brief Compile-time descriptor for a discrete functional space. The difference between a FunctionalSpace and a discrete functional space is that
* a discrete functional space carries some additional information which is needed to actually construct a finite element space (e.g. polynomial order, and rank).
* Once you have a discrete functional space you have, for MFEM at least, enough information to fully define a finite element space.
*
* @tparam Space The functional space descriptor (e.g. L2, H1, H(div), H(curl)).
* @tparam Order The order of the finite element family (e.g. 0 for P0, 1 for P1, etc.).
* @tparam R The rank of the functional space (e.g. 0 for scalar, 1 for vector, 2 for tensor).
*/
template <SpaceDescriptor Space, int Order, std::size_t R>
struct DiscreteFunctionalSpace {
static_assert(Order >= 0, "Finite-element family order must be non-negative.");
static_assert((Space.family != Family::hdiv && Space.family != Family::hcurl) || R == 1, "H(div) and H(curl) spaces must be vector-valued.");
static constexpr SpaceDescriptor functional_space = Space;
static constexpr int order = Order;
using rank = Rank<R>;
};
}
/**
* @brief Specialization of the std::formatter for the functional space types. This allows us to use std::format to format the functional space types as strings.
*/
template <std::size_t R>
struct std::formatter<serif::discretization::functional_space::Rank<R>> : std::formatter<std::string> {
template <typename FormatContext>
@@ -109,6 +194,9 @@ struct std::formatter<serif::discretization::functional_space::Rank<R>> : std::f
}
};
/**
* @brief Specialization of the std::formatter for the SpaceDescriptor types. This allows us to use std::format to format the SpaceDescriptor types as strings.
*/
template <>
struct std::formatter<serif::discretization::functional_space::SpaceDescriptor> : std::formatter<std::string> {
template <typename FormatContext>
@@ -121,6 +209,9 @@ struct std::formatter<serif::discretization::functional_space::SpaceDescriptor>
}
};
/**
* @brief Specialization of the std::formatter for the DiscreteFunctionalSpace types. This allows us to use std::format to format the DiscreteFunctionalSpace types as strings.
*/
// formatter for DiscreteFunctionalSpace
template <serif::discretization::functional_space::SpaceDescriptor Space, int Order, std::size_t R>
struct std::formatter<serif::discretization::functional_space::DiscreteFunctionalSpace<Space, Order, R>> : std::formatter<std::string> {
@@ -129,11 +220,13 @@ struct std::formatter<serif::discretization::functional_space::DiscreteFunctiona
return std::formatter<std::string>::format(std::format("DiscreteFunctionalSpace(functional_space={}, order={}, rank={})",
space.functional_space,
space.order,
space.rank), ctx);
serif::discretization::functional_space::Rank<R>{}), ctx);
}
};
// formatter for each enum
/**
* @brief Specialization of the std::formatter for the Family enum. This allows us to use std::format to format the Family enum as strings.
*/
template <>
struct std::formatter<serif::discretization::functional_space::Family> : std::formatter<std::string> {
template <typename FormatContext>
@@ -142,6 +235,9 @@ struct std::formatter<serif::discretization::functional_space::Family> : std::fo
}
};
/**
* @brief Specialization of the std::formatter for the Continuity enum. This allows us to use std::format to format the Continuity enum as strings.
*/
template <>
struct std::formatter<serif::discretization::functional_space::Continuity> : std::formatter<std::string> {
template <typename FormatContext>
@@ -150,6 +246,9 @@ struct std::formatter<serif::discretization::functional_space::Continuity> : std
}
};
/**
* @brief Specialization of the std::formatter for the Trace enum. This allows us to use std::format to format the Trace enum as strings.
*/
template <>
struct std::formatter<serif::discretization::functional_space::Trace> : std::formatter<std::string> {
template <typename FormatContext>
@@ -158,6 +257,9 @@ struct std::formatter<serif::discretization::functional_space::Trace> : std::for
}
};
/**
* @brief Specialization of the std::formatter for the Mapping enum. This allows us to use std::format to format the Mapping enum as strings.
*/
template <>
struct std::formatter<serif::discretization::functional_space::Mapping> : std::formatter<std::string> {
template <typename FormatContext>