Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
trixi-framework
GitHub Repository: trixi-framework/Trixi.jl
Path: blob/main/docs/literate/src/files/adaptive_mesh_refinement.jl
5591 views
1
#src # Adaptive mesh refinement
2
3
# Adaptive mesh refinement (AMR) is a method of adapting the resolution of the numerical method
4
# to the solution features such as turbulent regions or shocks. In those critical regions
5
# of the domain, we want the simulation to use elements with smaller mesh sizes compared to other
6
# regions. This should be automatically and dynamically adapted during the run of the simulation.
7
8
# # Implementation in Trixi.jl
9
# In [Trixi.jl](https://github.com/trixi-framework/Trixi.jl), AMR is possible for the mesh types
10
# [`TreeMesh`](@ref) and [`P4estMesh`](@ref). Both meshes are organized in a tree structure
11
# and therefore, each element can be refined independently. In Trixi.jl, AMR is restricted
12
# to a 2:1 refinement ratio between neighbor elements. This means that the maximum resolution
13
# difference of neighboring elements is a factor of two.
14
15
# The implementation of AMR is divided into different steps. The basic refinement setting contains
16
# an indicator and a controller. These are added to the simulation by using an AMR callback.
17
18
# ### Indicators
19
# An indicator estimates the current accuracy of the numerical approximation. It indicates which regions
20
# of the domain need finer or coarser resolutions. In Trixi.jl, you can use for instance
21
# [`IndicatorLöhner`](@ref) and [`IndicatorHennemannGassner`](@ref).
22
23
# `IndicatorLöhner` (also callable with `IndicatorLoehner`) is an interpretation and adaptation of
24
# a FEM indicator by [Löhner (1987)](https://doi.org/10.1016/0045-7825(87)90098-3) and estimates a
25
# weighted second derivative of a specified variable locally.
26
# ````julia
27
# amr_indicator = IndicatorLöhner(semi, variable=variable)
28
# ````
29
# All indicators have the parameter `variable` which is used to specify the variable for the
30
# indicator calculation. You can use for instance `density`, `pressure` or `density_pressure`
31
# for the compressible Euler equations. Moreover, you have the option to use simply the first
32
# conservation variable with `first` for any equations. This might be a good choice for a starting
33
# example.
34
35
# `IndicatorHennemannGassner`, also used as a shock-capturing indicator, was developed by
36
# [Hennemann et al. (2021)](https://doi.org/10.1016/j.jcp.2020.109935) and is explained in detail
37
# in the [tutorial about shock-capturing](@ref shock_capturing). It can be constructed as follows.
38
# ````julia
39
# amr_indicator = IndicatorHennemannGassner(semi,
40
# alpha_max=0.5,
41
# alpha_min=0.001,
42
# alpha_smooth=true,
43
# variable=variable)
44
# ````
45
46
# Another indicator is the very basic `IndicatorMax`. It indicates the maximal value of a variable
47
# and is therefore mostly used for verification and testing. But it might be useful for the basic
48
# understanding of the implementation of indicators and AMR in Trixi.jl.
49
# ````julia
50
# amr_indicator = IndicatorMax(semi, variable=variable)
51
# ````
52
53
# ### Controllers
54
# The spatial discretization into elements is tree-based for both AMR supporting mesh types `TreeMesh`
55
# and `P4estMesh`. Thus, the higher the level in the tree the higher the level of refinement.
56
# For instance, a mesh element of level `3` has double resolution in each direction compared to
57
# another element with level `2`.
58
59
# To map specific indicator values to a desired level of refinement, Trixi.jl uses controllers.
60
# They are build in three levels: There is a base level of refinement `base_level`, which is the
61
# minimum allowed refinement level. Then, there is a medium level `med_level`, which corresponds
62
# to the initial level of refinement, for indicator values above the threshold `med_threshold`
63
# and equally, a maximal level `max_level` for values above `max_threshold`.
64
# This variant of controller is called [`ControllerThreeLevel`](@ref) in Trixi.jl.
65
# ````julia
66
# amr_controller = ControllerThreeLevel(semi, amr_indicator;
67
# base_level=4,
68
# med_level=5, med_threshold=0.1,
69
# max_level=6, max_threshold=0.6)
70
# ````
71
# You can also set `med_level=0` to use the current level as target, see the docstring of
72
# [`ControllerThreeLevel`](@ref).
73
74
# An extension is [`ControllerThreeLevelCombined`](@ref), which uses two different indicators.
75
# The primary indicator works the same as the single indicator for `ControllerThreeLevel`.
76
# The second indicator with its own maximum threshold adds the property, that the target level is set to
77
# `max_level` additionally if this indicator's value is greater than `max_threshold_secondary`.
78
# This is for instance used to assure that a shock has always the maximum refinement level.
79
# ````julia
80
# amr_controller = ControllerThreeLevelCombined(semi, indicator_primary, indicator_secondary;
81
# base_level=2,
82
# med_level=6, med_threshold=0.0003,
83
# max_level=8, max_threshold=0.003,
84
# max_threshold_secondary=0.3)
85
# ````
86
# This controller is for instance used in
87
# [`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).
88
89
# ### Callback
90
# The AMR indicator and controller are added to the simulation through the callback [`AMRCallback`](@ref).
91
# It contains a semidiscretization `semi`, the controller `amr_controller` and the parameters `interval`,
92
# `adapt_initial_condition`, and `adapt_initial_condition_only_refine`.
93
94
# Adaptive mesh refinement will be performed every `interval` time steps. `adapt_initial_condition` indicates
95
# whether the initial condition already should be adapted before the first time step. And with
96
# `adapt_initial_condition_only_refine=true` the mesh is only refined at the beginning but not coarsened.
97
# ````julia
98
# amr_callback = AMRCallback(semi, amr_controller,
99
# interval=5,
100
# adapt_initial_condition=true,
101
# adapt_initial_condition_only_refine=true)
102
# ````
103
104
# # Exemplary simulation
105
# Here, we want to implement a simple AMR simulation of the 2D linear advection equation for a Gaussian pulse.
106
107
using OrdinaryDiffEqLowStorageRK
108
using Trixi
109
110
advection_velocity = (0.2, -0.7)
111
equations = LinearScalarAdvectionEquation2D(advection_velocity)
112
113
initial_condition = initial_condition_gauss
114
solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs)
115
116
coordinates_min = (-5.0, -5.0)
117
coordinates_max = (5.0, 5.0)
118
mesh = TreeMesh(coordinates_min, coordinates_max,
119
initial_refinement_level = 4,
120
n_cells_max = 30_000,
121
periodicity = true)
122
123
semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver;
124
boundary_conditions = boundary_condition_periodic)
125
126
tspan = (0.0, 10.0)
127
ode = semidiscretize(semi, tspan);
128
129
# For the best understanding about indicators and controllers, we use the simple AMR indicator
130
# `IndicatorMax`. As described before, it returns the maximal value of the specified variable
131
# (here the only conserved variable). Therefore, regions with a high maximum are refined.
132
# This is not really useful numerical application, but a nice demonstration example.
133
amr_indicator = IndicatorMax(semi, variable = first)
134
135
# These values are transferred to a refinement level with the `ControllerThreeLevel`, such that
136
# every element with maximal value greater than `0.1` is refined once and elements with maximum
137
# above `0.6` are refined twice.
138
amr_controller = ControllerThreeLevel(semi, amr_indicator,
139
base_level = 4,
140
med_level = 5, med_threshold = 0.1,
141
max_level = 6, max_threshold = 0.6)
142
143
amr_callback = AMRCallback(semi, amr_controller,
144
interval = 5,
145
adapt_initial_condition = true,
146
adapt_initial_condition_only_refine = true)
147
148
stepsize_callback = StepsizeCallback(cfl = 0.9)
149
150
callbacks = CallbackSet(amr_callback, stepsize_callback);
151
152
# Running the simulation.
153
sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false);
154
dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback
155
ode_default_options()..., callback = callbacks);
156
157
# We plot the solution and add the refined mesh at the end of the simulation.
158
using Plots
159
pd = PlotData2D(sol)
160
plot(pd)
161
plot!(getmesh(pd))
162
163
# # More examples
164
# Trixi.jl provides many elixirs using AMR. We want to give some examples for different mesh types:
165
# - `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)
166
# and [`P4estMesh`](https://github.com/trixi-framework/Trixi.jl/blob/main/examples/p4est_2d_dgsem/elixir_euler_blast_wave_amr.jl)
167
# - [`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`
168
# - [`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`
169
170
# Animations of more interesting and complicated AMR simulations can be found below and on Trixi.jl's youtube channel
171
# ["Trixi Framework"](https://www.youtube.com/channel/UCpd92vU2HjjTPup-AIN0pkg).
172
173
# First, we give a [purely hyperbolic simulation of a Sedov blast wave with self-gravity](https://www.youtube.com/watch?v=dxgzgteJdOA).
174
# This simulation uses the mesh type `TreeMesh` as we did and the AMR indicator `IndicatorHennemannGassner`.
175
# ```@raw html
176
# <!--
177
# Video details
178
# * Source: https://www.youtube.com/watch?v=dxgzgteJdOA
179
# * Authors: Michael Schlottke-Lakemper, Andrew R. Winters, Hendrik Ranocha, Gregor Gassner
180
# * Setup described in detail in: A purely hyperbolic discontinuous Galerkin approach for self-gravitating gas dynamics,
181
# Journal of Computational Physics (2021),(https://doi.org/10.1016/j.jcp.2021.110467).
182
# * Obtain responsive code by inserting link on https://embedresponsively.com
183
# -->
184
# <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>
185
# ```
186
# Source: Trixi.jl's YouTube channel [`Trixi Framework`](https://www.youtube.com/channel/UCpd92vU2HjjTPup-AIN0pkg)
187
188
# The next example is a numerical simulation of an [ideal MHD rotor on an unstructured AMR mesh](https://www.youtube.com/watch?v=Iei7e9oQ0hs).
189
# The used mesh type is a `P4estMesh`.
190
# ```@raw html
191
# <!--
192
# Video details
193
# * Source: https://www.youtube.com/watch?v=Iei7e9oQ0hs
194
# * Author: Andrew R. Winters (https://liu.se/en/employee/andwi94)
195
# * Obtain responsive code by inserting link on https://embedresponsively.com
196
# -->
197
# <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>
198
# ```
199
# Source: Trixi.jl's YouTube channel [`Trixi Framework`](https://www.youtube.com/channel/UCpd92vU2HjjTPup-AIN0pkg)
200
201
# For more information, please have a look at the respective links.
202
203
# ## Package versions
204
205
# These results were obtained using the following versions.
206
207
using InteractiveUtils
208
versioninfo()
209
210
using Pkg
211
Pkg.status(["Trixi", "OrdinaryDiffEqLowStorageRK", "Plots"],
212
mode = PKGMODE_MANIFEST)
213
214