calibrated_mass.cpp serif/solver/preconditioner/backend/mfem/surface/calibrated_mass.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/calibrated_mass.hpp" #include<cmath> #include"serif/solver/preconditioner/backend/mfem/surface/detail/calibration.hpp" namespaceserif::solver::preconditioner::backend::mfem { std::expected<SurfaceMassInverse,Failure>try_calibrated_surface_mass_inverse(std::span<constdouble>reference_metric,constSurfaceTargets&targets,strategies::surface::CalibratedSurfaceMassoptions) { usingstrategies::surface::CalibrationObjective; usingutils::errors::SERiFErrorCode; if(options.probe_count<=0||options.probe_count>64||(options.objective!=CalibrationObjective::operator_action&&options.objective!=CalibrationObjective::right_preconditioned_action)) { returnstd::unexpected(Failure{.code=SERiFErrorCode::PRECONDITIONER_INVALID_OPTIONS,.message="Surfacemasscalibrationrequiresbetweenoneand64probesandasupportedfittingobjective."}); } if(constautovalid=detail::validate_surface_metric(reference_metric);!valid) { returnstd::unexpected(valid.error()); } constintsize=static_cast<int>(reference_metric.size()); constautotarget=detail::surface_target(targets,options.target,size); if(!target) { returnstd::unexpected(target.error()); } ::mfem::Vectorprobe(size),direction(size),action(size); doublenumerator=0.0; doubledenominator=0.0; for(intsample=0;sample<options.probe_count;++sample) { if(constautofilled=detail::fill_surface_probe(sample,probe,false);!filled) { returnstd::unexpected(filled.error()); } for(intindex=0;index<size;++index) { direction[index]=options.objective==CalibrationObjective::operator_action?probe[index]:probe[index]/reference_metric[index]; if(!std::isfinite(direction[index])) { returnstd::unexpected(Failure{.code=SERiFErrorCode::PRECONDITIONER_INVALID_CALIBRATION,.message="Aright-preconditionedsurfaceprobeisnotrepresentable.Rescalethereferencemetricbeforefittingitsinverseaction."}); } } action=0.0; (*target)->Mult(direction,action); for(intindex=0;index<size;++index) { constdoublemass_action=reference_metric[index]*probe[index]; numerator+=options.objective==CalibrationObjective::operator_action?mass_action*action[index]:action[index]*probe[index]; denominator+=options.objective==CalibrationObjective::operator_action?mass_action*mass_action:action[index]*action[index]; } } constautofit=strategies::surface::try_fit_surface_mass(numerator,denominator,options.objective); if(!fit) { returnstd::unexpected(fit.error()); } returndetail::surface_mass_inverse(reference_metric,*fit,options.regularization); } }//namespaceserif::solver::preconditioner::backend::mfem