{ "cells": [ { "cell_type": "markdown", "source": [ "# 18: Explicit time stepping" ], "metadata": {} }, { "cell_type": "markdown", "source": [ "**Note:** To improve responsiveness via caching, the notebooks are updated only once a week. They are only\n", "available for the latest stable release of Trixi.jl at the time of caching." ], "metadata": {} }, { "cell_type": "markdown", "source": [ "For the time integration, [Trixi.jl](https://github.com/trixi-framework/Trixi.jl) uses the package\n", "[OrdinaryDiffEq.jl](https://github.com/SciML/OrdinaryDiffEq.jl) from the SciML ecosystem.\n", "The interface to this package is the `solve(...)` function. It always requires an ODE problem and\n", "a time integration algorithm as input parameters.\n", "````julia\n", "solve(ode, alg; kwargs...)\n", "````\n", "In Trixi.jl, the ODE problem is created by `semidiscretize(semi, tspan)` for a semidiscretization\n", "`semi` and the time span `tspan`. In particular, `semidiscretize` returns an `ODEProblem`\n", "used by OrdinaryDiffEq.jl." ], "metadata": {} }, { "cell_type": "markdown", "source": [ "OrdinaryDiffEq.jl provides many integration algorithms, which are summarized in\n", "the [documentation](https://diffeq.sciml.ai/stable/solvers/ode_solve/#Full-List-of-Methods).\n", "Particularly interesting for Trixi.jl are their\n", "[strong stability preserving (SSP) methods](https://diffeq.sciml.ai/stable/solvers/ode_solve/#Explicit-Strong-Stability-Preserving-Runge-Kutta-Methods-for-Hyperbolic-PDEs-(Conservation-Laws))\n", "and [low-storage methods](https://diffeq.sciml.ai/stable/solvers/ode_solve/#Low-Storage-Methods).\n", "There are some differences regarding the choice of the used time step." ], "metadata": {} }, { "cell_type": "markdown", "source": [ "# Error-based adaptive step sizes\n", "First, we treat time integration algorithms with adaptive step sizes, such as `SSPRK43`. It is used in\n", "some elixirs, like [`elixir_euler_colliding_flow.jl`](https://github.com/trixi-framework/Trixi.jl/blob/main/examples/tree_2d_dgsem/elixir_euler_colliding_flow.jl)\n", "or [`elixir_euler_astro_jet_amr.jl`](https://github.com/trixi-framework/Trixi.jl/blob/main/examples/tree_2d_dgsem/elixir_euler_astro_jet_amr.jl)." ], "metadata": {} }, { "cell_type": "markdown", "source": [ "Other error-based adaptive integration algorithms are for instance `RDPK3SpFSAL35`, `RDPK3Sp35`,\n", "`RDPK3SpFSAL49`, `RDPK3Sp49`, `RDPK3SpFSAL510`, `RDPK3Sp510`." ], "metadata": {} }, { "cell_type": "markdown", "source": [ "They already contain an error-based adaptive step size control and heuristics to guess\n", "a starting step size. If this heuristic fails in your case, you can specify an appropriately\n", "small initial step size as keyword argument `dt=...` of `solve`." ], "metadata": {} }, { "cell_type": "markdown", "source": [ "If you run Trixi in parallel with MPI you need to pass `internalnorm=ode_norm` and you should pass `unstable_check=ode_unstable_check`\n", "to enable MPI aware error-based adaptive step size control. These keyword arguments are also included in `ode_default_options`." ], "metadata": {} }, { "cell_type": "markdown", "source": [ "# CFL-based step size control\n", "The SciML ecosystem also provides time integration algorithms without adaptive time stepping on\n", "their own, such as `CarpenterKennedy2N54`. Moreover, you also can deactivate the automatic adaptivity\n", "of adaptive integration algorithms by passing `adaptive=false` in the `solve` function." ], "metadata": {} }, { "cell_type": "markdown", "source": [ "These algorithms require another way of setting the step size. You have to pass `dt=...`\n", "in the `solve` function. Without other settings, the simulation uses this fixed time step." ], "metadata": {} }, { "cell_type": "markdown", "source": [ "For hyperbolic PDEs, it is natural to use an adaptive CFL-based step size control. Here, the time\n", "step is proportional to a ratio of the local measure of mesh spacing $\\Delta x_i$ for an element `i`\n", "and the maximum (local) wave speed $\\lambda_{\\max}$ related to the largest-magnitude eigenvalue of\n", "the flux Jacobian of the hyperbolic system.\n", "$$\n", "\\Delta t_n = \\text{CFL} * \\min_i \\frac{\\Delta x_i}{\\lambda_{\\max}(u_i^n)}\n", "$$\n", "We compute $\\Delta x_i$ by scaling the element size by a factor of $1/(N+1)$, cf.\n", "[Gassner and Kopriva (2011)](https://doi.org/10.1137/100807211), Section 5." ], "metadata": {} }, { "cell_type": "markdown", "source": [ "Trixi.jl provides such a CFL-based step size control. It is implemented as the callback\n", "`StepsizeCallback`.\n", "````julia\n", "stepsize_callback = StepsizeCallback(; cfl=1.0)\n", "````\n", "A suitable CFL number depends on many parameters such as the chosen grid, the integration\n", "algorithm and the polynomial degree of the spatial DG discretization. So, the optimal number\n", "for an example is mostly determined experimentally." ], "metadata": {} }, { "cell_type": "markdown", "source": [ "You can add this CFL-based step size control to your simulation like any other callback.\n", "````julia\n", "callbacks = CallbackSet(stepsize_callback)\n", "alg = CarpenterKennedy2N54(williamson_condition=false)\n", "solve(ode, alg;\n", " dt=1.0 # solve needs some value here but it will be overwritten by the stepsize_callback\n", " callback=callbacks)\n", "````" ], "metadata": {} }, { "cell_type": "markdown", "source": [ "You can find simple examples with a CFL-based step size control for instance in the elixirs\n", "[`elixir_advection_basic.jl`](https://github.com/trixi-framework/Trixi.jl/blob/main/examples/tree_2d_dgsem/elixir_advection_basic.jl)\n", "or [`elixir_euler_source_terms.jl`](https://github.com/trixi-framework/Trixi.jl/blob/main/examples/tree_2d_dgsem/elixir_euler_source_terms.jl)." ], "metadata": {} }, { "cell_type": "markdown", "source": [ "## Package versions" ], "metadata": {} }, { "cell_type": "markdown", "source": [ "These results were obtained using the following versions." ], "metadata": {} }, { "outputs": [], "cell_type": "code", "source": [ "using InteractiveUtils\n", "versioninfo()\n", "\n", "using Pkg\n", "Pkg.status([\"Trixi\", \"OrdinaryDiffEq\"],\n", " mode=PKGMODE_MANIFEST)" ], "metadata": {}, "execution_count": null } ], "nbformat_minor": 3, "metadata": { "language_info": { "file_extension": ".jl", "mimetype": "application/julia", "name": "julia", "version": "1.9.4" }, "kernelspec": { "name": "julia-1.9", "display_name": "Julia 1.9.4", "language": "julia" } }, "nbformat": 4 }