Skip to content

Commit 925f4c9

Browse files
jagooswglwagnernavidcy
authored
Changes default AMD poincare coefficient (#4494)
* Changes default AMD poincare coefficient * Update test_nonhydrostatic_regression.jl * Update anisotropic_minimum_dissipation.jl * update amd dockets * updated docstrings + added validation case * Update src/TurbulenceClosures/turbulence_closure_implementations/anisotropic_minimum_dissipation.jl Co-authored-by: Gregory L. Wagner <[email protected]> * Update anisotropic_minimum_dissipation.jl --------- Co-authored-by: Gregory L. Wagner <[email protected]> Co-authored-by: Navid C. Constantinou <[email protected]>
1 parent 7c561b6 commit 925f4c9

File tree

5 files changed

+125
-22
lines changed

5 files changed

+125
-22
lines changed

docs/oceananigans.bib

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -990,4 +990,13 @@ @article{Lan2022
990990
pages = {111050},
991991
year = {2022},
992992
doi = {https://doi.org/10.1016/j.jcp.2022.111050},
993+
}
994+
995+
@article{Verstappen14,
996+
author = {Verstappen, Roel and Rozema, Wybe and Bae, H. Jane},
997+
year = {2014},
998+
month = {12},
999+
pages = {417-426},
1000+
title = {Numerical scale separation in large-eddy simulation},
1001+
url = {https://www.researchgate.net/publication/311885631}
9931002
}

docs/src/model_setup/turbulent_diffusivity_closures_and_les_models.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,8 @@ julia> using Oceananigans.TurbulenceClosures
8282
8383
julia> closure = AnisotropicMinimumDissipation()
8484
AnisotropicMinimumDissipation{ExplicitTimeDiscretization} turbulence closure with:
85-
Poincaré constant for momentum eddy viscosity Cν: 0.08333333333333333
86-
Poincaré constant for tracer(s) eddy diffusivit(ies) Cκ: 0.08333333333333333
85+
Poincaré constant for momentum eddy viscosity Cν: 0.3333333333333333
86+
Poincaré constant for tracer(s) eddy diffusivit(ies) Cκ: 0.3333333333333333
8787
Buoyancy modification multiplier Cb: nothing
8888
```
8989

src/TurbulenceClosures/turbulence_closure_implementations/anisotropic_minimum_dissipation.jl

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,13 @@ const AMD = AnisotropicMinimumDissipation
2424

2525
Base.show(io::IO, closure::AMD{TD}) where TD =
2626
print(io, "AnisotropicMinimumDissipation{$TD} turbulence closure with:\n",
27-
" Poincaré constant for momentum eddy viscosity Cν: ", closure.Cν, "\n",
28-
" Poincaré constant for tracer(s) eddy diffusivit(ies) Cκ: ", closure.Cκ, "\n",
27+
" Poincaré constant for momentum eddy viscosity Cν: ", closure.Cν, "\n",
28+
" Poincaré constant for tracer(s) eddy diffusivit(ies) Cκ: ", closure.Cκ, "\n",
2929
" Buoyancy modification multiplier Cb: ", closure.Cb)
3030

3131
"""
3232
AnisotropicMinimumDissipation([time_discretization = ExplicitTimeDiscretization, FT = Float64;]
33-
C = 1/12, Cν = nothing, Cκ = nothing, Cb = nothing)
33+
C = 1/3, Cν = nothing, Cκ = nothing, Cb = nothing)
3434
3535
3636
Return parameters of type `FT` for the `AnisotropicMinimumDissipation`
@@ -49,24 +49,29 @@ Arguments
4949
5050
Keyword arguments
5151
=================
52-
* `C`: Poincaré constant for both eddy viscosity and eddy diffusivities. `C` is overridden
53-
for eddy viscosity or eddy diffusivity if `Cν` or `Cκ` are set, respecitvely.
52+
* `C`: Poincaré constant for both eddy viscosity and eddy diffusivities. `C` is overridden
53+
for eddy viscosity or eddy diffusivity if `Cν` or `Cκ` are set, respectively.
5454
55-
* `Cν`: Poincaré constant for momentum eddy viscosity.
55+
* `Cν`: Poincaré constant for momentum eddy viscosity.
5656
57-
* `Cκ`: Poincaré constant for tracer eddy diffusivities. If one number or function, the same
57+
* `Cκ`: Poincaré constant for tracer eddy diffusivities. If one number or function, the same
5858
number or function is applied to all tracers. If a `NamedTuple`, it must possess
59-
a field specifying the Poncaré constant for every tracer.
59+
a field specifying the Poncaré constant for every tracer.
6060
6161
* `Cb`: Buoyancy modification multiplier (`Cb = nothing` turns it off, `Cb = 1` was used by [Abkar16](@citet)).
6262
*Note*: that we _do not_ subtract the horizontally-average component before computing this
6363
buoyancy modification term. This implementation differs from [Abkar16](@citet)'s proposal
6464
and the impact of this approximation has not been tested or validated.
6565
66-
By default: `C = Cν = Cκ = 1/12`, which is appropriate for a finite-volume method employing a
67-
second-order advection scheme, and `Cb = nothing`, which turns off the buoyancy modification term.
66+
By default: `C = Cν = Cκ = 1/3`, and `Cb = nothing`, which turns off the buoyancy modification term.
67+
The default Poincaré constant is found by discretizing subgrid scale energy production, assuming a
68+
second-order advection scheme. [Verstappen14](@citeo) shows that the Poincaré constant
69+
should be 4 times larger than for straightforward (spectral) discretisation, resulting in `C = 1/3`
70+
in our formulation. They also empirically demonstrated that this coefficient produces the correct
71+
discrete production-dissipation balance. We further demonstrated this in
72+
https://github.com/CliMA/Oceananigans.jl/issues/4367.
6873
69-
`Cν` or `Cκ` may be numbers, or functions of `x, y, z`.
74+
`C`, `Cν` and `Cκ` may be numbers, or functions of `x, y, z`.
7075
7176
Examples
7277
========
@@ -76,8 +81,8 @@ julia> using Oceananigans
7681
7782
julia> pretty_diffusive_closure = AnisotropicMinimumDissipation(C=1/2)
7883
AnisotropicMinimumDissipation{ExplicitTimeDiscretization} turbulence closure with:
79-
Poincaré constant for momentum eddy viscosity Cν: 0.5
80-
Poincaré constant for tracer(s) eddy diffusivit(ies) Cκ: 0.5
84+
Poincaré constant for momentum eddy viscosity Cν: 0.5
85+
Poincaré constant for tracer(s) eddy diffusivit(ies) Cκ: 0.5
8186
Buoyancy modification multiplier Cb: nothing
8287
```
8388
@@ -90,8 +95,8 @@ julia> surface_enhanced_tracer_C(x, y, z) = 1/12 * (1 + exp((z + Δz/2) / 8Δz))
9095
9196
julia> fancy_closure = AnisotropicMinimumDissipation(Cκ=surface_enhanced_tracer_C)
9297
AnisotropicMinimumDissipation{ExplicitTimeDiscretization} turbulence closure with:
93-
Poincaré constant for momentum eddy viscosity Cν: 0.08333333333333333
94-
Poincaré constant for tracer(s) eddy diffusivit(ies) Cκ: surface_enhanced_tracer_C
98+
Poincaré constant for momentum eddy viscosity Cν: 0.3333333333333333
99+
Poincaré constant for tracer(s) eddy diffusivit(ies) Cκ: surface_enhanced_tracer_C
95100
Buoyancy modification multiplier Cb: nothing
96101
```
97102
@@ -100,23 +105,27 @@ julia> using Oceananigans
100105
101106
julia> tracer_specific_closure = AnisotropicMinimumDissipation(Cκ=(c₁=1/12, c₂=1/6))
102107
AnisotropicMinimumDissipation{ExplicitTimeDiscretization} turbulence closure with:
103-
Poincaré constant for momentum eddy viscosity Cν: 0.08333333333333333
104-
Poincaré constant for tracer(s) eddy diffusivit(ies) Cκ: (c₁ = 0.08333333333333333, c₂ = 0.16666666666666666)
108+
Poincaré constant for momentum eddy viscosity Cν: 0.3333333333333333
109+
Poincaré constant for tracer(s) eddy diffusivit(ies) Cκ: (c₁ = 0.08333333333333333, c₂ = 0.16666666666666666)
105110
Buoyancy modification multiplier Cb: nothing
106111
```
107112
108113
References
109114
==========
110115
116+
Verstappen, R. & Rozema, W. & Bae, J.H. (2014), "Numerical scale separation in large-eddy
117+
simulation", Center for Turbulence ResearchProceedings of the Summer Program 2014.
118+
111119
Vreugdenhil C., and Taylor J. (2018), "Large-eddy simulations of stratified plane Couette
112120
flow using the anisotropic minimum-dissipation model", Physics of Fluids 30, 085104.
113121
114122
Verstappen, R. (2018), "How much eddy dissipation is needed to counterbalance the nonlinear
115123
production of small, unresolved scales in a large-eddy simulation of turbulence?",
116124
Computers & Fluids 176, pp. 276-284.
125+
}
117126
"""
118127
function AnisotropicMinimumDissipation(time_disc::TD = ExplicitTimeDiscretization(), FT = Oceananigans.defaults.FloatType;
119-
C = FT(1/12), Cν = nothing, Cκ = nothing, Cb = nothing) where TD
128+
C = FT(1/3), Cν = nothing, Cκ = nothing, Cb = nothing) where TD
120129

121130
==== nothing ? C :
122131
==== nothing ? C :

test/test_nonhydrostatic_regression.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ include("regression_tests/ocean_large_eddy_simulation_regression_test.jl")
6464
run_thermal_bubble_regression_test(arch, grid_type)
6565
end
6666

67-
amd_closure = (AnisotropicMinimumDissipation(), ScalarDiffusivity=1.05e-6, κ=1.46e-7))
67+
amd_closure = (AnisotropicMinimumDissipation(C=1/12), ScalarDiffusivity=1.05e-6, κ=1.46e-7))
6868
smag_closure = (SmagorinskyLilly(C=0.23, Cb=1, Pr=1), ScalarDiffusivity=1.05e-6, κ=1.46e-7))
6969

7070
for closure in (amd_closure, smag_closure)
@@ -77,4 +77,4 @@ include("regression_tests/ocean_large_eddy_simulation_regression_test.jl")
7777
end
7878
end
7979
end
80-
end
80+
end
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
using Oceananigans, FFTW, StatsBase, CairoMakie
2+
3+
using Oceananigans.Models.HydrostaticFreeSurfaceModels: compute_w_from_continuity!
4+
5+
arch = CPU()
6+
7+
grid = RectilinearGrid(arch, size = (32, 32, 32), extent = (1, 1, 1))
8+
9+
closure = AnisotropicMinimumDissipation(VerticallyImplicitTimeDiscretization(), C=1/3)
10+
11+
model = NonhydrostaticModel(; grid, closure)
12+
13+
u, v, w = model.velocities
14+
15+
set!(u, (args...)->randn())
16+
set!(v, (args...)->randn())
17+
18+
compute_w_from_continuity!((; u, v, w), arch, grid)
19+
20+
function extract_energy(u, v, w, grid)
21+
û = fftshift(fft(@at (Center, Center, Center) u))
22+
= fftshift(fft(@at (Center, Center, Center) v))
23+
ŵ = fftshift(fft(@at (Center, Center, Center) w))
24+
25+
Nx, Ny, Nz = u.grid.Nx, u.grid.Ny, u.grid.Nz
26+
27+
kx = fftshift(fftfreq(Nx, 1/u.grid.Δxᶜᵃᵃ))
28+
ky = fftshift(fftfreq(Ny, 1/u.grid.Δyᵃᶜᵃ))
29+
kz = fftshift(fftfreq(Nz, 1/u.grid.z.Δᵃᵃᶜ))
30+
31+
Nx, Ny, Nz = length(kx), length(ky), length(kz)
32+
33+
KX = reshape(kx, Nx, 1, 1)
34+
KY = reshape(ky, 1, Ny, 1)
35+
KZ = reshape(kz, 1, 1, Nz)
36+
37+
K = sqrt.(KX.^2 .+ KY.^2 .+ KZ.^2)
38+
39+
E = abs.((û.^2 .+.^2 .+ ŵ.^2)./2)
40+
41+
return E, K
42+
end
43+
44+
fig = Figure()
45+
46+
ax = Axis(fig[1, 1], xscale=log, yscale=log, xlabel = "Wavenumber (1/m)", ylabel = "Energy density (m³/s²)")
47+
48+
k_bins = exp.(0:0.25:4)
49+
50+
xlims!(ax, minimum(k_bins), maximum(k_bins))
51+
ylims!(ax, exp(-1), exp(25))
52+
53+
E, K = extract_energy(u, v, w, grid)
54+
55+
E_binned = fit(Histogram, [K...], weights([E...]), k_bins).weights
56+
57+
lines!(ax, (k_bins[1:end-1] .+ k_bins[2:end])./2, E_binned, color = 0, colorrange = (0, 10), colormap = :oslo)
58+
59+
simulation = Simulation(model, Δt = 0.5 * minimum_xspacing(grid) / 5, stop_time = 10)
60+
61+
add_callback!(simulation, (sim)->(@info "$(prettytime(time(sim))) in $(prettytime(sim.run_wall_time))"), IterationInterval(100))
62+
63+
function add_line!(sim)
64+
E, K = extract_energy(u, v, w, grid)
65+
E_binned = fit(Histogram, [K...], weights([E...]), k_bins).weights
66+
lines!(ax, (k_bins[1:end-1] .+ k_bins[2:end])./2, E_binned, color = time(sim), colorrange = (0, 10), colormap = :oslo)
67+
end
68+
69+
add_callback!(simulation, add_line!, TimeInterval(0.1))
70+
71+
run!(simulation)
72+
73+
lines!(ax, [exp(1), exp(3)], x->(x/exp(1))^(-5/3)*exp(15), color = :red, linestyle = :dash)
74+
75+
text!(ax, exp(0.8), exp(13); text = L"$E(k)\sim k^{-5/3}$", color = :white)
76+
77+
Colorbar(fig[1, 2], colormap = :oslo, colorrange = (0, 10), label = "Time (s)")
78+
79+
k_filt = 1/sqrt(closure.* 3 / (1/(2*minimum_xspacing(grid))^2 + 1/(2*minimum_yspacing(grid))^2 + 1/(2*minimum_zspacing(grid))^2))
80+
81+
lines!(ax, ones(2) .* k_filt, [exp(0), exp(10)], color = :red, linestyle = :dash)
82+
83+
text!(ax, k_filt, exp(10); text = "1/δ")
84+
85+
save("energy.png", fig)

0 commit comments

Comments
 (0)