Skip to content

Commit 9ce4606

Browse files
committed
relaxation, consumption, scale_sst
1 parent 759c200 commit 9ce4606

File tree

8 files changed

+98
-84
lines changed

8 files changed

+98
-84
lines changed

src/constants.jl

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -46,16 +46,17 @@ struct Constants{T<:AbstractFloat,Tprog<:AbstractFloat}
4646
γ::T # frequency of interface relaxation
4747
cSmag::T # Smagorinsky constant
4848
νB::T # biharmonic diffusion coefficient
49-
rSST::T # tracer restoring timescale
49+
τSST::T # tracer restoring timescale
5050
jSST::T # tracer consumption timescale
51-
SSTmin::T # tracer minimum
5251
ωFη::Float64 # frequency [1/s] of seasonal surface forcing incl 2π
5352
ωFx::Float64 # frequency [1/s] of seasonal wind x incl 2π
5453
ωFy::Float64 # frequency [1/2] of seasonal wind y incl 2π
5554

5655
# SCALING
5756
scale::T # multiplicative constant for low-precision arithmetics
58-
scale_inv::T # and it's inverse
57+
scale_inv::T # and its inverse
58+
scale_sst::T # scale for sst
59+
scale_sst_inv::T # and its inverse
5960
end
6061

6162
"""Generator function for the mutable struct Constants."""
@@ -105,22 +106,24 @@ function Constants{T,Tprog}(P::Parameter,G::Grid) where {T<:AbstractFloat,Tprog<
105106
νB = T(-P.νB/30000) # linear scaling based on 540m^s/s at Δ=30km
106107

107108
# TRACER ADVECTION
108-
rSST = T(G.dtadvint/(P.τSST*3600*24)) # tracer restoring [1]
109+
τSST = T(G.dtadvint/(P.τSST*3600*24)) # tracer restoring [1]
109110
jSST = T(G.dtadvint/(P.jSST*3600*24)) # tracer consumption [1]
110-
SSTmin = T(P.SSTmin)
111111

112112
# TIME DEPENDENT FORCING
113113
ωFη = -2π*P.ωFη/24/365.25/3600
114114
ωFx = 2π*P.ωFx/24/365.25/3600
115115
ωFy = 2π*P.ωFy/24/365.25/3600
116116

117117
# SCALING
118-
scale = T(P.scale)
119-
scale_inv = T(1/P.scale)
118+
scale = convert(T,P.scale)
119+
scale_inv = convert(T,1/P.scale)
120+
scale_sst = convert(T,P.scale_sst)
121+
scale_sst_inv = convert(T,1/P.scale_sst)
120122

121123
return Constants{T,Tprog}( RKaΔt,RKbΔt,Δt_Δs,Δt_Δ,Δt_Δ_half,
122124
SSPRK3c,one_minus_α,
123-
g,cD,rD,γ,cSmag,νB,rSST,
124-
jSST,SSTmin,ωFη,ωFx,ωFy,
125-
scale,scale_inv)
125+
g,cD,rD,γ,cSmag,νB,τSST,jSST,
126+
ωFη,ωFx,ωFy,
127+
scale,scale_inv,
128+
scale_sst,scale_sst_inv)
126129
end

src/default_parameters.jl

Lines changed: 33 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -20,20 +20,22 @@
2020
R::Real=6.371e6 # Earth's radius [m]
2121

2222
# SCALE
23-
scale::Real=1 # multiplicative scale for the momentum equations u,v
23+
scale::Real=2^6 # multiplicative scale for the momentum equations u,v
24+
scale_sst::Real=2^15 # multiplicative scale for sst
2425

