views.hpp span serif/eos/runtime/concepts.hpp src/compile_time_checks/serif/eos/runtime/views.cpp serif::eos::runtime::EOSView serif serif::eos serif::eos::runtime File containing the EOSView class. This class is used to provide a runtime view of an EOS model and its relations. Emily M. Boudreaux #pragmaonce #include<span> #include"serif/eos/runtime/concepts.hpp" namespaceserif::eos::runtime{ classEOSViewfinal{ public: template<typenameEOS> requiresRuntimeEOSModel<std::remove_cvref_t<EOS>> explicitEOSView(constEOS&eos)noexcept: m_object(std::addressof(eos)), m_relations(runtimeRelationDescriptors<std::remove_cvref_t<EOS>>()), m_evaluate(&RuntimeEOSAdapter<std::remove_cvref_t<EOS>>::evaluate), m_partialDerivative(&RuntimeEOSAdapter<std::remove_cvref_t<EOS>>::partial_derivative){} template<typenameEOS> requiresRuntimeEOSModel<std::remove_cvref_t<EOS>> explicitEOSView(constEOS&&)=delete; [[nodiscard]]std::span<constdimensions::runtime::RuntimeRelationDescriptor>relations()constnoexcept{ returnm_relations; } [[nodiscard]]boolsupports( constdimensions::runtime::ThermodynamicQuantityIDoutputQuantity, conststd::span<constdimensions::runtime::ThermodynamicQuantityID>inputQuantities )constnoexcept{ returnfind_relation(outputQuantity,inputQuantities)!=nullptr; } [[nodiscard]]std::expected<dimensions::runtime::RuntimeQuantityValue,utils::errors::SERiFErrorCode>try_evaluate( constdimensions::runtime::ThermodynamicQuantityIDoutputQuantity, conststd::span<constdimensions::runtime::RuntimeQuantityValue>inputQuantities )const{ constautovalidation=validate_relation_request(outputQuantity,inputQuantities); if(!validation.has_value()){ returnstd::unexpected{validation.error()}; } autoresult=m_evaluate(m_object,outputQuantity,inputQuantities); if(!result.has_value()){ returnstd::unexpected{result.error()}; } returndimensions::runtime::RuntimeQuantityValue{outputQuantity,*result}; } template<dimensions::runtime::RuntimeIdentifiedThermodynamicQuantityOutputQuantity,dimensions::ThermodynamicQuantityValueType...InputValues> [[nodiscard]]std::expected<dimensions::QuantityValue<OutputQuantity>,utils::errors::SERiFErrorCode>try_evaluate( constInputValues...inputValues )const{ constexprboolinputsHaveRuntimeIdentifiers=(dimensions::runtime::RuntimeIdentifiedThermodynamicQuantity<dimensions::QuantityOfT<InputValues>>&&...); static_assert(inputsHaveRuntimeIdentifiers,"EveryruntimeEOSinputquantityneedsastableidentifier."); conststd::array<dimensions::runtime::RuntimeQuantityValue,sizeof...(InputValues)>runtimeInputs{ dimensions::runtime::RuntimeQuantityValue{ .id=dimensions::runtime::thermodynamicQuantityID<dimensions::QuantityOfT<InputValues>>,.value=inputValues.value() }... }; autoresult=try_evaluate( dimensions::runtime::thermodynamicQuantityID<OutputQuantity>,std::span<constdimensions::runtime::RuntimeQuantityValue>{runtimeInputs} ); if(!result.has_value()){ returnstd::unexpected<utils::errors::SERiFErrorCode>{result.error()}; } returndimensions::QuantityValue<OutputQuantity>{result->value}; } [[nodiscard]]std::expected<double,utils::errors::SERiFErrorCode>try_partial_derivative( constdimensions::runtime::ThermodynamicQuantityIDoutputQuantity, constdimensions::runtime::ThermodynamicQuantityIDwithRespectTo, conststd::span<constdimensions::runtime::RuntimeQuantityValue>inputValues )const{ constautovalidation=validate_relation_request(outputQuantity,inputValues); if(!validation.has_value()){ returnstd::unexpected<utils::errors::SERiFErrorCode>{validation.error()}; } constdimensions::runtime::RuntimeRelationDescriptor&descriptor=**validation; boolderivativeAvailable=false; for(std::size_tindex=0;index<descriptor.inputQuantities.size();++index){ if(descriptor.inputQuantities[index]==withRespectTo){ derivativeAvailable=descriptor.hasPartialDerivative(index); break; } } if(!derivativeAvailable){ returnruntime_failure<double>(utils::errors::SERiFErrorCode::EOS_UNSUPPORTED_DERIVATIVE); } returnm_partialDerivative(m_object,outputQuantity,withRespectTo,inputValues); } template<dimensions::runtime::RuntimeIdentifiedThermodynamicQuantityOutputQuantity,dimensions::runtime::RuntimeIdentifiedThermodynamicQuantityInputQuantity,dimensions::QuantityValueType...InputValues> [[nodiscard]]std::expected<dimensions::PartialDerivative<OutputQuantity,InputQuantity>,utils::errors::SERiFErrorCode>try_partial_derivative( constInputValues...inputValues )const{ constexprboolinputHaveRuntimeIdentifiers=(dimensions::runtime::RuntimeIdentifiedThermodynamicQuantity<dimensions::QuantityOfT<InputValues>>&&...); static_assert(inputHaveRuntimeIdentifiers,"EveryruntimeEOSinputquantityneedsastableidentifier."); conststd::array<dimensions::runtime::RuntimeQuantityValue,sizeof...(InputValues)>runtimeInputs{ dimensions::runtime::RuntimeQuantityValue{.id=dimensions::runtime::thermodynamicQuantityID<dimensions::QuantityOfT<InputValues>>,.value=inputValues.value()}... }; autoresult=try_partial_derivative( dimensions::runtime::thermodynamicQuantityID<OutputQuantity>,//output dimensions::runtime::thermodynamicQuantityID<InputQuantity>,//input std::span<constdimensions::runtime::RuntimeQuantityValue>{runtimeInputs}//wheretoevaluate ); if(!result.has_value()){ returnstd::unexpected<utils::errors::SERiFErrorCode>{result.error()}; } returndimensions::PartialDerivative<OutputQuantity, InputQuantity>{*result}; } private://Typealiases usingRuntimeEvaluateFunction=std::expected<double,utils::errors::SERiFErrorCode>(*)( constvoid*, constdimensions::runtime::ThermodynamicQuantityID&, std::span<constdimensions::runtime::RuntimeQuantityValue> ); usingRuntimePartialDerivativeFunction=std::expected<double,utils::errors::SERiFErrorCode>(*)( constvoid*, constdimensions::runtime::ThermodynamicQuantityID&, constdimensions::runtime::ThermodynamicQuantityID&, std::span<constdimensions::runtime::RuntimeQuantityValue> ); private://Privatemethods [[nodiscard]]constdimensions::runtime::RuntimeRelationDescriptor*find_relation( constdimensions::runtime::ThermodynamicQuantityIDoutputQuantity, conststd::span<constdimensions::runtime::ThermodynamicQuantityID>inputQuantities )constnoexcept{ for(constauto&descriptor:m_relations){ if(descriptor.outputQuantity!=outputQuantity||descriptor.inputQuantities.size()!=inputQuantities.size()){ continue; } boolmatches=true; for(std::size_tindex=0;index<inputQuantities.size();++index){ if(descriptor.inputQuantities[index]!=inputQuantities[index]){ matches=false; break; } } if(matches){ returnstd::addressof(descriptor); } } returnnullptr; } [[nodiscard]]std::expected<constdimensions::runtime::RuntimeRelationDescriptor*,utils::errors::SERiFErrorCode>validate_relation_request( constdimensions::runtime::ThermodynamicQuantityIDoutputQuantity, conststd::span<constdimensions::runtime::RuntimeQuantityValue>inputValues )const{ booloutputAvailable=false; boolinputCountAvailable=false; for(constauto&descriptor:m_relations){ if(descriptor.outputQuantity!=outputQuantity){ continue; } outputAvailable=true; if(descriptor.inputQuantities.size()!=inputValues.size()){ continue; } inputCountAvailable=true; boolmatches=true; for(std::size_tindex=0;index<inputValues.size();++index){ if(descriptor.inputQuantities[index]!=inputValues[index].id){ matches=false; break; } } if(matches){ returnstd::addressof(descriptor); } } if(!outputAvailable){ returnruntime_failure<const dimensions::runtime::RuntimeRelationDescriptor *>( utils::errors::SERiFErrorCode::EOS_UNSUPPORTED_RELATION ); } if(!inputCountAvailable){ returnruntime_failure<const dimensions::runtime::RuntimeRelationDescriptor *>( utils::errors::SERiFErrorCode::EOS_WRONG_INPUT_COUNT ); } returnruntime_failure<const dimensions::runtime::RuntimeRelationDescriptor *>( utils::errors::SERiFErrorCode::EOS_WRONG_INPUT_QUANTITY ); } template<typenameValue> [[nodiscard]]staticstd::expected<Value,utils::errors::SERiFErrorCode>runtime_failure( constutils::errors::SERiFErrorCodecode ){ returnstd::unexpected{code}; } private://Privatemembers constvoid*m_object; std::span<constdimensions::runtime::RuntimeRelationDescriptor>m_relations; RuntimeEvaluateFunctionm_evaluate; RuntimePartialDerivativeFunctionm_partialDerivative; }; }