Skip to content

Stratified Couette flow verification #381

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 43 commits into from
Oct 14, 2019
Merged
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
c7dd889
Stratified Couette flow verification script
ali-ramadhan Aug 28, 2019
5e6a924
More comments
ali-ramadhan Aug 28, 2019
ba1afef
Use new HorizontalAverage diagnostic
ali-ramadhan Aug 28, 2019
b573c1f
Update script
ali-ramadhan Aug 28, 2019
1e280be
Diagnose viscous and diffusive CFL numbers from LES
ali-ramadhan Aug 28, 2019
84cb1f7
Don't divide time by length of Earth day.
ali-ramadhan Aug 29, 2019
42848ef
Fix errors in simulation setup
ali-ramadhan Aug 30, 2019
eb729dd
Add a lot more noise
ali-ramadhan Sep 5, 2019
259db0a
Use correct h when calculating frictional Re and Nu
ali-ramadhan Sep 6, 2019
8317668
Update model setup a bit
ali-ramadhan Sep 6, 2019
bccfd7c
Larger initial sine wave to encourage instability
ali-ramadhan Sep 6, 2019
5537310
Better notation for stratified Couette flow parameters
ali-ramadhan Sep 9, 2019
e2396a8
Nuke unused parameters
ali-ramadhan Sep 9, 2019
d5665b3
simulate_stratified_couette_flow function for automation
ali-ramadhan Sep 11, 2019
cc8ffe4
Simulate the three Pr = 0.7 cases
ali-ramadhan Sep 11, 2019
cdd04ba
Merge branch 'master' into stratified-couette-flow
ali-ramadhan Sep 11, 2019
73e9886
Use parameters to store stuff for Re and Nu functions
ali-ramadhan Sep 11, 2019
19ff426
Stratified Couette flow Re and Nu timeseries plot.
ali-ramadhan Sep 11, 2019
bdaa79b
Re and Nu scatter plot
ali-ramadhan Sep 11, 2019
0f8b229
Temperature and velocity profile verification
ali-ramadhan Sep 12, 2019
f06cdc4
Need N=128^3 to match published results
ali-ramadhan Sep 12, 2019
0277c6d
Plot LES profiles and U,T slices
ali-ramadhan Sep 12, 2019
1f3e271
No max filesize for output so analysis script always works
ali-ramadhan Sep 12, 2019
a1350a5
Clean up plots
ali-ramadhan Sep 12, 2019
1df3ca1
Uses horizontal averages directly for output, adds horizontal average…
glwagner Sep 12, 2019
fd3b351
Restores correct resolutions architecture for verification
glwagner Sep 12, 2019
b1c4957
Cannot set parameters to a dict because it must be kernel-ready
glwagner Sep 12, 2019
8c62fed
Some notational improvements to avoid confusion associated with the f…
glwagner Sep 12, 2019
8975044
changes scalars to statistics in stratified couette verification
glwagner Sep 12, 2019
6bc878c
Move verification directory to top-level
ali-ramadhan Sep 18, 2019
c1f121f
Spawn off run script and add arch kwarg
ali-ramadhan Sep 18, 2019
0fd80a6
end_time kwarg
ali-ramadhan Sep 18, 2019
4bb6901
Test that verification scripts run
ali-ramadhan Sep 18, 2019
9dfabba
Not sure why but test fails unless I include in global scope
ali-ramadhan Sep 18, 2019
773aef1
Only run for a single time step and actually include test
ali-ramadhan Sep 18, 2019
b78b37e
Specifically use Float64
ali-ramadhan Sep 19, 2019
ce661b4
Merge branch 'master' into stratified-couette-flow
ali-ramadhan Sep 20, 2019
929872f
Fix typo in test_examples.jl
ali-ramadhan Sep 20, 2019
fe044a4
Refactor stratified_couette_flow.jl for v0.11.0
ali-ramadhan Sep 20, 2019
6dc21af
Fix deepening_mixed_layer.jl example
ali-ramadhan Sep 20, 2019
3e6b73f
Try T0 to avoid conflicting with another T₀
ali-ramadhan Sep 20, 2019
54948b6
Merge branch 'master' into stratified-couette-flow
ali-ramadhan Oct 14, 2019
55ae7b1
Delete deepening_mixed_layer.jl
ali-ramadhan Oct 14, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
276 changes: 276 additions & 0 deletions test/verification/stratified_couette_flow/stratified_couette_flow.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,276 @@
using Statistics, Printf

