feat(field-support): added field support system, mid migration
currently the barotope and the pressure force operator are migrated to the new support system
This commit is contained in:
114
libmeanfield/interface/models/stellar_model.cppm
Normal file
114
libmeanfield/interface/models/stellar_model.cppm
Normal file
@@ -0,0 +1,114 @@
|
||||
module;
|
||||
|
||||
#include <concepts>
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
export module mean_field:model.stellar;
|
||||
|
||||
export import :eos.base;
|
||||
export import :model.structure.base;
|
||||
export import :surface.base;
|
||||
|
||||
export namespace mean_field::models {
|
||||
template <typename Candidate>
|
||||
concept StructurePrescription =
|
||||
std::derived_from<std::remove_cvref_t<Candidate>, mean_field::models::structure::StructureBase>;
|
||||
|
||||
template <typename Candidate>
|
||||
concept SurfacePrescription = std::derived_from<std::remove_cvref_t<Candidate>, mean_field::surface::SurfaceBase>;
|
||||
|
||||
/*
|
||||
* Public ownership facade for a physical structure prescription and its
|
||||
* stellar-surface prescription.
|
||||
*
|
||||
* The concrete prescriptions are allocated once at construction. Their
|
||||
* stable addresses allow future prepared operators and contexts to borrow
|
||||
* references without making ownership part of the user-facing API.
|
||||
*/
|
||||
class StellarModel final {
|
||||
public:
|
||||
template <
|
||||
StructurePrescription StructureType,
|
||||
SurfacePrescription SurfaceType>
|
||||
explicit StellarModel(
|
||||
StructureType &&structurePrescription,
|
||||
SurfaceType &&surfacePrescription
|
||||
)
|
||||
: StellarModel(
|
||||
std::make_unique<std::remove_cvref_t<StructureType>>(
|
||||
std::forward<StructureType>(structurePrescription)
|
||||
),
|
||||
std::make_unique<std::remove_cvref_t<SurfaceType>>(std::forward<SurfaceType>(surfacePrescription))
|
||||
) {
|
||||
}
|
||||
|
||||
~StellarModel() = default;
|
||||
|
||||
StellarModel(const StellarModel &) = delete;
|
||||
|
||||
StellarModel &operator=(const StellarModel &) = delete;
|
||||
|
||||
StellarModel(StellarModel &&) noexcept = default;
|
||||
|
||||
StellarModel &operator=(StellarModel &&) noexcept = default;
|
||||
|
||||
[[nodiscard]] const mean_field::models::structure::StructureBase &structurePrescription() const noexcept {
|
||||
return *m_structurePrescription;
|
||||
}
|
||||
|
||||
[[nodiscard]] const mean_field::surface::SurfaceBase &surfacePrescription() const noexcept {
|
||||
return *m_surfacePrescription;
|
||||
}
|
||||
|
||||
[[nodiscard]] const mean_field::eos::EquationOfState &equationOfState() const noexcept {
|
||||
return m_structurePrescription->equationOfState();
|
||||
}
|
||||
|
||||
[[nodiscard]] double targetMass() const noexcept {
|
||||
return m_structurePrescription->targetMass();
|
||||
}
|
||||
|
||||
[[nodiscard]] mean_field::models::structure::StructureSeed
|
||||
makeInitialSeed(const mean_field::models::structure::StructureSeedRequest &request) const {
|
||||
return m_structurePrescription->makeInitialSeed(request);
|
||||
}
|
||||
|
||||
[[nodiscard]] const mean_field::surface::ResolvedSurfaceCondition &resolvedSurfaceCondition() const noexcept {
|
||||
return m_resolvedSurfaceCondition;
|
||||
}
|
||||
|
||||
private:
|
||||
explicit StellarModel(
|
||||
std::unique_ptr<mean_field::models::structure::StructureBase> structurePrescription,
|
||||
std::unique_ptr<mean_field::surface::SurfaceBase> surfacePrescription
|
||||
)
|
||||
: m_structurePrescription(std::move(structurePrescription)),
|
||||
m_surfacePrescription(std::move(surfacePrescription)),
|
||||
m_resolvedSurfaceCondition(validateAndResolve(
|
||||
*m_structurePrescription,
|
||||
*m_surfacePrescription
|
||||
)) {
|
||||
}
|
||||
|
||||
[[nodiscard]] static mean_field::surface::ResolvedSurfaceCondition validateAndResolve(
|
||||
const mean_field::models::structure::StructureBase &structurePrescription,
|
||||
const mean_field::surface::SurfaceBase &surfacePrescription
|
||||
) {
|
||||
structurePrescription.validate();
|
||||
|
||||
const mean_field::eos::EquationOfState &equationOfState = structurePrescription.equationOfState();
|
||||
|
||||
surfacePrescription.validate(equationOfState);
|
||||
|
||||
return surfacePrescription.resolve(equationOfState);
|
||||
}
|
||||
|
||||
std::unique_ptr<mean_field::models::structure::StructureBase> m_structurePrescription;
|
||||
|
||||
std::unique_ptr<mean_field::surface::SurfaceBase> m_surfacePrescription;
|
||||
|
||||
mean_field::surface::ResolvedSurfaceCondition m_resolvedSurfaceCondition;
|
||||
};
|
||||
} // namespace mean_field::models
|
||||
68
libmeanfield/interface/models/structure/polytropic.cppm
Normal file
68
libmeanfield/interface/models/structure/polytropic.cppm
Normal file
@@ -0,0 +1,68 @@
|
||||
module;
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <mfem.hpp>
|
||||
|
||||
export module mean_field:model.structure.polytropic;
|
||||
|
||||
export import :eos.polytrope;
|
||||
export import :model.structure.base;
|
||||
|
||||
import :utils.misc;
|
||||
|
||||
export namespace mean_field::models::structure {
|
||||
class PolytropicStructure final : public StructureBase {
|
||||
public:
|
||||
explicit PolytropicStructure(
|
||||
eos::Polytrope equationOfState,
|
||||
double targetMass
|
||||
);
|
||||
|
||||
[[nodiscard]] const eos::EquationOfState &equationOfState() const noexcept override;
|
||||
|
||||
[[nodiscard]] double targetMass() const noexcept override;
|
||||
|
||||
[[nodiscard]] StructureSeed makeInitialSeed(const StructureSeedRequest &request) const override;
|
||||
|
||||
void validate() const override;
|
||||
|
||||
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;
|
||||
};
|
||||
} // namespace mean_field::models::structure
|
||||
37
libmeanfield/interface/models/structure/structure_base.cppm
Normal file
37
libmeanfield/interface/models/structure/structure_base.cppm
Normal file
@@ -0,0 +1,37 @@
|
||||
module;
|
||||
#include <mfem.hpp>
|
||||
export module mean_field:model.structure.base;
|
||||
export import :eos.base;
|
||||
|
||||
export namespace mean_field::models::structure {
|
||||
struct StructureSeed {
|
||||
mfem::Vector radius;
|
||||
mfem::Vector density;
|
||||
mfem::Vector enthalpy;
|
||||
|
||||
double stellarRadius;
|
||||
double centralDensity;
|
||||
double centralEnthalpy;
|
||||
};
|
||||
|
||||
struct StructureSeedRequest {
|
||||
double centralDensity;
|
||||
int radialSampleCount{512};
|
||||
};
|
||||
|
||||
class StructureBase {
|
||||
public:
|
||||
virtual ~StructureBase() = default;
|
||||
|
||||
[[nodiscard]] virtual const eos::EquationOfState &equationOfState() const noexcept = 0;
|
||||
|
||||
[[nodiscard]] virtual double targetMass() const noexcept = 0;
|
||||
|
||||
[[nodiscard]] virtual StructureSeed makeInitialSeed(const StructureSeedRequest &request) const = 0;
|
||||
|
||||
virtual void validate() const = 0;
|
||||
|
||||
protected:
|
||||
StructureBase() = default;
|
||||
};
|
||||
} // namespace mean_field::models::structure
|
||||
146
libmeanfield/interface/models/structure_profile.cppm
Normal file
146
libmeanfield/interface/models/structure_profile.cppm
Normal file
@@ -0,0 +1,146 @@
|
||||
module;
|
||||
#include <mfem.hpp>
|
||||
|
||||
export module mean_field:model.structure_profile;
|
||||
export import :fem;
|
||||
|
||||
export namespace mean_field::models {
|
||||
constexpr double DEFAULT_COLATITUDE_DEGREES = 90;
|
||||
constexpr double DEFAULT_LONGITUDE_DEGREES = 0;
|
||||
|
||||
struct RadialDirection {
|
||||
double coLatitudeDegrees{DEFAULT_COLATITUDE_DEGREES};
|
||||
double longitudeDegrees{DEFAULT_LONGITUDE_DEGREES};
|
||||
|
||||
[[nodiscard]] mfem::Vector toUnitCartesian() const;
|
||||
};
|
||||
|
||||
struct RadialProfile {
|
||||
double coLatitudeDegrees;
|
||||
double longitudeDegrees;
|
||||
|
||||
mfem::Vector radius;
|
||||
mfem::Vector param;
|
||||
};
|
||||
|
||||
struct SliceProfile {
|
||||
double radius;
|
||||
std::array<double, 2> normal;
|
||||
|
||||
mfem::GridFunction param;
|
||||
};
|
||||
|
||||
class StructureProfile {
|
||||
public:
|
||||
explicit StructureProfile(
|
||||
const fem::FEM &fem,
|
||||
mfem::Vector state
|
||||
);
|
||||
|
||||
// Profiles
|
||||
mfem::GridFunction pressureProfile();
|
||||
mfem::GridFunction densityProfile();
|
||||
mfem::GridFunction gravitationalPotentialProfile();
|
||||
mfem::GridFunction gravitationalFieldProfile();
|
||||
mfem::GridFunction enthalpyProfile();
|
||||
mfem::GridFunction entropyProfile();
|
||||
mfem::GridFunction temperatureProfile();
|
||||
mfem::GridFunction internalEnergyProfile();
|
||||
|
||||
// Local Evaluation
|
||||
double pressureAt(const mfem::Vector &position);
|
||||
double densityAt(const mfem::Vector &position);
|
||||
double gravitationalPotentialAt(const mfem::Vector &position);
|
||||
mfem::Vector gravitationalFieldAt(const mfem::Vector &position);
|
||||
double enthalpyAt(const mfem::Vector &position);
|
||||
double entropyAt(const mfem::Vector &position);
|
||||
double temperatureAt(const mfem::Vector &position);
|
||||
double internalEnergyAt(const mfem::Vector &position);
|
||||
|
||||
// Radial helpers
|
||||
mfem::Vector radius(RadialDirection direction = {});
|
||||
|
||||
RadialProfile radialPressureProfile(RadialDirection direction = {});
|
||||
RadialProfile radialDensityProfile(RadialDirection direction = {});
|
||||
RadialProfile radialGravitationalPotentialProfile(RadialDirection direction = {});
|
||||
RadialProfile radialGravitationalFieldProfile(RadialDirection direction = {});
|
||||
RadialProfile radialEnthalpyProfile(RadialDirection direction = {});
|
||||
RadialProfile radialEntropyProfile(RadialDirection direction = {});
|
||||
RadialProfile radialTemperatureProfile(RadialDirection direction = {});
|
||||
RadialProfile radialInternalEnergyProfile(RadialDirection direction = {});
|
||||
|
||||
// Ellipsoidal Slices
|
||||
SliceProfile slicePressureProfile(
|
||||
double radius,
|
||||
const std::array<
|
||||
double,
|
||||
2> &normal
|
||||
);
|
||||
SliceProfile sliceDensityProfile(
|
||||
double radius,
|
||||
const std::array<
|
||||
double,
|
||||
2> &normal
|
||||
);
|
||||
SliceProfile sliceGravitationalPotentialProfile(
|
||||
double radius,
|
||||
const std::array<
|
||||
double,
|
||||
2> &normal
|
||||
);
|
||||
SliceProfile sliceGravitationalFieldProfile(
|
||||
double radius,
|
||||
const std::array<
|
||||
double,
|
||||
2> &normal
|
||||
);
|
||||
SliceProfile sliceEnthalpyProfile(
|
||||
double radius,
|
||||
const std::array<
|
||||
double,
|
||||
2> &normal
|
||||
);
|
||||
SliceProfile sliceEntropyProfile(
|
||||
double radius,
|
||||
const std::array<
|
||||
double,
|
||||
2> &normal
|
||||
);
|
||||
SliceProfile sliceTemperatureProfile(
|
||||
double radius,
|
||||
const std::array<
|
||||
double,
|
||||
2> &normal
|
||||
);
|
||||
SliceProfile sliceInternalEnergyProfile(
|
||||
double radius,
|
||||
const std::array<
|
||||
double,
|
||||
2> &normal
|
||||
);
|
||||
|
||||
// Integral Constraints
|
||||
double totalMass();
|
||||
double virialRatio();
|
||||
|
||||
// Diagnostics
|
||||
bool isBound();
|
||||
|
||||
// IO
|
||||
void radialToCSV(
|
||||
const std::string &filename,
|
||||
RadialDirection direction = {}
|
||||
);
|
||||
void radialToBIN(
|
||||
const std::string &filename,
|
||||
RadialDirection direction = {}
|
||||
);
|
||||
void toBIN(const std::string &filename);
|
||||
|
||||
private:
|
||||
const fem::FEM &m_fem;
|
||||
const mfem::Vector m_state;
|
||||
};
|
||||
|
||||
StructureProfile StructureProfileFromBIN(const std::string &filename);
|
||||
} // namespace mean_field::models
|
||||
Reference in New Issue
Block a user