Skip to content

Commit df3ecb7

Browse files
authored
Merge pull request #1280 from CliMA/gb/bulk_scheme
Remove surface_scheme
2 parents 239501f + f4c2d82 commit df3ecb7

File tree

6 files changed

+24
-140
lines changed

6 files changed

+24
-140
lines changed

NEWS.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@ This PR adds the config option `land_model`, which can be set to either
2121
Instead of zeroing out all NaNs in a surface field, we zero out all values
2222
where the area fraction is 0, which is logically what we want to do.
2323

24+
#### Removed `SurfaceScheme`. PR[#1280](https://github.com/CliMA/ClimaCoupler.jl/pull/1280)
25+
26+
The `BulkScheme` option for computing fluxes was removed. Now, fluxes
27+
are always computed with the `MoninObukhovScheme`.
28+
2429
#### Removed `CombinedStateFluxes`. PR[#1276](https://github.com/CliMA/ClimaCoupler.jl/pull/1276)
2530

2631
The `CombinedStateFluxes` option for computing fluxes was removed. Now, fluxes

experiments/ClimaEarth/components/atmosphere/climaatmos.jl

Lines changed: 0 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -520,38 +520,6 @@ function get_atmos_config_dict(coupler_dict::Dict, job_id::String, atmos_output_
520520
end
521521

522522

523-
# flux calculation borrowed from atmos
524-
"""
525-
CoupledMoninObukhov()
526-
A modified version of a Monin-Obukhov surface for the Coupler, see the link below for more information
527-
https://clima.github.io/SurfaceFluxes.jl/dev/SurfaceFluxes/#Monin-Obukhov-Similarity-Theory-(MOST)
528-
"""
529-
struct CoupledMoninObukhov end
530-
"""
531-
coupler_surface_setup(::CoupledMoninObukhov, p, csf_sfc = (; T = nothing, z0m = nothing, z0b = nothing, beta = nothing, q_vap = nothing))
532-
533-
Sets up `surface_setup` as a `CC.Fields.Field` of `SurfaceState`s.
534-
"""
535-
function coupler_surface_setup(
536-
::CoupledMoninObukhov,
537-
p,
538-
T = nothing,
539-
z0m = nothing,
540-
z0b = nothing,
541-
beta = nothing,
542-
q_vap = nothing,
543-
)
544-
545-
surface_state(z0m, z0b, T, beta, q_vap) = CA.SurfaceConditions.SurfaceState(;
546-
parameterization = CA.SurfaceConditions.MoninObukhov(; z0m, z0b),
547-
T,
548-
beta,
549-
q_vap,
550-
)
551-
surface_state_field = @. surface_state(z0m, z0b, T, beta, q_vap)
552-
return surface_state_field
553-
end
554-
555523
"""
556524
get_thermo_params(sim::ClimaAtmosSimulation)
557525

experiments/ClimaEarth/components/ocean/eisenman_seaice.jl

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -238,12 +238,11 @@ function FluxCalculator.differentiate_turbulent_fluxes!(
238238
fluxes;
239239
δT_sfc = 0.1,
240240
)
241-
(; thermo_state_int, surface_params, surface_scheme) = input_args
241+
(; thermo_state_int, surface_params) = input_args
242242
thermo_state_sfc_dT = FluxCalculator.surface_thermo_state(sim, thermo_params, thermo_state_int, δT_sfc = δT_sfc)
243243
input_args = merge(input_args, (; thermo_state_sfc = thermo_state_sfc_dT))
244244

245-
# set inputs based on whether the surface_scheme is `MoninObukhovScheme` or `BulkScheme`
246-
inputs = FluxCalculator.surface_inputs(surface_scheme, input_args)
245+
inputs = FluxCalculator.surface_inputs(input_args)
247246

248247
# calculate the surface fluxes
249248
area_fraction = Interfacer.get_field(sim, Val(:area_fraction))

experiments/ClimaEarth/setup_run.jl

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -570,13 +570,7 @@ function CoupledSimulation(config_dict::AbstractDict)
570570
# turbulent surface fluxes
571571

572572
## calculate turbulent fluxes in surface models and save the weighted average in coupler fields
573-
FluxCalculator.turbulent_fluxes!(
574-
cs.model_sims,
575-
cs.fields,
576-
cs.boundary_space,
577-
FluxCalculator.MoninObukhovScheme(),
578-
cs.thermo_params,
579-
)
573+
FluxCalculator.turbulent_fluxes!(cs.model_sims, cs.fields, cs.boundary_space, cs.thermo_params)
580574

581575
# Updating only surface temperature because it is required by the RRTGMP callback (
582576
# called below at reinit). Turbulent fluxes in atmos are updated in `update_model_sims`.
@@ -749,13 +743,7 @@ function step!(cs::CoupledSimulation)
749743
## update the coupler with the new surface properties and calculate the turbulent fluxes
750744
FieldExchanger.import_combined_surface_fields!(cs.fields, cs.model_sims) # i.e. T_sfc, surface_albedo, z0, beta
751745
## calculate turbulent fluxes in surfaces and save the weighted average in coupler fields
752-
FluxCalculator.turbulent_fluxes!(
753-
cs.model_sims,
754-
cs.fields,
755-
cs.boundary_space,
756-
FluxCalculator.MoninObukhovScheme(),
757-
cs.thermo_params,
758-
)
746+
FluxCalculator.turbulent_fluxes!(cs.model_sims, cs.fields, cs.boundary_space, cs.thermo_params)
759747

760748
Interfacer.update_field!(atmos_sim, Val(:surface_temperature), cs.fields)
761749

src/FluxCalculator.jl

Lines changed: 12 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,6 @@ import ..Interfacer, ..Utilities
1414

1515
export calculate_surface_air_density,
1616
extrapolate_ρ_to_sfc,
17-
MoninObukhovScheme,
18-
BulkScheme,
1917
turbulent_fluxes!,
2018
get_surface_params,
2119
update_turbulent_fluxes!,
@@ -35,7 +33,6 @@ end
3533
turbulent_fluxes!(model_sims::NamedTuple,
3634
csf::CC.Fields.Field,
3735
boundary_space::CC.Spaces.AbstractSpace,
38-
surface_scheme,
3936
thermo_params::TD.Parameters.ThermodynamicsParameters)
4037
4138
Compute turbulent fluxes and associated quantities. Store the results in `fields` as
@@ -47,7 +44,6 @@ Args:
4744
- `model_sims`: [NamedTuple] containing `ComponentModelSimulation`s.
4845
- `fields`: [NamedTuple] containing coupler fields.
4946
- `boundary_space`: [CC.Spaces.AbstractSpace] the space of the coupler surface.
50-
- `surface_scheme`: [AbstractSurfaceFluxScheme] the surface flux scheme.
5147
- `thermo_params`: [TD.Parameters.ThermodynamicsParameters] the thermodynamic parameters.
5248
5349
TODO:
@@ -61,7 +57,6 @@ function turbulent_fluxes!(
6157
model_sims::NamedTuple,
6258
csf::CC.Fields.Field,
6359
boundary_space::CC.Spaces.AbstractSpace,
64-
surface_scheme,
6560
thermo_params::TD.Parameters.ThermodynamicsParameters,
6661
)
6762
atmos_sim = model_sims.atmos_sim
@@ -83,77 +78,15 @@ function turbulent_fluxes!(
8378

8479
# Compute the surface fluxes for each surface model and add them to `csf`
8580
for sim in model_sims
86-
compute_surface_fluxes!(csf, sim, atmos_sim, boundary_space, thermo_params, surface_scheme)
81+
compute_surface_fluxes!(csf, sim, atmos_sim, boundary_space, thermo_params)
8782
end
8883

8984
# TODO: add allowable bounds here, check explicitly that all fluxes are equal
9085
return nothing
9186
end
9287

93-
abstract type AbstractSurfaceFluxScheme end
94-
struct BulkScheme <: AbstractSurfaceFluxScheme end
95-
struct MoninObukhovScheme <: AbstractSurfaceFluxScheme end
9688

97-
"""
98-
get_scheme_properties(scheme::AbstractSurfaceFluxScheme, sim::Interfacer.SurfaceModelSimulation)
99-
100-
Returns the scheme-specific properties for the surface model simulation `sim`.
101-
"""
102-
function get_scheme_properties(::BulkScheme, sim::Interfacer.SurfaceModelSimulation)
103-
Ch = Interfacer.get_field(sim, Val(:heat_transfer_coefficient))
104-
Cd = Interfacer.get_field(sim, Val(:drag_coefficient))
105-
beta = Interfacer.get_field(sim, Val(:beta))
106-
FT = eltype(Ch)
107-
return (; z0b = FT(0), z0m = FT(0), Ch = Ch, Cd = Cd, beta = beta, gustiness = FT(1))
108-
end
109-
function get_scheme_properties(::MoninObukhovScheme, sim::Interfacer.SurfaceModelSimulation)
110-
z0m = Interfacer.get_field(sim, Val(:roughness_momentum))
111-
z0b = Interfacer.get_field(sim, Val(:roughness_buoyancy))
112-
beta = Interfacer.get_field(sim, Val(:beta))
113-
FT = eltype(z0m)
114-
return (; z0b = z0b, z0m = z0m, Ch = FT(0), Cd = FT(0), beta = beta, gustiness = FT(1))
115-
end
116-
117-
"""
118-
surface_inputs(scheme::AbstractSurfaceFluxScheme, thermo_state_sfc, thermo_state_int, uₕ_int, z_int, z_sfc, z0b, z0m, Ch, Cd, beta, gustiness)
119-
120-
Returns the inputs for the surface model simulation `sim`.
121-
"""
122-
function surface_inputs(::BulkScheme, input_args::NamedTuple)
123-
124-
(; thermo_state_sfc, thermo_state_int, uₕ_int, z_int, z_sfc, scheme_properties, boundary_space) = input_args
125-
FT = CC.Spaces.undertype(axes(z_sfc))
126-
(; Ch, Cd, beta, gustiness) = scheme_properties
127-
128-
# Extract the underlying data layouts of each field
129-
# Note: this is a bit "dangerous" because it circumvents ClimaCore, but
130-
# it allows us to broadcast over fields on slightly different spaces
131-
fv = CC.Fields.field_values
132-
z_int_fv = fv(z_int)
133-
uₕ_int_fv = fv(uₕ_int)
134-
thermo_state_int_fv = fv(thermo_state_int)
135-
z_sfc_fv = fv(z_sfc)
136-
thermo_state_sfc_fv = fv(thermo_state_sfc)
137-
beta_fv = fv(beta)
138-
139-
# wrap state values
140-
result = @. SF.Coefficients(
141-
SF.StateValues(z_int_fv, uₕ_int_fv, thermo_state_int_fv), # state_in
142-
SF.StateValues( # state_sfc
143-
z_sfc_fv,
144-
StaticArrays.SVector(FT(0), FT(0)),
145-
thermo_state_sfc_fv,
146-
),
147-
Cd, # Cd
148-
Ch, # Ch
149-
gustiness, # gustiness
150-
beta_fv, # beta
151-
)
152-
153-
# Put the result data layout back onto the surface space
154-
return CC.Fields.Field(result, boundary_space)
155-
end
156-
function surface_inputs(::MoninObukhovScheme, input_args::NamedTuple)
89+
function surface_inputs(input_args::NamedTuple)
15790
(; thermo_state_sfc, thermo_state_int, uₕ_int, z_int, z_sfc, scheme_properties, boundary_space) = input_args
15891
FT = CC.Spaces.undertype(boundary_space)
15992
(; z0b, z0m, beta, gustiness) = scheme_properties
@@ -333,7 +266,7 @@ function water_albedo_from_atmosphere!(atmos_sim::Interfacer.AtmosModelSimulatio
333266
end
334267

335268
"""
336-
compute_surface_fluxes!(csf, sim, atmos_sim, boundary_space, thermo_params, surface_scheme)
269+
compute_surface_fluxes!(csf, sim, atmos_sim, boundary_space, thermo_params)
337270
338271
This function computes surface fluxes between the input component model
339272
simulation and the atmosphere.
@@ -351,15 +284,13 @@ function does nothing if called on an atmosphere model simulation.
351284
- `atmos_sim`: [Interfacer.AtmosModelSimulation] the atmosphere simulation to compute fluxes with.
352285
- `boundary_space`: [CC.Spaces.AbstractSpace] the space of the coupler surface.
353286
- `thermo_params`: [TD.Parameters.ThermodynamicsParameters] the thermodynamic parameters.
354-
- `surface_scheme`: [AbstractSurfaceFluxScheme] the surface flux scheme.
355287
"""
356288
function compute_surface_fluxes!(
357289
csf,
358290
sim::Interfacer.AtmosModelSimulation,
359291
atmos_sim::Interfacer.AtmosModelSimulation,
360292
boundary_space,
361293
thermo_params,
362-
surface_scheme,
363294
)
364295
# do nothing for atmos model
365296
return nothing
@@ -371,7 +302,6 @@ function compute_surface_fluxes!(
371302
atmos_sim::Interfacer.AtmosModelSimulation,
372303
boundary_space,
373304
thermo_params,
374-
surface_scheme,
375305
)
376306
# `_int` refers to atmos state of center level 1
377307
z_int = Interfacer.get_field(atmos_sim, Val(:height_int))
@@ -384,23 +314,18 @@ function compute_surface_fluxes!(
384314

385315
thermo_state_sfc = FluxCalculator.surface_thermo_state(sim, thermo_params, thermo_state_int)
386316

387-
# set inputs based on whether the surface_scheme is `MoninObukhovScheme` or `BulkScheme`
388317
surface_params = FluxCalculator.get_surface_params(atmos_sim)
389-
scheme_properties = FluxCalculator.get_scheme_properties(surface_scheme, sim)
318+
319+
z0m = Interfacer.get_field(sim, Val(:roughness_momentum))
320+
z0b = Interfacer.get_field(sim, Val(:roughness_buoyancy))
321+
beta = Interfacer.get_field(sim, Val(:beta))
322+
FT = eltype(z0m)
323+
scheme_properties = (; z0b = z0b, z0m = z0m, Ch = FT(0), Cd = FT(0), beta = beta, gustiness = FT(1))
390324

391325
# surface_params, surface_scheme are used by EinsenmanIceSimulation
392-
input_args = (;
393-
thermo_state_sfc,
394-
thermo_state_int,
395-
uₕ_int,
396-
z_int,
397-
z_sfc,
398-
scheme_properties,
399-
boundary_space,
400-
surface_params,
401-
surface_scheme,
402-
)
403-
inputs = FluxCalculator.surface_inputs(surface_scheme, input_args)
326+
input_args =
327+
(; thermo_state_sfc, thermo_state_int, uₕ_int, z_int, z_sfc, scheme_properties, boundary_space, surface_params)
328+
inputs = FluxCalculator.surface_inputs(input_args)
404329

405330
# calculate the surface fluxes
406331
fluxes = FluxCalculator.get_surface_fluxes!(inputs, surface_params)

test/flux_calculator_tests.jl

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -125,10 +125,9 @@ for FT in (Float32, Float64)
125125
end
126126

127127
@testset "calculate correct fluxes: dry for FT=$FT" begin
128-
scheme = FluxCalculator.MoninObukhovScheme()
129128
boundary_space = CC.CommonSpaces.CubedSphereSpace(FT; radius = FT(6371e3), n_quad_points = 4, h_elem = 4)
130129

131-
params = (; surface_scheme = scheme, FT = FT)
130+
params = (; FT = FT)
132131

133132
# atmos
134133
p = (;
@@ -188,11 +187,11 @@ for FT in (Float32, Float64)
188187

189188
# calculate turbulent fluxes
190189
thermo_params = get_thermo_params(atmos_sim)
191-
FluxCalculator.turbulent_fluxes!(model_sims, fields, boundary_space, scheme, thermo_params)
190+
FluxCalculator.turbulent_fluxes!(model_sims, fields, boundary_space, thermo_params)
192191

193192
# calculating the fluxes twice ensures that no accumulation occurred (i.e. fluxes are reset to zero each time)
194193
# TODO: this will need to be extended once flux accumulation is re-enabled
195-
FluxCalculator.turbulent_fluxes!(model_sims, fields, boundary_space, scheme, thermo_params)
194+
FluxCalculator.turbulent_fluxes!(model_sims, fields, boundary_space, thermo_params)
196195

197196
windspeed = @. hypot(atmos_sim.integrator.p.u, atmos_sim.integrator.p.v)
198197

0 commit comments

Comments
 (0)