surface_metric.cpp serif/backend/mfem/geometry/deformation/surface_metric.hpp cmath cstddef span mfem/fem/bilininteg.hpp mfem/fem/fespace.hpp mfem/linalg/densemat.hpp serif/backend/mfem/geometry/deformation/reference_geometry.hpp serif/backend/mfem/shared/boundary_elements.hpp serif serif::geometry serif::geometry::deformation serif::geometry::deformation::backend serif::geometry::deformation::backend::mfem #include"serif/backend/mfem/geometry/deformation/surface_metric.hpp" #include<cmath> #include<cstddef> #include<span> #include"mfem/fem/bilininteg.hpp" #include"mfem/fem/fespace.hpp" #include"mfem/linalg/densemat.hpp" #include"serif/backend/mfem/geometry/deformation/reference_geometry.hpp" #include"serif/backend/mfem/shared/boundary_elements.hpp" namespaceserif::geometry::deformation::backend::mfem{ namespace{ voidinclude_radial_directions(::mfem::DenseMatrix&mass,std::span<constint>surface_nodes,std::span<constint>encoded_dofs,constSurfaceEmbedding&embedding){ for(introw=0;row<mass.Height();++row){ for(intcolumn=0;column<mass.Width();++column){ doubleradial_product=0.0; for(std::size_tcomponent=0;component<3;++component){ radial_product+=embedding.radial_directions()[surface_nodes[row]][component]*embedding.radial_directions()[surface_nodes[column]][component]; } constdoubleorientation=(encoded_dofs[row]<0)==(encoded_dofs[column]<0)?1.0:-1.0; mass(row,column)*=orientation*radial_product; } } } voidadd_parameter_metric(const::mfem::DenseMatrix&mass,std::span<constint>surface_nodes,constSurfaceEmbedding&embedding,std::span<longdouble>diagonal){ if(embedding.has_nodal_parameters()){ for(introw=0;row<mass.Height();++row){ diagonal[surface_nodes[row]]+=mass(row,row); } return; } conststd::span<constdouble>basis=embedding.nodal_basis(); for(std::size_tparameter=0;parameter<embedding.input_size();++parameter){ longdoubleentry=0.0L; for(introw=0;row<mass.Height();++row){ constdoublefirst=basis[static_cast<std::size_t>(surface_nodes[row])*embedding.input_size()+parameter]; for(intcolumn=0;column<mass.Width();++column){ constdoublesecond=basis[static_cast<std::size_t>(surface_nodes[column])*embedding.input_size()+parameter]; entry+=static_cast<longdouble>(first)*mass(row,column)*second; } } diagonal[parameter]+=entry; } } }//namespace std::expected<std::vector<double>,DeformationFailure>detail::surface_parameter_mass_diagonal(const::mfem::FiniteElementSpace&scalar_space,intsurface_attribute,constReferenceSurface&reference_surface,constSurfaceEmbedding&embedding){ namespaceshared=::serif::backend::mfem::shared; std::vector<longdouble>diagonal(embedding.input_size(),0.0L); ::mfem::DenseMatrixmass; ::mfem::MassIntegratorintegrator; constshared::BoundaryStatusstatus=shared::for_each_boundary_element(scalar_space,surface_attribute,reference_surface.scalar_dofs, [&](constshared::BoundaryElement&element)->shared::BoundaryStatus{ integrator.AssembleElementMatrix(element.finite_element,element.transformation,mass); include_radial_directions(mass,element.selected_nodes,element.encoded_dofs,embedding); add_parameter_metric(mass,element.selected_nodes,embedding,diagonal); return{}; }); if(!status){ returnstd::unexpected(DeformationFailure{.reason=DeformationFailureReason::incompatible_discretization,.message=status.error().message,.element=status.error().element}); } std::vector<double>result(diagonal.size()); for(std::size_tparameter=0;parameter<diagonal.size();++parameter){ result[parameter]=static_cast<double>(diagonal[parameter]); if(!std::isfinite(result[parameter])||result[parameter]<=0.0){ returnstd::unexpected(DeformationFailure{.reason=DeformationFailureReason::invalid_geometry,.message="Ashapeparameterhasanonpositiveornon-finitereferenceboundarymassnorm."}); } } returnresult; } std::expected<std::vector<double>,DeformationFailure>surface_parameter_mass_diagonal(const::mfem::FiniteElementSpace&scalar_space,intsurface_attribute,constReferenceSurface&reference_surface,constSurfaceEmbedding&embedding){ if(constDeformationStatusstatus=validate_surface_trace(scalar_space,surface_attribute,reference_surface,embedding);!status){ returnstd::unexpected(status.error()); } returndetail::surface_parameter_mass_diagonal(scalar_space,surface_attribute,reference_surface,embedding); } }//namespaceserif::geometry::deformation::backend::mfem