binding.hpp tuple utility serif/model/computations/point_constraints.hpp serif/model/equilibrium_plan.hpp serif/model/backend/mfem/inputs.hpp serif/geometry/surface/backend/mfem/pressure_boundary.hpp serif/geometry/deformation/backend/mfem/inputs.hpp src/include/serif/model/backend/mfem/equilibrium.hpp serif::model::backend::mfem::BoundModel serif serif::model serif::model::backend serif::model::backend::mfem serif::model::backend::mfem::detail #pragmaonce #include<tuple> #include<utility> #include"serif/model/computations/point_constraints.hpp" #include"serif/model/equilibrium_plan.hpp" #include"serif/model/backend/mfem/inputs.hpp" #include"serif/geometry/surface/backend/mfem/pressure_boundary.hpp" #include"serif/geometry/deformation/backend/mfem/inputs.hpp" namespaceserif::model::backend::mfem { template<typenameModel,typenameDescriptionT,typenameDiscretization,typenameBoundary,typenameConstraintsT,typenamePlanT> structBoundModel { usingDescription=DescriptionT; usingConstraintBindings=ConstraintsT; usingPlan=PlanT; std::shared_ptr<constModel>model; Descriptiondefinition; std::shared_ptr<constDiscretization>discretization; Boundaryboundary; ConstraintBindingsconstraints; template<typenameRow> [[nodiscard]]autoequation_discretization()const { returndiscretization->templateequation_discretization<Row>(); } }; template<utils::dependencies::IsKeyListPrescribed=utils::dependencies::KeyList<>,typenameModel,typenameDiscretization,typenameCoefficients> [[nodiscard]]autobind_model_definition(std::shared_ptr<constModel>model,std::shared_ptr<constDiscretization>discretization, constCoefficients&coefficients) { usingnamespaceutils::errors; serif_ensure<SERiFErrorCode::INVALID_ARGUMENT>(model!=nullptr&&discretization!=nullptr,"Bindingastellarmodelrequiresbothanowningphysicaldescriptionandanowningdiscretization."); autodefinition=resolve_equilibrium_equations(*model); usingDescription=decltype(definition); usingAvailableFields=typenameCoefficients::Keys; usingPlan=EquilibriumPlan<typename Model::EquationOfState, Description, Prescribed, AvailableFields>; static_assert(Plan::Surface::supported, "Theisobaricconditionhasnouniquesupportedequation.ChecktheEOSrelations,availableboundaryfields,derivativesandsolvedequationrows.ForgenuinelyambiguousrowsanequationmaynameitsIsobaricSurfaceField."); detail::validate_coefficient_owners(*discretization,coefficients,typenamePlan::Coefficients{}); constautoboundary=[&]() { ifconstexpr(Plan::has_surface&&Plan::Surface::supported) { usingFormulation=typenamePlan::Surface::Formulation; returngeometry::surface::backend::mfem::make_pressure_boundary<Formulation>(coefficients); } else { returnNoSurfaceCondition{}; } }(); autoconstraints=std::apply([&](constauto&...equation) { returnstd::tuple{computations::point_constraint_discretization(equation,*discretization)...}; },definition.constraints); usingBinding=BoundModel<Model,Description,Discretization,decltype(boundary),decltype(constraints),Plan>; returnstd::make_shared<constBinding>(Binding{.model=std::move(model),.definition=std::move(definition), .discretization=std::move(discretization),.boundary=boundary,.constraints=std::move(constraints)}); } namespacedetail { template<typenameGeometry> [[nodiscard]]std::size_tgeometry_size(constGeometry&coefficients) { ifconstexpr(requires{coefficients.Size();}) { returnstatic_cast<std::size_t>(coefficients.Size()); } else { returncoefficients.size(); } } template<typenameBound,typenameCoefficients,std::size_t...Indices> [[nodiscard]]autoconstraint_inputs(constBound&bound,constCoefficients&coefficients,std::index_sequence<Indices...>) { returnutils::dependencies::make_dependency_context(operators::backend::mfem::make_point_border_binding_input< typenamestd::tuple_element_t<Indices,typenameBound::ConstraintBindings>::Equation::Border>(std::get<Indices>(bound.constraints),coefficients)...); } } template<typenameBound,typenameCoefficients,typenameGeometry> [[nodiscard]]autoequilibrium_inputs(constBound&bound,constCoefficients&coefficients,constGeometry&geometry_coefficients) { namespaceexecution=operators::backend::mfem; usingDescription=typenameBound::Description; usingPlan=typenameBound::Plan; constauto&discretization=*bound.discretization; detail::validate_coefficient_owners(discretization,coefficients,typenamePlan::Coefficients{}); constautocommon=detail::model_inputs(discretization,coefficients,typenameDescription::InteriorEquations::Equations{},typenamePlan::Coefficients{}); constautodeformation=[&]() { ifconstexpr(Plan::has_shape) { returngeometry::deformation::backend::mfem::make_deformation_inputs(discretization.deformation.model,discretization.deformation.reference,geometry_coefficients); } else { returnutils::dependencies::make_dependency_context(utils::dependencies::own<execution::DisplacementCoefficients>( execution::bind(discretization.templatebinding<discretization::blocks::displacement::vector>(),geometry_coefficients),discretization::backend::mfem::CoefficientTracking{})); } }(); constautoshape=[&]() { ifconstexpr(Plan::has_shape) { returnutils::dependencies::make_dependency_context(execution::make_volume_binding_input<typenameDescription::ShapeForce,discretization::blocks::surface_deformation::shape_equilibrium>( discretization.templateequation_discretization<typenameDescription::ShapeForce::Test>(),coefficients)); } else { returnutils::dependencies::make_dependency_context(); } }(); constautoboundary=[&]() { usingnamespaceutils::dependencies; ifconstexpr(Plan::has_surface) { constautoeos=borrow<geometry::surface::keys::EquationOfState>(bound.model->equation_of_state(),track_by([](constauto&value) { returnstd::addressof(value); })); returngeometry::surface::backend::mfem::make_pressure_boundary_metadata(bound.boundary,eos,bound.definition.surface_condition); } else { returnmake_dependency_context(); } }(); constautoconstraints=detail::constraint_inputs(bound,coefficients,std::make_index_sequence<std::tuple_size_v<typenameBound::ConstraintBindings>>{}); returnutils::dependencies::combine_dependency_contexts(common,deformation,shape,boundary,constraints); } template<typenamePlan,typenameDiscretization,typenameGeometry> [[nodiscard]]typenamePlan::Layoutequilibrium_layout(constDiscretization&discretization,constGeometry&geometry_coefficients) { constautosize=[&]<typenameTerm>()->std::size_t { ifconstexpr(std::same_as<Term,discretization::blocks::surface_deformation::coefficients>||std::same_as<Term,discretization::blocks::surface_deformation::shape_equilibrium>) { returndetail::geometry_size(geometry_coefficients); } else { returnstatic_cast<std::size_t>(discretization.templatebinding<Term>().size()); } }; constautosizes=[&]<typename...Terms>(utils::dependencies::KeyList<Terms...>) { returnstd::array<std::size_t,sizeof...(Terms)>{size.templateoperator()<Terms>()...}; }; return{.state_sizes=sizes(typenamePlan::Values{}),.residual_sizes=sizes(typenamePlan::Residuals{})}; } }