Files
meson-mfem/src/lib/serif/eos/models/polytropic.cpp
Emily Boudreaux d1f59d6d70 feat(mean_field): added dimensions, discritization, and start of eos
The full rewrite of mean_field into something maintainable is progressing. dimensions is mostly done, discritization (domain, blocks, and fields) is done, and eos is progressing quickly
2026-09-15 10:42:00 -04:00

147 lines
6.2 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "serif/eos/models/polytropic.hpp"
#include "serif/utils/misc/finite.hpp"
#include "serif/eos/exceptions.hpp"
namespace serif::eos::models {
using utils::misc::validate_finite;
using utils::misc::validate_greater_than;
using utils::misc::validate_less_than;
using utils::misc::validate_nonnegativity;
using namespace dimensions;
using namespace relations;
Polytrope::Polytrope(const PolytropeParameters& parameters) : Polytrope(parameters.n, parameters.K) {}
Polytrope::Polytrope(const double n, const double K):
m_polytropic_index(n),
m_polytropic_constant(K),
m_enthalpy_scale((n + 1.0) * K) {
validate_finite<EOSEvaluationError>(m_polytropic_index, EOSEvaluationErrorCode::outside_domain);
validate_greater_than<EOSEvaluationError>(m_polytropic_index, 1.0, EOSEvaluationErrorCode::outside_domain);
validate_finite<EOSEvaluationError>(m_polytropic_constant, EOSEvaluationErrorCode::outside_domain);
validate_greater_than<EOSEvaluationError>(m_polytropic_constant, 0.0, EOSEvaluationErrorCode::outside_domain);
}
[[nodiscard]] double Polytrope::polytropic_index() const noexcept {
return m_polytropic_index;
}
[[nodiscard]] double Polytrope::polytropic_constant() const noexcept {
return m_polytropic_constant;
}
[[nodiscard]] double Polytrope::enthalpy_scale() const noexcept {
return m_enthalpy_scale;
}
[[nodiscard]] PressureValue Polytrope::evaluate(PressureFromDensity, const DensityValue density) const {
validate_nonnegativity<EOSEvaluationError>(density.value(), EOSEvaluationErrorCode::invalid_thermodynamic_input);
if (density.value() == 0.0) {
// P = 0
return PressureValue{0.0};
}
// P = K * (ρ)^(1 + 1/n)
return PressureValue{
m_polytropic_constant * std::pow(density.value(), 1.0 + 1.0 / m_polytropic_index)
};
}
[[nodiscard]] SpecificEnthalpyValue Polytrope::evaluate(SpecificEnthalpyFromDensity, const DensityValue density) const {
validate_nonnegativity<EOSEvaluationError>(density.value(), EOSEvaluationErrorCode::invalid_thermodynamic_input);
if (density.value() == 0.0) {
// h = 0
return SpecificEnthalpyValue{0.0};
}
// h = hs * (ρ)^(1/n)
return SpecificEnthalpyValue{
m_enthalpy_scale * std::pow(density.value(), 1.0 / m_polytropic_index)
};
}
[[nodiscard]] DensityValue Polytrope::evaluate(DensityFromSpecificEnthalpy, SpecificEnthalpyValue specific_enthalpy) const {
validate_finite<EOSEvaluationError>(specific_enthalpy.value(), EOSEvaluationErrorCode::invalid_thermodynamic_input);
if (specific_enthalpy.value() <= 0.0) {
// ρ = 0
return DensityValue{0.0};
}
// ρ = (h/hs)^n
return DensityValue{std::pow(specific_enthalpy.value() / m_enthalpy_scale, m_polytropic_index)};
}
[[nodiscard]] PressureValue Polytrope::evaluate(PressureFromSpecificEnthalpy, SpecificEnthalpyValue specific_enthalpy) const {
const DensityValue density = evaluate(DensityFromSpecificEnthalpy{}, specific_enthalpy);
if (specific_enthalpy.value() <= 0.0) {
// P = 0
return PressureValue{0.0};
}
// P = ρ * h / (n + 1)
return PressureValue{density.value() * specific_enthalpy.value()/ (m_polytropic_index + 1.0)};
}
[[nodiscard]] SpecificEnthalpyValue Polytrope::evaluate(SpecificEnthalpyFromPressure, PressureValue pressure) const {
validate_nonnegativity<EOSEvaluationError>(pressure.value(), EOSEvaluationErrorCode::invalid_thermodynamic_input);
if (pressure.value() == 0.0) {
// h = 0
return SpecificEnthalpyValue{0.0};
}
const double indexPlusOne = m_polytropic_index + 1.0;
// h = (n+1) * (K^(n/(n+1))) * (P^(1/(n+1)))
return SpecificEnthalpyValue{
indexPlusOne * std::pow(m_polytropic_constant, m_polytropic_index / indexPlusOne) *
std::pow(pressure.value(), 1.0 / indexPlusOne)
};
}
[[nodiscard]] PartialDerivative<Density, SpecificEnthalpy> Polytrope::partial_derivative(DensityFromSpecificEnthalpy, WithRespectTo<SpecificEnthalpy>, const SpecificEnthalpyValue specific_enthalpy) const {
validate_finite<EOSEvaluationError>(specific_enthalpy.value(), EOSEvaluationErrorCode::invalid_thermodynamic_input);
if (specific_enthalpy.value() < 0.0) {
// dρ/dh = 0
return PartialDerivative<Density, SpecificEnthalpy>{0.0};
}
if (specific_enthalpy.value() == 0.0) {
// dρ/dh = n == 1 -> 1/hs
// dρ/dh = else -> 0
return PartialDerivative<Density, SpecificEnthalpy>{
m_polytropic_index == 1.0 ? 1.0 / m_enthalpy_scale : 0.0
};
}
// dρ/dh = (n/hs) * (h/hs)^(n-1)
return PartialDerivative<Density, SpecificEnthalpy>{
m_polytropic_index / m_enthalpy_scale * std::pow(specific_enthalpy.value() / m_enthalpy_scale, m_polytropic_index - 1.0)
};
}
[[nodiscard]] PartialDerivative<Pressure, SpecificEnthalpy> Polytrope::partial_derivative(PressureFromSpecificEnthalpy, WithRespectTo<SpecificEnthalpy>, const SpecificEnthalpyValue specific_enthalpy) const {
const DensityValue density = evaluate(DensityFromSpecificEnthalpy{}, specific_enthalpy);
// dP/dh = ρ
return PartialDerivative<Pressure, SpecificEnthalpy>{density.value()};
}
[[nodiscard]] PartialDerivative<Pressure, Density> Polytrope::partial_derivative(PressureFromDensity, WithRespectTo<Density>, const DensityValue density) const {
validate_nonnegativity<EOSEvaluationError>(density.value(), EOSEvaluationErrorCode::invalid_thermodynamic_input);
if (density.value() == 0.0) {
// dP/dρ = 0
return PartialDerivative<Pressure, Density>{0.0};
}
// dP/dρ = K * (1 + 1/n) * (ρ)^(1/n)
return PartialDerivative<Pressure, Density>{
m_polytropic_constant * (1.0 + 1.0 / m_polytropic_index) * std::pow(density.value(), 1.0 / m_polytropic_index)
};
}
}