Skip to content

Commit f41929c

Browse files
committed
try
q_vap fix syntax fix clean dry runs dry runs format
1 parent 6a5c89c commit f41929c

File tree

6 files changed

+187
-113
lines changed

6 files changed

+187
-113
lines changed

.buildkite/pipeline.yml

+7
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,13 @@ steps:
162162
agents:
163163
slurm_mem: 20GB
164164

165+
- label: "Slabplanet: dry, no radiation"
166+
key: "slabplanet_dry_norad"
167+
command: "julia --color=yes --project=experiments/AMIP/ experiments/AMIP/coupler_driver.jl --config_file $CONFIG_PATH/slabplanet_dry_norad.yml"
168+
artifact_paths: "experiments/AMIP/output/slabplanet/slabplanet_dry_norad_artifacts/*"
169+
agents:
170+
slurm_mem: 20GB
171+
165172
- label: "Slabplanet: default with Float32"
166173
key: "slabplanet_ft32"
167174
command: "julia --color=yes --project=experiments/AMIP/ experiments/AMIP/coupler_driver.jl --config_file $CONFIG_PATH/slabplanet_ft32.yml"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
anim: false
2+
apply_limiter: false
3+
conservation_softfail: true
4+
dt: "200secs"
5+
dt_cpl: 200
6+
dt_save_to_sol: "9days"
7+
energy_check: true
8+
h_elem: 4
9+
job_id: "slabplanet_dry_norad"
10+
mode_name: "slabplanet"
11+
moist: "dry"
12+
mono_surface: true
13+
precip_model: nothing
14+
rad: nothing
15+
run_name: "slabplanet_dry_norad"
16+
t_end: "10days"
17+
vert_diff: "true"
18+
output_default_diagnostics: false

experiments/AMIP/cli_options.jl

-13
Original file line numberDiff line numberDiff line change
@@ -181,19 +181,6 @@ function print_repl_script(str)
181181
println(ib)
182182
end
183183

184-
function time_to_seconds(s::String)
185-
factor = Dict("secs" => 1, "mins" => 60, "hours" => 60 * 60, "days" => 60 * 60 * 24)
186-
s == "Inf" && return Inf
187-
if count(occursin.(keys(factor), Ref(s))) != 1
188-
error("Bad format for flag $s. Examples: [`10secs`, `20mins`, `30hours`, `40days`]")
189-
end
190-
for match in keys(factor)
191-
occursin(match, s) || continue
192-
return parse(Float64, first(split(s, match))) * factor[match]
193-
end
194-
error("Uncaught case in computing time from given string.")
195-
end
196-
197184
parsed_args_from_ARGS(ARGS, parsed_args = Dict()) = parsed_args_from_ARGS_string(strip(join(ARGS, " ")), parsed_args)
198185

199186
parsed_args_from_command_line_flags(str, parsed_args = Dict()) =

experiments/AMIP/components/atmosphere/climaatmos.jl

+94-63
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,18 @@ struct ClimaAtmosSimulation{P, Y, D, I} <: Interfacer.AtmosModelSimulation
2121
end
2222
Interfacer.name(::ClimaAtmosSimulation) = "ClimaAtmosSimulation"
2323

24+
hasradiation = function (integrator)
25+
return !isnothing(integrator.p.atmos.radiation_mode)
26+
end
27+
28+
hasmoisture = function (integrator)
29+
return !(integrator.p.atmos.moisture_model isa CA.DryModel)
30+
end
31+
32+
zero_scalar_half(integrator) = zeros(axes(CC.Fields.level(integrator.p.scratch.ᶠtemp_scalar, CC.Utilities.half)))
33+
zero_scalar_one(integrator) = zeros(axes(CC.Fields.level(integrator.p.scratch.ᶜtemp_scalar, 1)))
34+
zero_scalar_center(integrator) = zeros(axes(integrator.p.scratch.ᶜtemp_scalar))
35+
2436
function atmos_init(::Type{FT}, atmos_config_dict::Dict) where {FT}
2537
# By passing `parsed_args` to `AtmosConfig`, `parsed_args` overwrites the default atmos config
2638
atmos_config_dict["surface_albedo"] = "CouplerAlbedo"
@@ -35,27 +47,30 @@ function atmos_init(::Type{FT}, atmos_config_dict::Dict) where {FT}
3547
@warn("Running with ρe_int in coupled mode is not tested yet.", maxlog = 1)
3648
end
3749

