riesz_factors.cpp serif/solver/normalization/point_rows.hpp cmath serif/solver/normalization/diagonal.hpp serif/utils/error/errors.hpp serif serif::solver serif::solver::normalization #include"serif/solver/normalization/point_rows.hpp" #include<cmath> #include"serif/solver/normalization/diagonal.hpp" #include"serif/utils/error/errors.hpp" namespaceserif::solver::normalization { namespace { usingKind=discretization::blocks::RepresentedValueKind; [[nodiscard]]std::expected<void,std::string>validate_scale(doublephysical_scale) { usingnamespaceutils::errors; if(!std::isfinite(physical_scale)||physical_scale<=0.0) { returnstd::unexpected(format_error_message<SERiFErrorCode::NORMALIZATION_ERROR>("Aphysicalnormalizationscalemustbefiniteandpositive(received{}).Chooseavalidreferencescale.",physical_scale)); } return{}; } [[nodiscard]]std::expected<void,std::string>validate_riesz_parameters(Kindkind,doublephysical_scale) { usingnamespaceutils::errors; constautovalid_scale=validate_scale(physical_scale); if(!valid_scale) { returnvalid_scale; } if(kind!=Kind::value&&kind!=Kind::residual) { returnstd::unexpected(format_error_message<SERiFErrorCode::INVALID_ARGUMENT>("Rieszfactorsrequireavalueorresidualcoordinatekind.SupplyasupportedRepresentedValueKind.")); } return{}; } [[nodiscard]]std::expected<double,std::string>riesz_factor(booldual,doublemetric,doublephysical_scale,std::size_tcoordinate) { usingnamespaceutils::errors; if(!std::isfinite(metric)||metric<=0.0) { returnstd::unexpected(format_error_message<SERiFErrorCode::NORMALIZATION_ERROR>("Normalizationmetricentry{}mustbefiniteandpositive(received{}).UseavalidreferenceGramdiagonal.",coordinate,metric)); } constdoubleroot_metric=std::sqrt(metric); //Invertingtherootfirstavoidsoverflowofscale*root_metricwhenitsreciprocalisrepresentable. constdoublefactor=dual?(1.0/root_metric)/physical_scale:root_metric/physical_scale; if(!std::isfinite(factor)||factor<=0.0) { returnstd::unexpected(format_error_message<SERiFErrorCode::NORMALIZATION_ERROR>("Normalizationfactor{}isnotrepresentableasafinitepositivedoubleformetric{}andscale{}.Changethereferenceunits.",coordinate,metric,physical_scale)); } returnfactor; } } std::expected<double,std::string>make_riesz_factor(Kindkind,doublemetric,doublephysical_scale) { constautovalid=validate_riesz_parameters(kind,physical_scale); if(!valid) { returnstd::unexpected(valid.error()); } returnriesz_factor(kind==Kind::residual,metric,physical_scale,0); } std::expected<std::vector<double>,std::string>make_riesz_factors(Kindkind,std::span<constdouble>metric,doublephysical_scale) { constautovalid=validate_riesz_parameters(kind,physical_scale); if(!valid) { returnstd::unexpected(valid.error()); } constbooldual=kind==Kind::residual; std::vector<double>factors(metric.size()); for(std::size_tindex=0;index<metric.size();++index) { constautofactor=riesz_factor(dual,metric[index],physical_scale,index); if(!factor) { returnstd::unexpected(factor.error()); } factors[index]=*factor; } returnfactors; } std::expected<std::vector<double>,std::string>make_point_replaced_residual_factors(std::span<constdouble>volume_metric,doublevolume_scale,std::span<constint>selected_rows,doublepoint_scale) { usingnamespaceutils::errors; for(constdoublescale:{volume_scale,point_scale}) { constautovalid=validate_scale(scale); if(!valid) { returnstd::unexpected(valid.error()); } } std::vector<bool>replaced(volume_metric.size(),false); for(constintrow:selected_rows) { if(row<0||static_cast<std::size_t>(row)>=volume_metric.size()) { returnstd::unexpected(format_error_message<SERiFErrorCode::OUT_OF_RANGE_ERROR>("Replacementnormalizationrow{}liesoutsideitsresidualcoordinateofsize{}.Usethephysicalequation'sreducedrowselection.",row,volume_metric.size())); } if(replaced[row]) { returnstd::unexpected(format_error_message<SERiFErrorCode::INVALID_ARGUMENT>("Residualrow{}wasselectedmorethanonceforpointnormalization.Supplydisjointreplacementrows.",row)); } replaced[row]=true; } std::vector<double>factors(volume_metric.size()); for(std::size_trow=0;row<factors.size();++row) { constdoublemetric=replaced[row]?1.0:volume_metric[row]; constdoublescale=replaced[row]?point_scale:volume_scale; constautofactor=riesz_factor(true,metric,scale,row); if(!factor) { returnstd::unexpected(factor.error()); } factors[row]=*factor; } returnfactors; } }