Skip to content

Commit 2ad562d

Browse files
authored
add energy from rain to snow (#1176)
1 parent f2337fa commit 2ad562d

File tree

9 files changed

+72
-30
lines changed

9 files changed

+72
-30
lines changed

.buildkite/Manifest-v1.11.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# This file is machine-generated - editing it directly is not advised
22

3-
julia_version = "1.11.5"
3+
julia_version = "1.11.4"
44
manifest_format = "2.0"
55
project_hash = "c057205b5dfa45d173ab89f45dff9c1d2ab4a915"
66

@@ -472,7 +472,7 @@ uuid = "1ecacbb8-0713-4841-9a07-eb5aa8a2d53f"
472472
version = "0.2.14"
473473

474474
[[deps.ClimaLand]]
475-
deps = ["ClimaComms", "ClimaCore", "ClimaDiagnostics", "ClimaTimeSteppers", "ClimaUtilities", "Dates", "DocStringExtensions", "Insolation", "Interpolations", "LazyArtifacts", "LinearAlgebra", "NCDatasets", "SciMLBase", "StaticArrays", "SurfaceFluxes", "Thermodynamics"]
475+
deps = ["ClimaComms", "ClimaCore", "ClimaDiagnostics", "ClimaTimeSteppers", "ClimaUtilities", "Dates", "DocStringExtensions", "Insolation", "Interpolations", "LazyArtifacts", "LazyBroadcast", "LinearAlgebra", "NCDatasets", "SciMLBase", "StaticArrays", "SurfaceFluxes", "Thermodynamics"]
476476
path = ".."
477477
uuid = "08f4d4ce-cf43-44bb-ad95-9d2d5f413532"
478478
version = "0.16.2"
@@ -2245,7 +2245,7 @@ version = "2.5.4+0"
22452245
[[deps.OpenLibm_jll]]
22462246
deps = ["Artifacts", "Libdl"]
22472247
uuid = "05823500-19ac-5b8b-9628-191a04bc5112"
2248-
version = "0.8.5+0"
2248+
version = "0.8.1+4"
22492249

22502250
[[deps.OpenMPI_jll]]
22512251
deps = ["Artifacts", "CompilerSupportLibraries_jll", "Hwloc_jll", "JLLWrappers", "LazyArtifacts", "Libdl", "MPIPreferences", "TOML", "Zlib_jll"]

Project.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ DocStringExtensions = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae"
1414
Insolation = "e98cc03f-d57e-4e3c-b70c-8d51efe9e0d8"
1515
Interpolations = "a98d9a8b-a2ab-59e6-89dd-64a1c18fca59"
1616
LazyArtifacts = "4af54fe1-eca0-43a8-85a7-787d91b784e3"
17+
LazyBroadcast = "9dccce8e-a116-406d-9fcc-a88ed4f510c8"
1718
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
1819
NCDatasets = "85f8d34a-cbdd-5861-8df4-14fed0d494ab"
1920
SciMLBase = "0bca4576-84f4-4d90-8ffe-ffa030f20462"
@@ -23,8 +24,8 @@ Thermodynamics = "b60c26fb-14c3-4610-9d3e-2d17fe7ff00c"
2324

2425
[weakdeps]
2526
BSON = "fbb218c0-5317-5bc6-957e-2ee96dd4b1f0"
26-
ClimaParams = "5c42b081-d73a-476f-9059-fd94b934656c"
2727
CSV = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b"
28+
ClimaParams = "5c42b081-d73a-476f-9059-fd94b934656c"
2829
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
2930
Flux = "587475ba-b771-5e3f-ad9e-33799f191a9c"
3031
HTTP = "cd3eb016-35fb-5094-929b-558a96fad6f3"
@@ -51,6 +52,7 @@ HTTP = "1.10"
5152
Insolation = "0.9.2"
5253
Interpolations = "0.15.1, 0.16"
5354
LazyArtifacts = "1"
55+
LazyBroadcast = "1.0.0"
5456
LinearAlgebra = "1"
5557
NCDatasets = "0.14"
5658
SciMLBase = "2.53"

docs/src/APIs/Snow.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ ClimaLand.Snow.compute_water_runoff
2323
ClimaLand.Snow.energy_from_q_l_and_swe
2424
ClimaLand.Snow.energy_from_T_and_swe
2525
ClimaLand.Snow.snow_cover_fraction
26+
ClimaLand.Snow.volumetric_energy_flux_falling_rain
27+
ClimaLand.Snow.volumetric_energy_flux_falling_snow
2628
```
2729

2830
## Computing fluxes for snow

src/ClimaLand.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ module ClimaLand
22
using DocStringExtensions
33

44
using ClimaCore
5+
using LazyBroadcast: @lazy
56
import ClimaCore: Fields, Spaces
67

78
include("shared_utilities/Parameters.jl")

src/integrated/land.jl

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -570,20 +570,19 @@ function snow_boundary_fluxes!(
570570
p.snow.water_runoff
571571
) * p.snow.snow_cover_fraction
572572

573-
# I think we want dU/dt to include energy of falling snow.
574-
# otherwise snow can fall but energy wont change
575-
# We are assuming that the sensible heat portion of snow is negligible.
576-
_LH_f0 = FT(LP.LH_f0(model.parameters.earth_param_set))
577-
_ρ_liq = FT(LP.ρ_cloud_liq(model.parameters.earth_param_set))
578-
ρe_falling_snow = -_LH_f0 * _ρ_liq # per unit vol of liquid water
573+
ρe_flux_falling_snow =
574+
Snow.volumetric_energy_flux_falling_snow(bc.atmos, p, model.parameters)
575+
ρe_flux_falling_rain =
576+
Snow.volumetric_energy_flux_falling_rain(bc.atmos, p, model.parameters)
579577

580578
# positive fluxes are TOWARDS atmos, but R_n positive if snow absorbs energy
581579
@. p.snow.total_energy_flux =
582-
P_snow * ρe_falling_snow +
580+
ρe_flux_falling_snow +
583581
(
584582
p.snow.turbulent_fluxes.lhf +
585583
p.snow.turbulent_fluxes.shf +
586-
p.snow.R_n - p.snow.energy_runoff - p.ground_heat_flux
584+
p.snow.R_n - p.snow.energy_runoff - p.ground_heat_flux +
585+
ρe_flux_falling_rain
587586
) * p.snow.snow_cover_fraction
588587
return nothing
589588
end

src/integrated/soil_snow_model.jl

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -312,20 +312,19 @@ function snow_boundary_fluxes!(
312312
p.snow.water_runoff
313313
) * p.snow.snow_cover_fraction
314314

315-
# I think we want dU/dt to include energy of falling snow.
316-
# otherwise snow can fall but energy wont change
317-
# We are assuming that the sensible heat portion of snow is negligible.
318-
_LH_f0 = FT(LP.LH_f0(model.parameters.earth_param_set))
319-
_ρ_liq = FT(LP.ρ_cloud_liq(model.parameters.earth_param_set))
320-
ρe_falling_snow = -_LH_f0 * _ρ_liq # per unit vol of liquid water
315+
ρe_flux_falling_snow =
316+
Snow.volumetric_energy_flux_falling_snow(bc.atmos, p, model.parameters)
317+
ρe_flux_falling_rain =
318+
Snow.volumetric_energy_flux_falling_rain(bc.atmos, p, model.parameters)
321319

322320
# positive fluxes are TOWARDS atmos
323321
@. p.snow.total_energy_flux =
324-
P_snow * ρe_falling_snow +
322+
ρe_flux_falling_snow +
325323
(
326324
p.snow.turbulent_fluxes.lhf +
327325
p.snow.turbulent_fluxes.shf +
328-
p.snow.R_n - p.snow.energy_runoff - p.ground_heat_flux
326+
p.snow.R_n - p.snow.energy_runoff - p.ground_heat_flux +
327+
ρe_flux_falling_rain
329328
) * p.snow.snow_cover_fraction
330329
end
331330

src/standalone/Snow/Snow.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ module Snow
33
using DocStringExtensions
44
import ...Parameters as LP
55
using ClimaCore
6+
using LazyBroadcast: @lazy
67
using Thermodynamics
78
using ClimaLand
89
using ClimaLand:

src/standalone/Snow/boundary_fluxes.jl

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -102,10 +102,6 @@ function snow_boundary_fluxes!(
102102
p,
103103
t,
104104
) where {FT}
105-
parameters = model.parameters
106-
_LH_f0 = FT(LP.LH_f0(parameters.earth_param_set))
107-
_ρ_liq = FT(LP.ρ_cloud_liq(parameters.earth_param_set))
108-
109105
bc = model.boundary_conditions
110106

111107
turbulent_fluxes!(p.snow.turbulent_fluxes, bc.atmos, model, Y, p, t)
@@ -125,17 +121,18 @@ function snow_boundary_fluxes!(
125121
p.snow.water_runoff
126122
) * p.snow.snow_cover_fraction
127123

128-
# We are assuming that the sensible heat portion of snow is negligible.
129-
ρe_falling_snow = -_LH_f0 * _ρ_liq # per unit vol of liquid water
124+
ρe_flux_falling_snow =
125+
volumetric_energy_flux_falling_snow(bc.atmos, p, model.parameters)
126+
ρe_flux_falling_rain =
127+
volumetric_energy_flux_falling_rain(bc.atmos, p, model.parameters)
130128

131129
# positive fluxes are TOWARDS atmos
132-
# This does not include the energy in rain yet
133130
@. p.snow.total_energy_flux =
134-
P_snow * ρe_falling_snow +
131+
ρe_flux_falling_snow +
135132
(
136133
p.snow.turbulent_fluxes.lhf +
137134
p.snow.turbulent_fluxes.shf +
138-
p.snow.R_n - p.snow.energy_runoff
135+
p.snow.R_n - p.snow.energy_runoff + ρe_flux_falling_rain
139136
) * p.snow.snow_cover_fraction
140137
return nothing
141138

src/standalone/Snow/snow_parameterizations.jl

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@ export snow_surface_temperature,
1111
update_snow_cover_fraction!,
1212
snow_bulk_density,
1313
phase_change_flux,
14-
update_snow_albedo!
14+
update_snow_albedo!,
15+
volumetric_energy_flux_falling_snow,
16+
volumetric_energy_flux_falling_rain
1517

1618
"""
1719
update_snow_albedo!(α, m::ConstantAlbedoModel, Y, p, t, earth_param_set)
@@ -477,6 +479,45 @@ function energy_from_T_and_swe(S::FT, T::FT, parameters) where {FT}
477479

478480
end
479481

482+
"""
483+
volumetric_energy_flux_falling_snow(atmos, p, parameters)
484+
485+
Returns the volumetric energy flux of falling snow for a PrescribedAtmosphere,
486+
approximated as ρe_snow * P_snow, where ρe_snow = -LH_f0 * _ρ_liq.
487+
This is a negative internal energy, due the to negative contribution of
488+
the latent heat of melting to the energy of the snow,
489+
and it neglects the sensible heat portion of the snow. The overall flux
490+
is per unit volume of liquid water, and P_snow is expressed as
491+
the volume flux of liquid water resulting from the snow.
492+
493+
This method can be extended to coupled simulations, where atmos is of type
494+
CoupledAtmosphere, and the energy flux of the falling snow is passed in the
495+
cache `p`. In that case, this should specify `atmos::PrescribedAtmosphere`.
496+
"""
497+
function volumetric_energy_flux_falling_snow(atmos, p, parameters)
498+
_LH_f0 = LP.LH_f0(parameters.earth_param_set)
499+
_ρ_liq = LP.ρ_cloud_liq(parameters.earth_param_set)
500+
ρe_snow = -_LH_f0 * _ρ_liq
501+
return @lazy @. ρe_snow * p.drivers.P_snow # per unit vol of liquid water
502+
end
503+
504+
"""
505+
volumetric_energy_flux_falling_rain(atmos, p, parameters)
506+
507+
Returns the volumetric energy flux of falling rain for a PrescribedAtmosphere,
508+
approximated as ρ_l e_l(T_atmos) * P_liq. This is per unit volume of liquid water,
509+
and P_liq is expressed as the volume flux of liquid water resulting from the rain.
510+
511+
This method can be extended to coupled simulations, where atmos is of type
512+
CoupledAtmosphere, and the energy flux of the falling rain is passed in the
513+
cache `p`. In that case, this should specify `atmos::PrescribedAtmosphere`.
514+
"""
515+
function volumetric_energy_flux_falling_rain(atmos, p, parameters)
516+
return @lazy @. volumetric_internal_energy_liq(p.drivers.T, parameters) *
517+
p.drivers.P_liq
518+
end
519+
520+
480521
"""
481522
update_density_and_depth!(ρ_snow, z_snow, density::MinimumDensityModel, Y, p, params::SnowParameters)
482523

0 commit comments

Comments
 (0)