partial.hpp serif/dimensions/quantities.hpp serif/utils/misc/concepts/numeric.hpp src/compile_time_checks/serif/dimensions/quantities.cpp src/include/serif/eos/models/polytropic.hpp src/include/serif/eos/models/traits.hpp serif::dimensions::WithRespectTo serif::dimensions::SecondPartialDerivative serif::dimensions::PartialDerivative serif serif::dimensions Compile time tools to represent a partial derivative of one quantity wrt. another quantity. Note that this system is not responsible for computing partials or in fact derivatives of any kind. Rather, it is responsible for forcing the developer or compiler at least to ask for a specific, explicit, partial and have to spell out what that is. That in turn gives the compiler enough information to do a lot of downstream things. A motivating example would be automatic verification of the provided EOS against all partials that might be needed to ensure they are all exported by the EOS. Emily M. Boudreaux #pragmaonce #include"serif/dimensions/quantities.hpp" #include"serif/utils/misc/concepts/numeric.hpp" namespaceserif::dimensions{ template<ThermodynamicQuantityTypeQuantity> structWithRespectTofinal{}; template<ThermodynamicQuantityTypeOutputQuantity,ThermodynamicQuantityTypeFirstInput,ThermodynamicQuantityTypeSecondInput> classSecondPartialDerivativefinal{ public: explicitconstexprSecondPartialDerivative(doublevalue)noexcept:m_value(value){} [[nodiscard]]constexprdoublevalue()constnoexcept{returnm_value;} private: doublem_value; }; template<ThermodynamicQuantityTypeOutputQuantity,ThermodynamicQuantityTypeInputQuantity> classPartialDerivativefinal{ public: explicitconstexprPartialDerivative(constdoublevalue)noexcept:m_value(value){} [[nodiscard]]constexprdoublevalue()constnoexcept{ returnm_value; } friendconstexprPartialDerivative<OutputQuantity, InputQuantity>operator+( constPartialDerivative<OutputQuantity, InputQuantity>&lhs, constPartialDerivative<OutputQuantity, InputQuantity>&rhs )noexcept{ returnPartialDerivative<OutputQuantity, InputQuantity>{lhs.m_value+rhs.m_value}; } friendconstexprPartialDerivative<OutputQuantity, InputQuantity>operator-( constPartialDerivative<OutputQuantity, InputQuantity>&lhs, constPartialDerivative<OutputQuantity, InputQuantity>&rhs )noexcept{ returnPartialDerivative<OutputQuantity, InputQuantity>{lhs.m_value-rhs.m_value}; } template<utils::misc::concepts::IsNumericScalar> friendconstexprPartialDerivative<OutputQuantity, InputQuantity>operator*( constPartialDerivative<OutputQuantity, InputQuantity>&lhs, constScalar&rhs )noexcept{ returnPartialDerivative<OutputQuantity, InputQuantity>{lhs.m_value*rhs}; } template<utils::misc::concepts::IsNumericScalar> friendconstexprPartialDerivative<OutputQuantity, InputQuantity>operator*( constScalar&lhs, constPartialDerivative<OutputQuantity, InputQuantity>&rhs )noexcept{ returnPartialDerivative<OutputQuantity, InputQuantity>{lhs*rhs.m_value}; } template<utils::misc::concepts::IsNumericScalar> friendconstexprPartialDerivative<OutputQuantity, InputQuantity>operator/( constPartialDerivative<OutputQuantity, InputQuantity>&lhs, constScalar&rhs )noexcept{ returnPartialDerivative<OutputQuantity, InputQuantity>{lhs.m_value/rhs}; } template<utils::misc::concepts::IsNumericScalar> friendconstexprstd::partial_orderingoperator<=>( constPartialDerivative<OutputQuantity, InputQuantity>&lhs, Scalarrhs )noexcept{ returnlhs.m_value<=>rhs; } template<utils::misc::concepts::IsNumericScalar> friendconstexprstd::partial_orderingoperator<=>( Scalarlhs, constPartialDerivative<OutputQuantity, InputQuantity>&rhs )noexcept{ returnlhs<=>rhs.m_value; } friendconstexprstd::partial_orderingoperator<=>( constPartialDerivative<OutputQuantity, InputQuantity>&lhs, constPartialDerivative<OutputQuantity, InputQuantity>&rhs )noexcept{ returnlhs.m_value<=>rhs.m_value; } private: doublem_value; }; }