2526
# WIND FORCING OPTIONS
26-
wind_forcing_x::String="channel" # "channel", "double_gyre", "shear","constant" or "none"
27+
wind_forcing_x::String="shear" # "channel", "double_gyre", "shear","constant" or "none"
2728
wind_forcing_y::String="constant" # "channel", "double_gyre", "shear","constant" or "none"
2829
Fx0::Real=0.12 # wind stress strength [Pa] in x-direction
2930
Fy0::Real=0.0 # wind stress strength [Pa] in y-direction
30-
seasonal_wind_x::Bool=false # Change the wind stress with a sine of frequency ωFx,ωFy
31+
seasonal_wind_x::Bool=true # Change the wind stress with a sine of frequency ωFx,ωFy
3132
seasonal_wind_y::Bool=false # same for y-component
32-
ωFx::Real=1.0 # frequency [1/year] for x component
33-
ωFy::Real=1.0 # frequency [1/year] for y component
33+
ωFx::Real=2 # frequency [1/year] for x component
34+
ωFy::Real=2 # frequency [1/year] for y component
3435

3536
# BOTTOM TOPOGRAPHY OPTIONS
3637
topography::String="ridges" # "ridge", "seamount", "flat", "ridges", "bathtub"
38+
topo_ridges_positions::Vector = [0.05,0.25,0.45,0.9]
3739
topo_height::Real=100. # height of seamount [m]
3840
topo_width::Real=300e3 # horizontal scale [m] of the seamount
3941

@@ -83,23 +85,21 @@
8385

8486
# TRACER ADVECTION
8587
tracer_advection::Bool=true # yes?
86-
tracer_relaxation::Bool=false # yes?
88+
tracer_relaxation::Bool=true # yes?
8789
tracer_consumption::Bool=false # yes?
88-
tracer_pumping::Bool=false # yes?
89-
injection_region::String="west" # "west", "south", "rect" or "flat"
90-
sst_initial::String="south" # "west", "south", "rect", "flat" or "restart"
90+
sst_initial::String="waves" # "west", "south", "linear", "waves","rect", "flat" or "restart"
9191
sst_rect_coords::Array{Float64,1}=[0.,0.15,0.,1.0]
9292
# (x0,x1,y0,y1) are the size of the rectangle in [0,1]
9393
Uadv::Real=0.2 # Velocity scale [m/s] for tracer advection
94-
SSTmax::Real=1. # tracer (sea surface temperature) max for restoring
95-
SSTmin::Real=-1. # tracer (sea surface temperature) min for restoring
96-
τSST::Real=500. # tracer restoring time scale [days]
97-
jSST::Real=365. # tracer consumption [days]
98-
SST_λ0::Real=222e3 # [m] transition position of relaxation timescale
99-
SST_λs::Real=111e3 # [m] transition width of relaxation timescale
100-
SST_γ0::Real=8.35 # [days] injection time scale
94+
SSTmax::Real=1. # tracer (sea surface temperature) max for initial conditions
95+
SSTmin::Real=-1. # tracer (sea surface temperature) min for initial conditions
96+
τSST::Real=100 # tracer restoring time scale [days]
97+
jSST::Real=365 # tracer consumption [days]
10198
SSTw::Real=5e5 # width [m] of the tangent used for the IC and interface relaxation
10299
SSTϕ::Real=0.5 # latitude/longitude fraction ∈ [0,1] of sst edge
100+
SSTwaves_ny::Real=4 # wave crests/troughs in y
101+
SSTwaves_nx::Real=SSTwaves_ny*L_ratio # wave crests/troughs in x
102+
SSTwaves_p::Real=1/2 # power for rectangles (p<1)/smootheness(p>=1) of waves
103103