using Oceananigans
using Oceananigans.TurbulenceClosures

""" Friction velocity. See equation (16) of Vreugdenhil & Taylor (2018). """
function uτ(model)
Nz, Hz, Δz = model.grid.Nz, model.grid.Hz, model.grid.Δz
Uw = model.parameters.Uw
ν = model.closure.ν

Up = HorizontalAverage(model, model.velocities.u; frequency=Inf)
U = Up(model)[1+Hz:end-Hz] # Exclude average of halo region.

# Use a finite difference to calculate dU/dz at the top and bottom walls.
# The distance between the center of the cell adjacent to the wall and the
# wall itself is Δz/2.
uτ²⁺ = ν * abs(U[1] - Uw) / (Δz/2) # Top wall where u = +Uw
uτ²⁻ = ν * abs(-Uw - U[Nz]) / (Δz/2) # Bottom wall where u = -Uw

uτ⁺, uτ⁻ = √uτ²⁺, √uτ²⁻

return uτ⁺, uτ⁻
end

""" Heat flux at the wall. See equation (16) of Vreugdenhil & Taylor (2018). """
function q_wall(model)
Nz, Hz, Δz = model.grid.Nz, model.grid.Hz, model.grid.Δz
Θw = model.parameters.Θw
κ = model.closure.κ

Tp = HorizontalAverage(model, model.tracers.T; frequency=Inf)
Θ = Tp(model)[1+Hz:end-Hz] # Exclude average of halo region.

# Use a finite difference to calculate dθ/dz at the top and bottom walls.
# The distance between the center of the cell adjacent to the wall and the
# wall itself is Δz/2.
q_wall⁺ = κ * abs(Θ[1] - Θw) / (Δz/2) # Top wall where Θ = +Θw
q_wall⁻ = κ * abs(-Θw - Θ[Nz]) / (Δz/2) # Bottom wall where Θ = -Θw

return q_wall⁺, q_wall⁻
end

""" Friction Reynolds number. See equation (20) of Vreugdenhil & Taylor (2018). """
function Reτ(model)
ν = model.closure.ν
h = model.grid.Lz / 2
uτ⁺, uτ⁻ = uτ(model)

return h * uτ⁺ / ν, h * uτ⁻ / ν
end

""" Friction Nusselt number. See equation (20) of Vreugdenhil & Taylor (2018). """
function Nu(model)
κ = model.closure.κ
h = model.grid.Lz / 2
Θw = model.parameters.Θw

q_wall⁺, q_wall⁻ = q_wall(model)

return (q_wall⁺ * h)/(κ * Θw), (q_wall⁻ * h)/(κ * Θw)
end

"""
simulate_stratified_couette_flow(; Nxy, Nz, h, Uw, Re, Pr, Ri)

Simulate stratified plane Couette flow with `Nxy` grid cells in each horizontal
direction, `Nz` grid cells in the vertical, in a domain of size (4πh, 2πh, 2h),
with wall velocities of `Uw` at the top and -`Uw` at the bottom, at a Reynolds
number `Re, Prandtl number `Pr`, and Richardson number `Ri`.
"""
function simulate_stratified_couette_flow(; Nxy, Nz, h=1, Uw=1, Re=4250, Pr=0.7, Ri)
####
#### Computed parameters
####

ν = Uw * h / Re # From Re = Uw h / ν
Θw = Ri * Uw^2 / h # From Ri = L Θw / Uw²
κ = ν / Pr # From Pr = ν / κ