38-
# define shorter references for long variable Interfacer.names to increase readability
50+
# define shorter references for long variable Interfacer.names to increase readability, and set to zero
3951
ρ_flux_h_tot = integrator.p.precomputed.sfc_conditions.ρ_flux_h_tot
40-
ρ_flux_q_tot = integrator.p.precomputed.sfc_conditions.ρ_flux_q_tot
41-
ᶠradiation_flux = integrator.p.radiation.ᶠradiation_flux
4252
ρ_flux_uₕ = integrator.p.precomputed.sfc_conditions.ρ_flux_uₕ
43-
col_integrated_rain = integrator.p.precipitation.col_integrated_rain
44-
col_integrated_snow = integrator.p.precipitation.col_integrated_snow
45-
ᶜS_ρq_tot = integrator.p.precipitation.ᶜS_ρq_tot
46-
ᶜ3d_rain = integrator.p.precipitation.ᶜ3d_rain
47-
ᶜ3d_snow = integrator.p.precipitation.ᶜ3d_snow
48-
49-
# set initial fluxes to zero
5053
@. ρ_flux_h_tot = CC.Geometry.Covariant3Vector(FT(0.0))
51-
@. ρ_flux_q_tot = CC.Geometry.Covariant3Vector(FT(0.0))
52-
@. ᶠradiation_flux = CC.Geometry.WVector(FT(0))
5354
ρ_flux_uₕ.components .= Ref(StaticArrays.SMatrix{1, 2}([FT(0), FT(0)]))
54-
col_integrated_rain .= FT(0)
55-
col_integrated_snow .= FT(0)
56-
ᶜS_ρq_tot .= FT(0)
57-
ᶜ3d_rain .= FT(0)
58-
ᶜ3d_snow .= FT(0)
55+
56+
if hasmoisture(integrator)
57+
ρ_flux_q_tot = integrator.p.precomputed.sfc_conditions.ρ_flux_q_tot
58+
col_integrated_rain = integrator.p.precipitation.col_integrated_rain
59+
col_integrated_snow = integrator.p.precipitation.col_integrated_snow
60+
ᶜS_ρq_tot = integrator.p.precipitation.ᶜS_ρq_tot
61+
ᶜ3d_rain = integrator.p.precipitation.ᶜ3d_rain
62+
ᶜ3d_snow = integrator.p.precipitation.ᶜ3d_snow
63+
@. ρ_flux_q_tot = CC.Geometry.Covariant3Vector(FT(0.0))
64+
col_integrated_rain .= FT(0)
65+
col_integrated_snow .= FT(0)
66+
ᶜS_ρq_tot .= FT(0)
67+
ᶜ3d_rain .= FT(0)
68+
ᶜ3d_snow .= FT(0)
69+
end
70+
if hasradiation(integrator)
71+
ᶠradiation_flux = integrator.p.radiation.ᶠradiation_flux
72+
@. ᶠradiation_flux = CC.Geometry.WVector(FT(0))
73+
end
5974

6075
sim = ClimaAtmosSimulation(integrator.p.params, Y, spaces, integrator)
6176

@@ -82,7 +97,7 @@ upward and downward longwave and shortwave radiation.
8297
function Interfacer.get_field(atmos_sim::ClimaAtmosSimulation, ::Val{:radiative_energy_flux_toa})
8398
FT = eltype(atmos_sim.integrator.u)
8499

85-
if atmos_sim.integrator.p.radiation.radiation_model != nothing
100+
if hasradiation(atmos_sim.integrator)
86101
face_space = axes(atmos_sim.integrator.u.f)
87102
nz_faces = length(CC.Spaces.vertical_topology(face_space).mesh.faces)
88103