104104
# OUTPUT OPTIONS
105105
output::Bool=false # netcdf output?
@@ -143,7 +143,6 @@
143143
@assert diffusion in ["Smagorinsky", "constant"] "Diffusion '$diffusion' unsupported."
144144
@assert νB > 0.0 "Diffusion scaling constant νB has to be >0, $νB given."
145145
@assert cSmag > 0.0 "Smagorinsky coefficient cSmag has to be >0, $cSmag given."
146-
@assert injection_region in ["west","south"] "Injection region '$injection_region' unsupported."
147146
@assert Uadv > 0.0 "Advection velocity scale Uadv has to be >0, $Uadv given."
148147
@assert output_dt > 0 "Output time step has to be >0, $output_dt given."
149148
@assert initial_cond in ["rest", "ncfile"] "Initial conditions '$initial_cond' unsupported."
@@ -175,20 +174,22 @@ Creates a Parameter struct with following options and default values
175174
R::Real=6.371e6 # Earth's radius [m]
176175
177176
# SCALE
178-
scale::Real=1 # multiplicative scale for the momentum equations u,v
177+
scale::Real=2^6 # multiplicative scale for the momentum equations u,v
178+
scale_sst::Real=2^15 # multiplicative scale for sst
179179
180180
# WIND FORCING OPTIONS
181-
wind_forcing_x::String="channel" # "channel", "double_gyre", "shear","constant" or "none"
181+
wind_forcing_x::String="shear" # "channel", "double_gyre", "shear","constant" or "none"
182182
wind_forcing_y::String="constant" # "channel", "double_gyre", "shear","constant" or "none"
183183
Fx0::Real=0.12 # wind stress strength [Pa] in x-direction
184184
Fy0::Real=0.0 # wind stress strength [Pa] in y-direction
185-
seasonal_wind_x::Bool=false # Change the wind stress with a sine of frequency ωFx,ωFy
185+
seasonal_wind_x::Bool=true # Change the wind stress with a sine of frequency ωFx,ωFy
186186
seasonal_wind_y::Bool=false # same for y-component
187-
ωFx::Real=1.0 # frequency [1/year] for x component
188-
ωFy::Real=1.0 # frequency [1/year] for y component
187+
ωFx::Real=2 # frequency [1/year] for x component
188+
ωFy::Real=2 # frequency [1/year] for y component
189189
190190
# BOTTOM TOPOGRAPHY OPTIONS
191191
topography::String="ridges" # "ridge", "seamount", "flat", "ridges", "bathtub"
192+
topo_ridges_positions::Vector = [0.05,0.25,0.45,0.9]
192193
topo_height::Real=100. # height of seamount [m]
193194
topo_width::Real=300e3 # horizontal scale [m] of the seamount
194195
@@ -238,29 +239,28 @@ Creates a Parameter struct with following options and default values
238239
239240
# TRACER ADVECTION
240241
tracer_advection::Bool=true # yes?
241-
tracer_relaxation::Bool=false # yes?
242+
tracer_relaxation::Bool=true # yes?
242243
tracer_consumption::Bool=false # yes?
243-
tracer_pumping::Bool=false # yes?
244-
injection_region::String="west" # "west", "south", "rect" or "flat"
245-
sst_initial::String="south" # "west", "south", "rect", "flat" or "restart"
244+
sst_initial::String="waves" # "west", "south", "linear", "waves","rect", "flat" or "restart"
246245
sst_rect_coords::Array{Float64,1}=[0.,0.15,0.,1.0]
247246
# (x0,x1,y0,y1) are the size of the rectangle in [0,1]
248247
Uadv::Real=0.2 # Velocity scale [m/s] for tracer advection
249-
SSTmax::Real=1. # tracer (sea surface temperature) max for restoring
250-
SSTmin::Real=-1. # tracer (sea surface temperature) min for restoring
251-
τSST::Real=500. # tracer restoring time scale [days]
252-
jSST::Real=365. # tracer consumption [days]
253-
SST_λ0::Real=222e3 # [m] transition position of relaxation timescale
254-
SST_λs::Real=111e3 # [m] transition width of relaxation timescale
255-
SST_γ0::Real=8.35 # [days] injection time scale
248+
SSTmax::Real=1. # tracer (sea surface temperature) max for initial conditions
249+
SSTmin::Real=-1. # tracer (sea surface temperature) min for initial conditions
250+
τSST::Real=100 # tracer restoring time scale [days]
251+
jSST::Real=365 # tracer consumption [days]
256252
SSTw::Real=5e5 # width [m] of the tangent used for the IC and interface relaxation
257253
SSTϕ::Real=0.5 # latitude/longitude fraction ∈ [0,1] of sst edge
254+
SSTwaves_ny::Real=4 # wave crests/troughs in y
255+
SSTwaves_nx::Real=SSTwaves_ny*L_ratio # wave crests/troughs in x
256+
SSTwaves_p::Real=1/2 # power for rectangles (p<1)/smootheness(p>=1) of waves
258257
259258
# OUTPUT OPTIONS
260259
output::Bool=false # netcdf output?
261260
output_vars::Array{String,1}=["u","v","η","sst"] # which variables to output? "du","dv","dη" also allowed
262261
output_dt::Real=24 # output time step [hours]
263262
outpath::String=pwd() # path to output folder
263+
compression_level::Int=3 # compression level
264264
265265
# INITIAL CONDITIONS
266266
initial_cond::String="rest" # "rest" or "ncfile" for restart from file

