equilibrium.hpp functional memory tuple type_traits utility serif/backend/mfem/model/equilibrium_evaluator.hpp serif/backend/mfem/model/discretization.hpp serif/model/configured_discretization.hpp serif/backend/mfem/model/normalization/computations.hpp serif/backend/mfem/model/graph.hpp serif/model/execution_validation.hpp src/compile_time_checks/serif/model/state.cpp src/include/serif/backend/mfem/solver/nonlinear/stellar_problem.hpp serif::model::backend::mfem::detail::PhysicalEvaluation serif::model::backend::mfem::detail::NoAdditionalComputations serif serif::model serif::model::backend serif::model::backend::mfem serif::model::backend::mfem::detail #pragmaonce #include<functional> #include<memory> #include<tuple> #include<type_traits> #include<utility> #include"serif/backend/mfem/model/equilibrium_evaluator.hpp" #include"serif/backend/mfem/model/discretization.hpp" #include"serif/model/configured_discretization.hpp" #include"serif/backend/mfem/model/normalization/computations.hpp" #include"serif/backend/mfem/model/graph.hpp" #include"serif/model/execution_validation.hpp" namespaceserif::model::backend::mfem{ namespacedetail{ structPhysicalEvaluationfinal{}; structNoAdditionalComputations{ autooperator()(constauto&,constauto&,auto,constauto&)const{returnstd::pair{std::tuple{},std::tuple{}};} }; template<typename...Computations> [[nodiscard]]autocomputation_keys(conststd::tuple<Computations...>&){ returnutils::dependencies::KeyList<typenameComputations::Key...>{}; } template<typenamePrescribed,typenameSpecificationMap,typenameExplicitZeroCouplings,typenameModel,typenameDiscretization, typenameCoefficients,typenameGeometry,typenameNumericalOptions=PhysicalEvaluation,typenamePreconditioner=preconditioning::None, typenameServices=NoAdditionalComputations,typenameObserverFactory=utils::dependencies::NoGraphObservers> [[nodiscard]]autobind_evaluator(std::shared_ptr<constModel>model,std::shared_ptr<constDiscretization>discretization, constCoefficients&coefficients,constGeometry&geometry,operators::backend::mfem::VolumeOptionsoptions,NumericalOptionsnumerical_options={},Preconditionerpreconditioner={},Servicesservices={},ObserverFactoryobserver_factory={}){ constautobound=bind_model_definition<Prescribed>(std::move(model),std::move(discretization),coefficients); usingBound=typenamedecltype(bound)::element_type; usingPlan=typenameBound::Plan; static_assert(executable_model_topology<Model, typename Bound::Description, Plan, SpecificationMap, ExplicitZeroCouplings>(), "Theselectedmodelneedscompleteequationandprescriptionbindings,includingexplicitgenerated-coordinateeffects.Thischeckdoesnotprovemathematicalclosure."); constautolayout=equilibrium_layout<Plan>(*bound->discretization,geometry); constautoconstruct=[&]<typenameResultKey>(ResultKey,autonumerical,autoadditional){ autoinverse=[&](){ ifconstexpr(std::same_as<Preconditioner,preconditioning::None>){ returnstd::tuple{}; }else{ returnpreconditioning::make_computations<ResultKey>(preconditioner,layout,numerical); } }(); autonumerical_services=std::tuple_cat(std::move(numerical),std::move(inverse)); autoextensions=services(bound,layout,ResultKey{},numerical_services); usingEvaluationServices=decltype(computation_keys(extensions.first)); usingLinearServices=decltype(computation_keys(extensions.second)); autograph=make_equilibrium_graph(bound,layout, std::tuple_cat(std::move(numerical_services),std::move(extensions.first),std::move(extensions.second)),options); constautoinputs=utils::dependencies::combine_dependency_contexts(candidate_inputs(*bound,coefficients,geometry),additional); //Observationseesthefinalgraph,butdoesnotbecomeaphysicalinputorinvalidatecachedresults. autoobservers=std::invoke(observer_factory,std::type_identity<decltype(graph)>{}); returnEquilibriumEvaluator<std::remove_const_t<Bound>,decltype(graph),std::remove_cvref_t<decltype(inputs)>,decltype(additional),ResultKey,EvaluationServices,LinearServices,decltype(observers)>( bound,std::move(graph),layout,std::move(additional),std::move(observers)); }; ifconstexpr(std::same_as<NumericalOptions,PhysicalEvaluation>){ returnconstruct(keys::PhysicalSystem{},std::tuple{},utils::dependencies::make_dependency_context()); }else{ autoresolved=normalization::resolve_configuration(std::move(numerical_options),*bound->model); usingNormalizationPlan=normalization::PlanFor<decltype(resolved.plan),decltype(resolved.coordinates),Bound>; static_assert(solver::normalization::NormalizationPreparable<NormalizationPlan,decltype(layout)>, "Thenormalizationplanmustprovideonecompatibleruleforeveryunknownandresidualrow."); constautoconfiguration=std::make_shared<constdecltype(resolved)>(std::move(resolved)); constautometrics=normalization::MetricsFor<NormalizationPlan>{}; constautoadditional=normalization::make_inputs(configuration,*bound->discretization,metrics); constautonumerical=normalization::make_computations<NormalizationPlan>(*bound,*configuration,layout,metrics); returnconstruct(normalization::PreparedSystem{},numerical,additional); } } template<typenamePrescribed,typenameSpecificationMap,typenameExplicitZeroCouplings,typenameModel,typenameDiscretization, typenameLayout,typenameGeometry,typenameInputs,typenameNumericalOptions=PhysicalEvaluation,typenamePreconditioner=preconditioning::None, typenameServices=NoAdditionalComputations,typenameObserverFactory=utils::dependencies::NoGraphObservers> [[nodiscard]]autobind_state_evaluator(Modelmodel,Discretizationdiscretization,constStellarState<Layout>&state, constGeometry&geometry,operators::backend::mfem::VolumeOptionsoptions,constInputs&prescribed,NumericalOptionsnumerical={},Preconditionerpreconditioner={},Servicesservices={},ObserverFactoryobserver_factory={}){ usingnamespaceutils::errors; usingPrescribedKeys=utils::dependencies::CombinedKeyList<Prescribed, typename Inputs::Keys>; constautoowner=std::make_shared<constDiscretization>(std::move(discretization)); constautofields=state_coefficients(*owner,state,prescribed); constautocoefficients=fields.context(); autoevaluator=bind_evaluator<PrescribedKeys, SpecificationMap, ExplicitZeroCouplings>(std::make_shared<constModel>(std::move(model)), owner,coefficients,geometry,options,std::move(numerical),std::move(preconditioner),std::move(services),std::move(observer_factory)); static_assert(std::same_as<typenameStellarState<Layout>::Layout,typenamedecltype(evaluator)::Layout>, "Thestate'sphysicalcoordinateidentitiesmustmatchtheselectedequationsandprescribedfields."); serif_ensure<SERiFErrorCode::INVALID_DOF_COUNT>(state.layout()==evaluator.layout(), "Thestellarstate'sfieldorequationsizesdonotmatchtheboundequations.Constructitwiththematchingphysicallayout."); returnevaluator; } } template<utils::dependencies::IsKeyListPrescribed=utils::dependencies::KeyList<>, utils::dependencies::IsBindingsSpecificationMap=DefaultSpecificationBindings, utils::dependencies::IsKeyListExplicitZeroCouplings=utils::dependencies::KeyList<>,StellarModelTypeModel, typenameDiscretization,typenameCoefficients,typenameGeometry,typenameObserverFactory=utils::dependencies::NoGraphObservers> requiresrequires{typenameCoefficients::Keys;} [[nodiscard]]autobind_stellar_model(Modelmodel,Discretizationdiscretization,constCoefficients&coefficients, constGeometry&geometry,operators::backend::mfem::VolumeOptionsoptions={},ObserverFactoryobserver_factory={}){ returndetail::bind_evaluator<Prescribed, SpecificationMap, ExplicitZeroCouplings>(std::make_shared<constModel>(std::move(model)), std::make_shared<constDiscretization>(std::move(discretization)),coefficients,geometry,options,detail::PhysicalEvaluation{},preconditioning::None{},detail::NoAdditionalComputations{},std::move(observer_factory)); } template<utils::dependencies::IsKeyListPrescribed=utils::dependencies::KeyList<>, utils::dependencies::IsBindingsSpecificationMap=DefaultSpecificationBindings, utils::dependencies::IsKeyListExplicitZeroCouplings=utils::dependencies::KeyList<>,StellarModelTypeModel, typenameDiscretization,typenameOptions,typenamePreconditioner,typenameCoefficients,typenameGeometry,typenameObserverFactory=utils::dependencies::NoGraphObservers> requiresrequires{typenameCoefficients::Keys;} [[nodiscard]]autobind_stellar_model(DiscretizationOptions<Model,Discretization,Options,Preconditioner>configuration, constCoefficients&coefficients,constGeometry&geometry,operators::backend::mfem::VolumeOptionsoptions={},ObserverFactoryobserver_factory={}){ returndetail::bind_evaluator<Prescribed, SpecificationMap, ExplicitZeroCouplings>(std::make_shared<constModel>(std::move(configuration.model)), std::make_shared<constDiscretization>(std::move(configuration.finite_elements)),coefficients,geometry,options,std::move(configuration.normalization),std::move(configuration.preconditioner),detail::NoAdditionalComputations{},std::move(observer_factory)); } template<utils::dependencies::IsKeyListPrescribed=utils::dependencies::KeyList<>, utils::dependencies::IsBindingsSpecificationMap=DefaultSpecificationBindings, utils::dependencies::IsKeyListExplicitZeroCouplings=utils::dependencies::KeyList<>,StellarModelTypeModel, typenameDiscretization,typenameLayout,utils::dependencies::IsDependencyContextInputs=utils::dependencies::DependencyContext<>, typenameObserverFactory=utils::dependencies::NoGraphObservers> requiresutils::dependencies::ContainsKey<discretization::blocks::surface_deformation::coefficients,typenameLayout::Values> [[nodiscard]]autobind_stellar_model(Modelmodel,Discretizationdiscretization,constStellarState<Layout>&state, operators::backend::mfem::VolumeOptionsoptions={},constInputs&prescribed=Inputs{},ObserverFactoryobserver_factory={}){ returndetail::bind_state_evaluator<Prescribed, SpecificationMap, ExplicitZeroCouplings>(std::move(model),std::move(discretization),state, state.templateget<discretization::blocks::surface_deformation::coefficients>(),options,prescribed,detail::PhysicalEvaluation{},preconditioning::None{},detail::NoAdditionalComputations{},std::move(observer_factory)); } template<utils::dependencies::IsKeyListPrescribed=utils::dependencies::KeyList<>, utils::dependencies::IsBindingsSpecificationMap=DefaultSpecificationBindings, utils::dependencies::IsKeyListExplicitZeroCouplings=utils::dependencies::KeyList<>,StellarModelTypeModel, typenameDiscretization,typenameLayout,utils::dependencies::IsDependencyContextInputs=utils::dependencies::DependencyContext<>, typenameObserverFactory=utils::dependencies::NoGraphObservers> requires(!utils::dependencies::ContainsKey<discretization::blocks::surface_deformation::coefficients,typenameLayout::Values>) [[nodiscard]]autobind_stellar_model(Modelmodel,Discretizationdiscretization,constStellarState<Layout>&state,const::mfem::Vector&displacement, operators::backend::mfem::VolumeOptionsoptions={},constInputs&prescribed=Inputs{},ObserverFactoryobserver_factory={}){ returndetail::bind_state_evaluator<Prescribed, SpecificationMap, ExplicitZeroCouplings>(std::move(model),std::move(discretization),state, displacement,options,prescribed,detail::PhysicalEvaluation{},preconditioning::None{},detail::NoAdditionalComputations{},std::move(observer_factory)); } template<utils::dependencies::IsKeyListPrescribed=utils::dependencies::KeyList<>, utils::dependencies::IsBindingsSpecificationMap=DefaultSpecificationBindings, utils::dependencies::IsKeyListExplicitZeroCouplings=utils::dependencies::KeyList<>,StellarModelTypeModel, typenameDiscretization,typenameOptions,typenamePreconditioner,typenameLayout,utils::dependencies::IsDependencyContextInputs=utils::dependencies::DependencyContext<>, typenameServices=detail::NoAdditionalComputations,typenameObserverFactory=utils::dependencies::NoGraphObservers> requiresutils::dependencies::ContainsKey<discretization::blocks::surface_deformation::coefficients,typenameLayout::Values> [[nodiscard]]autobind_stellar_model(DiscretizationOptions<Model,Discretization,Options,Preconditioner>configuration,constStellarState<Layout>&state, operators::backend::mfem::VolumeOptionsoptions={},constInputs&prescribed=Inputs{},Servicesservices={},ObserverFactoryobserver_factory={}){ returndetail::bind_state_evaluator<Prescribed, SpecificationMap, ExplicitZeroCouplings>(std::move(configuration.model),std::move(configuration.finite_elements),state, state.templateget<discretization::blocks::surface_deformation::coefficients>(),options,prescribed,std::move(configuration.normalization),std::move(configuration.preconditioner),std::move(services),std::move(observer_factory)); } template<utils::dependencies::IsKeyListPrescribed=utils::dependencies::KeyList<>, utils::dependencies::IsBindingsSpecificationMap=DefaultSpecificationBindings, utils::dependencies::IsKeyListExplicitZeroCouplings=utils::dependencies::KeyList<>,StellarModelTypeModel, typenameDiscretization,typenameOptions,typenamePreconditioner,typenameLayout,utils::dependencies::IsDependencyContextInputs=utils::dependencies::DependencyContext<>, typenameServices=detail::NoAdditionalComputations,typenameObserverFactory=utils::dependencies::NoGraphObservers> requires(!utils::dependencies::ContainsKey<discretization::blocks::surface_deformation::coefficients,typenameLayout::Values>) [[nodiscard]]autobind_stellar_model(DiscretizationOptions<Model,Discretization,Options,Preconditioner>configuration,constStellarState<Layout>&state, const::mfem::Vector&displacement,operators::backend::mfem::VolumeOptionsoptions={},constInputs&prescribed=Inputs{},Servicesservices={},ObserverFactoryobserver_factory={}){ returndetail::bind_state_evaluator<Prescribed, SpecificationMap, ExplicitZeroCouplings>(std::move(configuration.model),std::move(configuration.finite_elements),state, displacement,options,prescribed,std::move(configuration.normalization),std::move(configuration.preconditioner),std::move(services),std::move(observer_factory)); } }