forked from agdestein/IncompressibleNavierStokes.jl
-
Notifications
You must be signed in to change notification settings - Fork 0
/
DecayingTurbulence3D.jl
163 lines (136 loc) · 4.58 KB
/
DecayingTurbulence3D.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
# Little LSP hack to get function signatures, go #src
# to definition etc. #src
if isdefined(@__MODULE__, :LanguageServer) #src
include("../src/IncompressibleNavierStokes.jl") #src
using .IncompressibleNavierStokes #src
end #src
# # Decaying Homogeneous Isotropic Turbulence - 3D
#
# In this example we consider decaying homogeneous isotropic turbulence,
# similar to the cases considered in [Kochkov2021](@cite) and
# [Kurz2022](@cite). The initial velocity field is created randomly, but with a
# specific energy spectrum. Due to viscous dissipation, the turbulent features
# eventually group to form larger visible eddies.
# We start by loading packages.
# A [Makie](https://github.com/JuliaPlots/Makie.jl) plotting backend is needed
# for plotting. `GLMakie` creates an interactive window (useful for real-time
# plotting), but does not work when building this example on GitHub.
# `CairoMakie` makes high-quality static vector-graphics plots.
using FFTW
#md using CairoMakie
using GLMakie #!md
using IncompressibleNavierStokes
using LaTeXStrings
# Case name for saving results
name = "DecayingTurbulence3D"
# Viscosity model
viscosity_model = LaminarModel(; Re = 1e4)
# A 3D grid is a Cartesian product of three vectors
n = 50
x = LinRange(0.0, 1.0, n + 1)
y = LinRange(0.0, 1.0, n + 1)
z = LinRange(0.0, 1.0, n + 1)
plot_grid(x, y, z)
# Build setup and assemble operators
setup = Setup(x, y, z; viscosity_model);
# Since the grid is uniform and identical for x, y, and z, we may use a
# specialized Fourier pressure solver
pressure_solver = FourierPressureSolver(setup)
# Initial conditions
K = n ÷ 2
σ = 30
## σ = 10
s = 5
function create_spectrum(K)
a =
1e6 * [
1 / sqrt((2π)^3 * 3σ^2) *
exp(-((i - s)^2 + (j - s)^2 + (k - s)^2) / 2σ^2) *
exp(-2π * im * rand()) for i = 1:K, j = 1:K, k = 1:K
]
[
a reverse(a; dims = 2); reverse(a; dims = 1) reverse(a; dims = (1, 2));;;
reverse(a; dims = 3) reverse(a; dims = (2, 3)); reverse(a; dims = (1, 3)) reverse(a)
]
end
u = real.(ifft(create_spectrum(K)))
v = real.(ifft(create_spectrum(K)))
w = real.(ifft(create_spectrum(K)))
V = [reshape(u, :); reshape(v, :); reshape(w, :)]
f = setup.operators.M * V
p = zero(f)
# Boundary conditions
bc_vectors = get_bc_vectors(setup, 0.0)
(; yM) = bc_vectors
# Make velocity field divergence free
(; Ω⁻¹) = setup.grid
(; G, M) = setup.operators
f = M * V + yM
Δp = pressure_poisson(pressure_solver, f)
V .-= Ω⁻¹ .* (G * Δp)
p = pressure_additional_solve(pressure_solver, V, p, 0.0, setup; bc_vectors)
V₀, p₀ = V, p
# Time interval
t_start, t_end = tlims = (0.0, 0.1)
# Iteration processors
logger = Logger()
observer = StateObserver(1, V₀, p₀, t_start)
writer = VTKWriter(; nupdate = 100, dir = "output/$name", filename = "solution")
tracer = QuantityTracer()
## processors = [logger, observer, tracer, writer]
processors = [logger, observer, tracer]
# Real time plot
rtp = real_time_plot(observer, setup)
# Plot energy history
(; Ωp) = setup.grid
_points = Point2f[]
points = @lift begin
V, p, t = $(observer.state)
up, vp, wp = get_velocity(V, t, setup)
up = reshape(up, :)
vp = reshape(vp, :)
wp = reshape(wp, :)
E = sum(@. Ωp * (up^2 + vp^2 + wp^2))
push!(_points, Point2f(t, E))
end
ehist = lines(points; axis = (; xlabel = "t", ylabel = "Kinetic energy"))
# Plot energy spectrum
k = 1:(K-1)
kk = reshape([sqrt(kx^2 + ky^2 + kz^2) for kx ∈ k, ky ∈ k, kz ∈ k], :)
ehat = @lift begin
V, p, t = $(observer.state)
up, vp, wp = get_velocity(V, t, setup)
e = @. up^2 + vp^2 + wp^2
reshape(abs.(fft(e)[k.+1, k.+1, k.+1]), :)
end
espec = Figure()
ax =
Axis(espec[1, 1]; xlabel = L"k", ylabel = L"\hat{e}(k)", xscale = log10, yscale = log10)
## ylims!(ax, (1e-20, 1))
scatter!(ax, kk, ehat; label = "Kinetic energy")
krange = LinRange(extrema(kk)..., 100)
lines!(ax, krange, 1e6 * krange .^ (-5 / 3); label = L"k^{-5/3}", color = :red)
axislegend(ax)
espec
# Solve unsteady problem
problem = UnsteadyProblem(setup, V₀, p₀, tlims);
V, p = solve(problem, RK44(); Δt = 0.001, processors, pressure_solver, inplace = true);
# Real time plot
rtp
# Energy history
ehist
# Energy spectrum
espec
# ## Post-process
#
# We may visualize or export the computed fields `(V, p)`
# Export to VTK
save_vtk(V, p, t_end, setup, "output/solution")
# Plot tracers
plot_tracers(tracer)
# Plot pressure
plot_pressure(setup, p)
# Plot velocity
plot_velocity(setup, V, t_end)
# Plot vorticity
plot_vorticity(setup, V, t_end)