parameters = (Uw=Uw, Θw=Θw, Re=Re, Pr=Pr, Ri=Ri)

####
#### Impose boundary conditions
####

Tbcs = HorizontallyPeriodicBCs( top = BoundaryCondition(Value, Θw),
bottom = BoundaryCondition(Value, -Θw))

ubcs = HorizontallyPeriodicBCs( top = BoundaryCondition(Value, Uw),
bottom = BoundaryCondition(Value, -Uw))

vbcs = HorizontallyPeriodicBCs( top = BoundaryCondition(Value, 0),
bottom = BoundaryCondition(Value, 0))

####
#### Non-dimensional model setup
####

model = Model(N = (Nxy, Nxy, Nz),
L = (4π*h, 2π*h, 2h),
arch = GPU(),
closure = AnisotropicMinimumDissipation(ν=ν, κ=κ),
eos = LinearEquationOfState(βT=1, βS=0),
constants = PlanetaryConstants(f=0, g=1),
bcs = BoundaryConditions(u=ubcs, v=vbcs, T=Tbcs),
parameters = parameters)

####
#### Set initial conditions
####

# Add a bit of surface-concentrated noise to the initial condition
ε(σ, z) = σ * randn() * z/model.grid.Lz * (1 + z/model.grid.Lz)

# We add a sinusoidal initial condition to u to encourage instability.
T₀(x, y, z) = 2Θw * (1/2 + z/model.grid.Lz) * (1 + ε(5e-1, z))
u₀(x, y, z) = 2Uw * (1/2 + z/model.grid.Lz) * (1 + ε(5e-1, z)) * (1 + 0.5*sin(4π/model.grid.Lx * x))
v₀(x, y, z) = ε(5e-1, z)
w₀(x, y, z) = ε(5e-1, z)
S₀(x, y, z) = ε(5e-1, z)

set_ic!(model, u=u₀, v=v₀, w=w₀, T=T₀, S=S₀)

####
#### Print simulation banner
####

@printf(
"""
Simulating stratified plane Couette flow

N : %d, %d, %d
L : %.3g, %.3g, %.3g
Re : %.3f
Ri : %.3f
Pr : %.3f
ν : %.3g
κ : %.3g
Uw : %.3f
Θw : %.3f

""", model.grid.Nx, model.grid.Ny, model.grid.Nz,
model.grid.Lx, model.grid.Ly, model.grid.Lz,
Re, Ri, Pr, ν, κ, Uw, Θw)

####
#### Set up field output writer
####

base_dir = @sprintf("stratified_couette_flow_data_Nxy%d_Nz%d_Ri%.2f", Nxy, Nz, Ri)
prefix = @sprintf("stratified_couette_flow_Nxy%d_Nz%d_Ri%.2f", Nxy, Nz, Ri)

function init_save_parameters_and_bcs(file, model)
file["parameters/reynolds_number"] = Re
file["parameters/richardson_number"] = Ri
file["parameters/prandtl_number"] = Pr
file["parameters/viscosity"] = ν
file["parameters/diffusivity"] = κ
file["parameters/wall_velocity"] = Uw
file["parameters/wall_temperature"] = Θw
end

fields = Dict(
:u => model -> Array(model.velocities.u.data.parent),
:v => model -> Array(model.velocities.v.data.parent),
:w => model -> Array(model.velocities.w.data.parent),
:T => model -> Array(model.tracers.T.data.parent),
:kappaT => model -> Array(model.diffusivities.κₑ.T.data.parent),
:nu => model -> Array(model.diffusivities.νₑ.data.parent))


field_writer = JLD2OutputWriter(model, fields; dir=base_dir, prefix=prefix * "_fields",
init=init_save_parameters_and_bcs,
interval=10, force=true, verbose=true)

push!(model.output_writers, field_writer)

####
#### Set up diagnostics
####

push!(model.diagnostics, NaNChecker(model))

Δtₚ = 1 # Time interval for computing and saving profiles.

