fitted_h1.cpp serif/solver/preconditioner/backend/mfem/surface/fitted_h1.hpp cmath serif/solver/preconditioner/backend/mfem/surface/detail/calibration.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<cmath> #include"serif/solver/preconditioner/backend/mfem/surface/detail/calibration.hpp" namespaceserif::solver::preconditioner::backend::mfem { std::expected<FittedSurfaceOperator,Failure>try_fitted_surface_h1(constSurfaceH1Matrices&matrices,constSurfaceTargets&targets,strategies::surface::FittedSurfaceH1options) { usingutils::errors::SERiFErrorCode; if(options.probe_count<3||options.probe_count>64) { returnstd::unexpected(Failure{.code=SERiFErrorCode::PRECONDITIONER_INVALID_OPTIONS,.message="SurfaceH1calibrationrequiresbetweenthreeand64deterministicprobes."}); } if(!matrices.mass||!matrices.stiffness||!matrices.mass->Finalized()||!matrices.stiffness->Finalized()) { returnstd::unexpected(Failure{.code=SERiFErrorCode::PRECONDITIONER_INVALID_OPERATOR,.message="SurfaceH1calibrationrequiresfinalizedreferencemassandstiffnessmatrices.Completereferenceassemblybeforepreparingthefit."}); } constintsize=matrices.mass->Height(); if(size<=0||matrices.mass->Width()!=size||matrices.stiffness->Height()!=size||matrices.stiffness->Width()!=size) { returnstd::unexpected(Failure{.code=SERiFErrorCode::PRECONDITIONER_SIZE_MISMATCH,.message="SurfaceH1massandstiffnessmustbenonemptysquarematricesinthesamenativenodallayout."}); } constautotarget=detail::surface_target(targets,options.target,size); if(!target) { returnstd::unexpected(target.error()); } strategies::surface::SurfaceH1Momentsmoments; ::mfem::Vectorprobe(size),mass_action(size),stiffness_action(size),target_action(size); for(intsample=0;sample<options.probe_count;++sample) { if(constautofilled=detail::fill_surface_probe(sample,probe,true);!filled) { returnstd::unexpected(filled.error()); } matrices.mass->Mult(probe,mass_action); matrices.stiffness->Mult(probe,stiffness_action); target_action=0.0; (*target)->Mult(probe,target_action); moments.mass_mass+=mass_action*mass_action; moments.mass_stiffness+=mass_action*stiffness_action; moments.stiffness_stiffness+=stiffness_action*stiffness_action; moments.mass_target+=mass_action*target_action; moments.stiffness_target+=stiffness_action*target_action; moments.target_target+=target_action*target_action; } constautofit=strategies::surface::try_fit_surface_h1_coefficients(moments,options); if(!fit) { returnstd::unexpected(fit.error()); } std::shared_ptr<::mfem::SparseMatrix>positive(::mfem::Add(fit->mass_coefficient,*matrices.mass,fit->stiffness_coefficient,*matrices.stiffness)); for(intentry=0;entry<positive->NumNonZeroElems();++entry) { if(!std::isfinite(positive->GetData()[entry])) { returnstd::unexpected(Failure{.code=SERiFErrorCode::PRECONDITIONER_NONFINITE_VALUE,.message="ThefittedpositivesurfaceH1matrixcontainsanonfiniteentry.Rescalethereferenceunits."}); } } returnFittedSurfaceOperator{.positive_operator=std::move(positive),.fit=*fit}; } }//namespaceserif::solver::preconditioner::backend::mfem