equilibrium_evaluator.hpp expected span serif/backend/mfem/model/binding.hpp serif/backend/mfem/model/failure.hpp serif/backend/mfem/model/state.hpp serif/backend/mfem/model/preconditioning/computations.hpp serif/backend/mfem/shared/finite.hpp serif/utils/dependencies/computation_cache.hpp src/include/serif/backend/mfem/model/equilibrium.hpp serif::model::backend::mfem::EquilibriumEvaluator serif serif::model serif::model::backend serif::model::backend::mfem serif::model::backend::mfem::detail #pragmaonce #include<expected> #include<span> #include"serif/backend/mfem/model/binding.hpp" #include"serif/backend/mfem/model/failure.hpp" #include"serif/backend/mfem/model/state.hpp" #include"serif/backend/mfem/model/preconditioning/computations.hpp" #include"serif/backend/mfem/shared/finite.hpp" #include"serif/utils/dependencies/computation_cache.hpp" namespaceserif::model::backend::mfem{ namespacedetail{ template<typenameBound,typenameCoefficients,typenameGeometry> [[nodiscard]]autocandidate_inputs(constBound&bound,constCoefficients&coefficients,constGeometry&geometry){ ifconstexpr(Bound::Plan::has_shape){ returnequilibrium_inputs(bound,coefficients,std::span<constdouble>{geometry}); }else{ returnequilibrium_inputs(bound,coefficients,geometry); } } } template<typenameBound,typenameGraph,typenameInputs,typenameAdditionalInputs=utils::dependencies::DependencyContext<>, typenameResultKey=keys::PhysicalSystem, utils::dependencies::IsKeyListEvaluationServices=utils::dependencies::KeyList<>, utils::dependencies::IsKeyListLinearServices=utils::dependencies::KeyList<>, typenameObservers=utils::dependencies::Observers<>> classEquilibriumEvaluatorfinal{ public: usingPlan=typenameBound::Plan; usingLayout=typenamePlan::Layout; usingSurfaceFormulation=typenamePlan::Surface::Formulation; usingCache=utils::dependencies::ComputationCache<Graph, Inputs, EquilibriumFailure, Observers>; usingResult=std::remove_cvref_t<decltype(std::declval<constCache&>().templateget<ResultKey>())>; usingEvaluation=std::expected<Result,typenameCache::Failure>; template<typenameRequestedKey> usingEvaluationFor=std::expected<std::remove_cvref_t<decltype(std::declval<constCache&>().templateget<RequestedKey>())>,typenameCache::Failure>; EquilibriumEvaluator(std::shared_ptr<constBound>bound,Graphgraph,Layoutlayout,AdditionalInputsadditional,Observersobservers=Observers{}): m_bound(std::move(bound)),m_cache(std::move(graph),std::move(observers)),m_layout(std::move(layout)),m_additional(std::move(additional)){ } [[nodiscard]]constLayout&layout()constnoexcept{ returnm_layout; } [[nodiscard]]constCache&cache()constnoexcept{ returnm_cache; } [[nodiscard]]constauto&model()constnoexcept{ return*m_bound->model; } [[nodiscard]]constBound&binding()constnoexcept{ return*m_bound; } private: template<typenameRequestedKey,typenameCoefficients,typenameGeometry> requires(detail::coefficient_inputs<Coefficients>(typenamePlan::Coefficients{})) [[nodiscard]]autoevaluate_result(constCoefficients&coefficients,constGeometry&geometry, utils::dependencies::PreparationModemode=utils::dependencies::PreparationMode::reuse_unchanged)->EvaluationFor<RequestedKey>{ m_cache.clear_preparation(); constboolfinite=[&]<typename...Terms>(utils::dependencies::KeyList<Terms...>){ return(utils::checks::is_finite(coefficients.templateget<Terms>().values)&&...); }(typenamePlan::Coefficients{}); if(!finite){ returnstd::unexpected(typenameCache::Failure{.computation_index=Graph::size, .error=EquilibriumFailure{operators::backend::mfem::PreparationRejection{ .reason=operators::backend::mfem::PreparationRejectionReason::NON_FINITE, .message="Astellarcandidatecontainsanon-finitephysicalcoefficient.Supplyfinitefieldandscalarvaluesbeforeevaluatingit." }}}); } constautoinputs=utils::dependencies::combine_dependency_contexts(detail::candidate_inputs(*m_bound,coefficients,geometry),m_additional); usingRequested=utils::dependencies::CombinedKeyList<utils::dependencies::KeyList<RequestedKey>,EvaluationServices, std::conditional_t<std::same_as<RequestedKey,preconditioning::PreparedSystem>,LinearServices,utils::dependencies::KeyList<>>>; constautopreparation=m_cache.try_prepare(inputs,Requested{},mode); if(!preparation){ returnstd::unexpected(preparation.error()); } returnm_cache.templateget<RequestedKey>(); } template<typenameRequestedKey,utils::dependencies::IsDependencyContextPrescribed=utils::dependencies::DependencyContext<>> requiresPlan::has_shape&&detail::PrescribedInputsFor<Plan, Prescribed> [[nodiscard]]autoevaluate_result(constStellarState<Layout>&state,constPrescribed&prescribed=Prescribed{}, utils::dependencies::PreparationModemode=utils::dependencies::PreparationMode::reuse_unchanged)->EvaluationFor<RequestedKey>{ validate_state(state); constautofields=detail::state_coefficients(*m_bound->discretization,state,prescribed); constautocoefficients=fields.context(); returnevaluate_result<RequestedKey>(coefficients,state.templateget<discretization::blocks::surface_deformation::coefficients>(),mode); } template<typenameRequestedKey,utils::dependencies::IsDependencyContextPrescribed=utils::dependencies::DependencyContext<>> requires(!Plan::has_shape)&&detail::PrescribedInputsFor<Plan, Prescribed> [[nodiscard]]autoevaluate_result(constStellarState<Layout>&state,const::mfem::Vector&displacement,constPrescribed&prescribed=Prescribed{}, utils::dependencies::PreparationModemode=utils::dependencies::PreparationMode::reuse_unchanged)->EvaluationFor<RequestedKey>{ validate_state(state); constautofields=detail::state_coefficients(*m_bound->discretization,state,prescribed); constautocoefficients=fields.context(); returnevaluate_result<RequestedKey>(coefficients,displacement,mode); } voidvalidate_state(constStellarState<Layout>&state){ usingnamespaceutils::errors; m_cache.clear_preparation(); serif_ensure<SERiFErrorCode::INVALID_DOF_COUNT>(state.layout()==m_layout, "Thestellarstate'sfieldorequationsizesdifferfromthisevaluator'slayout.Constructthestatewiththematchingdiscretizationlayout."); } public: template<typename...InputsT> requiresrequires(EquilibriumEvaluator&evaluator,constInputsT&...inputs){ evaluator.templateevaluate_result<ResultKey>(inputs...); } [[nodiscard]]Evaluationevaluate(constInputsT&...inputs){ returnevaluate_result<ResultKey>(inputs...); } template<typename...InputsT> requiresutils::dependencies::ContainsKey<preconditioning::PreparedSystem, typename Graph::Results>&& requires(EquilibriumEvaluator&evaluator,constInputsT&...inputs){ evaluator.templateevaluate_result<preconditioning::PreparedSystem>(inputs...); } [[nodiscard]]autoprepare_linear_system(constInputsT&...inputs)->decltype(evaluate_result<preconditioning::PreparedSystem>(inputs...)){ returnevaluate_result<preconditioning::PreparedSystem>(inputs...); } private: std::shared_ptr<constBound>m_bound; Cachem_cache; Layoutm_layout; AdditionalInputsm_additional; }; }