Up = HorizontalAverage(model, model.velocities.u; interval=Δtₚ)
Vp = HorizontalAverage(model, model.velocities.v; interval=Δtₚ)
Wp = HorizontalAverage(model, model.velocities.w; interval=Δtₚ)
Tp = HorizontalAverage(model, model.tracers.T; interval=Δtₚ)
νp = HorizontalAverage(model, model.diffusivities.νₑ; interval=Δtₚ)
κp = HorizontalAverage(model, model.diffusivities.κₑ.T; interval=Δtₚ)

append!(model.diagnostics, [Up, Vp, Wp, Tp, νp, κp])

####
#### Set up profile output writer
####

profiles = Dict(
:u => model -> Array(Up.profile),
:v => model -> Array(Vp.profile),
:w => model -> Array(Wp.profile),
:T => model -> Array(Tp.profile),
:nu => model -> Array(νp.profile),
:kappaT => model -> Array(κp.profile))

profile_writer = JLD2OutputWriter(model, profiles; dir=base_dir, prefix=prefix * "_profiles",
init=init_save_parameters_and_bcs, interval=Δtₚ, force=true, verbose=true)

push!(model.output_writers, profile_writer)

####
#### Set up scalar output writer
####

scalars = Dict(
:Re_tau => model -> Reτ(model),
:Nu_tau => model -> Nu(model))

scalar_writer = JLD2OutputWriter(model, scalars; dir=base_dir, prefix=prefix * "_scalars",
init=init_save_parameters_and_bcs, interval=Δtₚ/2, force=true, verbose=true)

push!(model.output_writers, scalar_writer)

####
#### Time stepping
####

wizard = TimeStepWizard(cfl=0.02, Δt=0.0001, max_change=1.1, max_Δt=0.02)

function cell_diffusion_timescale(model)
Δ = min(model.grid.Δx, model.grid.Δy, model.grid.Δz)
max_ν = maximum(model.diffusivities.νₑ.data.parent)
max_κ = max(Tuple(maximum(κₑ.data.parent) for κₑ in model.diffusivities.κₑ)...)
return min(Δ^2 / max_ν, Δ^2 / max_κ)
end

# Take Ni "intermediate" time steps at a time before printing a progress
# statement and updating the time step.
Ni = 10

cfl(t) = min(0.01*t, 0.1)

end_time = 1000
while model.clock.time < end_time
wizard.cfl = cfl(model.clock.time)

walltime = @elapsed time_step!(model; Nt=Ni, Δt=wizard.Δt)
progress = 100 * (model.clock.time / end_time)

umax = maximum(abs, model.velocities.u.data.parent)
vmax = maximum(abs, model.velocities.v.data.parent)
wmax = maximum(abs, model.velocities.w.data.parent)
CFL = wizard.Δt / cell_advection_timescale(model)

νmax = maximum(model.diffusivities.νₑ.data.parent)
κmax = maximum(model.diffusivities.κₑ.T.data.parent)

Δ = min(model.grid.Δx, model.grid.Δy, model.grid.Δz)
νCFL = wizard.Δt / (Δ^2 / νmax)
κCFL = wizard.Δt / (Δ^2 / κmax)

update_Δt!(wizard, model)

@printf("[%06.2f%%] i: %d, t: %4.2f, umax: (%6.3g, %6.3g, %6.3g) m/s, CFL: %6.4g, νκmax: (%6.3g, %6.3g), νκCFL: (%6.4g, %6.4g), next Δt: %8.5g, ⟨wall time⟩: %s\n",
progress, model.clock.iteration, model.clock.time,
umax, vmax, wmax, CFL, νmax, κmax, νCFL, κCFL,
wizard.Δt, prettytime(walltime / Ni))
end
end

simulate_stratified_couette_flow(Nxy=128, Nz=128, Ri=0)
simulate_stratified_couette_flow(Nxy=128, Nz=128, Ri=0.01)
simulate_stratified_couette_flow(Nxy=128, Nz=128, Ri=0.04)

Loading