feat(surface): major work on implementing surface constraints in a presciption agnostic manner

This commit is contained in:
2026-08-30 16:41:14 -04:00
parent 36adfa1174
commit 0a7f18c5c7
95 changed files with 30144 additions and 25766 deletions

View File

@@ -3,11 +3,18 @@ module;
#include <format>
#include <stdexcept>
export module mean_field:eos.polytrope;
export import :eos.base;
export import :eos.evaluation;
export namespace mean_field::eos {
class Polytrope final : public EquationOfState {
class Polytrope final {
public:
using Relations = RelationCatalog<
PressureFromDensity,
PressureFromSpecificEnthalpy,
SpecificEnthalpyFromDensity,
SpecificEnthalpyFromPressure,
DensityFromSpecificEnthalpy>;
Polytrope(
const double polytropic_index,
const double polytropic_constant
@@ -49,82 +56,128 @@ export namespace mean_field::eos {
return m_enthalpy_scale;
}
[[nodiscard]] double pressure_from_density(const double density) const override {
validate_nonnegativity(density, "density");
if (density == 0.0) {
return 0.0;
[[nodiscard]] PressureValue evaluate(
PressureFromDensity,
const DensityValue density
) const {
validate_nonnegativity(density.value(), "density");
if (density.value() == 0.0) {
return PressureValue{0.0};
}
return m_polytropic_constant * std::pow(density, 1.0 + 1.0 / m_polytropic_index);
return PressureValue{m_polytropic_constant * std::pow(density.value(), 1.0 + 1.0 / m_polytropic_index)};
}
[[nodiscard]] double enthalpy_from_density(const double density) const override {
validate_nonnegativity(density, "density");
if (density == 0.0) {
return 0.0;
[[nodiscard]] SpecificEnthalpyValue evaluate(
SpecificEnthalpyFromDensity,
const DensityValue density
) const {
validate_nonnegativity(density.value(), "density");
if (density.value() == 0.0) {
return SpecificEnthalpyValue{0.0};
}
return m_enthalpy_scale * std::pow(density, 1.0 / m_polytropic_index);
return SpecificEnthalpyValue{m_enthalpy_scale * std::pow(density.value(), 1.0 / m_polytropic_index)};
}
[[nodiscard]] double density_from_enthalpy(const double enthalpy) const override {
validate_finite(enthalpy, "enthalpy");
[[nodiscard]] DensityValue evaluate(
DensityFromSpecificEnthalpy,
const SpecificEnthalpyValue specificEnthalpy
) const {
validate_finite(specificEnthalpy.value(), "specific enthalpy");
if (enthalpy <= 0.0) {
return 0.0;
if (specificEnthalpy.value() <= 0.0) {
return DensityValue{0.0};
}
return std::pow(enthalpy / m_enthalpy_scale, m_polytropic_index);
return DensityValue{std::pow(specificEnthalpy.value() / m_enthalpy_scale, m_polytropic_index)};
}
[[nodiscard]] double pressure_from_enthalpy(const double enthalpy) const override {
validate_finite(enthalpy, "enthalpy");
[[nodiscard]] PressureValue evaluate(
PressureFromSpecificEnthalpy,
const SpecificEnthalpyValue specificEnthalpy
) const {
const DensityValue density = evaluate(DensityFromSpecificEnthalpy{}, specificEnthalpy);
if (enthalpy <= 0.0) {
return 0.0;
if (specificEnthalpy.value() <= 0.0) {
return PressureValue{0.0};
}
return density_from_enthalpy(enthalpy) * enthalpy / (m_polytropic_index + 1.0);
return PressureValue{density.value() * specificEnthalpy.value() / (m_polytropic_index + 1.0)};
}
[[nodiscard]] double density_derivative_from_enthalpy(const double enthalpy) const override {
validate_finite(enthalpy, "enthalpy");
if (enthalpy < 0.0) {
return 0.0;
[[nodiscard]] SpecificEnthalpyValue evaluate(
SpecificEnthalpyFromPressure,
const PressureValue pressure
) const {
validate_nonnegativity(pressure.value(), "pressure");
if (pressure.value() == 0.0) {
return SpecificEnthalpyValue{0.0};
}
if (enthalpy == 0.0) {
return m_polytropic_index == 1.0 ? 1.0 / m_enthalpy_scale : 0.0;
}
const double indexPlusOne = m_polytropic_index + 1.0;
return m_polytropic_index / m_enthalpy_scale *
std::pow(enthalpy / m_enthalpy_scale, m_polytropic_index - 1.0);
return SpecificEnthalpyValue{
indexPlusOne * std::pow(m_polytropic_constant, m_polytropic_index / indexPlusOne) *
std::pow(pressure.value(), 1.0 / indexPlusOne)
};
}
[[nodiscard]] double pressure_derivative_from_enthalpy(const double enthalpy) const override {
validate_finite(enthalpy, "enthalpy");
if (enthalpy <= 0.0) {
return 0.0;
[[nodiscard]] PartialDerivative<
quantity::Density,
quantity::SpecificEnthalpy>
partialDerivative(
DensityFromSpecificEnthalpy,
WithRespectTo<quantity::SpecificEnthalpy>,
const SpecificEnthalpyValue specificEnthalpy
) const {
validate_finite(specificEnthalpy.value(), "specific enthalpy");
if (specificEnthalpy.value() < 0.0) {
return PartialDerivative<quantity::Density, quantity::SpecificEnthalpy>{0.0};
}
return density_from_enthalpy(enthalpy);
}
[[nodiscard]] double pressure_derivative_from_density(const double density) const override {
validate_nonnegativity(density, "density");
if (density == 0.0) {
return 0.0;
if (specificEnthalpy.value() == 0.0) {
return PartialDerivative<quantity::Density, quantity::SpecificEnthalpy>{
m_polytropic_index == 1.0 ? 1.0 / m_enthalpy_scale : 0.0
};
}
return m_polytropic_constant * (1.0 + 1.0 / m_polytropic_index) *
std::pow(density, 1.0 / m_polytropic_index);
return PartialDerivative<quantity::Density, quantity::SpecificEnthalpy>{
m_polytropic_index / m_enthalpy_scale *
std::pow(specificEnthalpy.value() / m_enthalpy_scale, m_polytropic_index - 1.0)
};
}
[[nodiscard]] double enthalpy_from_pressure(const double pressure) const override {
validate_nonnegativity(pressure, "pressure");
const double np1 = m_polytropic_index + 1;
return np1 * std::pow(m_polytropic_constant, m_polytropic_index / np1) * std::pow(pressure, 1.0 / np1);
[[nodiscard]] PartialDerivative<
quantity::Pressure,
quantity::SpecificEnthalpy>
partialDerivative(
PressureFromSpecificEnthalpy,
WithRespectTo<quantity::SpecificEnthalpy>,
const SpecificEnthalpyValue specificEnthalpy
) const {
const DensityValue density = evaluate(DensityFromSpecificEnthalpy{}, specificEnthalpy);
return PartialDerivative<quantity::Pressure, quantity::SpecificEnthalpy>{density.value()};
}
[[nodiscard]] PartialDerivative<
quantity::Pressure,
quantity::Density>
partialDerivative(
PressureFromDensity,
WithRespectTo<quantity::Density>,
const DensityValue density
) const {
validate_nonnegativity(density.value(), "density");
if (density.value() == 0.0) {
return PartialDerivative<quantity::Pressure, quantity::Density>{0.0};
}
return PartialDerivative<quantity::Pressure, quantity::Density>{
m_polytropic_constant * (1.0 + 1.0 / m_polytropic_index) *
std::pow(density.value(), 1.0 / m_polytropic_index)
};
}
private:
@@ -133,12 +186,12 @@ export namespace mean_field::eos {
const char *quantity
) {
if (!std::isfinite(value)) {
throw std::domain_error(
std::format(
"The {} must be finite. Instead a value of {} has been "
"provided",
quantity, value
)
throw EvaluationError(
EvaluationErrorCode::nonfinite_input, std::format(
"The {} must be finite. Instead a value of {} has been "
"provided",
quantity, value
)
);
}
}
@@ -149,13 +202,13 @@ export namespace mean_field::eos {
) {
validate_finite(value, quantity);
if (value < 0.0) {
throw std::domain_error(
std::format(
"The {} must be non-negative. Instead a value of {} "
"has been "
"provided",
quantity, value
)
throw EvaluationError(
EvaluationErrorCode::outside_domain, std::format(
"The {} must be non-negative. Instead a value of {} "
"has been "
"provided",
quantity, value
)
);
}
}