Source code for pycif.plugins.transforms.complex.diagmet.utils.friction_velocity
import numpy as np
from .mean_z0_shf_extra_urban_temp import mean_z0_shf_extra_urban_temp
from .sv_heat_flux import sv_heat_flux
[docs]
def friction_velocity(transf, inout_datastore, ddi, mapper):
"""Compute friction velocity u* using the Louis (1982) stability function.
Only run when ``usta: recompute`` (the default); otherwise :math:`u_*` is
read directly from ECMWF. Builds a bulk Richardson number between the
surface and 10 m from virtual potential temperature and wind speed, applies
the Louis (1982) stability correction to the neutral drag coefficient, and
combines the mechanical and convective (``wstar0``, see
:func:`~pycif.plugins.transforms.complex.diagmet.utils.sv_heat_flux.sv_heat_flux`)
contributions. See :doc:`/documentation/doc-models/chimere/diagmet`
(section 6) for the full derivation.
Args:
transf (Plugin): diagmet transform instance.
inout_datastore (dict): mutable datastore.
ddi (datetime): current sub-simulation date.
mapper (dict): transform mapper.
"""
# Wind speed at 10m
w10m = np.sqrt(
inout_datastore["inputs"][("meteo", "u10m")][ddi]["spec"] ** 2
+ inout_datastore["inputs"][("meteo", "v10m")][ddi]["spec"] ** 2
).values
# Inputs
pres = transf.diag_misc["pres"]
temp = transf.diag_misc["temp"]
sphu = transf.diag_misc["sphu"]
water = transf.diag_misc["water"]
# Correction by urban heat
awf = transf.diag_misc["awf"]
az0 = transf.diag_misc["az0"]
auf = transf.diag_misc["auf"]
pm = transf.diag_misc["pm"]
w10s = w10m * awf
# SV heat flux
wstar0 = transf.diag_misc["wstar0"]
# Fixed parameters
woff = 0.5 # Wind offset to smooth Richardson numbers (m / s)
g = 9.81 # Gravity constant
xkappa = 0.2857 # Kappa
vkarm = 0.4 # von Karman constant
p0 = 1e5 # Reference pressure(Pa)
# Compute auxiliary parameters
po = (1.0 + 0.61 * sphu - water) * temp * (p0 / pres) ** xkappa
th = temp * (p0 / pres) ** xkappa
transf.diag_misc["po"] = po
if transf.usta == 'recompute':
# Compute ustar
zustar = 10.
vustar = np.maximum(w10s, woff)
dtheta = po[:, [1]] - po[:, [0]]
rich = dtheta * g * zustar / (th[:, [0]] * vustar ** 2)
cdnm = vkarm / np.log(zustar / az0)
cdn2 = cdnm * cdnm
facm = 75.0 * cdn2 * np.sqrt(zustar / az0)
fm = np.where(
rich < 0.,
1.0 - 10.0 * rich / (1.0 + facm * np.sqrt(-rich)),
1.0 / (1.0 + 10.0 * rich / np.sqrt(1. + 5. * rich))
)
cd = cdnm * np.sqrt(fm)
ustar = cd * np.sqrt(vustar ** 2 + (1.2 * wstar0) ** 2)
inout_datastore["outputs"][("meteo", "usta")][ddi]["spec"] = \
0 * inout_datastore["outputs"][("meteo", "hght")][ddi]["spec"] + ustar