Path: blob/main/src/time_integration/time_integration.jl
2055 views
# By default, Julia/LLVM does not use fused multiply-add operations (FMAs).1# Since these FMAs can increase the performance of many numerical algorithms,2# we need to opt-in explicitly.3# See https://ranocha.de/blog/Optimizing_EC_Trixi for further details.4@muladd begin5#! format: noindent67# Wrapper type for solutions from Trixi.jl's own time integrators, partially mimicking8# SciMLBase.ODESolution9struct TimeIntegratorSolution{tType, uType, P}10t::tType11u::uType12prob::P13end1415# Abstract supertype of Trixi.jl's own time integrators for dispatch16abstract type AbstractTimeIntegrator end1718# Abstract supertype for the time integration algorithms of Trixi.jl19abstract type AbstractTimeIntegrationAlgorithm end2021# get a cache where the RHS can be stored22get_du(integrator::AbstractTimeIntegrator) = integrator.du2324# Forward integrator.stats.naccept to integrator.iter (see GitHub PR#771)25function Base.getproperty(integrator::AbstractTimeIntegrator, field::Symbol)26if field === :stats27return (naccept = getfield(integrator, :iter),)28end29# general fallback30return getfield(integrator, field)31end3233# used by adaptive timestepping algorithms in DiffEq34@inline function set_proposed_dt!(integrator::AbstractTimeIntegrator, dt)35(integrator.dt = dt; integrator.dtcache = dt)3637return nothing38end3940# Required e.g. for `glm_speed_callback`41@inline function get_proposed_dt(integrator::AbstractTimeIntegrator)42return integrator.dt43end4445@inline function limit_dt!(integrator::AbstractTimeIntegrator, t_end)46# if the next iteration would push the simulation beyond the end time, set dt accordingly47if integrator.t + integrator.dt > t_end ||48isapprox(integrator.t + integrator.dt, t_end)49integrator.dt = t_end - integrator.t50terminate!(integrator)51end5253return nothing54end5556function initialize_callbacks!(callbacks::Union{CallbackSet, Nothing},57integrator::AbstractTimeIntegrator)58# initialize callbacks59if callbacks isa CallbackSet60foreach(callbacks.continuous_callbacks) do cb61throw(ArgumentError("Continuous callbacks are unsupported."))62end63foreach(callbacks.discrete_callbacks) do cb64cb.initialize(cb, integrator.u, integrator.t, integrator)65end66end6768return nothing69end7071function handle_callbacks!(callbacks::Union{CallbackSet, Nothing},72integrator::AbstractTimeIntegrator)73# handle callbacks74if callbacks isa CallbackSet75foreach(callbacks.discrete_callbacks) do cb76if cb.condition(integrator.u, integrator.t, integrator)77cb.affect!(integrator)78end79return nothing80end81end8283return nothing84end8586@inline function check_max_iter!(integrator::AbstractTimeIntegrator)87# respect maximum number of iterations88if integrator.iter >= integrator.opts.maxiters && !integrator.finalstep89@warn "Interrupted. Larger maxiters is needed."90terminate!(integrator)91end9293return nothing94end9596"""97Trixi.solve(ode::ODEProblem, alg::AbstractTimeIntegrationAlgorithm;98dt, callbacks, kwargs...)99100Fakes `solve` from https://diffeq.sciml.ai/v6.8/basics/overview/#Solving-the-Problems-1101"""102function solve(ode::ODEProblem, alg::AbstractTimeIntegrationAlgorithm;103dt, callback = nothing, kwargs...)104integrator = init(ode, alg, dt = dt, callback = callback; kwargs...)105106# Start actual solve107solve!(integrator)108end109110function solve!(integrator::AbstractTimeIntegrator)111@unpack prob = integrator.sol112113integrator.finalstep = false114115@trixi_timeit timer() "main loop" while !integrator.finalstep116step!(integrator)117end118119finalize_callbacks(integrator)120121return TimeIntegratorSolution((first(prob.tspan), integrator.t),122(prob.u0, integrator.u), prob)123end124125# Interface required by DiffEqCallbacks.jl126function DiffEqBase.get_tstops(integrator::AbstractTimeIntegrator)127return integrator.opts.tstops128end129function DiffEqBase.get_tstops_array(integrator::AbstractTimeIntegrator)130return get_tstops(integrator).valtree131end132function DiffEqBase.get_tstops_max(integrator::AbstractTimeIntegrator)133return maximum(get_tstops_array(integrator))134end135136function finalize_callbacks(integrator::AbstractTimeIntegrator)137callbacks = integrator.opts.callback138139if callbacks isa CallbackSet140foreach(callbacks.discrete_callbacks) do cb141cb.finalize(cb, integrator.u, integrator.t, integrator)142end143foreach(callbacks.continuous_callbacks) do cb144cb.finalize(cb, integrator.u, integrator.t, integrator)145end146end147148return nothing149end150151include("methods_2N.jl")152include("methods_3Sstar.jl")153include("methods_SSP.jl")154include("paired_explicit_runge_kutta/paired_explicit_runge_kutta.jl")155include("relaxation_methods/relaxation_methods.jl")156end # @muladd157158159