feat(surface): major work on implementing surface constraints in a presciption agnostic manner
This commit is contained in:
@@ -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
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user