Path: blob/main/docs/literate/src/files/adaptive_mesh_refinement.jl
5591 views
#src # Adaptive mesh refinement12# Adaptive mesh refinement (AMR) is a method of adapting the resolution of the numerical method3# to the solution features such as turbulent regions or shocks. In those critical regions4# of the domain, we want the simulation to use elements with smaller mesh sizes compared to other5# regions. This should be automatically and dynamically adapted during the run of the simulation.67# # Implementation in Trixi.jl8# In [Trixi.jl](https://github.com/trixi-framework/Trixi.jl), AMR is possible for the mesh types9# [`TreeMesh`](@ref) and [`P4estMesh`](@ref). Both meshes are organized in a tree structure10# and therefore, each element can be refined independently. In Trixi.jl, AMR is restricted11# to a 2:1 refinement ratio between neighbor elements. This means that the maximum resolution12# difference of neighboring elements is a factor of two.1314# The implementation of AMR is divided into different steps. The basic refinement setting contains15# an indicator and a controller. These are added to the simulation by using an AMR callback.1617# ### Indicators18# An indicator estimates the current accuracy of the numerical approximation. It indicates which regions19# of the domain need finer or coarser resolutions. In Trixi.jl, you can use for instance20# [`IndicatorLöhner`](@ref) and [`IndicatorHennemannGassner`](@ref).2122# `IndicatorLöhner` (also callable with `IndicatorLoehner`) is an interpretation and adaptation of23# a FEM indicator by [Löhner (1987)](https://doi.org/10.1016/0045-7825(87)90098-3) and estimates a24# weighted second derivative of a specified variable locally.25# ````julia26# amr_indicator = IndicatorLöhner(semi, variable=variable)27# ````28# All indicators have the parameter `variable` which is used to specify the variable for the29# indicator calculation. You can use for instance `density`, `pressure` or `density_pressure`30# for the compressible Euler equations. Moreover, you have the option to use simply the first31# conservation variable with `first` for any equations. This might be a good choice for a starting32# example.3334# `IndicatorHennemannGassner`, also used as a shock-capturing indicator, was developed by35# [Hennemann et al. (2021)](https://doi.org/10.1016/j.jcp.2020.109935) and is explained in detail36# in the [tutorial about shock-capturing](@ref shock_capturing). It can be constructed as follows.37# ````julia38# amr_indicator = IndicatorHennemannGassner(semi,39# alpha_max=0.5,40# alpha_min=0.001,41# alpha_smooth=true,42# variable=variable)43# ````4445# Another indicator is the very basic `IndicatorMax`. It indicates the maximal value of a variable46# and is therefore mostly used for verification and testing. But it might be useful for the basic47# understanding of the implementation of indicators and AMR in Trixi.jl.48# ````julia49# amr_indicator = IndicatorMax(semi, variable=variable)50# ````5152# ### Controllers53# The spatial discretization into elements is tree-based for both AMR supporting mesh types `TreeMesh`54# and `P4estMesh`. Thus, the higher the level in the tree the higher the level of refinement.55# For instance, a mesh element of level `3` has double resolution in each direction compared to56# another element with level `2`.5758# To map specific indicator values to a desired level of refinement, Trixi.jl uses controllers.59# They are build in three levels: There is a base level of refinement `base_level`, which is the60# minimum allowed refinement level. Then, there is a medium level `med_level`, which corresponds61# to the initial level of refinement, for indicator values above the threshold `med_threshold`62# and equally, a maximal level `max_level` for values above `max_threshold`.63# This variant of controller is called [`ControllerThreeLevel`](@ref) in Trixi.jl.64# ````julia65# amr_controller = ControllerThreeLevel(semi, amr_indicator;66# base_level=4,67# med_level=5, med_threshold=0.1,68# max_level=6, max_threshold=0.6)69# ````70# You can also set `med_level=0` to use the current level as target, see the docstring of71# [`ControllerThreeLevel`](@ref).7273# An extension is [`ControllerThreeLevelCombined`](@ref), which uses two different indicators.74# The primary indicator works the same as the single indicator for `ControllerThreeLevel`.75# The second indicator with its own maximum threshold adds the property, that the target level is set to76# `max_level` additionally if this indicator's value is greater than `max_threshold_secondary`.77# This is for instance used to assure that a shock has always the maximum refinement level.78# ````julia79# amr_controller = ControllerThreeLevelCombined(semi, indicator_primary, indicator_secondary;80# base_level=2,81# med_level=6, med_threshold=0.0003,82# max_level=8, max_threshold=0.003,83# max_threshold_secondary=0.3)84# ````85# This controller is for instance used in86# [`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).8788# ### Callback89# The AMR indicator and controller are added to the simulation through the callback [`AMRCallback`](@ref).90# It contains a semidiscretization `semi`, the controller `amr_controller` and the parameters `interval`,91# `adapt_initial_condition`, and `adapt_initial_condition_only_refine`.9293# Adaptive mesh refinement will be performed every `interval` time steps. `adapt_initial_condition` indicates94# whether the initial condition already should be adapted before the first time step. And with95# `adapt_initial_condition_only_refine=true` the mesh is only refined at the beginning but not coarsened.96# ````julia97# amr_callback = AMRCallback(semi, amr_controller,98# interval=5,99# adapt_initial_condition=true,100# adapt_initial_condition_only_refine=true)101# ````102103# # Exemplary simulation104# Here, we want to implement a simple AMR simulation of the 2D linear advection equation for a Gaussian pulse.105106using OrdinaryDiffEqLowStorageRK107using Trixi108109advection_velocity = (0.2, -0.7)110equations = LinearScalarAdvectionEquation2D(advection_velocity)111112initial_condition = initial_condition_gauss113solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs)114115coordinates_min = (-5.0, -5.0)116coordinates_max = (5.0, 5.0)117mesh = TreeMesh(coordinates_min, coordinates_max,118initial_refinement_level = 4,119n_cells_max = 30_000,120periodicity = true)121122semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver;123boundary_conditions = boundary_condition_periodic)124125tspan = (0.0, 10.0)126ode = semidiscretize(semi, tspan);127128# For the best understanding about indicators and controllers, we use the simple AMR indicator129# `IndicatorMax`. As described before, it returns the maximal value of the specified variable130# (here the only conserved variable). Therefore, regions with a high maximum are refined.131# This is not really useful numerical application, but a nice demonstration example.132amr_indicator = IndicatorMax(semi, variable = first)133134# These values are transferred to a refinement level with the `ControllerThreeLevel`, such that135# every element with maximal value greater than `0.1` is refined once and elements with maximum136# above `0.6` are refined twice.137amr_controller = ControllerThreeLevel(semi, amr_indicator,138base_level = 4,139med_level = 5, med_threshold = 0.1,140max_level = 6, max_threshold = 0.6)141142amr_callback = AMRCallback(semi, amr_controller,143interval = 5,144adapt_initial_condition = true,145adapt_initial_condition_only_refine = true)146147stepsize_callback = StepsizeCallback(cfl = 0.9)148149callbacks = CallbackSet(amr_callback, stepsize_callback);150151# Running the simulation.152sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false);153dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback154ode_default_options()..., callback = callbacks);155156# We plot the solution and add the refined mesh at the end of the simulation.157using Plots158pd = PlotData2D(sol)159plot(pd)160plot!(getmesh(pd))161162# # More examples163# Trixi.jl provides many elixirs using AMR. We want to give some examples for different mesh types:164# - `elixir_euler_blast_wave_amr.jl` for [`TreeMesh`](https://github.com/trixi-framework/Trixi.jl/blob/main/examples/tree_2d_dgsem/elixir_euler_blast_wave_amr.jl)165# and [`P4estMesh`](https://github.com/trixi-framework/Trixi.jl/blob/main/examples/p4est_2d_dgsem/elixir_euler_blast_wave_amr.jl)166# - [`elixir_euler_kelvin_helmholtz_instability_amr.jl`](https://github.com/trixi-framework/Trixi.jl/blob/main/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_amr.jl) for `TreeMesh`167# - [`elixir_euler_double_mach_amr.jl`](https://github.com/trixi-framework/Trixi.jl/blob/main/examples/p4est_2d_dgsem/elixir_euler_double_mach_amr.jl) for `P4estMesh`168169# Animations of more interesting and complicated AMR simulations can be found below and on Trixi.jl's youtube channel170# ["Trixi Framework"](https://www.youtube.com/channel/UCpd92vU2HjjTPup-AIN0pkg).171172# First, we give a [purely hyperbolic simulation of a Sedov blast wave with self-gravity](https://www.youtube.com/watch?v=dxgzgteJdOA).173# This simulation uses the mesh type `TreeMesh` as we did and the AMR indicator `IndicatorHennemannGassner`.174# ```@raw html175# <!--176# Video details177# * Source: https://www.youtube.com/watch?v=dxgzgteJdOA178# * Authors: Michael Schlottke-Lakemper, Andrew R. Winters, Hendrik Ranocha, Gregor Gassner179# * Setup described in detail in: A purely hyperbolic discontinuous Galerkin approach for self-gravitating gas dynamics,180# Journal of Computational Physics (2021),(https://doi.org/10.1016/j.jcp.2021.110467).181# * Obtain responsive code by inserting link on https://embedresponsively.com182# -->183# <style>.embed-container { position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden; max-width: 100%; } .embed-container iframe, .embed-container object, .embed-container embed { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }</style><div class='embed-container'><iframe src='https://www.youtube-nocookie.com/embed/dxgzgteJdOA' frameborder='0' allowfullscreen></iframe></div>184# ```185# Source: Trixi.jl's YouTube channel [`Trixi Framework`](https://www.youtube.com/channel/UCpd92vU2HjjTPup-AIN0pkg)186187# The next example is a numerical simulation of an [ideal MHD rotor on an unstructured AMR mesh](https://www.youtube.com/watch?v=Iei7e9oQ0hs).188# The used mesh type is a `P4estMesh`.189# ```@raw html190# <!--191# Video details192# * Source: https://www.youtube.com/watch?v=Iei7e9oQ0hs193# * Author: Andrew R. Winters (https://liu.se/en/employee/andwi94)194# * Obtain responsive code by inserting link on https://embedresponsively.com195# -->196# <style>.embed-container { position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden; max-width: 100%; } .embed-container iframe, .embed-container object, .embed-container embed { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }</style><div class='embed-container'><iframe src='https://www.youtube-nocookie.com/embed/Iei7e9oQ0hs' frameborder='0' allowfullscreen></iframe></div>197# ```198# Source: Trixi.jl's YouTube channel [`Trixi Framework`](https://www.youtube.com/channel/UCpd92vU2HjjTPup-AIN0pkg)199200# For more information, please have a look at the respective links.201202# ## Package versions203204# These results were obtained using the following versions.205206using InteractiveUtils207versioninfo()208209using Pkg210Pkg.status(["Trixi", "OrdinaryDiffEqLowStorageRK", "Plots"],211mode = PKGMODE_MANIFEST)212213214