computations.hpp algorithm utility serif/geometry/deformation/backend/mfem/inputs.hpp serif/geometry/deformation/backend/mfem/radial_interpolation.hpp serif/geometry/deformation/backend/mfem/surface_metric.hpp serif/geometry/deformation/surface_embedding.hpp serif serif::geometry serif::geometry::deformation serif::geometry::deformation::backend serif::geometry::deformation::backend::mfem serif::geometry::deformation::backend::mfem::detail #pragmaonce #include<algorithm> #include<utility> #include"serif/geometry/deformation/backend/mfem/inputs.hpp" #include"serif/geometry/deformation/backend/mfem/radial_interpolation.hpp" #include"serif/geometry/deformation/backend/mfem/surface_metric.hpp" #include"serif/geometry/deformation/surface_embedding.hpp" namespaceserif::geometry::deformation::backend::mfem { namespacedetail { template<typenameValue> [[nodiscard]]std::expected<std::shared_ptr<constValue>,DeformationFailure>share_reference_result(std::expected<Value,DeformationFailure>result) { if(!result) { returnstd::unexpected(result.error()); } returnstd::make_shared<constValue>(std::move(*result)); } [[nodiscard]]inlinestd::expected<RadialInterpolation,DeformationFailure>compile_radial_reference(constReferenceDiscretization&input,conststd::vector<int>&selected) { const::mfem::Mesh*mesh=input.scalar_space.GetMesh(); if(!mesh) { returnstd::unexpected(DeformationFailure{.reason=DeformationFailureReason::incompatible_discretization,.message="Radialdeformationrequiresaninitializedscalarreferencemesh."}); } std::vector<int>stellar_support(mesh->GetNE()); std::vector<int>vacuum_support(mesh->GetNE()); for(intelement=0;element<mesh->GetNE();++element) { constintattribute=mesh->GetAttribute(element); stellar_support[element]=std::ranges::find(input.stellar_attributes,attribute)!=input.stellar_attributes.end(); vacuum_support[element]=std::ranges::find(input.vacuum_attributes,attribute)!=input.vacuum_attributes.end(); if(stellar_support[element]==0&&vacuum_support[element]==0) { returnstd::unexpected(DeformationFailure{.reason=DeformationFailureReason::incompatible_discretization,.message="Avolumeelementbelongstoneitherthestellarnorvacuumdeformationsupport.",.element=element}); } } returndetail::build_radial_interpolation(input.scalar_space,input.displacement_space,input.logical_mesh,stellar_support,vacuum_support,input.surface_attribute,input.infinity_attribute,selected); } }//namespacedetail [[nodiscard]]inlineautomake_surface_metric_computation() { usingnamespaceutils::dependencies; returnmake_computation<keys::SurfaceMetric,InputList<keys::SurfaceDiscretization,keys::ReferenceSurface,keys::SurfaceMap>>( [](constSurfaceDiscretization&input,conststd::shared_ptr<constReferenceSurface>&reference,conststd::shared_ptr<constSurfaceEmbedding>&surface)->std::expected<std::vector<double>,DeformationFailure> { if(!reference||!surface) { returnstd::unexpected(DeformationFailure{.reason=DeformationFailureReason::invalid_configuration,.message="Theshapemetricrequirescompiledsurfacereferencegeometryanditsembedding."}); } returndetail::surface_parameter_mass_diagonal(input.scalar_space,input.surface_attribute,*reference,*surface); }); } template<typenameSurface> requiresrequires(constSurface&model,std::span<conststd::array<double,3>>positions) { {build_surface_embedding(model,positions)}->std::same_as<std::expected<SurfaceEmbedding,DeformationFailure>>; } [[nodiscard]]automake_deformation_computations() { usingnamespaceutils::dependencies; constautosurface_nodes=make_computation<keys::SurfaceNodes,InputList<keys::SurfaceDiscretization>>( [](constSurfaceDiscretization&input) { returnselect_surface_scalar_dofs(input.scalar_space,input.surface_attribute); }); constautoreference_surface=make_computation<keys::ReferenceSurface,InputList<keys::SurfaceDiscretization,keys::ReferenceCoordinates,keys::SurfaceNodes>>( [](constSurfaceDiscretization&input,const::mfem::FiniteElementSpace&,conststd::vector<int>&selected) { returndetail::share_reference_result(detail::sample_reference_surface(input.scalar_space,selected)); }); constautoradial_interpolation=make_computation<keys::RadialInterpolation,InputList<keys::ReferenceDiscretization,keys::SurfaceNodes>>( [](constReferenceDiscretization&input,conststd::vector<int>&selected) { returndetail::share_reference_result(detail::compile_radial_reference(input,selected)); }); constautosurface_map=make_computation<keys::SurfaceMap,InputList<keys::ReferenceSurface,keys::SurfaceModel>>( [](conststd::shared_ptr<constReferenceSurface>&reference,constSurface&model) { returndetail::share_reference_result(build_surface_embedding(model,reference->positions)); }); constautoextension=make_computation<keys::VolumeExtension,InputList<keys::RadialInterpolation,keys::InteriorModel,keys::VacuumModel>>( [](conststd::shared_ptr<constRadialInterpolation>&interpolation,constPowerLawRadialExtension&interior,constFixedInfinityRadialExtension&vacuum) { returndetail::share_reference_result(make_radial_extension(interpolation,interior,vacuum)); }); returnstd::tuple_cat(std::tuple{surface_nodes,reference_surface,radial_interpolation,surface_map,extension},deformation::make_deformation_computations<SurfaceEmbedding, RadialExtension>()); } template<typenameSurface> [[nodiscard]]automake_deformation_graph() { returnstd::apply([](auto...computations) { returnutils::dependencies::make_computation_graph(std::move(computations)...); }, make_deformation_computations<Surface>()); } }//namespaceserif::geometry::deformation::backend::mfem