options.hpp serif/solver/continuation/family.hpp serif/solver/continuation/controller.hpp src/compile_time_checks/serif/solver/continuation.cpp src/include/serif/solver/continuation/driver.hpp serif::solver::continuation::Options serif::solver::continuation::StartingAt serif::solver::continuation::Ordering serif::solver::continuation::NumericalControls serif serif::solver serif::solver::continuation #pragmaonce #include"serif/solver/continuation/family.hpp" #include"serif/solver/continuation/controller.hpp" namespaceserif::solver::continuation{ template<typenameFamily> structOptionsfinal{ CoordinateOptions<Family::coordinate_count>steps{}; typenameFamily::Coordinatesstart{}; std::array<bool,Family::coordinate_count>specified{}; boolexplicit_start{false}; boolhas_ordering{false}; boolhas_numerics{false}; std::uint64_tmaximum_work{100000}; std::size_tmaximum_records{128}; }; template<PhysicalParameterParameter> structStartingAtfinal{ typenameParameter::Valuevalue; template<typenameFamily> requiresFamily::templatehas_coordinate<Parameter> voidapply(Options<Family>&options)const{ constexprstd::size_taxis=Family::coordinate_index(Parameter{}); utils::errors::serif_ensure<utils::errors::SERiFErrorCode::INVALID_ARGUMENT, std::invalid_argument>(!options.specified[axis]&&Parameter::valid(value), "Thestarting{}mustbespecifiedonceandliewithinitsphysicaldomain.",Parameter::name); options.start[axis]=coordinate_value(value); options.specified[axis]=true; options.explicit_start=true; } }; template<PhysicalParameterParameter> [[nodiscard]]autostarting_at(Parameter,typenameParameter::Valuevalue){returnStartingAt<Parameter>{value};} template<boolStrict,PhysicalParameter...Parameters> requires(sizeof...(Parameters)>0)&&utils::dependencies::IsKeyList<ParameterList<Parameters...>> structOrderingfinal{ template<typenameFamily> requires(Family::templatehas_coordinate<Parameters>&&...)&&(!Strict||sizeof...(Parameters)==Family::coordinate_count) voidapply(Options<Family>&options)const{ utils::errors::serif_ensure<utils::errors::SERiFErrorCode::INVALID_ARGUMENT, std::invalid_argument>(!options.has_ordering, "Chooseonlyonecontinuationorderingpolicy."); constexprstd::arrayselected{Family::coordinate_index(Parameters{})...}; std::size_tindex=0; for(conststd::size_taxis:selected){ options.steps.axis_order[index++]=axis; } for(std::size_taxis=0;axis<Family::coordinate_count;++axis){ if(std::ranges::find(selected,axis)==selected.end()){ options.steps.axis_order[index++]=axis; } } options.steps.order=Strict?CoordinateOrder::strict:CoordinateOrder::preferred; options.has_ordering=true; } }; template<PhysicalParameter...Parameters> requires(sizeof...(Parameters)>0)&&utils::dependencies::IsKeyList<ParameterList<Parameters...>> [[nodiscard]]autoprefer(Parameters...){returnOrdering<false,Parameters...>{};} template<PhysicalParameter...Parameters> requires(sizeof...(Parameters)>0)&&utils::dependencies::IsKeyList<ParameterList<Parameters...>> [[nodiscard]]autostages(Parameters...){returnOrdering<true,Parameters...>{};} template<std::size_tCount> structNumericalControlsfinal{ CoordinateOptions<Count>options; template<typenameFamily> requires(Family::coordinate_count==Count) voidapply(Options<Family>&target)const{ utils::errors::serif_ensure<utils::errors::SERiFErrorCode::INVALID_ARGUMENT, std::invalid_argument>(!target.has_numerics, "Continuationnumericalcontrolsmaybesuppliedonlyonce."); constautoorder=target.steps.order; constautoaxes=target.steps.axis_order; target.steps=options; if(target.has_ordering){ target.steps.order=order; target.steps.axis_order=axes; } target.has_numerics=true; } }; template<std::size_tCount> [[nodiscard]]autonumerics(CoordinateOptions<Count>options){returnNumericalControls<Count>{options};} template<typenameFamily,typename...Settings> requires(requires(constSettings&setting,Options<Family>&options){setting.apply(options);}&&...) [[nodiscard]]automake_options(constFamily&family,constSettings&...settings){ Options<Family>result{.start=family.starting_coordinates()}; (settings.apply(result),...); returnresult; } }