src/ghost_points.jl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,10 @@ function add_halo( u::Array{T,2},
2222
sst = cat(zeros(T,nx+2*halosstx,halossty),sst,zeros(T,nx+2*halosstx,halossty),dims=2)
2323

2424
# SCALING
25-
@unpack scale = S.constants
25+
@unpack scale,scale_sst = S.constants
2626
u *= scale
2727
v *= scale
28-
sst *= scale
28+
sst *= scale_sst
2929

3030
ghost_points!(u,v,η,S)
3131
ghost_points_sst!(sst,S)
@@ -40,13 +40,13 @@ function remove_halo( u::Array{T,2},
4040
S::ModelSetup) where {T<:AbstractFloat}
4141

4242
@unpack halo,haloη,halosstx,halossty = S.grid
43-
@unpack scale_inv = S.constants
43+
@unpack scale_inv,scale_sst_inv = S.constants
4444

4545
# undo scaling as well
4646
ucut = scale_inv*u[halo+1:end-halo,halo+1:end-halo]
4747
vcut = scale_inv*v[halo+1:end-halo,halo+1:end-halo]
4848
ηcut = η[haloη+1:end-haloη,haloη+1:end-haloη]
49-
sstcut = scale_inv*sst[halosstx+1:end-halosstx,halossty+1:end-halossty]
49+
sstcut = scale_sst_inv*sst[halosstx+1:end-halosstx,halossty+1:end-halossty]
5050

5151
return ucut,vcut,ηcut,sstcut
5252
end

src/initial_conditions.jl

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ function initial_conditions(::Type{T},S::ModelSetup) where {T<:AbstractFloat}
119119
## SST
120120

121121
@unpack SSTmin, SSTmax, SSTw, SSTϕ = S.parameters
122+
@unpack SSTwaves_nx,SSTwaves_ny,SSTwaves_p = S.parameters
122123
@unpack sst_initial,scale = S.parameters
123124
@unpack x_T,y_T,Lx,Ly = S.grid
124125

@@ -128,6 +129,10 @@ function initial_conditions(::Type{T},S::ModelSetup) where {T<:AbstractFloat}
128129
sst = (SSTmin+SSTmax)/2 .+ tanh.(2π*(Ly/(4*SSTw))*(yy_T/Ly .- SSTϕ))*(SSTmin-SSTmax)/2
129130
elseif sst_initial == "west"
130131
sst = (SSTmin+SSTmax)/2 .+ tanh.(2π*(Lx/(4*SSTw))*(xx_T/Lx .- SSTϕ))*(SSTmin-SSTmax)/2
132+
elseif sst_initial == "linear"
133+
sst = SSTmin .+ yy_T/Ly*(SSTmax-SSTmin)
134+
elseif sst_initial == "waves"
135+
sst = waves(xx_T/Lx,yy_T/Ly,SSTwaves_nx,SSTwaves_ny,SSTwaves_p)
131136
elseif sst_initial == "flat"
132137
sst = fill(SSTmin,size(xx_T))
133138
elseif sst_initial == "rect"
@@ -158,3 +163,13 @@ function initial_conditions(::Type{T},S::ModelSetup) where {T<:AbstractFloat}
158163

159164
return PrognosticVars{T}(u,v,η,sst)
160165
end
166+
167+
"""Create a wave-checkerboard pattern over xx,yy like a nx x ny checkerboard.
168+
p is the power to which the waves are raised. Choose p<1 for rectangles, and
169+
p > 1 for more smootheness."""
170+
function waves(xx::AbstractMatrix,yy::AbstractMatrix,nx::Real,ny::Real,p::Real)
171+
@boundscheck size(xx) == size(yy) || throw(BoundsError())
172+
w = sin.(nx*π*xx) .* sin.(ny*π*yy)
173+
s = sign.(w)
174+
return s.*abs.(w).^p
175+
end

src/output.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ function output_nc!(i::Int,
9090

9191
@unpack halo,haloη,halosstx,halossty = S.grid
9292
@unpack f_q,ep,dtint = S.grid
93-
@unpack scale,scale_inv = S.constants
93+
@unpack scale,scale_inv,scale_sst_inv = S.constants
9494

9595
# CUT OFF HALOS
9696
# As output is before copyto!(u,u0), take u0,v0,η0
@@ -109,7 +109,7 @@ function output_nc!(i::Int,
109109
NetCDF.putvar(ncs.η,"eta",η,start=[1,1,iout],count=[-1,-1,1])
110110
end
111111
if ncs.sst != nothing
112-
@views sst = Float32.(scale_inv*Prog.sst[halosstx+1:end-halosstx,halossty+1:end-halossty])
112+
@views sst = Float32.(scale_sst_inv*Prog.sst[halosstx+1:end-halosstx,halossty+1:end-halossty])
113113
NetCDF.putvar(ncs.sst,"sst",sst,start=[1,1,iout],count=[-1,-1,1])
114114
end
115115
if ncs.q != nothing

src/preallocate.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -421,6 +421,7 @@ end
421421
vinterp::Array{T,2} = zeros(T,nx,ny) # v interpolated on mid-point xd,yd
422422

423423
ssti::Array{T,2} = zeros(T,nx+2*halosstx,ny+2*halossty) # sst interpolated on departure points
424+
sst_ref::Array{T,2} = zeros(T,nx+2*halosstx,ny+2*halossty) # sst initial conditions for relaxation
424425
end
425426

426427
"""Generator function for SemiLagrange VarCollection."""

src/time_integration.jl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ function time_integration( Prog::PrognosticVars{Tprog},
3535
copyto!(v0,v)
3636
copyto!(η0,η)
3737

38+
# store initial conditions of sst for relaxation
39+
copyto!(Diag.SemiLagrange.sst_ref,sst)
40+
3841
# feedback, output initialisation and storing initial conditions
3942
feedback = feedback_init(S)
4043
netCDFfiles = NcFiles(feedback,S)

src/tracer_advection.jl

Lines changed: 27 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ function tracer!( i::Integer,
66
S::ModelSetup)
77

88
@unpack tracer_advection, tracer_consumption = S.parameters
9+
@unpack tracer_relaxation = S.parameters
910
@unpack nadvstep_half,nadvstep = S.grid
1011

1112
# mid point (in time) velocity for the advective time step
@@ -19,17 +20,17 @@ function tracer!( i::Integer,
1920
if tracer_advection && (i % nadvstep) == 0
2021

2122
@unpack sst = Prog
22-
@unpack ssti = Diag.SemiLagrange
23+
@unpack ssti,sst_ref = Diag.SemiLagrange
2324

2425
# convert to type T for mixed precision
2526
sstrhs = convert(Diag.PrognosticVarsRHS.sst,sst)
2627

2728
departure!(u,v,Diag,S)
2829
adv_sst!(sstrhs,Diag,S)
2930

30-
# if tracer_relaxation
31-
# tracer_relax!(ssti,sst_ref,SSTγ)
32-
# end
31+
if tracer_relaxation
32+
tracer_relax!(ssti,sst_ref,S)
33+
end
3334

3435
if tracer_consumption
3536
tracer_consumption!(ssti,S)
@@ -245,44 +246,35 @@ function bilin(f00::T,f10::T,f01::T,f11::T,x::T,y::T) where {T<:AbstractFloat}
245246
return f00*(oone-x)*(oone-y) + f10*x*(oone-y) + f01*(oone-x)*y + f11*x*y
246247
end
247248

248-
# """Tracer relaxation."""
249-
# function tracer_relax!(sst::AbstractMatrix,sst_ref::AbstractMatrix,SSTγ::AbstractMatrix)
250-
# m,n = size(sst)
251-
# @boundscheck (m-2*halosstx,n-2*halossty) == size(sst_ref) || throw(BoundsError())
252-
# @boundscheck (m-2*halosstx,n-2*halossty) == size(SSTγ) || throw(BoundsError())
253-
#
254-
# @inbounds for j ∈ 1+halossty:n-halossty
255-
# for i ∈ 1+halosstx:m-halosstx
256-
# sst[i,j] += SSTγ[i-halosstx,j-halossty]*(sst_ref[i-halosstx,j-halossty] - sst[i,j])
257-
# end
258-
# end
259-
# end
260-
261-
"""Tracer consumption via relaxation back to ."""
249+
"""Tracer relaxation."""
250+
function tracer_relax!( sst::AbstractMatrix,
251+
sst_ref::AbstractMatrix,
252+
S::ModelSetup)
253+
@unpack τSST = S.constants
254+
@unpack halosstx,halossty = S.grid
255+
256+
m,n = size(sst)
257+
@boundscheck size(sst) == size(sst_ref) || throw(BoundsError())
258+
259+
for j 1+halossty:n-halossty
260+
for i 1+halosstx:m-halosstx
261+
sst[i,j] += τSST*(sst_ref[i,j] - sst[i,j])
262+
end
263+
end
264+
end
265+
266+
"""Tracer consumption via relaxation back to 0."""
262267
function tracer_consumption!( sst::Array{T,2},
263268
S::ModelSetup) where {T<:AbstractFloat}
264269

265-
@unpack jSST,SSTmin = S.constants
270+
@unpack jSST = S.constants
266271
@unpack halosstx,halossty = S.grid
267272

268273
m,n = size(sst)
269274

270-
@inbounds for j 1+halossty:n-halossty
275+
for j 1+halossty:n-halossty
271276
for i 1+halosstx:m-halosstx
272-
sst[i,j] += jSST*(SSTmin - sst[i,j])
277+
sst[i,j] -= jSST*sst[i,j]
273278
end
274279
end
275-
end
276-
277-
# """Spatially dependent relaxation time scale."""
278-
# function sst_γ(x::AbstractVector,y::AbstractVector)
279-
# xx,yy = meshgrid(x,y)
280-
#
281-
# # convert from days to one over 1/s and include adv time step
282-
# γ0 = dtadvint/(SST_γ0*3600*24)
283-
#
284-
# x10E = 10*m_per_lat() # assume Equator: lat/lon equivalence
285-
# γ = γ0/2 .* (1 .- tanh.((xx.-SST_λ0)./SST_λs))
286-
# γ[xx .> x10E] .= 0.0
287-
# return Numtype.(γ)
288-
# end
280+
end

0 commit comments

Comments
 (0)