options.cpp serif/solver/nonlinear/options.hpp algorithm serif/utils/error/errors.hpp serif serif::solver #include"serif/solver/nonlinear/options.hpp" #include<algorithm> #include"serif/utils/error/errors.hpp" namespaceserif::solver{ voidNewton::validate()const{ usingnamespaceutils::errors; serif_ensure<SERiFErrorCode::INVALID_ARGUMENT>(std::isfinite(relative_tolerance)&&relative_tolerance>=0.0&& std::isfinite(absolute_tolerance)&&absolute_tolerance>=0.0&&maximum_iterations>=0, "Newtontolerancesmustbefiniteandnonnegative,anditsiterationbudgetmustbenonnegative."); linear_solve.validate(); } doubleNewton::convergence_threshold(constdoubleinitial_norm)const{ usingnamespaceutils::errors; validate(); constdoublerelative=relative_tolerance*initial_norm; serif_ensure<SERiFErrorCode::INVALID_ARGUMENT>(std::isfinite(initial_norm)&&initial_norm>=0.0&&std::isfinite(relative), "Newtonrequiresafiniteinitialnormandrepresentablerelativeconvergencethreshold."); returnstd::max(absolute_tolerance,relative); } voidBacktracking::validate()const{ usingnamespaceutils::errors; serif_ensure<SERiFErrorCode::INVALID_ARGUMENT>(std::isfinite(initial_step)&&initial_step>0.0&&initial_step<=1.0&& std::isfinite(contraction)&&contraction>0.0&&contraction<1.0&& std::isfinite(fraction_to_boundary)&&fraction_to_boundary>0.0&&fraction_to_boundary<1.0&& std::isfinite(sufficient_decrease)&&sufficient_decrease>0.0&&sufficient_decrease<1.0&& std::isfinite(minimum_step)&&minimum_step>0.0&&minimum_step <= initial_step && maximum_trials >0, "Backtrackingneeds0<minimumstep<=initialstep<=1,contraction,boundarysafetyandsufficientdecreasein(0,1),andapositivetrialbudget."); } MetricEvaluationNormalizedResidualMetric::operator()(std::span<constdouble>residual)const{ doublenorm=0.0; for(constdoublevalue:residual){ norm=std::hypot(norm,value); } return{.residual_norm=norm,.merit=0.5*norm*norm}; } doublenext_backtracking_step(constdoublerejected_step,constdoubleaccepted_determinant, constdoublerejected_determinant,constboolinverted,constBacktracking&options)noexcept{ constdoublecontracted=rejected_step*options.contraction; if(!inverted||!std::isfinite(accepted_determinant)||accepted_determinant<=0.0|| !std::isfinite(rejected_determinant)||rejected_determinant>0.0){ returncontracted; } constdoublechange=accepted_determinant-rejected_determinant; if(!std::isfinite(change)||change<=0.0){ returncontracted; } constdoublesafe_step=options.fraction_to_boundary*rejected_step*accepted_determinant/change; if(!std::isfinite(safe_step)||safe_step<=0.0||contracted<=safe_step){ returncontracted; } constdoublerung=std::ceil(std::log(safe_step/rejected_step)/std::log(options.contraction)); doubleskipped=rejected_step*std::pow(options.contraction,rung); if(!std::isfinite(skipped)||skipped<=0.0||skipped>=rejected_step){ returncontracted; } if(skipped>safe_step){ skipped*=options.contraction; } returnskipped; } }