@@ -100,48 +115,68 @@ function Interfacer.get_field(atmos_sim::ClimaAtmosSimulation, ::Val{:radiative_
100115

101116
return @. -(LWd_TOA + SWd_TOA - LWu_TOA - SWu_TOA)
102117
else
103-
return FT(0)
118+
return zero_scalar_half(atmos_sim.integrator)
104119
end
105120
end
106121

107122
function Interfacer.get_field(atmos_sim::ClimaAtmosSimulation, ::Val{:energy})
108-
thermo_params = get_thermo_params(atmos_sim)
123+
integrator = atmos_sim.integrator
124+
p = integrator.p
109125

110-
ᶜS_ρq_tot = atmos_sim.integrator.p.precipitation.ᶜS_ρq_tot
111-
ᶜts = atmos_sim.integrator.p.precomputed.ᶜts
112-
ᶜΦ = atmos_sim.integrator.p.core.ᶜΦ
113126

114127
# return total energy and (if Microphysics0Moment) the energy lost due to precipitation removal
115-
if atmos_sim.integrator.p.atmos.precip_model isa CA.Microphysics0Moment
116-
ᶜS_ρq_tot = atmos_sim.integrator.p.precipitation.ᶜS_ρq_tot
117-
ᶜts = atmos_sim.integrator.p.precomputed.ᶜts
118-
ᶜΦ = atmos_sim.integrator.p.core.ᶜΦ
119-
return atmos_sim.integrator.u.c.ρe_tot .-
120-
ᶜS_ρq_tot .* CA.e_tot_0M_precipitation_sources_helper.(Ref(thermo_params), ᶜts, ᶜΦ) .*
121-
atmos_sim.integrator.dt
128+
if p.atmos.precip_model isa CA.Microphysics0Moment
129+
ᶜts = p.precomputed.ᶜts
130+
ᶜΦ = p.core.ᶜΦ
131+
ᶜS_ρq_tot = p.precipitation.ᶜS_ρq_tot
132+
thermo_params = get_thermo_params(atmos_sim)
133+
return integrator.u.c.ρe_tot .-
134+
ᶜS_ρq_tot .* CA.e_tot_0M_precipitation_sources_helper.(Ref(thermo_params), ᶜts, ᶜΦ) .* integrator.dt
122135
else
123-
return atmos_sim.integrator.u.c.ρe_tot
136+
return integrator.u.c.ρe_tot
124137
end
125138
end
126139

140+
# helpers for get_field extensions
141+
142+
col_integrated_rain(::CA.DryModel, integrator) = zero_scalar_half(integrator)
143+
col_integrated_rain(::Union{CA.EquilMoistModel, CA.NonEquilMoistModel}, integrator) =
144+
integrator.p.precipitation.col_integrated_rain
145+
146+
col_integrated_snow(::CA.DryModel, integrator) = zero_scalar_half(integrator)
147+
col_integrated_snow(::Union{CA.EquilMoistModel, CA.NonEquilMoistModel}, integrator) =
148+
integrator.p.precipitation.col_integrated_snow
149+
150+
surface_radiation_flux(::Nothing, integrator) = zero_scalar_half(integrator)
151+
surface_radiation_flux(::CA.RRTMGPI.AbstractRRTMGPMode, integrator) =
152+
CC.Fields.level(integrator.p.radiation.ᶠradiation_flux, CC.Utilities.half)
153+
154+
moisture_flux(::CA.DryModel, integrator) = zero_scalar_half(integrator)
155+
moisture_flux(::Union{CA.EquilMoistModel, CA.NonEquilMoistModel}, integrator) =
156+
integrator.p.precomputed.sfc_conditions.ρ_flux_q_tot
157+
158+
ρq_tot(::CA.DryModel, integrator) = zero_scalar_center(integrator)
159+
ρq_tot(::Union{CA.EquilMoistModel, CA.NonEquilMoistModel}, integrator) = integrator.u.c.ρq_tot
160+
127161
# extensions required by the Interfacer
128162
Interfacer.get_field(sim::ClimaAtmosSimulation, ::Val{:air_density}) =
129163
TD.air_density.(thermo_params, sim.integrator.p.precomputed.ᶜts)
130164
Interfacer.get_field(sim::ClimaAtmosSimulation, ::Val{:air_temperature}) =
131165
TD.air_temperature.(thermo_params, sim.integrator.p.precomputed.ᶜts)
132166
Interfacer.get_field(sim::ClimaAtmosSimulation, ::Val{:liquid_precipitation}) =
133-
sim.integrator.p.precipitation.col_integrated_rain
167+
col_integrated_rain(sim.integrator.p.atmos.moisture_model, sim.integrator)
134168
Interfacer.get_field(sim::ClimaAtmosSimulation, ::Val{:radiative_energy_flux_sfc}) =
135-
CC.Fields.level(sim.integrator.p.radiation.ᶠradiation_flux, CC.Utilities.half)
169+
surface_radiation_flux(sim.integrator.p.atmos.radiation_mode, sim.integrator)
136170
Interfacer.get_field(sim::ClimaAtmosSimulation, ::Val{:snow_precipitation}) =
137-
sim.integrator.p.precipitation.col_integrated_snow
171+
col_integrated_snow(sim.integrator.p.atmos.moisture_model, sim.integrator)
138172
Interfacer.get_field(sim::ClimaAtmosSimulation, ::Val{:turbulent_energy_flux}) =
139173
CC.Geometry.WVector.(sim.integrator.p.precomputed.sfc_conditions.ρ_flux_h_tot)
140174
Interfacer.get_field(sim::ClimaAtmosSimulation, ::Val{:turbulent_moisture_flux}) =
141-
CC.Geometry.WVector.(sim.integrator.p.precomputed.sfc_conditions.ρ_flux_q_tot)
175+
CC.Geometry.WVector.(moisture_flux(sim.integrator.p.atmos.moisture_model, sim.integrator))
142176
Interfacer.get_field(sim::ClimaAtmosSimulation, ::Val{:thermo_state_int}) =
143177
CC.Spaces.level(sim.integrator.p.precomputed.ᶜts, 1)
144-
Interfacer.get_field(atmos_sim::ClimaAtmosSimulation, ::Val{:water}) = atmos_sim.integrator.u.c.ρq_tot
178+
Interfacer.get_field(atmos_sim::ClimaAtmosSimulation, ::Val{:water}) =
179+
ρq_tot(atmos_sim.integrator.p.atmos.moisture_model, atmos_sim.integrator)
145180

146181
# extensions required by FluxCalculator (partitioned fluxes)
147182
Interfacer.get_field(sim::ClimaAtmosSimulation, ::Val{:height_int}) =
@@ -162,10 +197,6 @@ function Interfacer.update_field!(atmos_sim::ClimaAtmosSimulation, ::Val{:co2},
162197
end
163198
end
164199
# extensions required by the Interfacer
165-
function Interfacer.update_field!(sim::ClimaAtmosSimulation, ::Val{:surface_temperature}, csf)
166-
sim.integrator.p.radiation.radiation_model.surface_temperature .= CA.RRTMGPI.field2array(csf.T_S)
167-
end
168-
169200
function Interfacer.update_field!(sim::ClimaAtmosSimulation, ::Val{:surface_direct_albedo}, field)
170201
sim.integrator.p.radiation.radiation_model.direct_sw_surface_albedo .=
171202
reshape(CA.RRTMGPI.field2array(field), 1, length(parent(field)))
@@ -180,7 +211,7 @@ function Interfacer.update_field!(sim::ClimaAtmosSimulation, ::Val{:turbulent_fl
180211
(; F_turb_energy, F_turb_moisture, F_turb_ρτxz, F_turb_ρτyz) = fields
181212

182213
Y = sim.integrator.u
183-
surface_local_geometry = CC.Fields.level(CC.Fields.local_geometry_field(Y.f), CC.Fields.half)
214+
surface_local_geometry = CC.Fields.level(CC.Fields.local_geometry_field(Y.f), CC.Utilities.half)
184215
surface_normal = @. CA.C3(CA.unit_basis_vector_data(CA.C3, surface_local_geometry))
185216

186217
# get template objects for the contravariant components of the momentum fluxes (required by Atmos boundary conditions)
@@ -208,9 +239,10 @@ Interfacer.step!(sim::ClimaAtmosSimulation, t) = Interfacer.step!(sim.integrator
208239
Interfacer.reinit!(sim::ClimaAtmosSimulation) = Interfacer.reinit!(sim.integrator)
209240

210241
function FieldExchanger.update_sim!(atmos_sim::ClimaAtmosSimulation, csf, turbulent_fluxes)
211-
Interfacer.update_field!(atmos_sim, Val(:surface_direct_albedo), csf.surface_direct_albedo)
212-
Interfacer.update_field!(atmos_sim, Val(:surface_diffuse_albedo), csf.surface_diffuse_albedo)
213-
Interfacer.update_field!(atmos_sim, Val(:surface_temperature), csf)
242+
if hasradiation(atmos_sim.integrator)
243+
Interfacer.update_field!(atmos_sim, Val(:surface_direct_albedo), csf.surface_direct_albedo)
244+
Interfacer.update_field!(atmos_sim, Val(:surface_diffuse_albedo), csf.surface_diffuse_albedo)
245+
end
214246

215247
if turbulent_fluxes isa FluxCalculator.PartitionedStateFluxes
216248
Interfacer.update_field!(atmos_sim, Val(:turbulent_fluxes), csf)
@@ -235,12 +267,12 @@ FluxCalculator.get_surface_params(sim::ClimaAtmosSimulation) = CAP.surface_fluxe
235267
### ClimaAtmos.jl model-specific functions (not explicitly required by ClimaCoupler.jl)
236268
###
237269
"""
238-
get_atmos_config(coupler_dict::Dict)
270+
get_atmos_config_dict(coupler_dict::Dict)
239271
240-
Returns the specified atmospheric configuration (`atmos_config_dict`) overwitten by arguments
241-
in the coupler dictionary (`config_dict`).
272+
Returns the specified atmospheric configuration (`atmos_config`) overwitten by arguments
273+
in the coupler dictionary (`config_dict`). The returned dictionary will then be passed to CA.AtmosConfig().
242274
"""
243-
function get_atmos_config(coupler_dict)
275+
function get_atmos_config_dict(coupler_dict)
244276
atmos_config_file = coupler_dict["atmos_config_file"]
245277
# override default or specified configs with coupler arguments, and set the correct atmos config_file
246278
if isnothing(atmos_config_file)
@@ -295,8 +327,12 @@ Sets up `surface_setup` as a `CC.Fields.Field` of `SurfaceState`s.
295327
"""
296328
function coupler_surface_setup(
297329
::CoupledMoninObukhov,
298-
p;
299-
csf_sfc = (; T = nothing, z0m = nothing, z0b = nothing, beta = nothing, q_vap = nothing),
330+
p,
331+
T = nothing,
332+
z0m = nothing,
333+
z0b = nothing,
334+
beta = nothing,
335+
q_vap = nothing,
300336
)
301337

302338
surface_state(z0m, z0b, T, beta, q_vap) = CA.SurfaceConditions.SurfaceState(;
@@ -305,7 +341,7 @@ function coupler_surface_setup(
305341
beta,
306342
q_vap,
307343
)
308-
surface_state_field = @. surface_state(csf_sfc.z0m, csf_sfc.z0b, csf_sfc.T, csf_sfc.beta, csf_sfc.q_vap)
344+
surface_state_field = @. surface_state(z0m, z0b, T, beta, q_vap)
309345
return surface_state_field
310346
end
311347

@@ -315,23 +351,18 @@ end
315351
Returns a new `p` with the updated surface conditions.
316352
"""
317353
function get_new_cache(atmos_sim::ClimaAtmosSimulation, csf)
318-
csf_sfc = (; T = csf.T_S, z0m = csf.z0m_S, z0b = csf.z0b_S, beta = csf.beta, q_vap = csf.q_sfc)
319-
modified_atmos_cache(atmos_sim, csf_sfc)
320-
end
321-
322-
"""
323-
modified_atmos_cache(atmos_sim, csf_sfc)
324-
325-
Returns a new `p` with the updated surface conditions.
326-
"""
327-
function modified_atmos_cache(atmos_sim, csf_sfc)
354+
if hasmoisture(atmos_sim.integrator)
355+
csf_sfc = (csf.T_S, csf.z0m_S, csf.z0b_S, csf.beta, csf.q_sfc)
356+
else
357+
csf_sfc = (csf.T_S, csf.z0m_S, csf.z0b_S, csf.beta)
358+
end
328359

329360
p = atmos_sim.integrator.p
330361

331-
coupler_sfc_setup = coupler_surface_setup(CoupledMoninObukhov(), p; csf_sfc = csf_sfc)
362+
coupler_sfc_setup = coupler_surface_setup(CoupledMoninObukhov(), p, csf_sfc...)
332363

333364
p_names = propertynames(p)
334-
p_values = map(x -> x == :sfc_setup ? coupler_sfc_setup : getproperty(p, x), p_names) # TODO: use merge here
365+
p_values = map(x -> x == :sfc_setup ? coupler_sfc_setup : getproperty(p, x), p_names)
335366

336367
(; zip(p_names, p_values)...)
337368
end

0 commit comments

Comments
 (0)