Skip to content

Commit 91411ae

Browse files
committed
Add logic for reading GCM forcings from file and storing in cache
1 parent c8305b3 commit 91411ae

File tree

5 files changed

+65
-19
lines changed

5 files changed

+65
-19
lines changed

config/default_configs/default_config.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,9 @@ ls_adv:
232232
external_forcing:
233233
help: "External forcing for single column experiments [`nothing` (default), `GCM`]"
234234
value: ~
235+
external_forcing_file:
236+
help: "External forcing file containing large-scale forcings, initial conditions, and boundary conditions [`nothing` (default), `path/to/file`]"
237+
value: ~
235238
fps:
236239
help: "Frames per second for animations"
237240
value: 5

config/model_configs/prognostic_edmfx_gcmdriven_column.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
job_id: "prognostic_edmfx_gcmdriven_column"
22
initial_condition: "Bomex"
33
external_forcing: "GCM"
4+
external_forcing_file: "/groups/esm/zhaoyi/GCMForcedLES/cfsite/07/HadGEM2-A/amip/Output.cfsite23_HadGEM2-A_amip_2004-2008.07.4x/stats/Stats.cfsite23_HadGEM2-A_amip_2004-2008.07.nc"
45
surface_setup: "Bomex"
56
turbconv: "prognostic_edmfx"
67
implicit_diffusion: true

src/prognostic_equations/forcing/external_forcing.jl

Lines changed: 57 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,24 @@
55
import Thermodynamics as TD
66
import ClimaCore.Spaces as Spaces
77
import ClimaCore.Fields as Fields
8+
import NCDatasets as NC
9+
import StatsBase
10+
import Dierckx
11+
12+
function interp_vertical_prof(x, xp, fp)
13+
spl = Dierckx.Spline1D(xp, fp; k = 1)
14+
return spl(vec(x))
15+
end
16+
17+
mean_nc_data(data, group, var; imin = 100) =
18+
StatsBase.mean(data.group[group][var][:, :][:, imin:end], dims = 2)[:]
19+
init_nc_data(data, group, var) = data.group[group][var][:, :][:, 1]
820

921
external_forcing_cache(Y, atmos::AtmosModel) =
1022
external_forcing_cache(Y, atmos.external_forcing)
1123

12-
external_forcing_cache(Y, ::Nothing) = (;)
13-
function external_forcing_cache(Y, ::GCMForcing)
24+
external_forcing_cache(Y, external_forcing::Nothing) = (;)
25+
function external_forcing_cache(Y, external_forcing::GCMForcing)
1426
FT = Spaces.undertype(axes(Y.c))
1527
ᶜdTdt_fluc = similar(Y.c, FT)
1628
ᶜdqtdt_fluc = similar(Y.c, FT)
@@ -25,21 +37,49 @@ function external_forcing_cache(Y, ::GCMForcing)
2537
ᶜτ_scalar = similar(Y.c, FT)
2638
ᶜls_subsidence = similar(Y.c, FT)
2739

28-
# TODO: read profiles from LES files and add here
29-
@. ᶜdTdt_fluc = 0
30-
@. ᶜdqtdt_fluc = 0
31-
@. ᶜdTdt_hadv = 0
32-
@. ᶜdqtdt_hadv = 0
33-
@. ᶜdTdt_rad = 0
34-
@. ᶜT_nudge = 290
35-
@. ᶜqt_nudge = FT(0.01)
36-
@. ᶜu_nudge = -5
37-
@. ᶜv_nudge = 0
38-
@. ᶜls_subsidence = 0
39-
# TODO: make it a function of z and add timescale to climaparams
40-
hr = 3600
41-
@. ᶜτ_wind = 6hr
42-
@. ᶜτ_scalar = 24hr
40+
external_forcing_file = external_forcing.external_forcing_file
41+
42+
NC.Dataset(external_forcing_file, "r") do ds
43+
function setvar!(cc_field, varname, colidx, zc_gcm, zc_les)
44+
parent(cc_field[colidx]) .= interp_vertical_prof(
45+
zc_gcm,
46+
zc_les,
47+
mean_nc_data(ds, "profiles", varname),
48+
)
49+
end
50+
51+
function setnudgevar!(cc_field, varname, colidx, zc_gcm, zc_les)
52+
parent(cc_field[colidx]) .= interp_vertical_prof(
53+
zc_gcm,
54+
zc_les,
55+
init_nc_data(ds, "profiles", varname),
56+
)
57+
end
58+
59+
Fields.bycolumn(axes(Y.c)) do colidx
60+
61+
zc_les = Array(ds.group["profiles"]["z_half"])
62+
zc_gcm = Fields.coordinate_field(Y.c).z[colidx]
63+
64+
setvar!(ᶜdTdt_fluc, "dtdt_fluc", colidx, zc_gcm, zc_les)
65+
setvar!(ᶜdqtdt_fluc, "dqtdt_fluc", colidx, zc_gcm, zc_les)
66+
setvar!(ᶜdTdt_hadv, "dtdt_hadv", colidx, zc_gcm, zc_les)
67+
setvar!(ᶜdqtdt_hadv, "dqtdt_hadv", colidx, zc_gcm, zc_les)
68+
setvar!(ᶜdTdt_rad, "dtdt_rad", colidx, zc_gcm, zc_les)
69+
setvar!(ᶜls_subsidence, "ls_subsidence", colidx, zc_gcm, zc_les)
70+
71+
setnudgevar!(ᶜT_nudge, "temperature_mean", colidx, zc_gcm, zc_les)
72+
setnudgevar!(ᶜqt_nudge, "qt_mean", colidx, zc_gcm, zc_les)
73+
setnudgevar!(ᶜu_nudge, "u_mean", colidx, zc_gcm, zc_les)
74+
setnudgevar!(ᶜv_nudge, "v_mean", colidx, zc_gcm, zc_les)
75+
76+
# TODO: make it a function of z for scalar (call function above)
77+
hr = 3600
78+
parent(ᶜτ_wind[colidx]) .= 6hr
79+
parent(ᶜτ_scalar[colidx]) .= 24hr
80+
end
81+
end
82+
4383
return (;
4484
ᶜdTdt_fluc,
4585
ᶜdqtdt_fluc,

src/solver/model_getters.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -362,7 +362,7 @@ function get_external_forcing_model(parsed_args)
362362
return if isnothing(external_forcing)
363363
nothing
364364
elseif external_forcing == "GCM"
365-
GCMForcing()
365+
GCMForcing(parsed_args["external_forcing_file"])
366366
end
367367
end
368368

src/solver/types.jl

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,9 @@ struct LargeScaleAdvection{PT, PQ}
115115
prof_dqtdt::PQ # Set large-scale drying
116116
end
117117
# maybe need to <: AbstractForcing
118-
struct GCMForcing end
118+
struct GCMForcing{S}
119+
external_forcing_file::S
120+
end
119121

120122
struct EDMFCoriolis{U, V, FT}
121123
prof_ug::U

0 commit comments

Comments
 (0)