model.hpp serif/utils/serialize/equations.hpp serif/model/state.hpp serif/model/stellar_model.hpp serif/discretization/blocks/fields.hpp serif/utils/dependencies/dependency_context.hpp src/include/serif/backend/mfem/serialize/discretization.hpp src/include/serif/utils/serialize/numerics.hpp src/include/serif/utils/serialize/solver.hpp serif::utils::serialize::TermIdentity serif::utils::serialize::TermIdentity< discretization::blocks::density::mass > serif::utils::serialize::TermIdentity< discretization::blocks::gravity::potential > serif::utils::serialize::TermIdentity< discretization::blocks::displacement::vector > serif::utils::serialize::TermIdentity< discretization::blocks::rotation::angular_velocity > serif::utils::serialize::TermIdentity< discretization::blocks::barotropic_constant::mass_normalization > serif::utils::serialize::TermIdentity< discretization::blocks::surface_deformation::coefficients > serif::utils::serialize::TermIdentity< discretization::blocks::surface_deformation::shape_equilibrium > serif::utils::serialize::TermIdentity< model::GeneratedCoordinateOf< Specification > > serif::utils::serialize::TermIdentity< model::ConstraintOf< Specification > > serif::utils::serialize::Serializer< dependencies::KeyList< Terms... > > serif::utils::serialize::Serializer< discretization::blocks::SystemLayout< Values, Residuals > > serif::utils::serialize::Serializer< model::StellarState< Layout > > serif::utils::serialize::Serializer< model::NoShapeForce > serif::utils::serialize::Serializer< model::NoSurfaceCondition > serif::utils::serialize::Serializer< model::EquilibriumEquations< Interior, Shape, Surface > > serif::utils::serialize::Serializer< model::StellarModel< EOS, Definition, types::TypeList< Specifications... > > > serif::utils::serialize::Serializer< dependencies::ValueSnapshot > serif::utils::serialize::Serializer< dependencies::Resource< Key, Storage, Policy > > serif::utils::serialize::Serializer< dependencies::DependencyContext< Resources... > > serif::utils::serialize::Serializer< dependencies::DependencyContext<> > serif serif::utils serif::utils::serialize serif::utils::serialize::detail #pragmaonce #include"serif/utils/serialize/equations.hpp" #include"serif/model/state.hpp" #include"serif/model/stellar_model.hpp" #include"serif/discretization/blocks/fields.hpp" #include"serif/utils/dependencies/dependency_context.hpp" namespaceserif::utils::serialize{ template<typenameTerm> structTermIdentity{ staticconstexprstd::string_viewid=[]{ ifconstexpr(requires{Term::stable_id;}){returnstd::string_view{Term::stable_id};} else{returnstd::string_view{};} }(); }; template<>structTermIdentity<discretization::blocks::density::mass>{staticconstexprstd::string_viewid="density.mass";}; template<>structTermIdentity<discretization::blocks::gravity::potential>{staticconstexprstd::string_viewid="gravity.potential";}; template<>structTermIdentity<discretization::blocks::displacement::vector>{staticconstexprstd::string_viewid="displacement.vector";}; template<>structTermIdentity<discretization::blocks::rotation::angular_velocity>{staticconstexprstd::string_viewid="rotation.angular_velocity";}; template<>structTermIdentity<discretization::blocks::barotropic_constant::mass_normalization>{staticconstexprstd::string_viewid="barotropic_constant.mass_normalization";}; template<>structTermIdentity<discretization::blocks::surface_deformation::coefficients>{staticconstexprstd::string_viewid="surface_deformation.coefficients";}; template<>structTermIdentity<discretization::blocks::surface_deformation::shape_equilibrium>{staticconstexprstd::string_viewid="surface_deformation.shape_equilibrium";}; template<typenameSpecification> structTermIdentity<model::GeneratedCoordinateOf<Specification>>{ staticconstexprstd::string_viewid=Specification::ModelDefinition::ScalarDescription::coordinate_id; }; template<typenameSpecification> structTermIdentity<model::ConstraintOf<Specification>>{ staticconstexprstd::string_viewid=Specification::ModelDefinition::ScalarDescription::residual_id; }; template<typenameTerm> [[nodiscard]]Nodeterm_schema(){ ifconstexpr(TermIdentity<Term>::id.empty()){ return{.type="unsupported",.value=std::string{"RegisterTermIdentity<T>orT::stable_idforthiscoordinate."}}; }else{ Noderesult=object("coordinate",field("id",std::string{TermIdentity<Term>::id})); ifconstexpr(requires{typenameTerm::Quantity;}){ result.children.emplace("dimension",encode(std::string{Term::Quantity::identifier})); } ifconstexpr(requires{typenameTerm::FunctionalSpace;}){ usingSpace=typenameTerm::FunctionalSpace; constexprstd::arraynames{"l2","h1","hdiv","hcurl"}; result.children.emplace("space",object("functional_space",field("family",std::string{names[static_cast<std::size_t>(Space::functional_space.family)]}), field("order",Space::order),field("rank",Space::rank::value))); } ifconstexpr(requires{Term::Support::names;}){ std::vector<std::string>support; for(std::string_viewname:Term::Support::names){support.emplace_back(name);} result.children.emplace("support",encode(support)); } ifconstexpr(std::same_as<Term,discretization::blocks::surface_deformation::coefficients>||std::same_as<Term,discretization::blocks::surface_deformation::shape_equilibrium>){ constexprboolcoefficients=std::same_as<Term,discretization::blocks::surface_deformation::coefficients>; result.children.emplace("dimension",encode(std::string{coefficients?"length":"force"})); result.children.emplace("support",encode(std::vector<std::string>{"stellar_surface"})); result.children.emplace("basis",encode(std::string{"declared_surface_representation"})); } ifconstexpr(requires{typenameTerm::SpecificationType;}){ usingDescription=typenameTerm::SpecificationType::ModelDefinition::ScalarDescription; ifconstexpr(std::same_as<Term,model::GeneratedCoordinateOf<typenameTerm::SpecificationType>>){ result.children.emplace("dimension",encode(std::string{Description::CoordinateQuantity::identifier})); }else{ result.children.emplace("dimension",encode(std::string{Description::ResidualQuantity::identifier})); } } returnresult; } } inlineResult<void>validate_schema(constNode&saved,constNode&expected){ if(expected.type=="unsupported"){returnstd::unexpected(Error{"","Acompiledidentityhasnostableserializationregistration."});} if(saved!=expected){returnstd::unexpected(Error{"","Savedphysicalcoordinatesdonotmatchtherequestedcompiledschema."});} for(constauto&[name,child]:expected.children){ autochecked=validate_schema(child,child); if(!checked){ checked.error().path=name+(checked.error().path.empty()?"":"/"+checked.error().path); returnchecked; } } return{}; } template<typename...Terms> structSerializer<dependencies::KeyList<Terms...>>{ staticconstexprstd::string_viewkey="coordinate_list"; [[nodiscard]]staticNodesave(dependencies::KeyList<Terms...>){ Noderesult=object(key); std::size_tindex=0; (result.children.emplace(std::to_string(index++),term_schema<Terms>()),...); returnresult; } [[nodiscard]]staticResult<dependencies::KeyList<Terms...>>load(constNode&node){ autovalid=validate_schema(node,save({})); if(!valid){returnstd::unexpected(valid.error());} returndependencies::KeyList<Terms...>{}; } }; template<typenameValues,typenameResiduals> structSerializer<discretization::blocks::SystemLayout<Values,Residuals>>{ usingT=discretization::blocks::SystemLayout<Values, Residuals>; staticconstexprstd::string_viewkey="system_layout"; [[nodiscard]]staticNodesave(constT&value){ returnobject(key,field("values",Values{}),field("residuals",Residuals{}),field("state_sizes",value.state_sizes),field("residual_sizes",value.residual_sizes)); } [[nodiscard]]staticResult<T>load(constNode&node){ returnread_object(node,key,[](Values,Residuals,decltype(T::state_sizes)states,decltype(T::residual_sizes)residuals){ (void)discretization::blocks::checked_block_size(states); (void)discretization::blocks::checked_block_size(residuals); returnT{states,residuals}; },member<Values>("values"),member<Residuals>("residuals"),member<decltype(T::state_sizes)>("state_sizes"),member<decltype(T::residual_sizes)>("residual_sizes")); } }; template<typenameLayout> structSerializer<model::StellarState<Layout>>{ usingT=model::StellarState<Layout>; staticconstexprstd::string_viewkey="stellar_state"; [[nodiscard]]staticNodesave(constT&value){ returnobject(key,field("layout",value.layout()),field("coefficients",std::vector<double>{value.values().begin(),value.values().end()})); } [[nodiscard]]staticResult<T>load(constNode&node){ returnread_object(node,key,[](Layoutlayout,std::vector<double>values){returnT{std::move(layout),std::move(values)};},member<Layout>("layout"),member<std::vector<double>>("coefficients")); } }; template<> structSerializer<model::NoShapeForce>:StructSerializer<model::NoShapeForce>{ staticconstexprstd::string_viewkey="equations.no_shape"; staticconstexprautomembers=std::tuple{}; }; template<> structSerializer<model::NoSurfaceCondition>:StructSerializer<model::NoSurfaceCondition>{ staticconstexprstd::string_viewkey="equations.no_surface"; staticconstexprautomembers=std::tuple{}; }; template<typenameInterior,typenameShape,typenameSurface> structSerializer<model::EquilibriumEquations<Interior,Shape,Surface>>{ usingT=model::EquilibriumEquations<Interior, Shape, Surface>; staticconstexprstd::string_viewkey="equilibrium_equations"; [[nodiscard]]staticNodesave(constT&value){ returnobject(key,field("interior",value.interior_equations),field("shape",value.shape_force),field("surface",value.surface_condition)); } [[nodiscard]]staticResult<T>load(constNode&node)requires(!std::is_reference_v<Interior>&&!std::is_reference_v<Shape>&& !std::is_reference_v<Surface>){ returnread_object(node,key,[](Interiorinterior,Shapeshape,Surfacesurface){ returnT{std::move(interior),std::move(shape),std::move(surface)}; },member<Interior>("interior"),member<Shape>("shape"),member<Surface>("surface")); } }; template<typenameEOS,typenameDefinition,typename...Specifications> structSerializer<model::StellarModel<EOS,Definition,types::TypeList<Specifications...>>>{ usingT=model::StellarModel<EOS,Definition,types::TypeList<Specifications...>>; staticconstexprstd::string_viewkey="stellar_model"; [[nodiscard]]staticNodesave(constT&value){ Noderesult=object(key,field("eos",value.equation_of_state()),field("authored_definition",value.equations()), field("prescriptions",std::tie(value.templatespecification<Specifications>()...))); ifconstexpr(requires{model::resolve_equilibrium_equations(value);}){ result.children.emplace("resolved_equations",encode(model::resolve_equilibrium_equations(value))); } returnresult; } [[nodiscard]]staticResult<T>load(constNode&node){ returnread_object(node,key,[](EOSeos,Definitionequations,std::tuple<Specifications...>specifications){ returnstd::apply([&](auto&&...values){returnT{std::move(eos),std::move(equations),std::move(values)...};},std::move(specifications)); },member<EOS>("eos"),member<Definition>("authored_definition"),member<std::tuple<Specifications...>>("prescriptions")); } }; namespacedetail{ template<typenameModel> usingResolvedEquations=decltype(model::resolve_equilibrium_equations(std::declval<constModel&>())); template<typenameModel> usingOwnedEquations=model::EquilibriumEquations<typename ResolvedEquations<Model>::InteriorEquations,typenameResolvedEquations<Model>::ShapeForce, typenameResolvedEquations<Model>::SurfaceCondition>; } template<typenameOriginalModel> usingRestoredStellarModel=model::StellarModel<typename OriginalModel::EquationOfState, detail::OwnedEquations<OriginalModel>,typenameOriginalModel::SpecificationTypes>; template<typenameOriginalModel> [[nodiscard]]Result<RestoredStellarModel<OriginalModel>>restore_stellar_model(constNode&node){ usingT=RestoredStellarModel<OriginalModel>; Nodeowning=node; constautofound=node.children.find("resolved_equations"); if(found==node.children.end()){returnstd::unexpected(Error{"resolved_equations","Thismodelhasnosavedconcreteequilibriumdescription."});} owning.children.insert_or_assign("authored_definition",found->second); returndecode<T>(owning); } template<> structSerializer<dependencies::ValueSnapshot>:StructSerializer<dependencies::ValueSnapshot>{ staticconstexprstd::string_viewkey="tracking.value"; staticconstexprautomembers=std::tuple{}; }; template<typenameKey,typenameStorage,typenamePolicy> structSerializer<dependencies::Resource<Key,Storage,Policy>>{ usingT=dependencies::Resource<Key, Storage, Policy>; usingValue=typenameT::Target; staticconstexprstd::string_viewkey="prescribed_resource"; staticconstexprboolowned=std::same_as<Storage,dependencies::detail::OwnedValue<Value>>; [[nodiscard]]staticNodesave(constT&value){ Noderesult=object(key,field("identity",term_schema<Key>()),field("value",value.get()),field("tracking",value.policy()), field("ownership",std::string{owned?"owned":"borrowed"})); ifconstexpr(!owned){ result.children.emplace("reconstruction",Node{.type="unsupported",.value=std::string{"Borrowedprescribeddatarequiresexplicitownerreconstructionandrebinding."}}); } returnresult; } [[nodiscard]]staticResult<T>load(constNode&node){ ifconstexpr(!owned){ returnstd::unexpected(Error{"ownership","Rebindthisborrowedprescribedvaluetoanexplicitlyreconstructedowner."}); }else{ autoidentity=read_field<Node>(node,"identity"); if(!identity){returnstd::unexpected(identity.error());} autovalid=validate_schema(*identity,term_schema<Key>()); if(!valid){returnstd::unexpected(valid.error());} returnread_object(node,key,[](Valuevalue,Policypolicy,std::stringownership){ errors::serif_ensure<errors::SERiFErrorCode::INVALID_ARGUMENT>(ownership=="owned","Asavedborrowedresourcecannotsilentlybecomeanownedinput."); returnT{Storage{.value=std::move(value)},std::move(policy)}; },member<Value>("value"),member<Policy>("tracking"),member<std::string>("ownership")); } } }; template<typename...Resources> structSerializer<dependencies::DependencyContext<Resources...>>{ usingT=dependencies::DependencyContext<Resources...>; staticconstexprstd::string_viewkey="prescribed_inputs"; [[nodiscard]]staticNodesave(constT&value){ returnobject(key,field("resources",std::tie(value.templateresource<typenameResources::Key>()...))); } [[nodiscard]]staticResult<T>load(constNode&node){ returnread_object(node,key,[](std::tuple<Resources...>resources){ returnstd::apply([](auto&&...values){returnT{std::move(values)...};},std::move(resources)); },member<std::tuple<Resources...>>("resources")); } }; template<> structSerializer<dependencies::DependencyContext<>>{ staticconstexprstd::string_viewkey="prescribed_inputs"; [[nodiscard]]staticNodesave(constdependencies::DependencyContext<>&){returnobject(key);} [[nodiscard]]staticResult<dependencies::DependencyContext<>>load(constNode&node){ if(!node.children.empty()){returnstd::unexpected(Error{"","Expectednoprescribedinputs."});} returnread_object(node,key,[]{returndependencies::make_dependency_context();}); } }; }