h1_matrices.cpp serif/solver/preconditioner/backend/mfem/surface/fitted_h1.hpp algorithm cmath vector mfem/fem/bilininteg.hpp mfem/fem/fespace.hpp serif/geometry/deformation/backend/mfem/reference_geometry.hpp serif serif::solver serif::solver::preconditioner serif::solver::preconditioner::backend serif::solver::preconditioner::backend::mfem #include"serif/solver/preconditioner/backend/mfem/surface/fitted_h1.hpp" #include<algorithm> #include<cmath> #include<vector> #include"mfem/fem/bilininteg.hpp" #include"mfem/fem/fespace.hpp" #include"serif/geometry/deformation/backend/mfem/reference_geometry.hpp" namespaceserif::solver::preconditioner::backend::mfem { std::expected<SurfaceH1Matrices,Failure>try_surface_h1_matrices(const::mfem::FiniteElementSpace&scalar_space,intsurface_attribute,constgeometry::deformation::ReferenceSurface&reference_surface,constgeometry::deformation::SurfaceEmbedding&embedding) { usingutils::errors::SERiFErrorCode; namespacedeformation=geometry::deformation; if(!embedding.has_nodal_parameters()) { returnstd::unexpected(Failure{.code=SERiFErrorCode::PRECONDITIONER_INCOMPATIBLE_STRATEGY,.message="ThesurfaceH1strategyrequiresnodalradialshapeparameters.Usenativereferencemassforaharmonicsurface."}); } constautocurrent=deformation::backend::mfem::sample_reference_surface(scalar_space,surface_attribute); if(!current) { returnstd::unexpected(Failure{.code=SERiFErrorCode::PRECONDITIONER_INVALID_OPERATOR,.message=current.error().message}); } if(reference_surface.scalar_dofs!=current->scalar_dofs||reference_surface.positions!=current->positions||!std::ranges::equal(reference_surface.positions,embedding.reference_positions())) { returnstd::unexpected(Failure{.code=SERiFErrorCode::PRECONDITIONER_INVALID_OPERATOR,.message="SurfaceH1assemblyrequiresthesameorderedreferencetraceasthenodalsurfaceembedding.Rebuildthereferencesurfaceandembeddingtogether."}); } constintsize=static_cast<int>(reference_surface.scalar_dofs.size()); automass=std::make_shared<::mfem::SparseMatrix>(size); autostiffness=std::make_shared<::mfem::SparseMatrix>(size); std::vector<int>surface_index(scalar_space.GetNDofs(),-1); for(intnode=0;node<size;++node) { surface_index[reference_surface.scalar_dofs[node]]=node; } ::mfem::MassIntegratormass_integrator; ::mfem::DiffusionIntegratorstiffness_integrator; ::mfem::Array<int>dofs; ::mfem::DenseMatrixelement_mass,element_stiffness; for(intboundary=0;boundary<scalar_space.GetMesh()->GetNBE();++boundary) { if(scalar_space.GetMesh()->GetBdrAttribute(boundary)!=surface_attribute) { continue; } if(scalar_space.GetBdrElementDofs(boundary,dofs)!=nullptr||scalar_space.GetBE(boundary)->GetDof()!=dofs.Size()) { returnstd::unexpected(Failure{.code=SERiFErrorCode::PRECONDITIONER_INCOMPATIBLE_STRATEGY,.message="SurfaceH1assemblyrequiresacanonicalscalarnodaltracewithoutadditionalDOFtransformations."}); } const::mfem::FiniteElement&element=*scalar_space.GetBE(boundary); ::mfem::ElementTransformation&transformation=*scalar_space.GetBdrElementTransformation(boundary); mass_integrator.AssembleElementMatrix(element,transformation,element_mass); stiffness_integrator.AssembleElementMatrix(element,transformation,element_stiffness); for(introw=0;row<dofs.Size();++row) { constintsurface_row=surface_index[::mfem::FiniteElementSpace::DecodeDof(dofs[row])]; for(intcolumn=0;column<dofs.Size();++column) { constintsurface_column=surface_index[::mfem::FiniteElementSpace::DecodeDof(dofs[column])]; if(surface_row<0||surface_column<0||!std::isfinite(element_mass(row,column))||!std::isfinite(element_stiffness(row,column))) { returnstd::unexpected(Failure{.code=SERiFErrorCode::PRECONDITIONER_INVALID_OPERATOR,.message="SurfaceH1assemblyencounteredanunmappednodeornonfiniteelemententry.Checkthereferencetraceandgeometry."}); } constdoubleorientation=(dofs[row]<0)==(dofs[column]<0)?1.0:-1.0; mass->Add(surface_row,surface_column,orientation*element_mass(row,column)); stiffness->Add(surface_row,surface_column,orientation*element_stiffness(row,column)); } } } mass->Finalize(); stiffness->Finalize(); returnSurfaceH1Matrices{.mass=std::move(mass),.stiffness=std::move(stiffness)}; } }//namespaceserif::solver::preconditioner::backend::mfem