graph.hpp limits memory tuple utility serif/model/computations/interior.hpp serif/model/computations/shape.hpp serif/model/computations/point_constraints.hpp serif/model/computations/pressure_boundary.hpp serif/model/equilibrium_plan.hpp serif/geometry/deformation/backend/mfem/computations.hpp serif/geometry/deformation/backend/mfem/volume_displacement.hpp serif/geometry/surface/backend/mfem/boundary_computations.hpp serif/model/keys.hpp serif/model/plan.hpp src/include/serif/model/backend/mfem/equilibrium.hpp serif serif::model serif::model::detail #pragmaonce #include<limits> #include<memory> #include<tuple> #include<utility> #include"serif/model/computations/interior.hpp" #include"serif/model/computations/shape.hpp" #include"serif/model/computations/point_constraints.hpp" #include"serif/model/computations/pressure_boundary.hpp" #include"serif/model/equilibrium_plan.hpp" #include"serif/geometry/deformation/backend/mfem/computations.hpp" #include"serif/geometry/deformation/backend/mfem/volume_displacement.hpp" #include"serif/geometry/surface/backend/mfem/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_accepted_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<typenameEquations::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)..., std::tuple{computations::interior_contribution<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,operators::backend::mfem::VolumeOptionsoptions) { usingDescription=typenameBound::Description; namespacedeformation=geometry::deformation::backend::mfem; namespaceexecution=operators::backend::mfem; usingShapeRow=discretization::blocks::surface_deformation::shape_equilibrium; ifconstexpr(Bound::Plan::has_shape) { usingForce=typenameDescription::ShapeForce; usingSurface=std::remove_cvref_t<decltype(bound->discretization->deformation.model.surface)>; usingMetadata=typenameexecution::volume_keys::Scoped<ShapeRow>::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), execution::make_volume_equation_computations<ShapeRow>(std::shared_ptr<constForce>(bound,&bound->definition.shape_force), bound->templateequation_discretization<typenameForce::Test>(),options), std::tuple{computations::shape_derivatives(displacement),computations::shape_contribution<Force>(layout)}); } else { returnstd::tuple{}; } } template<typenameBound,typenameLayout,std::size_t...Indices> [[nodiscard]]autoconstraint_computations(constBound&bound,constLayout&layout,std::index_sequence<Indices...>) { returnstd::tuple_cat(computations::make_point_constraint_computations( std::get<Indices>(bound.definition.constraints),std::get<Indices>(bound.constraints),layout)...); } 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,typename...Constraints> [[nodiscard]]constevalautoequilibrium_contribution_keys(std::tuple<Constraints...>*) { usingnamespaceutils::dependencies; usingShape=std::conditional_t<Plan::has_shape, KeyList<computations::ShapeContribution>,KeyList<>>; usingSurface=std::conditional_t<Plan::has_surface,KeyList<computations::PressureBoundaryContribution>,KeyList<>>; returnCombinedKeyList<Shape,Surface,KeyList<computations::PointConstraintContribution<typenameConstraints::Border>...>>{}; } } 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; usingConstraints=typenameDescription::Constraints; serif_ensure<SERiFErrorCode::INVALID_ARGUMENT>(bound!=nullptr,"Anequilibriumgraphrequiresaboundmodelowner.Bindthephysicaldescriptionanddiscretizationbeforeconstructingthegraph."); constautoshape=detail::shape_computations(bound,layout,options); constautosurface=detail::boundary_computations(*bound,layout); constautoconstraints=detail::constraint_computations(*bound,layout,std::make_index_sequence<std::tuple_size_v<Constraints>>{}); constautocontributions=detail::equilibrium_contribution_keys<typename Bound::Plan>(static_cast<Constraints*>(nullptr)); returnmake_model_graph(std::shared_ptr<constRegistry>(bound,&bound->definition.interior_equations),bound,layout, std::tuple_cat(shape,surface,constraints,std::move(numerical)),contributions,options); } }