perf(jacobian-action): major updates to jacobian action application by removing redudant quadrature work. ~5x increase in speed
This commit is contained in:
@@ -0,0 +1,95 @@
|
||||
module;
|
||||
|
||||
#include <concepts>
|
||||
#include <type_traits>
|
||||
|
||||
export module mean_field:model.compiled_fixed_central_density;
|
||||
|
||||
export import :eos.polytrope;
|
||||
export import :field.registry;
|
||||
export import :model.compiled_fixed_mass;
|
||||
export import :utils.blocks;
|
||||
|
||||
export namespace mean_field::models {
|
||||
struct CentralDensityLayoutRequest final {
|
||||
using SpecificationType = FixedCentralDensity;
|
||||
using GeneratedValueType = BorderFor<FixedCentralDensity>;
|
||||
using GeneratedResidualType = ResidualFor<FixedCentralDensity>;
|
||||
using ValueBlockType = utils::blocks::fixed_central_density::central_value::value;
|
||||
using ResidualBlockType = utils::blocks::fixed_central_density::central_value::residual;
|
||||
using TermType = utils::blocks::fixed_central_density::central_value;
|
||||
using StateValueBlockTypes = ModelTypeList<utils::blocks::enthalpy::specific::value>;
|
||||
|
||||
static constexpr ConstraintRowInjection rowInjection = ConstraintRowInjection::solver_border;
|
||||
static constexpr std::size_t valueArity = GeneratedValueType::scalarArity;
|
||||
static constexpr std::size_t residualArity = GeneratedResidualType::scalarArity;
|
||||
|
||||
template <typename Form> [[nodiscard]] static consteval auto valueBlock() {
|
||||
return utils::blocks::get_value_block<Form>(TermType{});
|
||||
}
|
||||
|
||||
template <typename Form> [[nodiscard]] static consteval auto residualBlock() {
|
||||
return utils::blocks::get_residual_block<Form>(TermType{});
|
||||
}
|
||||
};
|
||||
|
||||
class CompiledFixedCentralDensity final {
|
||||
public:
|
||||
using SpecificationType = FixedCentralDensity;
|
||||
using LayoutRequest = CentralDensityLayoutRequest;
|
||||
using BorderType = typename LayoutRequest::GeneratedValueType;
|
||||
using ResidualType = typename LayoutRequest::GeneratedResidualType;
|
||||
using CarrierField = field::Enthalpy;
|
||||
using BorderField = field::CentralDensityBorder;
|
||||
|
||||
CompiledFixedCentralDensity(
|
||||
const FixedCentralDensity specification,
|
||||
const eos::Polytrope &equationOfState
|
||||
)
|
||||
: m_specification(specification),
|
||||
m_equationOfState(equationOfState),
|
||||
m_targetEnthalpy(
|
||||
eos::evaluate<eos::quantity::SpecificEnthalpy>(
|
||||
m_equationOfState,
|
||||
m_specification.targetDensity()
|
||||
)
|
||||
) {
|
||||
}
|
||||
|
||||
[[nodiscard]] const FixedCentralDensity &specification() const noexcept {
|
||||
return m_specification;
|
||||
}
|
||||
|
||||
[[nodiscard]] dimensions::DensityValue targetDensity() const noexcept {
|
||||
return m_specification.targetDensity();
|
||||
}
|
||||
|
||||
[[nodiscard]] dimensions::SpecificEnthalpyValue targetEnthalpy() const noexcept {
|
||||
return m_targetEnthalpy;
|
||||
}
|
||||
|
||||
[[nodiscard]] dimensions::DensityValue
|
||||
densityFromEnthalpy(const dimensions::SpecificEnthalpyValue enthalpy) const {
|
||||
return eos::evaluate<eos::quantity::Density>(m_equationOfState, enthalpy);
|
||||
}
|
||||
|
||||
[[nodiscard]] static consteval LayoutRequest layoutRequest() noexcept {
|
||||
return {};
|
||||
}
|
||||
|
||||
private:
|
||||
FixedCentralDensity m_specification;
|
||||
eos::Polytrope m_equationOfState;
|
||||
dimensions::SpecificEnthalpyValue m_targetEnthalpy;
|
||||
};
|
||||
|
||||
[[nodiscard]] inline CompiledFixedCentralDensity compileConstraint(
|
||||
const FixedCentralDensity specification,
|
||||
const eos::Polytrope &equationOfState
|
||||
) {
|
||||
return {specification, equationOfState};
|
||||
}
|
||||
|
||||
static_assert(ConstraintLayoutRequestType<CentralDensityLayoutRequest>);
|
||||
static_assert(CompiledConstraint<CompiledFixedCentralDensity>);
|
||||
} // namespace mean_field::models
|
||||
115
libmeanfield/interface/models/compiled_fixed_mass.cppm
Normal file
115
libmeanfield/interface/models/compiled_fixed_mass.cppm
Normal file
@@ -0,0 +1,115 @@
|
||||
module;
|
||||
|
||||
#include <concepts>
|
||||
#include <type_traits>
|
||||
|
||||
export module mean_field:model.compiled_fixed_mass;
|
||||
|
||||
export import :field.registry;
|
||||
export import :model.specifications;
|
||||
export import :utils.blocks;
|
||||
|
||||
export namespace mean_field::models {
|
||||
enum class ConstraintRowInjection { append, solver_border };
|
||||
|
||||
template <
|
||||
ModelSpecification Specification,
|
||||
typename GeneratedValue,
|
||||
typename GeneratedResidual,
|
||||
typename ValueBlock,
|
||||
typename ResidualBlock,
|
||||
typename Term,
|
||||
typename... StateValueBlocks>
|
||||
struct ConstraintLayoutRequest final {
|
||||
using SpecificationType = Specification;
|
||||
using GeneratedValueType = GeneratedValue;
|
||||
using GeneratedResidualType = GeneratedResidual;
|
||||
using ValueBlockType = ValueBlock;
|
||||
using ResidualBlockType = ResidualBlock;
|
||||
using TermType = Term;
|
||||
using StateValueBlockTypes = ModelTypeList<StateValueBlocks...>;
|
||||
|
||||
static constexpr ConstraintRowInjection rowInjection = ConstraintRowInjection::append;
|
||||
static constexpr std::size_t valueArity = GeneratedValue::scalarArity;
|
||||
static constexpr std::size_t residualArity = GeneratedResidual::scalarArity;
|
||||
|
||||
template <typename Form> [[nodiscard]] static consteval auto valueBlock() {
|
||||
return utils::blocks::get_value_block<Form>(Term{});
|
||||
}
|
||||
|
||||
template <typename Form> [[nodiscard]] static consteval auto residualBlock() {
|
||||
return utils::blocks::get_residual_block<Form>(Term{});
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Candidate>
|
||||
concept ConstraintLayoutRequestType = requires {
|
||||
typename std::remove_cvref_t<Candidate>::SpecificationType;
|
||||
typename std::remove_cvref_t<Candidate>::GeneratedValueType;
|
||||
typename std::remove_cvref_t<Candidate>::GeneratedResidualType;
|
||||
typename std::remove_cvref_t<Candidate>::ValueBlockType;
|
||||
typename std::remove_cvref_t<Candidate>::ResidualBlockType;
|
||||
typename std::remove_cvref_t<Candidate>::StateValueBlockTypes;
|
||||
requires ModelSpecification<typename std::remove_cvref_t<Candidate>::SpecificationType>;
|
||||
requires std::remove_cvref_t<Candidate>::valueArity == std::remove_cvref_t<Candidate>::residualArity;
|
||||
};
|
||||
|
||||
using FixedMassLayoutRequest = ConstraintLayoutRequest<
|
||||
FixedTotalMass,
|
||||
MultiplierFor<FixedTotalMass>,
|
||||
ResidualFor<FixedTotalMass>,
|
||||
utils::blocks::fixed_total_mass::mass_normalization::value,
|
||||
utils::blocks::fixed_total_mass::mass_normalization::residual,
|
||||
utils::blocks::fixed_total_mass::mass_normalization,
|
||||
utils::blocks::density::mass::value,
|
||||
utils::blocks::displacement::geometry::value>;
|
||||
|
||||
class CompiledFixedMass final {
|
||||
public:
|
||||
using SpecificationType = FixedTotalMass;
|
||||
using LayoutRequest = FixedMassLayoutRequest;
|
||||
using MultiplierType = typename LayoutRequest::GeneratedValueType;
|
||||
using ResidualType = typename LayoutRequest::GeneratedResidualType;
|
||||
|
||||
// In the current barotropic formulation, the multiplier generated by
|
||||
// FixedTotalMass is realized by the historical scalar C field.
|
||||
using MultiplierField = field::BarotropicConstant;
|
||||
|
||||
explicit CompiledFixedMass(const FixedTotalMass specification) noexcept : m_specification(specification) {
|
||||
}
|
||||
|
||||
[[nodiscard]] const FixedTotalMass &specification() const noexcept {
|
||||
return m_specification;
|
||||
}
|
||||
|
||||
[[nodiscard]] dimensions::MassValue targetMass() const noexcept {
|
||||
return m_specification.targetMass();
|
||||
}
|
||||
|
||||
[[nodiscard]] static consteval LayoutRequest layoutRequest() noexcept {
|
||||
return {};
|
||||
}
|
||||
|
||||
private:
|
||||
FixedTotalMass m_specification;
|
||||
};
|
||||
|
||||
template <typename Candidate>
|
||||
concept CompiledConstraint = requires(const std::remove_cvref_t<Candidate> &constraint) {
|
||||
typename std::remove_cvref_t<Candidate>::SpecificationType;
|
||||
typename std::remove_cvref_t<Candidate>::LayoutRequest;
|
||||
requires ModelSpecification<typename std::remove_cvref_t<Candidate>::SpecificationType>;
|
||||
requires ConstraintLayoutRequestType<typename std::remove_cvref_t<Candidate>::LayoutRequest>;
|
||||
{
|
||||
constraint.specification()
|
||||
} noexcept -> std::same_as<const typename std::remove_cvref_t<Candidate>::SpecificationType &>;
|
||||
{ constraint.layoutRequest() } noexcept -> std::same_as<typename std::remove_cvref_t<Candidate>::LayoutRequest>;
|
||||
};
|
||||
|
||||
[[nodiscard]] inline CompiledFixedMass compileConstraint(const FixedTotalMass specification) noexcept {
|
||||
return CompiledFixedMass{specification};
|
||||
}
|
||||
|
||||
static_assert(ConstraintLayoutRequestType<FixedMassLayoutRequest>);
|
||||
static_assert(CompiledConstraint<CompiledFixedMass>);
|
||||
} // namespace mean_field::models
|
||||
481
libmeanfield/interface/models/specifications.cppm
Normal file
481
libmeanfield/interface/models/specifications.cppm
Normal file
@@ -0,0 +1,481 @@
|
||||
module;
|
||||
|
||||
#include <array>
|
||||
#include <cmath>
|
||||
#include <compare>
|
||||
#include <concepts>
|
||||
#include <cstddef>
|
||||
#include <format>
|
||||
#include <span>
|
||||
#include <stdexcept>
|
||||
#include <string_view>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
export module mean_field:model.specifications;
|
||||
|
||||
export import :eos.polytrope;
|
||||
export import :surface.constant;
|
||||
|
||||
export namespace mean_field::models {
|
||||
enum class SpecificationRole {
|
||||
constitutive_law,
|
||||
boundary_condition,
|
||||
invariant,
|
||||
phase_condition,
|
||||
gauge_choice,
|
||||
rotation_law
|
||||
};
|
||||
|
||||
struct SpecificationKey final {
|
||||
SpecificationRole role;
|
||||
std::size_t ordinal;
|
||||
|
||||
constexpr auto operator<=>(const SpecificationKey &) const = default;
|
||||
};
|
||||
|
||||
struct SpecificationDescriptor final {
|
||||
std::string_view name;
|
||||
SpecificationRole role;
|
||||
SpecificationKey key;
|
||||
std::size_t generatedValueArity;
|
||||
std::size_t generatedResidualArity;
|
||||
|
||||
constexpr bool operator==(const SpecificationDescriptor &) const = default;
|
||||
};
|
||||
|
||||
enum class EquilibriumSystemCompilation {
|
||||
complete_equilibrium_system,
|
||||
equation_contributions_only,
|
||||
|
||||
// Transitional spellings retained while internal solver code is
|
||||
// migrated to physics-facing equilibrium-system terminology.
|
||||
isolated_root = complete_equilibrium_system,
|
||||
assembly_only = equation_contributions_only
|
||||
};
|
||||
|
||||
using ModelCompilationClass = EquilibriumSystemCompilation;
|
||||
|
||||
struct RuntimeSpecificationDescriptor final {
|
||||
SpecificationDescriptor specification;
|
||||
std::size_t canonicalIndex;
|
||||
bool hasRootCompiler;
|
||||
|
||||
constexpr bool operator==(const RuntimeSpecificationDescriptor &) const = default;
|
||||
};
|
||||
|
||||
template <typename Candidate> struct SpecificationTraits;
|
||||
|
||||
template <typename Candidate>
|
||||
concept ModelSpecification = requires {
|
||||
typename std::remove_cvref_t<Candidate>::Parameters;
|
||||
{ SpecificationTraits<std::remove_cvref_t<Candidate>>::name } -> std::convertible_to<std::string_view>;
|
||||
{ SpecificationTraits<std::remove_cvref_t<Candidate>>::role } -> std::convertible_to<SpecificationRole>;
|
||||
{ SpecificationTraits<std::remove_cvref_t<Candidate>>::key } -> std::convertible_to<SpecificationKey>;
|
||||
} && std::constructible_from<std::remove_cvref_t<Candidate>, typename std::remove_cvref_t<Candidate>::Parameters>;
|
||||
|
||||
class FixedTotalMass final {
|
||||
public:
|
||||
struct Parameters final {
|
||||
dimensions::MassValue Mtotal;
|
||||
};
|
||||
|
||||
using TargetValue = dimensions::MassValue;
|
||||
|
||||
explicit FixedTotalMass(const Parameters parameters) : FixedTotalMass(parameters.Mtotal) {
|
||||
}
|
||||
|
||||
explicit FixedTotalMass(const TargetValue targetMass) : m_targetMass(targetMass) {
|
||||
if (!std::isfinite(targetMass.value()) || targetMass.value() <= 0.0) {
|
||||
throw std::invalid_argument(
|
||||
std::format(
|
||||
"The fixed total mass must be finite and positive. Instead M = {} was provided.",
|
||||
targetMass.value()
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] TargetValue targetMass() const noexcept {
|
||||
return m_targetMass;
|
||||
}
|
||||
|
||||
private:
|
||||
TargetValue m_targetMass;
|
||||
};
|
||||
|
||||
class FixedCentralDensity final {
|
||||
public:
|
||||
struct Parameters final {
|
||||
dimensions::DensityValue RhoC;
|
||||
};
|
||||
|
||||
using TargetValue = dimensions::DensityValue;
|
||||
|
||||
explicit FixedCentralDensity(const Parameters parameters) : FixedCentralDensity(parameters.RhoC) {
|
||||
}
|
||||
|
||||
explicit FixedCentralDensity(const TargetValue targetDensity) : m_targetDensity(targetDensity) {
|
||||
if (!std::isfinite(targetDensity.value()) || targetDensity.value() <= 0.0) {
|
||||
throw std::invalid_argument(
|
||||
std::format(
|
||||
"The fixed central density must be finite and positive. Instead rho_c = {} was provided.",
|
||||
targetDensity.value()
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] TargetValue targetDensity() const noexcept {
|
||||
return m_targetDensity;
|
||||
}
|
||||
|
||||
private:
|
||||
TargetValue m_targetDensity;
|
||||
};
|
||||
|
||||
template <> struct SpecificationTraits<eos::Polytrope> {
|
||||
static constexpr std::string_view name = "Polytrope";
|
||||
static constexpr SpecificationRole role = SpecificationRole::constitutive_law;
|
||||
static constexpr SpecificationKey key{role, 0};
|
||||
};
|
||||
|
||||
template <> struct SpecificationTraits<surface::ConstantPressureSurface> {
|
||||
static constexpr std::string_view name = "IsobaricSurface";
|
||||
static constexpr SpecificationRole role = SpecificationRole::boundary_condition;
|
||||
static constexpr SpecificationKey key{role, 0};
|
||||
};
|
||||
|
||||
template <> struct SpecificationTraits<FixedTotalMass> {
|
||||
static constexpr std::string_view name = "FixedTotalMass";
|
||||
static constexpr SpecificationRole role = SpecificationRole::invariant;
|
||||
static constexpr SpecificationKey key{role, 0};
|
||||
};
|
||||
|
||||
template <> struct SpecificationTraits<FixedCentralDensity> {
|
||||
static constexpr std::string_view name = "FixedCentralDensity";
|
||||
static constexpr SpecificationRole role = SpecificationRole::phase_condition;
|
||||
static constexpr SpecificationKey key{role, 0};
|
||||
};
|
||||
|
||||
template <typename... Types> struct ModelTypeList final {
|
||||
static constexpr std::size_t size = sizeof...(Types);
|
||||
};
|
||||
|
||||
template <typename Query, typename List> struct ModelTypeListContains;
|
||||
|
||||
template <typename Query, typename... Types>
|
||||
struct ModelTypeListContains<Query, ModelTypeList<Types...>>
|
||||
: std::bool_constant<(std::same_as<Query, Types> || ...)> { };
|
||||
|
||||
template <typename Query, typename List>
|
||||
inline constexpr bool modelTypeListContains = ModelTypeListContains<Query, List>::value;
|
||||
|
||||
template <ModelSpecification Specification> struct ResidualFor final {
|
||||
using SpecificationType = Specification;
|
||||
|
||||
static constexpr std::size_t scalarArity = 1;
|
||||
};
|
||||
|
||||
template <ModelSpecification Specification> struct MultiplierFor final {
|
||||
using SpecificationType = Specification;
|
||||
|
||||
static constexpr std::size_t scalarArity = 1;
|
||||
};
|
||||
|
||||
template <ModelSpecification Specification> struct BorderFor final {
|
||||
using SpecificationType = Specification;
|
||||
|
||||
static constexpr std::size_t scalarArity = 1;
|
||||
};
|
||||
|
||||
template <ModelSpecification Specification> struct SpecificationContribution {
|
||||
using GeneratedValues = ModelTypeList<>;
|
||||
using GeneratedResiduals = ModelTypeList<>;
|
||||
|
||||
static constexpr bool isDefined = false;
|
||||
static constexpr bool hasRootCompiler = false;
|
||||
};
|
||||
|
||||
template <> struct SpecificationContribution<eos::Polytrope> {
|
||||
using GeneratedValues = ModelTypeList<>;
|
||||
using GeneratedResiduals = ModelTypeList<>;
|
||||
|
||||
static constexpr bool isDefined = true;
|
||||
static constexpr bool hasRootCompiler = true;
|
||||
};
|
||||
|
||||
template <> struct SpecificationContribution<surface::ConstantPressureSurface> {
|
||||
using GeneratedValues = ModelTypeList<>;
|
||||
using GeneratedResiduals = ModelTypeList<>;
|
||||
|
||||
static constexpr bool isDefined = true;
|
||||
static constexpr bool hasRootCompiler = true;
|
||||
};
|
||||
|
||||
template <> struct SpecificationContribution<FixedTotalMass> {
|
||||
using GeneratedValues = ModelTypeList<MultiplierFor<FixedTotalMass>>;
|
||||
using GeneratedResiduals = ModelTypeList<ResidualFor<FixedTotalMass>>;
|
||||
|
||||
static constexpr bool isDefined = true;
|
||||
static constexpr bool hasRootCompiler = true;
|
||||
};
|
||||
|
||||
template <> struct SpecificationContribution<FixedCentralDensity> {
|
||||
using GeneratedValues = ModelTypeList<BorderFor<FixedCentralDensity>>;
|
||||
using GeneratedResiduals = ModelTypeList<ResidualFor<FixedCentralDensity>>;
|
||||
|
||||
static constexpr bool isDefined = true;
|
||||
static constexpr bool hasRootCompiler = true;
|
||||
};
|
||||
|
||||
template <typename Candidate>
|
||||
concept ResolvedModelSpecification =
|
||||
ModelSpecification<Candidate> && SpecificationContribution<std::remove_cvref_t<Candidate>>::isDefined;
|
||||
|
||||
namespace detail {
|
||||
template <typename... Specifications> struct SpecificationSetStorage final {
|
||||
static constexpr std::size_t size = sizeof...(Specifications);
|
||||
};
|
||||
|
||||
template <typename... Lists> struct ConcatenateModelTypeLists;
|
||||
|
||||
template <> struct ConcatenateModelTypeLists<> {
|
||||
using Type = ModelTypeList<>;
|
||||
};
|
||||
|
||||
template <typename... Types> struct ConcatenateModelTypeLists<ModelTypeList<Types...>> {
|
||||
using Type = ModelTypeList<Types...>;
|
||||
};
|
||||
|
||||
template <typename... First, typename... Second, typename... Remaining>
|
||||
struct ConcatenateModelTypeLists<ModelTypeList<First...>, ModelTypeList<Second...>, Remaining...> {
|
||||
using Type = typename ConcatenateModelTypeLists<ModelTypeList<First..., Second...>, Remaining...>::Type;
|
||||
};
|
||||
|
||||
template <ModelSpecification Specification, typename Set> struct InsertSpecification;
|
||||
|
||||
template <ModelSpecification Specification>
|
||||
struct InsertSpecification<Specification, SpecificationSetStorage<>> {
|
||||
using Type = SpecificationSetStorage<Specification>;
|
||||
};
|
||||
|
||||
template <ModelSpecification Specification, ModelSpecification Head, ModelSpecification... Tail>
|
||||
struct InsertSpecification<Specification, SpecificationSetStorage<Head, Tail...>> {
|
||||
private:
|
||||
using InsertedTail = typename InsertSpecification<Specification, SpecificationSetStorage<Tail...>>::Type;
|
||||
|
||||
template <typename First, typename Rest> struct PrependSpecification;
|
||||
|
||||
template <typename First, ModelSpecification... Rest>
|
||||
struct PrependSpecification<First, SpecificationSetStorage<Rest...>> {
|
||||
using Type = SpecificationSetStorage<First, Rest...>;
|
||||
};
|
||||
|
||||
public:
|
||||
using Type = std::conditional_t<
|
||||
(SpecificationTraits<Specification>::key < SpecificationTraits<Head>::key),
|
||||
SpecificationSetStorage<Specification, Head, Tail...>,
|
||||
typename PrependSpecification<Head, InsertedTail>::Type>;
|
||||
};
|
||||
|
||||
template <typename Set, ModelSpecification... Specifications> struct CanonicalizeSpecifications;
|
||||
|
||||
template <typename Set> struct CanonicalizeSpecifications<Set> {
|
||||
using Type = Set;
|
||||
};
|
||||
|
||||
template <typename Set, ModelSpecification Head, ModelSpecification... Tail>
|
||||
struct CanonicalizeSpecifications<Set, Head, Tail...> {
|
||||
using Inserted = typename InsertSpecification<Head, Set>::Type;
|
||||
using Type = typename CanonicalizeSpecifications<Inserted, Tail...>::Type;
|
||||
};
|
||||
|
||||
template <ModelSpecification... Specifications>
|
||||
using CanonicalSpecificationSet =
|
||||
typename CanonicalizeSpecifications<SpecificationSetStorage<>, Specifications...>::Type;
|
||||
|
||||
template <
|
||||
ModelSpecification Head,
|
||||
ModelSpecification... Tail>
|
||||
consteval bool specificationKeyIsUnique() {
|
||||
return ((SpecificationTraits<Head>::key != SpecificationTraits<Tail>::key) && ...);
|
||||
}
|
||||
|
||||
template <ModelSpecification... Specifications> struct SpecificationKeysAreUnique;
|
||||
|
||||
template <> struct SpecificationKeysAreUnique<> : std::true_type { };
|
||||
|
||||
template <ModelSpecification Head, ModelSpecification... Tail>
|
||||
struct SpecificationKeysAreUnique<Head, Tail...>
|
||||
: std::bool_constant<
|
||||
specificationKeyIsUnique<Head, Tail...>() && SpecificationKeysAreUnique<Tail...>::value> { };
|
||||
|
||||
template <SpecificationRole Role, ModelSpecification... Specifications>
|
||||
inline constexpr std::size_t specificationRoleCount =
|
||||
(std::size_t{0} + ... + (SpecificationTraits<Specifications>::role == Role ? 1 : 0));
|
||||
|
||||
template <typename List> struct ModelTypeListScalarArity;
|
||||
|
||||
template <typename... Types>
|
||||
struct ModelTypeListScalarArity<ModelTypeList<Types...>>
|
||||
: std::integral_constant<std::size_t, (std::size_t{0} + ... + Types::scalarArity)> { };
|
||||
|
||||
template <typename Query, typename... Types>
|
||||
inline constexpr bool isOneOf = (std::same_as<Query, Types> || ...);
|
||||
|
||||
template <typename Query, typename... Types>
|
||||
inline constexpr std::size_t typeCount =
|
||||
(std::size_t{0} + ... +
|
||||
(std::same_as<Query, std::remove_cvref_t<Types>> ? std::size_t{1} : std::size_t{0}));
|
||||
|
||||
template <typename CanonicalSet, typename... Arguments> struct ArgumentsMatchCanonicalSpecifications;
|
||||
|
||||
template <ModelSpecification... CanonicalSpecifications, typename... Arguments>
|
||||
struct ArgumentsMatchCanonicalSpecifications<SpecificationSetStorage<CanonicalSpecifications...>, Arguments...>
|
||||
: std::bool_constant<
|
||||
sizeof...(CanonicalSpecifications) == sizeof...(Arguments) &&
|
||||
(isOneOf<std::remove_cvref_t<Arguments>, CanonicalSpecifications...> && ...) &&
|
||||
((typeCount<CanonicalSpecifications, Arguments...> == 1) && ...)> { };
|
||||
} // namespace detail
|
||||
|
||||
template <ModelSpecification... Specifications>
|
||||
inline constexpr bool specificationKeysAreUnique = detail::SpecificationKeysAreUnique<Specifications...>::value;
|
||||
|
||||
template <typename... Specifications>
|
||||
concept ValidModelSpecificationPack =
|
||||
(ResolvedModelSpecification<Specifications> && ...) && specificationKeysAreUnique<Specifications...> &&
|
||||
detail::specificationRoleCount<SpecificationRole::constitutive_law, Specifications...> == 1;
|
||||
|
||||
template <ModelSpecification... Specifications>
|
||||
requires specificationKeysAreUnique<Specifications...>
|
||||
using SpecificationSet = detail::CanonicalSpecificationSet<Specifications...>;
|
||||
|
||||
template <typename SpecificationSet> struct SpecificationOperatorSignature;
|
||||
|
||||
template <ModelSpecification... Specifications>
|
||||
struct SpecificationOperatorSignature<detail::SpecificationSetStorage<Specifications...>> final {
|
||||
using GeneratedValues = typename detail::ConcatenateModelTypeLists<
|
||||
typename SpecificationContribution<Specifications>::GeneratedValues...>::Type;
|
||||
|
||||
using GeneratedResiduals = typename detail::ConcatenateModelTypeLists<
|
||||
typename SpecificationContribution<Specifications>::GeneratedResiduals...>::Type;
|
||||
|
||||
static constexpr std::size_t generatedValueArity = detail::ModelTypeListScalarArity<GeneratedValues>::value;
|
||||
|
||||
static constexpr std::size_t generatedResidualArity =
|
||||
detail::ModelTypeListScalarArity<GeneratedResiduals>::value;
|
||||
|
||||
static constexpr bool symbolicallySquare = generatedValueArity == generatedResidualArity;
|
||||
};
|
||||
|
||||
template <ResolvedModelSpecification Specification>
|
||||
[[nodiscard]] consteval SpecificationDescriptor specificationDescriptor() {
|
||||
using Contribution = SpecificationContribution<Specification>;
|
||||
|
||||
return {
|
||||
.name = SpecificationTraits<Specification>::name,
|
||||
.role = SpecificationTraits<Specification>::role,
|
||||
.key = SpecificationTraits<Specification>::key,
|
||||
.generatedValueArity = detail::ModelTypeListScalarArity<typename Contribution::GeneratedValues>::value,
|
||||
.generatedResidualArity = detail::ModelTypeListScalarArity<typename Contribution::GeneratedResiduals>::value
|
||||
};
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
template <typename Specifications> class SpecifiedModel;
|
||||
|
||||
template <ModelSpecification... Specifications>
|
||||
class SpecifiedModel<SpecificationSetStorage<Specifications...>> final {
|
||||
public:
|
||||
using SpecificationTypes = SpecificationSetStorage<Specifications...>;
|
||||
using OperatorSignature = SpecificationOperatorSignature<SpecificationTypes>;
|
||||
|
||||
static constexpr bool symbolicallySquare = OperatorSignature::symbolicallySquare;
|
||||
static constexpr bool hasCompleteRootCompiler =
|
||||
(SpecificationContribution<Specifications>::hasRootCompiler && ...);
|
||||
static constexpr EquilibriumSystemCompilation compilationClass =
|
||||
symbolicallySquare && hasCompleteRootCompiler
|
||||
? EquilibriumSystemCompilation::complete_equilibrium_system
|
||||
: EquilibriumSystemCompilation::equation_contributions_only;
|
||||
|
||||
template <typename... Arguments>
|
||||
requires ArgumentsMatchCanonicalSpecifications<
|
||||
SpecificationTypes,
|
||||
Arguments...>::value
|
||||
explicit SpecifiedModel(Arguments &&...arguments)
|
||||
: m_specifications(
|
||||
std::get<Specifications>(
|
||||
std::tuple<std::remove_cvref_t<Arguments>...>{std::forward<Arguments>(arguments)...}
|
||||
)...
|
||||
) {
|
||||
}
|
||||
|
||||
template <ModelSpecification Specification>
|
||||
requires isOneOf<
|
||||
Specification,
|
||||
Specifications...>
|
||||
[[nodiscard]] const Specification &specification() const noexcept {
|
||||
return std::get<Specification>(m_specifications);
|
||||
}
|
||||
|
||||
template <ModelSpecification Specification>
|
||||
static constexpr bool containsSpecification = isOneOf<Specification, Specifications...>;
|
||||
|
||||
[[nodiscard]] static constexpr std::span<const RuntimeSpecificationDescriptor>
|
||||
runtimeSpecificationDescriptors() noexcept {
|
||||
return runtimeDescriptors;
|
||||
}
|
||||
|
||||
private:
|
||||
inline static constexpr std::array<RuntimeSpecificationDescriptor, sizeof...(Specifications)>
|
||||
runtimeDescriptors = [] {
|
||||
std::array<RuntimeSpecificationDescriptor, sizeof...(Specifications)> descriptors{};
|
||||
std::size_t index = 0;
|
||||
((descriptors[index] =
|
||||
{.specification = specificationDescriptor<Specifications>(),
|
||||
.canonicalIndex = index,
|
||||
.hasRootCompiler = SpecificationContribution<Specifications>::hasRootCompiler},
|
||||
++index),
|
||||
...);
|
||||
return descriptors;
|
||||
}();
|
||||
|
||||
std::tuple<Specifications...> m_specifications;
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
template <ModelSpecification... Specifications>
|
||||
requires ValidModelSpecificationPack<Specifications...> &&
|
||||
SpecificationOperatorSignature<SpecificationSet<Specifications...>>::symbolicallySquare
|
||||
using Model = detail::SpecifiedModel<SpecificationSet<Specifications...>>;
|
||||
|
||||
template <typename Candidate>
|
||||
concept SpecifiedModelType = requires {
|
||||
typename std::remove_cvref_t<Candidate>::SpecificationTypes;
|
||||
typename std::remove_cvref_t<Candidate>::OperatorSignature;
|
||||
requires std::remove_cvref_t<Candidate>::symbolicallySquare;
|
||||
{ std::remove_cvref_t<Candidate>::compilationClass } -> std::convertible_to<ModelCompilationClass>;
|
||||
{
|
||||
std::remove_cvref_t<Candidate>::runtimeSpecificationDescriptors()
|
||||
} -> std::same_as<std::span<const RuntimeSpecificationDescriptor>>;
|
||||
};
|
||||
|
||||
static_assert(ModelSpecification<eos::Polytrope>);
|
||||
static_assert(ModelSpecification<surface::ConstantPressureSurface>);
|
||||
static_assert(ModelSpecification<FixedTotalMass>);
|
||||
static_assert(ModelSpecification<FixedCentralDensity>);
|
||||
static_assert(ResolvedModelSpecification<eos::Polytrope>);
|
||||
static_assert(ResolvedModelSpecification<surface::ConstantPressureSurface>);
|
||||
static_assert(ResolvedModelSpecification<FixedTotalMass>);
|
||||
static_assert(ResolvedModelSpecification<FixedCentralDensity>);
|
||||
} // namespace mean_field::models
|
||||
|
||||
export namespace mean_field::integral {
|
||||
using FixedTotalMass = models::FixedTotalMass;
|
||||
}
|
||||
|
||||
export namespace mean_field::constraint {
|
||||
using FixedCentralDensity = models::FixedCentralDensity;
|
||||
}
|
||||
@@ -1,13 +1,12 @@
|
||||
module;
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <mfem.hpp>
|
||||
|
||||
export module mean_field:model.structure.polytropic;
|
||||
|
||||
export import :eos.polytrope;
|
||||
export import :model.structure.base;
|
||||
export import :seed.lane_emden;
|
||||
|
||||
import :utils.misc;
|
||||
|
||||
@@ -28,40 +27,6 @@ export namespace mean_field::models::structure {
|
||||
void validate() const;
|
||||
|
||||
private:
|
||||
struct LaneEmdenPoint {
|
||||
double coordinate{0.0};
|
||||
double value{0.0};
|
||||
double derivative{0.0};
|
||||
};
|
||||
|
||||
struct LaneEmdenDerivative {
|
||||
double value{0.0};
|
||||
double derivative{0.0};
|
||||
};
|
||||
|
||||
static void validateSeedRequest(const StructureSeedRequest &request);
|
||||
|
||||
[[nodiscard]] static LaneEmdenDerivative evaluateLaneEmdenRhs(
|
||||
double coordinate,
|
||||
double value,
|
||||
double derivative,
|
||||
double polytropicIndex
|
||||
);
|
||||
|
||||
[[nodiscard]] static LaneEmdenPoint takeLaneEmdenStep(
|
||||
const LaneEmdenPoint &point,
|
||||
double step,
|
||||
double polytropicIndex
|
||||
);
|
||||
|
||||
[[nodiscard]] static std::vector<LaneEmdenPoint> solveLaneEmden(double polytropicIndex);
|
||||
|
||||
[[nodiscard]] static double interpolateLaneEmdenValue(
|
||||
const std::vector<LaneEmdenPoint> &solution,
|
||||
double coordinate,
|
||||
std::size_t &lowerIndex
|
||||
);
|
||||
|
||||
eos::Polytrope m_equationOfState;
|
||||
double m_targetMass;
|
||||
};
|
||||
|
||||
66
libmeanfield/interface/models/typed_stellar_model.cppm
Normal file
66
libmeanfield/interface/models/typed_stellar_model.cppm
Normal file
@@ -0,0 +1,66 @@
|
||||
module;
|
||||
|
||||
#include <concepts>
|
||||
#include <cstddef>
|
||||
#include <span>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
export module mean_field:model.typed_stellar;
|
||||
|
||||
export import :model.specifications;
|
||||
|
||||
export namespace mean_field::model {
|
||||
template <typename SpecificationSet> class StellarModel;
|
||||
|
||||
template <models::ModelSpecification... CanonicalSpecifications>
|
||||
class StellarModel<models::detail::SpecificationSetStorage<CanonicalSpecifications...>> final {
|
||||
public:
|
||||
using SpecificationTypes = models::detail::SpecificationSetStorage<CanonicalSpecifications...>;
|
||||
using OperatorSignature = models::SpecificationOperatorSignature<SpecificationTypes>;
|
||||
using Storage = models::Model<CanonicalSpecifications...>;
|
||||
|
||||
static constexpr std::size_t specificationCount = sizeof...(CanonicalSpecifications);
|
||||
static constexpr bool symbolicallySquare = Storage::symbolicallySquare;
|
||||
static constexpr bool hasCompleteEquilibriumCompiler = Storage::hasCompleteRootCompiler;
|
||||
static constexpr models::EquilibriumSystemCompilation compilationClass = Storage::compilationClass;
|
||||
|
||||
template <typename... Arguments>
|
||||
requires std::constructible_from<
|
||||
Storage,
|
||||
Arguments...>
|
||||
explicit StellarModel(Arguments &&...arguments) : m_specifications(std::forward<Arguments>(arguments)...) {
|
||||
}
|
||||
|
||||
template <models::ModelSpecification Specification>
|
||||
requires Storage::template
|
||||
containsSpecification<Specification> [[nodiscard]] const Specification &specification() const noexcept {
|
||||
return m_specifications.template specification<Specification>();
|
||||
}
|
||||
|
||||
template <models::ModelSpecification Specification>
|
||||
static constexpr bool containsSpecification = Storage::template containsSpecification<Specification>;
|
||||
|
||||
[[nodiscard]] static constexpr std::span<const models::RuntimeSpecificationDescriptor>
|
||||
runtimeSpecificationDescriptors() noexcept {
|
||||
return Storage::runtimeSpecificationDescriptors();
|
||||
}
|
||||
|
||||
private:
|
||||
Storage m_specifications;
|
||||
};
|
||||
|
||||
template <models::ResolvedModelSpecification... Specifications>
|
||||
requires models::ValidModelSpecificationPack<std::remove_cvref_t<Specifications>...>
|
||||
StellarModel(Specifications &&...)
|
||||
-> StellarModel<models::SpecificationSet<std::remove_cvref_t<Specifications>...>>;
|
||||
|
||||
namespace detail {
|
||||
template <typename Candidate> struct IsStellarModel : std::false_type { };
|
||||
|
||||
template <typename SpecificationSet> struct IsStellarModel<StellarModel<SpecificationSet>> : std::true_type { };
|
||||
} // namespace detail
|
||||
|
||||
template <typename Candidate>
|
||||
concept StellarModelType = detail::IsStellarModel<std::remove_cvref_t<Candidate>>::value;
|
||||
} // namespace mean_field::model
|
||||
Reference in New Issue
Block a user