calibration.cpp serif/solver/preconditioner/backend/mfem/surface/detail/calibration.hpp algorithm cmath cstdint limits serif serif::solver serif::solver::preconditioner serif::solver::preconditioner::backend serif::solver::preconditioner::backend::mfem serif::solver::preconditioner::backend::mfem::detail #include"serif/solver/preconditioner/backend/mfem/surface/detail/calibration.hpp" #include<algorithm> #include<cmath> #include<cstdint> #include<limits> namespaceserif::solver::preconditioner::backend::mfem::detail { std::expected<OperatorHandle,Failure>surface_target(constSurfaceTargets&targets,strategies::surface::CalibrationTargettarget,intsize) { usingstrategies::surface::CalibrationTarget; usingutils::errors::SERiFErrorCode; if(target!=CalibrationTarget::surface_jacobian&&target!=CalibrationTarget::material_schur) { returnstd::unexpected(Failure{.code=SERiFErrorCode::PRECONDITIONER_INVALID_OPTIONS,.message="SelectthesurfaceJacobianortheeffectivematerialSchuractionforsurfacecalibration."}); } OperatorHandleselected=target==CalibrationTarget::surface_jacobian?targets.surface_jacobian:targets.material_schur; if(!selected) { returnstd::unexpected(Failure{.code=SERiFErrorCode::PRECONDITIONER_INVALID_OPERATOR,.message="Theselectedsurfacecalibrationtargetisabsent.Prepareitsacceptedphysicalactionfirst."}); } if(selected->Width()!=size||selected->Height()!=size) { returnstd::unexpected(Failure{.code=SERiFErrorCode::PRECONDITIONER_SIZE_MISMATCH,.message="Thesurfacecalibrationtargetandreferencemetricusedifferentnativecoordinatecounts."}); } returnselected; } std::expected<void,Failure>validate_surface_metric(std::span<constdouble>metric) { usingutils::errors::SERiFErrorCode; if(metric.empty()||metric.size()>static_cast<std::size_t>(std::numeric_limits<int>::max())) { returnstd::unexpected(Failure{.code=SERiFErrorCode::PRECONDITIONER_SIZE_MISMATCH,.message="AsurfacemassinverserequiresanonemptynativemetricsupportedbyMFEM'scoordinatecount."}); } constautovalid_entry=[](doublevalue) { returnstd::isfinite(value)&&value>0.0; }; if(!std::ranges::all_of(metric,valid_entry)) { returnstd::unexpected(Failure{.code=SERiFErrorCode::PRECONDITIONER_INVALID_OPERATOR,.message="Thenativereferencesurfacemetricmustcontainfinitepositiveentries.Rebuilditfromtheacceptedreferencesurface."}); } return{}; } std::expected<void,Failure>fill_surface_probe(intsample,::mfem::Vector&probe,boolinclude_smooth_modes) { usingutils::errors::SERiFErrorCode; for(intindex=0;index<probe.Size();++index) { if(include_smooth_modes&&sample<3) { constdoublecoordinate=-1.0+2.0*(static_cast<double>(index)+0.5)/probe.Size(); doubleprevious=1.0; doublecurrent=coordinate; constintdegree_limit=sample==1?2:12; for(intdegree=2;degree<=degree_limit;++degree) { constdoublenext=((2.0*degree-1.0)*coordinate*current-(degree-1.0)*previous)/degree; previous=current; current=next; } probe[index]=sample==0?1.0:current; } else { std::uint64_tvalue=static_cast<std::uint64_t>(index); value+=0x9e3779b97f4a7c15ULL*static_cast<std::uint64_t>(sample+1); value=(value^(value>>30U))*0xbf58476d1ce4e5b9ULL; value=(value^(value>>27U))*0x94d049bb133111ebULL; value^=value>>31U; probe[index]=(value&1ULL)==0ULL?-1.0:1.0; } } if(include_smooth_modes) { constdoublenorm=probe.Norml2(); if(!std::isfinite(norm)||norm<=0.0) { returnstd::unexpected(Failure{.code=SERiFErrorCode::PRECONDITIONER_INVALID_CALIBRATION,.message="AsurfaceH1calibrationprobehaszeroornonfinitenorm.Increasethenumberofresolvednodalcoordinates."}); } probe/=norm; } return{}; } }//namespaceserif::solver::preconditioner::backend::mfem::detail