feat(surface): major work on implementing surface constraints in a presciption agnostic manner
This commit is contained in:
186
libmeanfield/interface/surface/dependencies.cppm
Normal file
186
libmeanfield/interface/surface/dependencies.cppm
Normal file
@@ -0,0 +1,186 @@
|
||||
module;
|
||||
|
||||
#include <array>
|
||||
#include <concepts>
|
||||
#include <cstddef>
|
||||
#include <span>
|
||||
#include <string_view>
|
||||
#include <type_traits>
|
||||
|
||||
export module mean_field:surface.dependencies;
|
||||
|
||||
export import :eos.relations;
|
||||
export import :field.registry;
|
||||
|
||||
export namespace mean_field::surface {
|
||||
template <typename Candidate>
|
||||
concept SurfaceFieldType = requires {
|
||||
{ Candidate::name } -> std::convertible_to<std::string_view>;
|
||||
} && (std::string_view{Candidate::name}.size() > 0);
|
||||
|
||||
class SurfaceFieldId final {
|
||||
public:
|
||||
explicit constexpr SurfaceFieldId(const std::string_view name) noexcept : m_name(name) {
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr std::string_view name() const noexcept {
|
||||
return m_name;
|
||||
}
|
||||
|
||||
[[nodiscard]] friend constexpr bool operator==(
|
||||
const SurfaceFieldId &,
|
||||
const SurfaceFieldId &
|
||||
) noexcept = default;
|
||||
|
||||
private:
|
||||
std::string_view m_name;
|
||||
};
|
||||
|
||||
template <SurfaceFieldType Field> inline constexpr SurfaceFieldId surfaceFieldId{std::string_view{Field::name}};
|
||||
|
||||
template <eos::ThermodynamicQuantityType ThermodynamicQuantity, SurfaceFieldType Field>
|
||||
struct SurfaceStateBinding final {
|
||||
using Quantity = ThermodynamicQuantity;
|
||||
using FieldType = Field;
|
||||
};
|
||||
|
||||
template <typename... Bindings> struct SurfaceStateBindings final { };
|
||||
|
||||
namespace detail {
|
||||
template <typename... Types> struct SurfaceTypesAreUnique : std::true_type { };
|
||||
|
||||
template <typename First, typename... Remaining>
|
||||
struct SurfaceTypesAreUnique<First, Remaining...>
|
||||
: std::bool_constant<
|
||||
(!std::same_as<First, Remaining> && ...) && SurfaceTypesAreUnique<Remaining...>::value> { };
|
||||
|
||||
template <typename Bindings> struct SurfaceBindingsAreValid : std::false_type { };
|
||||
|
||||
template <typename... Bindings>
|
||||
struct SurfaceBindingsAreValid<SurfaceStateBindings<Bindings...>>
|
||||
: std::bool_constant<
|
||||
(sizeof...(Bindings) > 0) &&
|
||||
(requires {
|
||||
typename Bindings::Quantity;
|
||||
typename Bindings::FieldType;
|
||||
} && ...) &&
|
||||
(eos::ThermodynamicQuantityType<
|
||||
typename Bindings::Quantity> && ...) &&
|
||||
(SurfaceFieldType<typename Bindings::FieldType> && ...) &&
|
||||
SurfaceTypesAreUnique<
|
||||
typename Bindings::Quantity...>::value> { };
|
||||
|
||||
template <typename Bindings, typename Quantity> struct SurfaceBindingCount;
|
||||
|
||||
template <typename Quantity, typename... Bindings>
|
||||
struct SurfaceBindingCount<SurfaceStateBindings<Bindings...>, Quantity>
|
||||
: std::integral_constant<
|
||||
std::size_t,
|
||||
(std::size_t{0} + ... +
|
||||
(std::same_as<Quantity, typename Bindings::Quantity> ? std::size_t{1} : std::size_t{0}))> {
|
||||
};
|
||||
|
||||
template <typename Bindings, typename Quantity> struct SurfaceFieldForQuantity;
|
||||
|
||||
template <typename Quantity, typename First, typename... Remaining>
|
||||
struct SurfaceFieldForQuantity<SurfaceStateBindings<First, Remaining...>, Quantity>
|
||||
: std::conditional_t<
|
||||
std::same_as<Quantity, typename First::Quantity>,
|
||||
std::type_identity<typename First::FieldType>,
|
||||
SurfaceFieldForQuantity<SurfaceStateBindings<Remaining...>, Quantity>> { };
|
||||
|
||||
template <typename Candidate, std::size_t CarrierBindingCount>
|
||||
struct CarrierFieldMatchesSurfaceBinding : std::false_type { };
|
||||
|
||||
template <typename Candidate>
|
||||
struct CarrierFieldMatchesSurfaceBinding<Candidate, 1>
|
||||
: std::bool_constant<std::same_as<
|
||||
typename SurfaceFieldForQuantity<
|
||||
typename Candidate::StateBindings,
|
||||
typename Candidate::CarrierQuantity>::type,
|
||||
typename Candidate::CarrierField>> { };
|
||||
|
||||
template <
|
||||
typename Candidate,
|
||||
bool BindingsAreValid = SurfaceBindingsAreValid<typename Candidate::StateBindings>::value>
|
||||
struct FormulationBindingsMatchCarrier : std::false_type { };
|
||||
|
||||
template <typename Candidate>
|
||||
struct FormulationBindingsMatchCarrier<Candidate, true>
|
||||
: CarrierFieldMatchesSurfaceBinding<
|
||||
Candidate,
|
||||
SurfaceBindingCount<
|
||||
typename Candidate::StateBindings,
|
||||
typename Candidate::CarrierQuantity>::value> { };
|
||||
|
||||
template <typename Candidate, typename = void>
|
||||
struct IsSurfaceConstraintFormulation : std::false_type { };
|
||||
|
||||
template <typename Candidate>
|
||||
struct IsSurfaceConstraintFormulation<
|
||||
Candidate,
|
||||
std::void_t<
|
||||
typename Candidate::CarrierQuantity,
|
||||
typename Candidate::CarrierField,
|
||||
typename Candidate::StateBindings>>
|
||||
: std::bool_constant<
|
||||
eos::ThermodynamicQuantityType<typename Candidate::CarrierQuantity> &&
|
||||
SurfaceFieldType<typename Candidate::CarrierField> &&
|
||||
FormulationBindingsMatchCarrier<Candidate>::value> { };
|
||||
} // namespace detail
|
||||
|
||||
template <typename Candidate>
|
||||
concept ValidSurfaceStateBindings = detail::SurfaceBindingsAreValid<std::remove_cv_t<Candidate>>::value;
|
||||
|
||||
template <ValidSurfaceStateBindings Bindings, typename Quantity>
|
||||
inline constexpr std::size_t surfaceBindingCount = detail::SurfaceBindingCount<Bindings, Quantity>::value;
|
||||
|
||||
template <ValidSurfaceStateBindings Bindings, typename Quantity>
|
||||
requires(surfaceBindingCount<Bindings, Quantity> == 1)
|
||||
using SurfaceFieldForQuantityT = typename detail::SurfaceFieldForQuantity<Bindings, Quantity>::type;
|
||||
|
||||
template <
|
||||
eos::ThermodynamicQuantityType CarrierThermodynamicQuantity,
|
||||
SurfaceFieldType CarrierFieldType,
|
||||
ValidSurfaceStateBindings Bindings>
|
||||
requires(
|
||||
surfaceBindingCount<Bindings, CarrierThermodynamicQuantity> == 1 &&
|
||||
std::same_as<SurfaceFieldForQuantityT<Bindings, CarrierThermodynamicQuantity>, CarrierFieldType>
|
||||
)
|
||||
struct SurfaceConstraintFormulation final {
|
||||
using CarrierQuantity = CarrierThermodynamicQuantity;
|
||||
using CarrierField = CarrierFieldType;
|
||||
using StateBindings = Bindings;
|
||||
};
|
||||
|
||||
using BarotropicSurfaceFormulation = SurfaceConstraintFormulation<
|
||||
eos::quantity::SpecificEnthalpy,
|
||||
field::Enthalpy,
|
||||
SurfaceStateBindings<SurfaceStateBinding<eos::quantity::SpecificEnthalpy, field::Enthalpy>>>;
|
||||
|
||||
template <typename Candidate>
|
||||
concept SurfaceConstraintFormulationType =
|
||||
detail::IsSurfaceConstraintFormulation<std::remove_cv_t<Candidate>>::value;
|
||||
|
||||
struct RuntimeSurfaceConstraintDependencies final {
|
||||
SurfaceFieldId residualRowField;
|
||||
std::span<const SurfaceFieldId> stateFields;
|
||||
};
|
||||
|
||||
template <SurfaceFieldType ResidualField, SurfaceFieldType... StateFields>
|
||||
struct SurfaceConstraintDependencies final {
|
||||
using RowField = ResidualField;
|
||||
using StateFieldTypes = field::TypeList<StateFields...>;
|
||||
|
||||
inline static constexpr std::array<SurfaceFieldId, sizeof...(StateFields)> runtimeStateFields{
|
||||
surfaceFieldId<StateFields>...
|
||||
};
|
||||
|
||||
[[nodiscard]] static constexpr RuntimeSurfaceConstraintDependencies runtimeDescription() noexcept {
|
||||
return RuntimeSurfaceConstraintDependencies{
|
||||
.residualRowField = surfaceFieldId<ResidualField>,
|
||||
.stateFields = std::span<const SurfaceFieldId>{runtimeStateFields}
|
||||
};
|
||||
}
|
||||
};
|
||||
} // namespace mean_field::surface
|
||||
Reference in New Issue
Block a user