Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
trixi-framework
GitHub Repository: trixi-framework/Trixi.jl
Path: blob/main/examples/structured_2d_dgsem/elixir_euler_warm_bubble.jl
2055 views
1
using OrdinaryDiffEqLowStorageRK
2
using Trixi
3
4
# Warm bubble test case from
5
# - Wicker, L. J., and Skamarock, W. C. (1998)
6
# A time-splitting scheme for the elastic equations incorporating
7
# second-order Runge–Kutta time differencing
8
# [DOI: 10.1175/1520-0493(1998)126%3C1992:ATSSFT%3E2.0.CO;2](https://doi.org/10.1175/1520-0493(1998)126%3C1992:ATSSFT%3E2.0.CO;2)
9
# See also
10
# - Bryan and Fritsch (2002)
11
# A Benchmark Simulation for Moist Nonhydrostatic Numerical Models
12
# [DOI: 10.1175/1520-0493(2002)130<2917:ABSFMN>2.0.CO;2](https://doi.org/10.1175/1520-0493(2002)130<2917:ABSFMN>2.0.CO;2)
13
# - Carpenter, Droegemeier, Woodward, Hane (1990)
14
# Application of the Piecewise Parabolic Method (PPM) to
15
# Meteorological Modeling
16
# [DOI: 10.1175/1520-0493(1990)118<0586:AOTPPM>2.0.CO;2](https://doi.org/10.1175/1520-0493(1990)118<0586:AOTPPM>2.0.CO;2)
17
struct WarmBubbleSetup
18
# Physical constants
19
g::Float64 # gravity of earth
20
c_p::Float64 # heat capacity for constant pressure (dry air)
21
c_v::Float64 # heat capacity for constant volume (dry air)
22
gamma::Float64 # heat capacity ratio (dry air)
23
24
function WarmBubbleSetup(; g = 9.81, c_p = 1004.0, c_v = 717.0, gamma = c_p / c_v)
25
new(g, c_p, c_v, gamma)
26
end
27
end
28
29
# Initial condition
30
function (setup::WarmBubbleSetup)(x, t, equations::CompressibleEulerEquations2D)
31
@unpack g, c_p, c_v = setup
32
33
# center of perturbation
34
center_x = 10000.0
35
center_z = 2000.0
36
# radius of perturbation
37
radius = 2000.0
38
# distance of current x to center of perturbation
39
r = sqrt((x[1] - center_x)^2 + (x[2] - center_z)^2)
40
41
# perturbation in potential temperature
42
potential_temperature_ref = 300.0
43
potential_temperature_perturbation = 0.0
44
if r <= radius
45
potential_temperature_perturbation = 2 * cospi(0.5 * r / radius)^2
46
end
47
potential_temperature = potential_temperature_ref + potential_temperature_perturbation
48
49
# Exner pressure, solves hydrostatic equation for x[2]
50
exner = 1 - g / (c_p * potential_temperature) * x[2]
51
52
# pressure
53
p_0 = 100_000.0 # reference pressure
54
R = c_p - c_v # gas constant (dry air)
55
p = p_0 * exner^(c_p / R)
56
57
# temperature
58
T = potential_temperature * exner
59
60
# density
61
rho = p / (R * T)
62
63
v1 = 20.0
64
v2 = 0.0
65
E = c_v * T + 0.5 * (v1^2 + v2^2)
66
return SVector(rho, rho * v1, rho * v2, rho * E)
67
end
68
69
# Source terms
70
@inline function (setup::WarmBubbleSetup)(u, x, t, equations::CompressibleEulerEquations2D)
71
@unpack g = setup
72
rho, _, rho_v2, _ = u
73
return SVector(zero(eltype(u)), zero(eltype(u)), -g * rho, -g * rho_v2)
74
end
75
76
###############################################################################
77
# semidiscretization of the compressible Euler equations
78
warm_bubble_setup = WarmBubbleSetup()
79
80
equations = CompressibleEulerEquations2D(warm_bubble_setup.gamma)
81
82
boundary_conditions = (x_neg = boundary_condition_periodic,
83
x_pos = boundary_condition_periodic,
84
y_neg = boundary_condition_slip_wall,
85
y_pos = boundary_condition_slip_wall)
86
87
polydeg = 3
88
basis = LobattoLegendreBasis(polydeg)
89
90
# This is a good estimate for the speed of sound in this example.
91
# Other values between 300 and 400 should work as well.
92
surface_flux = FluxLMARS(340.0)
93
94
volume_flux = flux_kennedy_gruber
95
volume_integral = VolumeIntegralFluxDifferencing(volume_flux)
96
97
solver = DGSEM(basis, surface_flux, volume_integral)
98
99
coordinates_min = (0.0, 0.0)
100
coordinates_max = (20_000.0, 10_000.0)
101
102
cells_per_dimension = (64, 32)
103
mesh = StructuredMesh(cells_per_dimension, coordinates_min, coordinates_max,
104
periodicity = (true, false))
105
106
semi = SemidiscretizationHyperbolic(mesh, equations, warm_bubble_setup, solver,
107
source_terms = warm_bubble_setup,
108
boundary_conditions = boundary_conditions)
109
110
###############################################################################
111
# ODE solvers, callbacks etc.
112
113
tspan = (0.0, 1000.0) # 1000 seconds final time
114
115
ode = semidiscretize(semi, tspan)
116
117
summary_callback = SummaryCallback()
118
119
analysis_interval = 1000
120
121
analysis_callback = AnalysisCallback(semi, interval = analysis_interval,
122
extra_analysis_errors = (:entropy_conservation_error,))
123
124
alive_callback = AliveCallback(analysis_interval = analysis_interval)
125
126
save_solution = SaveSolutionCallback(interval = analysis_interval,
127
save_initial_solution = true,
128
save_final_solution = true,
129
output_directory = "out",
130
solution_variables = cons2prim)
131
132
stepsize_callback = StepsizeCallback(cfl = 1.0)
133
134
callbacks = CallbackSet(summary_callback,
135
analysis_callback,
136
alive_callback,
137
save_solution,
138
stepsize_callback)
139
140
###############################################################################
141
# run the simulation
142
sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false);
143
maxiters = 1.0e7,
144
dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback
145
ode_default_options()..., callback = callbacks);
146
147