graph.hpp limits memory tuple utility serif/backend/mfem/model/computations/interior.hpp serif/backend/mfem/model/computations/surface_potential.hpp serif/backend/mfem/model/computations/potential_infinity.hpp serif/backend/mfem/model/computations/pressure_boundary.hpp serif/model/equilibrium_plan.hpp serif/backend/mfem/geometry/deformation/computations.hpp serif/backend/mfem/model/volume_displacement.hpp serif/backend/mfem/geometry/surface/boundary_computations.hpp serif/model/keys.hpp serif/model/plan.hpp src/include/serif/backend/mfem/model/equilibrium.hpp src/include/serif/backend/mfem/solver/admissibility/geometry.hpp serif serif::model serif::model::detail #pragmaonce #include<limits> #include<memory> #include<tuple> #include<utility> #include"serif/backend/mfem/model/computations/interior.hpp" #include"serif/backend/mfem/model/computations/surface_potential.hpp" #include"serif/backend/mfem/model/computations/potential_infinity.hpp" #include"serif/backend/mfem/model/computations/pressure_boundary.hpp" #include"serif/model/equilibrium_plan.hpp" #include"serif/backend/mfem/geometry/deformation/computations.hpp" #include"serif/backend/mfem/model/volume_displacement.hpp" #include"serif/backend/mfem/geometry/surface/boundary_computations.hpp" #include"serif/model/keys.hpp" #include"serif/model/plan.hpp" namespaceserif::model{ namespacedetail{ template<typenameLayout,typenameOwner,typename...ContributionKeys> [[nodiscard]]autophysical_system_computation(Layoutlayout,std::shared_ptr<constOwner>owner, utils::dependencies::KeyList<ContributionKeys...>){ usingnamespaceutils::dependencies; usingnamespacediscretization::blocks; usingnamespaceutils::errors; conststd::size_trows=layout.templatetotal_size<RepresentedValueKind::residual>(); conststd::size_tcolumns=layout.templatetotal_size<RepresentedValueKind::value>(); serif_ensure<SERiFErrorCode::INVALID_DOF_COUNT>(rows<=std::numeric_limits<int>::max()&&columns<=std::numeric_limits<int>::max(),"Stellarsystemdimensionsexceedthebackend'sintegerrange."); returnmake_computation<keys::PhysicalSystem,InputList<ContributionKeys...>>([layout,owner=std::move(owner)](constauto&...contributions){ computations::Contributionscombined; combined.actions.emplace(); constautoappend=[&](constcomputations::Contributions&part){ combined.residual.insert(combined.residual.end(),part.residual.begin(),part.residual.end()); combined.jacobian.insert(combined.jacobian.end(),part.jacobian.begin(),part.jacobian.end()); combined.replacements.insert(combined.replacements.end(),part.replacements.begin(),part.replacements.end()); constauto&actions=part.actions?*part.actions:part.jacobian; combined.actions->insert(combined.actions->end(),actions.begin(),actions.end()); }; (append(contributions),...); returnbackend::mfem::make_physical_system( static_cast<int>(layout.templatetotal_size<RepresentedValueKind::residual>()), static_cast<int>(layout.templatetotal_size<RepresentedValueKind::value>()), std::move(combined.residual),std::move(combined.jacobian),std::move(combined.replacements),owner,std::move(combined.actions)); }); } template<typename...Equations,typename...Additional> [[nodiscard]]constevalautocontribution_keys(utils::types::TypeList<Equations...>,utils::dependencies::KeyList<Additional...>){ returnutils::dependencies::KeyList<computations::InteriorContribution<typename Equations::Test>...,Additional...>{}; } template<typenameRegistry,typenameDiscretization,typenameLayout,typename...Equations> [[nodiscard]]autointerior_computations(conststd::shared_ptr<constRegistry>&registry,constDiscretization&discretization, constLayout&layout,operators::backend::mfem::VolumeOptionsoptions,utils::types::TypeList<Equations...>){ returnstd::tuple_cat(operators::backend::mfem::make_volume_equation_computations<typename Equations::Test>( std::shared_ptr<constEquations>(registry,&registry->templateget<Equations>()), discretization.templateequation_discretization<typenameEquations::Test>(),options)..., computations::interior_computations<Equations>(layout)...); } } template<ExecutableInteriorEquationsRegistry,typenameDiscretization,discretization::blocks::SystemLayoutTypeLayout, typename...AdditionalComputations,typename...AdditionalContributions> [[nodiscard]]automake_model_graph(std::shared_ptr<constRegistry>registry,std::shared_ptr<constDiscretization>discretization, constLayout&layout,std::tuple<AdditionalComputations...>additional={}, utils::dependencies::KeyList<AdditionalContributions...>contributions={},operators::backend::mfem::VolumeOptionsoptions={}){ usingnamespaceutils::errors; usingEquations=typenameRegistry::Equations; serif_ensure<SERiFErrorCode::INVALID_ARGUMENT>(registry!=nullptr&&discretization!=nullptr,"Modelgraphconstructionrequiresanowningequationregistryanddiscretizationbinding."); constautointerior=detail::interior_computations(registry,*discretization,layout,options,Equations{}); constautophysical=detail::physical_system_computation(layout,discretization,detail::contribution_keys(Equations{},contributions)); returnstd::apply([](auto...computations){ returnutils::dependencies::make_computation_graph(std::move(computations)...); },std::tuple_cat(interior,std::move(additional),std::tuple{physical})); } template<ExecutableInteriorEquationsRegistry,typenameDiscretization,discretization::blocks::SystemLayoutTypeLayout, typename...AdditionalComputations,typename...AdditionalContributions> [[nodiscard]]automake_model_graph(Registryregistry,std::shared_ptr<constDiscretization>discretization, constLayout&layout,std::tuple<AdditionalComputations...>additional={}, utils::dependencies::KeyList<AdditionalContributions...>contributions={},operators::backend::mfem::VolumeOptionsoptions={}){ returnmake_model_graph(std::make_shared<constRegistry>(std::move(registry)),std::move(discretization),layout,std::move(additional),contributions,std::move(options)); } namespacedetail{ template<typenameBound,typenameLayout> [[nodiscard]]autoshape_computations(conststd::shared_ptr<constBound>&bound,constLayout&layout){ namespacedeformation=geometry::deformation::backend::mfem; namespaceexecution=operators::backend::mfem; ifconstexpr(Bound::Plan::has_shape){ usingSurface=std::remove_cvref_t<decltype(bound->discretization->deformation.model.surface)>; usingMetadata=typenameexecution::volume_keys::Scoped<discretization::blocks::gravity::potential>::Bindings; constauto&displacement=bound->discretization->templatebinding<discretization::blocks::displacement::vector>(); returnstd::tuple_cat(deformation::make_deformation_computations<Surface>(), deformation::make_volume_displacement_computations<Metadata>(displacement), std::tuple{computations::shape_derivatives(displacement), computations::surface_potential_contribution(bound->definition.shape_force,layout)}); } else{ returnstd::tuple{}; } } template<typenameBound,typenameLayout> [[nodiscard]]autoboundary_computations(constBound&,constLayout&layout){ usingPlan=typenameBound::Plan; ifconstexpr(Plan::has_surface){ usingFormulation=typenamePlan::Surface::Formulation; returnstd::tuple_cat(geometry::surface::backend::mfem::make_pressure_boundary_computations<Formulation>(), std::tuple{computations::pressure_boundary_contribution<Formulation>(layout)}); } else{ returnstd::tuple{}; } } template<typenamePlan> [[nodiscard]]constevalautoequilibrium_contribution_keys(){ usingnamespaceutils::dependencies; usingShape=std::conditional_t<Plan::has_shape, KeyList<computations::ShapeContribution>,KeyList<>>; usingSurface=std::conditional_t<Plan::has_surface,KeyList<computations::PressureBoundaryContribution>,KeyList<>>; usingInfinity=std::conditional_t<Plan::has_primal_gravity,KeyList<computations::PotentialInfinityContribution>,KeyList<>>; returnCombinedKeyList<Shape,Surface,Infinity>{}; } } template<typenameBound,typenameLayout,typename...NumericalComputations> [[nodiscard]]automake_equilibrium_graph(std::shared_ptr<constBound>bound,constLayout&layout, std::tuple<NumericalComputations...>numerical={},operators::backend::mfem::VolumeOptionsoptions={}){ usingnamespaceutils::errors; usingDescription=typenameBound::Description; usingRegistry=typenameDescription::InteriorEquations; serif_ensure<SERiFErrorCode::INVALID_ARGUMENT>(bound!=nullptr,"Anequilibriumgraphrequiresaboundmodelowner.Bindthephysicaldescriptionanddiscretizationbeforeconstructingthegraph."); constautoshape=detail::shape_computations(bound,layout); constautosurface=detail::boundary_computations(*bound,layout); constautoinfinity=[&](){ ifconstexpr(Bound::Plan::has_primal_gravity){ returnstd::tuple{computations::potential_infinity_contribution(layout, bound->discretization->templatebinding<discretization::blocks::gravity::potential>())}; }else{ returnstd::tuple{}; } }(); constautocontributions=detail::equilibrium_contribution_keys<typename Bound::Plan>(); returnmake_model_graph(std::shared_ptr<constRegistry>(bound,&bound->definition.interior_equations),bound,layout, std::tuple_cat(shape,surface,infinity,std::move(numerical)),contributions,options); } }