result.hpp algorithm cmath memory optional string utility vector serif/geometry/deformation/geometry_step.hpp serif/solver/nonlinear/options.hpp serif/solver/linear/linear.hpp serif/utils/error/errors.hpp src/compile_time_checks/serif/solver/public_contracts.cpp src/include/serif/solver/nonlinear/observers.hpp src/include/serif/solver/nonlinear/qualification.hpp src/include/serif/utils/serialize/solver.hpp serif::solver::SolveDiagnostics serif::solver::NewtonProgress serif::solver::NewtonCheckpoint serif::solver::SolveEvent serif::solver::NoObserver serif::solver::NoModel serif::solver::SolveResult serif serif::solver serif::solver::detail #pragmaonce #include<algorithm> #include<cmath> #include<memory> #include<optional> #include<string> #include<utility> #include<vector> #include"serif/geometry/deformation/geometry_step.hpp" #include"serif/solver/nonlinear/options.hpp" #include"serif/solver/linear/linear.hpp" #include"serif/utils/error/errors.hpp" namespaceserif::solver{ enumclassSolveStatus{converged,initial_state_rejected,invalid_metric,preparation_failure, linear_solve_failure,globalization_failure,maximum_iterations,stopped}; structSolveDiagnostics{ intattempted_iterations{0}; intaccepted_iterations{0}; intline_search_trials{0}; intrejected_trials{0}; intgeometry_limited_iterations{0}; inttotal_linear_iterations{0}; std::optional<double>initial_residual_norm; std::optional<double>final_residual_norm; std::optional<double>convergence_threshold; std::optional<linear::Report>last_linear_solve; std::optional<geometry::deformation::GeometryStepLimit>last_geometry_preflight; doublelast_accepted_step{0.0}; }; namespacedetail{ template<typenameOptions> inlineconstexprboolcheckpointable_options= std::same_as<std::remove_cvref_t<decltype(std::declval<Options>().strategies)>,StandardNewton>&& std::same_as<std::remove_cvref_t<decltype(std::declval<Options>().metric)>,NormalizedResidualMetric>&& std::same_as<std::remove_cvref_t<decltype(std::declval<Options>().linear_solver)>,linear::FGMRES>; } structNewtonProgress{ MetricEvaluationaccepted_metric; std::vector<double>correction; doublenext_step{1.0}; SolveDiagnosticsdiagnostics; }; [[nodiscard]]inlinestd::optional<std::string>validate_newton_progress(constNewtonProgress&progress,conststd::size_tstate_size){ constSolveDiagnostics&diagnostics=progress.diagnostics; constautononnegative=[](conststd::optional<double>&value){ returnvalue&&std::isfinite(*value)&&*value>=0.0; }; if(!progress.accepted_metric.valid()||!std::isfinite(progress.next_step)||progress.next_step<=0.0|| progress.correction.size()!=state_size||!std::ranges::all_of(progress.correction,[](doublevalue){returnstd::isfinite(value);})){ return"Theacceptedmetric,correctionsize/valuesornexttrialstepisinvalid."; } if(!nonnegative(diagnostics.initial_residual_norm)||!nonnegative(diagnostics.final_residual_norm)|| !nonnegative(diagnostics.convergence_threshold)||*diagnostics.final_residual_norm!=progress.accepted_metric.residual_norm){ return"Theoriginalconvergencereferenceoracceptedresidualismissingorinconsistent."; } if(diagnostics.accepted_iterations<0||diagnostics.attempted_iterations!=diagnostics.accepted_iterations|| diagnostics.line_search_trials<diagnostics.accepted_iterations||diagnostics.rejected_trials<0|| diagnostics.line_search_trials-diagnostics.accepted_iterations!=diagnostics.rejected_trials|| diagnostics.geometry_limited_iterations<0||diagnostics.geometry_limited_iterations>diagnostics.attempted_iterations|| diagnostics.total_linear_iterations<0|| !std::isfinite(diagnostics.last_accepted_step)||diagnostics.last_accepted_step<0.0){ return"TheworkcountersdonotdescribeanacceptedNewtonboundary."; } returnstd::nullopt; } template<typenameState> structNewtonCheckpoint{ Statestate; NewtonProgressprogress; }; enumclassEventKind{initial,before_iteration,trial_rejected,before_accept,accepted,finished,resumed}; enumclassSolveControl{continue_solve,stop}; structSolveEvent{ EventKindkind; intiteration{0}; inttrial{0}; doublestep{0.0}; std::optional<MetricEvaluation>metric; std::stringmessage; constSolveDiagnostics&diagnostics; }; structNoObserver{ voidoperator()(constSolveEvent&,constauto&,constauto&)constnoexcept{} }; structNoModel{}; template<typenameState,typenameSystem,typenameModel=NoModel> classSolveResult{ public: explicitSolveResult(std::shared_ptr<constModel>model={}):m_model(std::move(model)){} [[nodiscard]]boolconverged()constnoexcept{returnm_status==SolveStatus::converged;} [[nodiscard]]boolhas_state()constnoexcept{returnm_state.has_value();} [[nodiscard]]constState&state()const{ utils::errors::serif_ensure<utils::errors::SERiFErrorCode::INVALID_ARGUMENT>(has_state(), "Thissolvehasnoacceptedstellarstate.Inspectstatus()andmessage()beforerequestingitsstate."); return*m_state; } [[nodiscard]]conststd::shared_ptr<constSystem>&system()constnoexcept{returnm_system;} [[nodiscard]]constModel&model()constrequires(!std::same_as<Model,NoModel>){return*m_model;} [[nodiscard]]constSolveDiagnostics&diagnostics()constnoexcept{returnm_diagnostics;} [[nodiscard]]SolveStatusstatus()constnoexcept{returnm_status;} [[nodiscard]]conststd::string&message()constnoexcept{returnm_message;} [[nodiscard]]boolhas_checkpoint()constnoexcept{returnm_progress.has_value();} [[nodiscard]]NewtonCheckpoint<State>checkpoint()const{ utils::errors::serif_ensure<utils::errors::SERiFErrorCode::INVALID_ARGUMENT>(has_state()&&has_checkpoint(), "ThisresulthasnosupportedNewtoncheckpoint.CheckpointingrequiresanacceptedstatewithStandardNewton,NormalizedResidualMetricandFGMRES;custompoliciesneedanexplicithistoryrestorationimplementation."); return{.state=*m_state,.progress=*m_progress}; } voidcheckpoint(NewtonProgressprogress){m_progress=std::move(progress);} voidaccept(Statestate,std::shared_ptr<constSystem>system){ m_state=std::move(state); m_system=std::move(system); } voidfinish(SolveStatusstatus,std::stringmessage,SolveDiagnosticsdiagnostics){ m_status=status; m_message=std::move(message); m_diagnostics=std::move(diagnostics); } private: std::shared_ptr<constModel>m_model; std::optional<State>m_state; std::shared_ptr<constSystem>m_system; std::optional<NewtonProgress>m_progress; SolveStatusm_status{SolveStatus::initial_state_rejected}; std::stringm_message; SolveDiagnosticsm_diagnostics; }; }