equilibrium.hpp serif/solver/continuation/driver.hpp serif/backend/mfem/solver/continuation/detail/physical_transfer.hpp serif/solver/equilibrium.hpp src/include/serif/solver/solver.hpp serif serif::solver serif::solver::continuation serif::solver::continuation::detail #pragmaonce #include"serif/solver/continuation/driver.hpp" #include"serif/backend/mfem/solver/continuation/detail/physical_transfer.hpp" #include"serif/solver/equilibrium.hpp" namespaceserif::solver::continuation{ [[nodiscard]]inlineSolverOptions<>default_solver_options(){ return{.method={.relative_tolerance=0.0,.absolute_tolerance=1.0e-10}}; } namespacedetail{ template<typenameFamily,typenameFactory,typenameSolverOptions,typenameSolve> [[nodiscard]]autocorrector(constFamily&family,Factory&configure,SolverOptionsoptions,Solvesolve){ options.method.validate(); utils::errors::serif_ensure<utils::errors::SERiFErrorCode::INVALID_ARGUMENT, std::invalid_argument>( options.method.relative_tolerance==0.0&&options.method.absolute_tolerance>0.0, "ContinuationrequireszerorelativetoleranceandafixedpositiveabsoluteNewtontolerance."); usingConfiguration=std::invoke_result_t<Factory&,typenameFamily::ModelType>; usingFiniteElements=std::remove_cvref_t<decltype(std::declval<Configuration>().finite_elements)>; usingTransferGuard=decltype(backend::mfem::physical_transfer_guard(std::declval<constFiniteElements&>())); return[&family,&configure,options=std::move(options),solve=std::move(solve),transfer=std::optional<TransferGuard>{}] (automodel,autostate,CorrectionControlscontrols)mutable{ constautoexpected=family.model_signature(model); autoconfiguration=std::invoke(configure,std::move(model)); utils::errors::serif_ensure<utils::errors::SERiFErrorCode::INVALID_ARGUMENT, std::invalid_argument>( family.model_signature(configuration.model)==expected, "Thecontinuationconfigurationfactorychangedtherequestedphysicalmodel.Preserveitsprescriptionsandequationidentity."); if(!transfer){ transfer.emplace(backend::mfem::physical_transfer_guard(configuration.finite_elements)); } utils::errors::serif_ensure<utils::errors::SERiFErrorCode::INVALID_ARGUMENT, std::invalid_argument>( (*transfer)(configuration.finite_elements), "Continuationcannottransferphysicalcoefficientstochangedfinite-elementbindings,referencegeometry,ordeformationcoordinates."); autostage_options=options; stage_options.method.absolute_tolerance=controls.absolute_tolerance; stage_options.method.maximum_iterations=static_cast<int>(std::min<std::uint64_t>( stage_options.method.maximum_iterations,controls.maximum_work)); returnstd::invoke(solve,std::move(configuration),std::move(state),std::move(stage_options)); }; } } } namespaceserif::solver{ template<typenameFamily,typenameFactory,typenameState,typenameOptions=SolverOptions<>> requiresstd::copy_constructible<Options> [[nodiscard]]autocontinue_equilibrium(constFamily&family,Factoryconfigure,constState&initial_state, continuation::Options<Family>continuation_options,Optionssolver_options=continuation::default_solver_options()){ constdoubletolerance=solver_options.method.absolute_tolerance; autocorrect=continuation::detail::corrector(family,configure,std::move(solver_options),[](autoconfiguration,autostate,autooptions){ returnsolve_equilibrium(std::move(configuration),std::move(state),std::move(options)); }); returncontinuation::run(family,initial_state,std::move(correct),std::move(continuation_options),tolerance); } template<typenameFamily,typenameFactory,typenameState> [[nodiscard]]autocontinue_equilibrium(constFamily&family,Factoryconfigure,constState&initial_state){ returncontinue_equilibrium(family,std::move(configure),initial_state,serif::solver::continuation::make_options(family)); } template<typenameFamily,typenameFactory,typenameState,typenameOptions=SolverOptions<>> requiresstd::copy_constructible<Options> [[nodiscard]]autocontinue_equilibrium(constFamily&family,Factoryconfigure,constState&initial_state,constVector&displacement, continuation::Options<Family>continuation_options,Optionssolver_options=continuation::default_solver_options()){ constdoubletolerance=solver_options.method.absolute_tolerance; autocorrect=continuation::detail::corrector(family,configure,std::move(solver_options),[&displacement](autoconfiguration,autostate,autooptions){ returnsolve_equilibrium(std::move(configuration),std::move(state),displacement,std::move(options)); }); returncontinuation::run(family,initial_state,std::move(correct),std::move(continuation_options),tolerance); } template<typenameFamily,typenameFactory,typenameState> [[nodiscard]]autocontinue_equilibrium(constFamily&family,Factoryconfigure,constState&initial_state,constVector&displacement){ returncontinue_equilibrium(family,std::move(configure),initial_state,displacement,serif::solver::continuation::make_options(family)); } }