polytropic.cpp serif/eos/models/polytropic.hpp serif/utils/misc/finite.hpp serif/eos/exceptions.hpp serif/utils/error/codes.hpp serif serif::eos serif::eos::models #include"serif/eos/models/polytropic.hpp" #include"serif/utils/misc/finite.hpp" #include"serif/eos/exceptions.hpp" #include"serif/utils/error/codes.hpp" namespaceserif::eos::models{ usingutils::misc::validate_finite; usingutils::misc::validate_greater_than; usingutils::misc::validate_less_than; usingutils::misc::validate_nonnegativity; usingutils::errors::SERiFErrorCode; usingnamespacedimensions; usingnamespacerelations; Polytrope::Polytrope(constPolytropeParameters&parameters):Polytrope(parameters.n,parameters.K){} Polytrope::Polytrope(constdoublen,constdoubleK): m_polytropic_index(n), m_polytropic_constant(K), m_enthalpy_scale((n+1.0)*K){ validate_finite<EOSEvaluationError,SERiFErrorCode::EOS_OUTSIDE_DOMAIN>(m_polytropic_index); validate_greater_than<EOSEvaluationError,SERiFErrorCode::EOS_OUTSIDE_DOMAIN>(m_polytropic_index,1.0); validate_finite<EOSEvaluationError,SERiFErrorCode::EOS_OUTSIDE_DOMAIN>(m_polytropic_constant); utils::errors::serif_ensure<SERiFErrorCode::EOS_OUTSIDE_DOMAIN,EOSEvaluationError>(m_polytropic_constant>0.0,"Thepolytropicconstantmustbepositive.Received{}.",m_polytropic_constant); } [[nodiscard]]doublePolytrope::polytropic_index()constnoexcept{ returnm_polytropic_index; } [[nodiscard]]doublePolytrope::polytropic_constant()constnoexcept{ returnm_polytropic_constant; } [[nodiscard]]doublePolytrope::enthalpy_scale()constnoexcept{ returnm_enthalpy_scale; } [[nodiscard]]PressureValuePolytrope::evaluate(PressureFromDensity,constDensityValuedensity)const{ validate_nonnegativity<EOSEvaluationError,SERiFErrorCode::EOS_INVALID_THERMODYNAMIC_INPUT>(density.value()); if(density.value()==0.0){ //P=0 returnPressureValue{0.0}; } //P=K*(ρ)^(1+1/n) returnPressureValue{ m_polytropic_constant*std::pow(density.value(),1.0+1.0/m_polytropic_index) }; } [[nodiscard]]DensityValuePolytrope::evaluate(DensityFromPressure,constPressureValuepressure)const{ validate_nonnegativity<EOSEvaluationError,SERiFErrorCode::EOS_INVALID_THERMODYNAMIC_INPUT>(pressure.value()); if(pressure.value()==0.0){ returnDensityValue{0.0}; } returnDensityValue{std::pow(pressure.value()/m_polytropic_constant,m_polytropic_index/(m_polytropic_index+1.0))}; } [[nodiscard]]SecondPartialDerivative<Pressure,MassDensity,MassDensity>Polytrope::second_partial_derivative( PressureFromDensity,WithRespectTo<MassDensity>,WithRespectTo<MassDensity>,constDensityValuedensity )const{ validate_nonnegativity<EOSEvaluationError,SERiFErrorCode::EOS_INVALID_THERMODYNAMIC_INPUT>(density.value()); utils::errors::serif_ensure<SERiFErrorCode::EOS_INVALID_THERMODYNAMIC_INPUT,EOSEvaluationError>( density.value()>0.0||m_polytropic_index==1.0, "Thesecondpressurederivativeissingularatzerodensityforpolytropicindex{}.ApplythevacuumdensitytracedirectlyandevaluatebulkNewtoncoefficientsonlyatpositivedensity.", m_polytropic_index); constdoubleexponent=1.0/m_polytropic_index; returnSecondPartialDerivative<Pressure,MassDensity,MassDensity>{ m_polytropic_constant*(1.0+exponent)*exponent*std::pow(density.value(),exponent-1.0)}; } [[nodiscard]]SpecificEnthalpyValuePolytrope::evaluate(SpecificEnthalpyFromDensity,constDensityValuedensity)const{ validate_nonnegativity<EOSEvaluationError,SERiFErrorCode::EOS_INVALID_THERMODYNAMIC_INPUT>(density.value()); if(density.value()==0.0){ //h=0 returnSpecificEnthalpyValue{0.0}; } //h=hs*(ρ)^(1/n) returnSpecificEnthalpyValue{ m_enthalpy_scale*std::pow(density.value(),1.0/m_polytropic_index) }; } [[nodiscard]]BarotropicPressurePotentialValuePolytrope::evaluate(PressurePotentialFromDensity,constDensityValuedensity)const{ returnBarotropicPressurePotentialValue{evaluate(SpecificEnthalpyFromDensity{},density).value()}; } [[nodiscard]]DensityValuePolytrope::evaluate(DensityFromSpecificEnthalpy,SpecificEnthalpyValuespecific_enthalpy)const{ validate_finite<EOSEvaluationError,SERiFErrorCode::EOS_INVALID_THERMODYNAMIC_INPUT>(specific_enthalpy.value()); if(specific_enthalpy.value()<=0.0){ //ρ=0 returnDensityValue{0.0}; } //ρ=(h/hs)^n returnDensityValue{std::pow(specific_enthalpy.value()/m_enthalpy_scale,m_polytropic_index)}; } [[nodiscard]]PressureValuePolytrope::evaluate(PressureFromSpecificEnthalpy,SpecificEnthalpyValuespecific_enthalpy)const{ constDensityValuedensity=evaluate(DensityFromSpecificEnthalpy{},specific_enthalpy); if(specific_enthalpy.value()<=0.0){ //P=0 returnPressureValue{0.0}; } //P=ρ*h/(n+1) returnPressureValue{density.value()*specific_enthalpy.value()/(m_polytropic_index+1.0)}; } [[nodiscard]]SpecificEnthalpyValuePolytrope::evaluate(SpecificEnthalpyFromPressure,PressureValuepressure)const{ validate_nonnegativity<EOSEvaluationError,SERiFErrorCode::EOS_INVALID_THERMODYNAMIC_INPUT>(pressure.value()); if(pressure.value()==0.0){ //h=0 returnSpecificEnthalpyValue{0.0}; } constdoubleindexPlusOne=m_polytropic_index+1.0; //h=(n+1)*(K^(n/(n+1)))*(P^(1/(n+1))) returnSpecificEnthalpyValue{ indexPlusOne*std::pow(m_polytropic_constant,m_polytropic_index/indexPlusOne)* std::pow(pressure.value(),1.0/indexPlusOne) }; } [[nodiscard]]PartialDerivative<MassDensity,SpecificEnthalpy>Polytrope::partial_derivative(DensityFromSpecificEnthalpy,WithRespectTo<SpecificEnthalpy>,constSpecificEnthalpyValuespecific_enthalpy)const{ validate_finite<EOSEvaluationError,SERiFErrorCode::EOS_INVALID_THERMODYNAMIC_INPUT>(specific_enthalpy.value()); if(specific_enthalpy.value()<0.0){ //dρ/dh=0 returnPartialDerivative<MassDensity,SpecificEnthalpy>{0.0}; } if(specific_enthalpy.value()==0.0){ //dρ/dh=n==1->1/hs //dρ/dh=else->0 returnPartialDerivative<MassDensity,SpecificEnthalpy>{ m_polytropic_index==1.0?1.0/m_enthalpy_scale:0.0 }; } //dρ/dh=(n/hs)*(h/hs)^(n-1) returnPartialDerivative<MassDensity,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>,constSpecificEnthalpyValuespecific_enthalpy)const{ constDensityValuedensity=evaluate(DensityFromSpecificEnthalpy{},specific_enthalpy); //dP/dh=ρ returnPartialDerivative<Pressure,SpecificEnthalpy>{density.value()}; } [[nodiscard]]PartialDerivative<Pressure,MassDensity>Polytrope::partial_derivative(PressureFromDensity,WithRespectTo<MassDensity>,constDensityValuedensity)const{ validate_nonnegativity<EOSEvaluationError,SERiFErrorCode::EOS_INVALID_THERMODYNAMIC_INPUT>(density.value()); if(density.value()==0.0){ //dP/dρ=0 returnPartialDerivative<Pressure,MassDensity>{0.0}; } //dP/dρ=K*(1+1/n)*(ρ)^(1/n) returnPartialDerivative<Pressure,MassDensity>{ m_polytropic_constant*(1.0+1.0/m_polytropic_index)*std::pow(density.value(),1.0/m_polytropic_index) }; } }