finite_elements.hpp serif/backend/mfem/discretization/resources.hpp serif/backend/mfem/discretization/term_binding.hpp serif/backend/mfem/model/discretization.hpp serif/model/equilibrium_plan.hpp serif/model/mesh_options.hpp serif/model/stellar_model.hpp src/include/serif/model/finite_elements.hpp src/lib/serif/backend/mfem/model/finite_elements.cpp serif serif::model serif::model::backend serif::model::backend::mfem serif::model::backend::mfem::detail #pragmaonce #include"serif/backend/mfem/discretization/resources.hpp" #include"serif/backend/mfem/discretization/term_binding.hpp" #include"serif/backend/mfem/model/discretization.hpp" #include"serif/model/equilibrium_plan.hpp" #include"serif/model/mesh_options.hpp" #include"serif/model/stellar_model.hpp" namespaceserif::model::backend::mfem{ [[nodiscard]]discretization::backend::mfem::Resourcesmake_stellar_resources(constStellarMeshOptions&options); [[nodiscard]]::mfem::FiniteElementSpace&make_space(discretization::backend::mfem::Resources&resources, std::unique_ptr<::mfem::FiniteElementCollection>collection,intcomponents,intordering=::mfem::Ordering::byNODES); namespacedetail{ template<typenameSpecification> conceptReconstructionSpecification=requires{typenameSpecification::Term;}; template<typenameOwner,typename...Terms,ReconstructionSpecificationSpecification> voidapply_reconstruction(Owner&owner,utils::dependencies::KeyList<Terms...>,constSpecification&specification){ usingnamespaceutils::errors; usingTerm=typenameSpecification::Term; usingKeys=utils::dependencies::KeyList<Terms...>; ifconstexpr(!(std::same_as<Term,Terms>||...)){ serif_error<std::invalid_argument,SERiFErrorCode::INVALID_ARGUMENT>("Thereconstruction'sfieldisnotpresentinthisstellarmodel."); }else{ auto&binding=std::get<utils::dependencies::key_index<Term,Keys>()>(owner.bindings); usingdiscretization::backend::mfem::make_reconstruction; ifconstexpr(requires{make_reconstruction(specification,*binding);}){ autoplan=make_reconstruction(specification,*binding); ifconstexpr(discretization::blocks::SpatialTerm<Term>){ usingBinding=typenameOwner::templateBinding<Term>; binding=std::make_unique<Binding>(binding->space(),std::move(plan)); }else{ serif_error<std::invalid_argument,SERiFErrorCode::INVALID_ARGUMENT>("Spatialreconstructioncannotbeattachedtoaglobalscalarfield."); } }else{ serif_error<std::invalid_argument,SERiFErrorCode::INVALID_ARGUMENT>("Thisreconstructionformhasnopreparationfunctionfortheselectedbackendandfield."); } } } template<ReconstructionSpecification...Specifications> voidvalidate_reconstruction_requests(){ usingnamespaceutils::errors; constexprboolunique=(([]<typenameSpecification>(){ return(0+...+int(std::same_as<typenameSpecification::Term,typenameSpecifications::Term>))==1; }.templateoperator()<Specifications>())&&...); serif_ensure<SERiFErrorCode::INVALID_ARGUMENT>(unique,"Specifyatmostonereconstructionforeachfield."); } template<discretization::blocks::SpatialTermTerm> [[nodiscard]]::mfem::FiniteElementSpace&term_space(discretization::backend::mfem::Resources&resources){ usingTraits=discretization::blocks::SpatialTermTraits<Term>; usingenumdiscretization::functional_space::Family; static_assert(Traits::rank<=1&&(Traits::family==h1||Traits::family==l2), "Theselectedbackendsupportsscalar/vectorH1andL2terms."); constexprintcomponents=Traits::rank==0?1:3; ifconstexpr(Traits::family==h1){ returnmake_space(resources,std::make_unique<::mfem::H1_FECollection>(Traits::order,3),components,components==1?::mfem::Ordering::byNODES:::mfem::Ordering::byVDIM); }else{ returnmake_space(resources,std::make_unique<::mfem::L2_FECollection>(Traits::order,3),components,components==1?::mfem::Ordering::byNODES:::mfem::Ordering::byVDIM); } } template<typename...Terms,ReconstructionSpecification...Specifications> [[nodiscard]]automake_bindings(constStellarMeshOptions&options,utils::dependencies::KeyList<Terms...>keys,constSpecifications&...specifications){ usingnamespaceutils::dependencies; usingSchema=discretization::domain::schema::CoreEnvelopeVacuumDomainSchema; usingContext=decltype(make_dependency_context(borrow<Terms>(std::declval<discretization::backend::mfem::TermBinding<Terms,Schema>&>())...)); usingOwner=discretization::backend::mfem::OwnedBindings<Context>; validate_reconstruction_requests<Specifications...>(); autoowner=std::make_shared<Owner>(); owner->resources=make_stellar_resources(options); ([&]{ usingBinding=typenameOwner::templateBinding<Terms>; auto&binding=std::get<key_index<Terms,KeyList<Terms...>>()>(owner->bindings); ifconstexpr(discretization::blocks::SpatialTerm<Terms>){ binding=std::make_unique<Binding>(term_space<Terms>(owner->resources)); }else{ binding=std::make_unique<Binding>(*owner->resources.meshes.front()); } }(),...); (apply_reconstruction(*owner,keys,specifications),...); returnowner; } } template<StellarModelTypeModel,detail::ReconstructionSpecification...Specifications> [[nodiscard]]automake_stellar_discretization(constModel&,constStellarMeshOptions&options={},constSpecifications&...specifications){ usingDescription=decltype(resolve_equilibrium_equations(std::declval<constModel&>())); usingPlan=EquilibriumPlan<typenameModel::EquationOfState,Description>; usingTerms=utils::dependencies::CombinedKeyList<typenamePlan::Coefficients, utils::dependencies::KeyList<discretization::blocks::displacement::vector>>; autoowner=detail::make_bindings(options,Terms{},specifications...); returnmake_stellar_discretization(owner,owner->context(),*owner->resources.compactification,*owner->resources.mapper); } template<StellarModelTypeModel,typenameSurface,typenameInterior,typenameVacuum,detail::ReconstructionSpecification...Specifications> [[nodiscard]]automake_stellar_discretization(constModel&model,constStellarMeshOptions&options, geometry::deformation::DomainDeformation<Surface,Interior,Vacuum>deformation,constSpecifications&...specifications){ usingDescription=decltype(resolve_equilibrium_equations(std::declval<constModel&>())); usingPlan=EquilibriumPlan<typenameModel::EquationOfState,Description>; usingTerms=utils::dependencies::CombinedKeyList<typenamePlan::Coefficients, utils::dependencies::KeyList<discretization::blocks::displacement::vector>>; autoowner=detail::make_bindings(options,Terms{},specifications...); usingDisplacement=discretization::blocks::displacement::vector; constautocontext=owner->context(); constauto*collection=context.templateget<Displacement>().space().FEColl(); auto&scalar=make_space(owner->resources,std::unique_ptr<::mfem::FiniteElementCollection>{::mfem::FiniteElementCollection::New(collection->Name())},1); auto&reference_displacement=make_space(owner->resources, std::unique_ptr<::mfem::FiniteElementCollection>{::mfem::FiniteElementCollection::New(collection->Name())},3,::mfem::Ordering::byNODES); constautoreference=geometry::deformation::backend::mfem::deformation_discretization( scalar,reference_displacement,*owner->resources.meshes[1]); returnwith_deformation(make_stellar_discretization(owner,context,*owner->resources.compactification,*owner->resources.mapper), std::move(deformation),reference); } }