Skip to content

Commit 55ff3f4

Browse files
authored
Correction to MOST formulation (#114)
* fix bug in wind speed profile formulation * update R/Fortran test output
1 parent 095b506 commit 55ff3f4

12 files changed

Lines changed: 6211 additions & 6209 deletions

src/boundary_layer/monin_obukhov.jl

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ function atmospheric_surface_profile!(bl::MoninObukhov, buffers;
143143
#ρcpTκg = u"cal*minute^2/cm^4"(ρ * c_p * T_ref_height / (κ * g_n))
144144
ρcpTκg = u"J*s^2/m^4"(6.003e-8u"cal*minute^2/cm^4")
145145

146-
log_z_ratio = log(z / z0 + 1)
146+
log_z_ratio = log(z / z0)
147147
ΔT = reference_temp - surface_temp
148148
mean_temp = (surface_temp + reference_temp) / 2
149149
# TODO call calc_ρ_cp method specific to elevation and RH in final version but do it this way for NicheMapR comparison
@@ -156,11 +156,11 @@ function atmospheric_surface_profile!(bl::MoninObukhov, buffers;
156156
convective_heat_flux = calc_convection(; friction_velocity, log_z_ratio, ΔT, ρ_cp, z0)
157157
roughness_height_temp = (reference_temp * bulk_stanton(log_z_ratio) + surface_temp * sublayer_stanton(z0, friction_velocity)) / (bulk_stanton(log_z_ratio) + sublayer_stanton(z0, friction_velocity))
158158
for i in 2:N_heights
159-
wind_speed[i] = calc_wind(height_array[i], z0, κ, friction_velocity, 1.0)
160-
air_temperature[i] = roughness_height_temp + (reference_temp - roughness_height_temp) * log(height_array[i] / z0 + 1.0) / log_z_ratio
159+
wind_speed[i] = calc_wind(height_array[i], z0, κ, friction_velocity, 0.0)
160+
air_temperature[i] = roughness_height_temp + (reference_temp - roughness_height_temp) * log(height_array[i] / z0) / log_z_ratio
161161
end
162162
else # unstable conditions during daytime, need to solve iteratively for Obukhov length
163-
Obukhov_out = calc_Obukhov_length(reference_temp, surface_temp, v_ref_height, z0, z, ρcpTκg, κ, log_z_ratio, ΔT, ρ_cp; max_iter=30, tol=1e-2, initial_obukhov_length=obukhov_length_prev[])
163+
Obukhov_out = calc_Obukhov_length(reference_temp, surface_temp, v_ref_height, z0, z, ρcpTκg, κ, ΔT, ρ_cp; max_iter=30, tol=1e-2, initial_obukhov_length=obukhov_length_prev[])
164164
obukhov_length = Obukhov_out.obukhov_length
165165
obukhov_length_prev[] = obukhov_length
166166
roughness_height_temp = Obukhov_out.roughness_height_temperature
@@ -172,12 +172,12 @@ function atmospheric_surface_profile!(bl::MoninObukhov, buffers;
172172
ψ_m1 = calc_ψ_m(φ_m1)
173173
ψ_h2 = calc_ψ_h(φ_m1)
174174
h_ratio = height_array[i] / z0 # dimensionless h/z0
175-
# Clamp log arguments to a small positive value to prevent NaN when
176-
# stability corrections exceed h/z0 at near-surface heights (e.g. 0.01 m).
177-
wind_log_arg = max(h_ratio - ψ_m1, 1e-6)
178-
wind_speed[i] = (friction_velocity / κ) * log(wind_log_arg)
179-
temp_log_arg = max(h_ratio - ψ_h2, 1e-6)
180-
air_temperature[i] = roughness_height_temp + (reference_temp - roughness_height_temp) * log(temp_log_arg) / log(z / z0 - ψ_h)
175+
# Clamp to a small positive value to prevent non-physical results when
176+
# stability corrections are large near the surface.
177+
wind_log_arg = max(log(h_ratio) - ψ_m1, 1e-6)
178+
wind_speed[i] = (friction_velocity / κ) * wind_log_arg
179+
temp_log_arg = max(log(h_ratio) - ψ_h2, 1e-6)
180+
air_temperature[i] = roughness_height_temp + (reference_temp - roughness_height_temp) * temp_log_arg / (log(z / z0) - ψ_h)
181181
end
182182
end
183183
reverse!(wind_speed)
@@ -199,7 +199,7 @@ function surface_fluxes(bl::MoninObukhov;
199199
roughness_height, reference_height, obukhov_length_prev=nothing,
200200
)
201201
κ = bl.karman_constant
202-
log_z_ratio = log(reference_height / roughness_height + 1)
202+
log_z_ratio = log(reference_height / roughness_height)
203203
ΔT = air_temperature - surface_temperature
204204
ρ_cp = calc_ρ_cp((surface_temperature + air_temperature) / 2)
205205

@@ -217,7 +217,7 @@ function surface_fluxes(bl::MoninObukhov;
217217
L0_raw = isnothing(obukhov_length_prev) ? -0.3u"m" : obukhov_length_prev[]
218218
L0 = L0_raw >= 0.0u"m" ? -0.3u"m" : L0_raw
219219
out = calc_Obukhov_length(air_temperature, surface_temperature, wind_speed,
220-
roughness_height, reference_height, ρcpTκg, κ, log_z_ratio, ΔT, ρ_cp;
220+
roughness_height, reference_height, ρcpTκg, κ, ΔT, ρ_cp;
221221
initial_obukhov_length=L0)
222222
friction_velocity = out.friction_velocity
223223
convective_heat_flux = out.convective_heat_flux
@@ -234,14 +234,13 @@ function init_surface_fluxes!(bl::MoninObukhov, buffers, forcing, site, heights,
234234
κ = bl.karman_constant
235235
roughness_height = site.roughness_height
236236
reference_height = last(heights)
237-
log_z_ratio = log(reference_height / roughness_height + 1)
238237
ΔT = air_temperature - surface_temperature
239238
ρ_cp = calc_ρ_cp((surface_temperature + air_temperature) / 2)
240239
ρcpTκg = 6.003e-8u"cal*minute^2/cm^4"
241240
L0_raw = buffers.soil_energy_balance.obukhov_length_prev[]
242241
L0 = L0_raw >= 0.0u"m" ? -0.3u"m" : L0_raw
243242
out = calc_Obukhov_length(air_temperature, surface_temperature, wind_speed,
244-
roughness_height, reference_height, ρcpTκg, κ, log_z_ratio, ΔT, ρ_cp;
243+
roughness_height, reference_height, ρcpTκg, κ, ΔT, ρ_cp;
245244
initial_obukhov_length=L0)
246245
buffers.soil_energy_balance.obukhov_length_prev[] = out.obukhov_length end
247246
end
@@ -430,11 +429,14 @@ Stability correction function φ for momentum in Monin–Obukhov similarity theo
430429
# Returns
431430
- Dimensionless stability correction factor φ.
432431
433-
This corresponds to the Businger–Dyer formulation for unstable stratification:
434-
435-
φₘ = (1 - γ z / L)^(1/4)
432+
Returns the Paulson (1970) x-substitution variable x = (1 - γ z / L)^(1/4),
433+
used as the argument to `calc_ψ_m` and `calc_ψ_h`. Note this is the reciprocal
434+
of the true Businger–Dyer φₘ stability function, φₘ = (1 - γ z / L)^(-1/4).
436435
437436
# References
437+
- Paulson, C. A. (1970). The mathematical representation of wind speed and
438+
temperature profiles in the unstable atmospheric surface layer.
439+
*Journal of Applied Meteorology*, 9(6), 857–861.
438440
- Businger, J. A., Wyngaard, J. C., Izumi, Y., & Bradley, E. F. (1971).
439441
Flux–profile relationships in the atmospheric surface layer.
440442
*Journal of the Atmospheric Sciences*, 28(2), 181–189.
@@ -505,7 +507,7 @@ end
505507
Iteratively solve for Monin-Obukhov length and convective heat flux.
506508
"""
507509
@inline function calc_Obukhov_length(
508-
reference_temp, surface_temp, v_ref_height, z0, z, ρcpTκg, κ, log_z_ratio, ΔT, ρ_cp;
510+
reference_temp, surface_temp, v_ref_height, z0, z, ρcpTκg, κ, ΔT, ρ_cp;
509511
γ=16.0, max_iter=30, tol=1e-2, initial_obukhov_length=-0.3u"m"
510512
)
511513
obukhov_length = initial_obukhov_length

0 commit comments

Comments
 (0)