pycontrails 0.58.0__cp314-cp314-macosx_10_13_x86_64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of pycontrails might be problematic. Click here for more details.
- pycontrails/__init__.py +70 -0
- pycontrails/_version.py +34 -0
- pycontrails/core/__init__.py +30 -0
- pycontrails/core/aircraft_performance.py +679 -0
- pycontrails/core/airports.py +228 -0
- pycontrails/core/cache.py +889 -0
- pycontrails/core/coordinates.py +174 -0
- pycontrails/core/fleet.py +483 -0
- pycontrails/core/flight.py +2185 -0
- pycontrails/core/flightplan.py +228 -0
- pycontrails/core/fuel.py +140 -0
- pycontrails/core/interpolation.py +702 -0
- pycontrails/core/met.py +2931 -0
- pycontrails/core/met_var.py +387 -0
- pycontrails/core/models.py +1321 -0
- pycontrails/core/polygon.py +549 -0
- pycontrails/core/rgi_cython.cpython-314-darwin.so +0 -0
- pycontrails/core/vector.py +2249 -0
- pycontrails/datalib/__init__.py +12 -0
- pycontrails/datalib/_met_utils/metsource.py +746 -0
- pycontrails/datalib/ecmwf/__init__.py +73 -0
- pycontrails/datalib/ecmwf/arco_era5.py +345 -0
- pycontrails/datalib/ecmwf/common.py +114 -0
- pycontrails/datalib/ecmwf/era5.py +554 -0
- pycontrails/datalib/ecmwf/era5_model_level.py +490 -0
- pycontrails/datalib/ecmwf/hres.py +804 -0
- pycontrails/datalib/ecmwf/hres_model_level.py +466 -0
- pycontrails/datalib/ecmwf/ifs.py +287 -0
- pycontrails/datalib/ecmwf/model_levels.py +435 -0
- pycontrails/datalib/ecmwf/static/model_level_dataframe_v20240418.csv +139 -0
- pycontrails/datalib/ecmwf/variables.py +268 -0
- pycontrails/datalib/geo_utils.py +261 -0
- pycontrails/datalib/gfs/__init__.py +28 -0
- pycontrails/datalib/gfs/gfs.py +656 -0
- pycontrails/datalib/gfs/variables.py +104 -0
- pycontrails/datalib/goes.py +757 -0
- pycontrails/datalib/himawari/__init__.py +27 -0
- pycontrails/datalib/himawari/header_struct.py +266 -0
- pycontrails/datalib/himawari/himawari.py +667 -0
- pycontrails/datalib/landsat.py +589 -0
- pycontrails/datalib/leo_utils/__init__.py +5 -0
- pycontrails/datalib/leo_utils/correction.py +266 -0
- pycontrails/datalib/leo_utils/landsat_metadata.py +300 -0
- pycontrails/datalib/leo_utils/search.py +250 -0
- pycontrails/datalib/leo_utils/sentinel_metadata.py +748 -0
- pycontrails/datalib/leo_utils/static/bq_roi_query.sql +6 -0
- pycontrails/datalib/leo_utils/vis.py +59 -0
- pycontrails/datalib/sentinel.py +650 -0
- pycontrails/datalib/spire/__init__.py +5 -0
- pycontrails/datalib/spire/exceptions.py +62 -0
- pycontrails/datalib/spire/spire.py +604 -0
- pycontrails/ext/bada.py +42 -0
- pycontrails/ext/cirium.py +14 -0
- pycontrails/ext/empirical_grid.py +140 -0
- pycontrails/ext/synthetic_flight.py +431 -0
- pycontrails/models/__init__.py +1 -0
- pycontrails/models/accf.py +425 -0
- pycontrails/models/apcemm/__init__.py +8 -0
- pycontrails/models/apcemm/apcemm.py +983 -0
- pycontrails/models/apcemm/inputs.py +226 -0
- pycontrails/models/apcemm/static/apcemm_yaml_template.yaml +183 -0
- pycontrails/models/apcemm/utils.py +437 -0
- pycontrails/models/cocip/__init__.py +29 -0
- pycontrails/models/cocip/cocip.py +2742 -0
- pycontrails/models/cocip/cocip_params.py +305 -0
- pycontrails/models/cocip/cocip_uncertainty.py +291 -0
- pycontrails/models/cocip/contrail_properties.py +1530 -0
- pycontrails/models/cocip/output_formats.py +2270 -0
- pycontrails/models/cocip/radiative_forcing.py +1260 -0
- pycontrails/models/cocip/radiative_heating.py +520 -0
- pycontrails/models/cocip/unterstrasser_wake_vortex.py +508 -0
- pycontrails/models/cocip/wake_vortex.py +396 -0
- pycontrails/models/cocip/wind_shear.py +120 -0
- pycontrails/models/cocipgrid/__init__.py +9 -0
- pycontrails/models/cocipgrid/cocip_grid.py +2552 -0
- pycontrails/models/cocipgrid/cocip_grid_params.py +138 -0
- pycontrails/models/dry_advection.py +602 -0
- pycontrails/models/emissions/__init__.py +21 -0
- pycontrails/models/emissions/black_carbon.py +599 -0
- pycontrails/models/emissions/emissions.py +1353 -0
- pycontrails/models/emissions/ffm2.py +336 -0
- pycontrails/models/emissions/static/default-engine-uids.csv +239 -0
- pycontrails/models/emissions/static/edb-gaseous-v29b-engines.csv +596 -0
- pycontrails/models/emissions/static/edb-nvpm-v29b-engines.csv +215 -0
- pycontrails/models/extended_k15.py +1327 -0
- pycontrails/models/humidity_scaling/__init__.py +37 -0
- pycontrails/models/humidity_scaling/humidity_scaling.py +1075 -0
- pycontrails/models/humidity_scaling/quantiles/era5-model-level-quantiles.pq +0 -0
- pycontrails/models/humidity_scaling/quantiles/era5-pressure-level-quantiles.pq +0 -0
- pycontrails/models/issr.py +210 -0
- pycontrails/models/pcc.py +326 -0
- pycontrails/models/pcr.py +154 -0
- pycontrails/models/ps_model/__init__.py +18 -0
- pycontrails/models/ps_model/ps_aircraft_params.py +381 -0
- pycontrails/models/ps_model/ps_grid.py +701 -0
- pycontrails/models/ps_model/ps_model.py +1000 -0
- pycontrails/models/ps_model/ps_operational_limits.py +525 -0
- pycontrails/models/ps_model/static/ps-aircraft-params-20250328.csv +69 -0
- pycontrails/models/ps_model/static/ps-synonym-list-20250328.csv +104 -0
- pycontrails/models/sac.py +442 -0
- pycontrails/models/tau_cirrus.py +183 -0
- pycontrails/physics/__init__.py +1 -0
- pycontrails/physics/constants.py +117 -0
- pycontrails/physics/geo.py +1138 -0
- pycontrails/physics/jet.py +968 -0
- pycontrails/physics/static/iata-cargo-load-factors-20250221.csv +74 -0
- pycontrails/physics/static/iata-passenger-load-factors-20250221.csv +74 -0
- pycontrails/physics/thermo.py +551 -0
- pycontrails/physics/units.py +472 -0
- pycontrails/py.typed +0 -0
- pycontrails/utils/__init__.py +1 -0
- pycontrails/utils/dependencies.py +66 -0
- pycontrails/utils/iteration.py +13 -0
- pycontrails/utils/json.py +187 -0
- pycontrails/utils/temp.py +50 -0
- pycontrails/utils/types.py +163 -0
- pycontrails-0.58.0.dist-info/METADATA +180 -0
- pycontrails-0.58.0.dist-info/RECORD +122 -0
- pycontrails-0.58.0.dist-info/WHEEL +6 -0
- pycontrails-0.58.0.dist-info/licenses/LICENSE +178 -0
- pycontrails-0.58.0.dist-info/licenses/NOTICE +43 -0
- pycontrails-0.58.0.dist-info/top_level.txt +3 -0
|
@@ -0,0 +1,520 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Radiative heating of contrail cirrus.
|
|
3
|
+
|
|
4
|
+
Contrails absorb incoming solar radiation and outgoing longwave radiation, causing it to heat up.
|
|
5
|
+
|
|
6
|
+
1. The additional heating energy drives a local updraft
|
|
7
|
+
(but this is negligible and not included in CoCiP);
|
|
8
|
+
2. The differential heating rate drives local turbulence.
|
|
9
|
+
As radiative emission from the contrail is limited by its low temperature,
|
|
10
|
+
the net result is deposition of radiative energy in the contrail.
|
|
11
|
+
|
|
12
|
+
These equations are provided by Ulrich Schumann and not included in any scientific publications,
|
|
13
|
+
The scientific rationale of including these effects can be found in the references below:
|
|
14
|
+
|
|
15
|
+
References
|
|
16
|
+
----------
|
|
17
|
+
- :cite:`jensenSpreadingGrowthContrails1998`
|
|
18
|
+
- :cite:`schumannLifeCycleIndividual2017`
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
from __future__ import annotations
|
|
22
|
+
|
|
23
|
+
from dataclasses import dataclass
|
|
24
|
+
|
|
25
|
+
import numpy as np
|
|
26
|
+
import numpy.typing as npt
|
|
27
|
+
|
|
28
|
+
from pycontrails.physics import constants
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@dataclass
|
|
32
|
+
class RadiativeHeatingConstants:
|
|
33
|
+
"""Constants/coefficients used to calculate the radiative heating rate.
|
|
34
|
+
|
|
35
|
+
Constants/coefficients used to calculate the:
|
|
36
|
+
- shortwave differential heating rate
|
|
37
|
+
- longwave differential heating rate
|
|
38
|
+
- shortwave heating rate
|
|
39
|
+
- longwave heating rate
|
|
40
|
+
|
|
41
|
+
These coefficients were calibrated based on a least-squares fit relative
|
|
42
|
+
to the libRadtran radiative transfer model. (Ulrich Schumann, personal communication).
|
|
43
|
+
|
|
44
|
+
References
|
|
45
|
+
----------
|
|
46
|
+
- :cite:`schumannRadiativeHeatingContrail2010`
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
#: Coefficients for shortwave differential heating rate
|
|
50
|
+
dacth: float = 0.205747e01
|
|
51
|
+
dacth3: float = 0.898366e00
|
|
52
|
+
dbcth: float = 0.791045e00
|
|
53
|
+
dccth: float = 0.612725e00
|
|
54
|
+
ddcth: float = 0.517342e-02
|
|
55
|
+
dexalb: float = 0.267568e01
|
|
56
|
+
dfrsw: float = 0.139286e01
|
|
57
|
+
dgalbs: float = 0.178497e01
|
|
58
|
+
d_gamma: float = 0.142104e01
|
|
59
|
+
d_gamma_s: float = 0.882497e00
|
|
60
|
+
dqsw: float = 0.631427e-01
|
|
61
|
+
draddsw: float = 0.261780e00
|
|
62
|
+
dtt: float = 0.339171e-01
|
|
63
|
+
|
|
64
|
+
#: Coefficients for longwave differential heating rate
|
|
65
|
+
dak: float = 0.357181e01
|
|
66
|
+
dcrhi: float = 0.623019e-01
|
|
67
|
+
ddelta: float = 0.198000e01
|
|
68
|
+
dfrlw: float = 0.609262e00
|
|
69
|
+
dqlw: float = 0.100000e-05
|
|
70
|
+
dqrlw: float = 0.160286e00
|
|
71
|
+
draddlw: float = 0.898529e-05
|
|
72
|
+
dsigma: float = 0.159884e-06
|
|
73
|
+
|
|
74
|
+
#: Coefficients for shortwave heating rate
|
|
75
|
+
acth: float = 0.156899e01
|
|
76
|
+
bcth: float = 0.875130e00
|
|
77
|
+
ccth: float = 0.112445e01
|
|
78
|
+
dcth: float = 0.236688e-01
|
|
79
|
+
exal_b: float = 0.410705e00
|
|
80
|
+
fr_sw: float = 0.537577e01
|
|
81
|
+
gamma_r: float = 0.762254e00
|
|
82
|
+
q_sw: float = 0.454176e-01
|
|
83
|
+
radd_sw: float = 0.991554e00
|
|
84
|
+
ttt: float = 0.985031e-01
|
|
85
|
+
|
|
86
|
+
#: Coefficients for longwave heating rate
|
|
87
|
+
ak: float = 0.294930e01
|
|
88
|
+
crhi: float = 0.174422e00
|
|
89
|
+
czlw: float = 0.393884e-01
|
|
90
|
+
delta: float = 0.860746e00
|
|
91
|
+
fr_lw: float = 0.760423e00
|
|
92
|
+
q_lw: float = 0.152075e02
|
|
93
|
+
radd_lw: float = 0.308486e-02
|
|
94
|
+
sigma: float = 0.253499e-04
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
RAD_HEAT = RadiativeHeatingConstants()
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def convective_velocity_scale(
|
|
101
|
+
depth_eff: npt.NDArray[np.floating],
|
|
102
|
+
eff_heat_rate: npt.NDArray[np.floating],
|
|
103
|
+
air_temperature: npt.NDArray[np.floating],
|
|
104
|
+
) -> npt.NDArray[np.floating]:
|
|
105
|
+
"""
|
|
106
|
+
Calculate the convective velocity scale, i.e., vertical mixing rate.
|
|
107
|
+
|
|
108
|
+
Parameters
|
|
109
|
+
----------
|
|
110
|
+
depth_eff : npt.NDArray[np.floating]
|
|
111
|
+
Effective depth of the contrail plume, [:math:`m`]
|
|
112
|
+
eff_heat_rate: npt.NDArray[np.floating]
|
|
113
|
+
Effective heating rate, i.e., rate of which the contrail plume is heated, [:math:`K s^{-1}`]
|
|
114
|
+
air_temperature : npt.NDArray[np.floating]
|
|
115
|
+
Ambient temperature for each waypoint, [:math:`K`]
|
|
116
|
+
|
|
117
|
+
Returns
|
|
118
|
+
-------
|
|
119
|
+
npt.NDArray[np.floating]
|
|
120
|
+
Convective velocity scale, [:math:`m s^{-1}`]
|
|
121
|
+
"""
|
|
122
|
+
return ((constants.g * depth_eff**2 * np.maximum(-eff_heat_rate, 0)) / air_temperature) ** (
|
|
123
|
+
1 / 3
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
def effective_heating_rate(
|
|
128
|
+
d_heat_rate: npt.NDArray[np.floating],
|
|
129
|
+
cumul_rad_heat: npt.NDArray[np.floating],
|
|
130
|
+
dT_dz: npt.NDArray[np.floating],
|
|
131
|
+
depth: npt.NDArray[np.floating],
|
|
132
|
+
) -> npt.NDArray[np.floating]:
|
|
133
|
+
"""Calculate effective heating rate.
|
|
134
|
+
|
|
135
|
+
The effective heating rate accounts for the heat required to overcome the stable stratification.
|
|
136
|
+
Turbulence will occur after the cumulative heating overcomes the stable stratification.
|
|
137
|
+
|
|
138
|
+
Parameters
|
|
139
|
+
----------
|
|
140
|
+
d_heat_rate: npt.NDArray[np.floating]
|
|
141
|
+
Differential heating rate, i.e., rate of which the contrail
|
|
142
|
+
plume is heated, [:math:`K s^{-1}`]
|
|
143
|
+
cumul_rad_heat: npt.NDArray[np.floating]
|
|
144
|
+
Cumulative solar and terrestrial radiative heating energy
|
|
145
|
+
absorbed by the contrail, [:math:`K`]
|
|
146
|
+
dT_dz: npt.NDArray[np.floating]
|
|
147
|
+
Temperature gradient with respect to altitude (dz), [:math:`K m^{-1}`]
|
|
148
|
+
depth : npt.NDArray[np.floating]
|
|
149
|
+
Contrail depth at each waypoint, [:math:`m`]
|
|
150
|
+
|
|
151
|
+
Returns
|
|
152
|
+
-------
|
|
153
|
+
npt.NDArray[np.floating]
|
|
154
|
+
Effective heating rate, [:math:`K s^{-1}`]
|
|
155
|
+
"""
|
|
156
|
+
filt = cumul_rad_heat > 0.0
|
|
157
|
+
heat_denom = 0.5 * dT_dz[filt] * depth[filt]
|
|
158
|
+
heat_denom.clip(min=0.0, out=heat_denom)
|
|
159
|
+
|
|
160
|
+
heat_ratio = np.zeros_like(cumul_rad_heat)
|
|
161
|
+
heat_ratio[filt] = cumul_rad_heat[filt] / (cumul_rad_heat[filt] + heat_denom)
|
|
162
|
+
|
|
163
|
+
return d_heat_rate * heat_ratio
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
def differential_heating_rate(
|
|
167
|
+
air_temperature: npt.NDArray[np.floating],
|
|
168
|
+
rhi: npt.NDArray[np.floating],
|
|
169
|
+
rho_air: npt.NDArray[np.floating],
|
|
170
|
+
r_ice_vol: npt.NDArray[np.floating],
|
|
171
|
+
depth_eff: npt.NDArray[np.floating],
|
|
172
|
+
tau_contrail: npt.NDArray[np.floating],
|
|
173
|
+
tau_cirrus: npt.NDArray[np.floating],
|
|
174
|
+
sd0: npt.NDArray[np.floating],
|
|
175
|
+
sdr: npt.NDArray[np.floating],
|
|
176
|
+
rsr: npt.NDArray[np.floating],
|
|
177
|
+
olr: npt.NDArray[np.floating],
|
|
178
|
+
) -> npt.NDArray[np.floating]:
|
|
179
|
+
"""
|
|
180
|
+
Calculate the differential heating rate affecting the contrail plume.
|
|
181
|
+
|
|
182
|
+
Differential heating rate is the heating rate difference between the upper and
|
|
183
|
+
lower half of the cirrus layer. The radiative heating effect is dominated by the
|
|
184
|
+
longwave component. Therefore, this output will always be a positive
|
|
185
|
+
value (i.e., warmer at the upper contrail edge and cooler at the bottom).
|
|
186
|
+
|
|
187
|
+
Parameters
|
|
188
|
+
----------
|
|
189
|
+
air_temperature : npt.NDArray[np.floating]
|
|
190
|
+
Ambient temperature at each waypoint, [:math:`K`]
|
|
191
|
+
rhi : npt.NDArray[np.floating]
|
|
192
|
+
Relative humidity with respect to ice at each waypoint
|
|
193
|
+
rho_air : npt.NDArray[np.floating]
|
|
194
|
+
Density of air for each waypoint, [:math:`kg m^{-3}`]
|
|
195
|
+
r_ice_vol : npt.NDArray[np.floating]
|
|
196
|
+
Ice particle volume mean radius, [:math:`m`]
|
|
197
|
+
depth_eff : npt.NDArray[np.floating]
|
|
198
|
+
Effective depth of the contrail plume, [:math:`m`]
|
|
199
|
+
tau_contrail : npt.NDArray[np.floating]
|
|
200
|
+
Contrail optical depth for each waypoint
|
|
201
|
+
tau_cirrus : npt.NDArray[np.floating]
|
|
202
|
+
Optical depth of numerical weather prediction (NWP) cirrus above the contrail
|
|
203
|
+
sd0 : npt.NDArray[np.floating]
|
|
204
|
+
Solar constant, [:math:`W m^{-2}`]
|
|
205
|
+
sdr : npt.NDArray[np.floating]
|
|
206
|
+
Solar direct radiation, [:math:`W m^{-2}`]
|
|
207
|
+
rsr : npt.NDArray[np.floating]
|
|
208
|
+
Reflected solar radiation, [:math:`W m^{-2}`]
|
|
209
|
+
olr : npt.NDArray[np.floating]
|
|
210
|
+
Outgoing longwave radiation at each waypoint, [:math:`W m^{-2}`]
|
|
211
|
+
|
|
212
|
+
Returns
|
|
213
|
+
-------
|
|
214
|
+
npt.NDArray[np.floating]
|
|
215
|
+
Differential heating rate, [:math:`K s^{-1}`]
|
|
216
|
+
"""
|
|
217
|
+
r_ice_vol_um = r_ice_vol * 1e6
|
|
218
|
+
cp_contrail = contrail_heat_capacity(rho_air, depth_eff)
|
|
219
|
+
d_heat_rate_sw = differential_heating_rate_shortwave(
|
|
220
|
+
cp_contrail, r_ice_vol_um, tau_contrail, tau_cirrus, sd0, sdr, rsr
|
|
221
|
+
)
|
|
222
|
+
d_heat_rate_lw = differential_heating_rate_longwave(
|
|
223
|
+
air_temperature, rhi, cp_contrail, r_ice_vol_um, tau_contrail, tau_cirrus, olr
|
|
224
|
+
)
|
|
225
|
+
return np.minimum(d_heat_rate_sw + d_heat_rate_lw, 0.0)
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
def differential_heating_rate_shortwave(
|
|
229
|
+
cp_contrail: npt.NDArray[np.floating],
|
|
230
|
+
r_ice_vol_um: npt.NDArray[np.floating],
|
|
231
|
+
tau_contrail: npt.NDArray[np.floating],
|
|
232
|
+
tau_cirrus: npt.NDArray[np.floating],
|
|
233
|
+
sd0: npt.NDArray[np.floating],
|
|
234
|
+
sdr: npt.NDArray[np.floating],
|
|
235
|
+
rsr: npt.NDArray[np.floating],
|
|
236
|
+
) -> npt.NDArray[np.floating]:
|
|
237
|
+
r"""
|
|
238
|
+
Calculate shortwave differential heating rate.
|
|
239
|
+
|
|
240
|
+
Incoming solar radiation heats the contrail top. Therefore, this output will
|
|
241
|
+
always be a positive value (i.e., warmer at the upper contrail edge and cooler
|
|
242
|
+
at the bottom). This effect is approximated using a parametric model
|
|
243
|
+
that is calibrated with the libRadtran radiative transfer model.
|
|
244
|
+
|
|
245
|
+
Parameters
|
|
246
|
+
----------
|
|
247
|
+
cp_contrail : npt.NDArray[np.floating]
|
|
248
|
+
Contrail heat capacity per unit length and width, [:math:`J K^{-1} m^{-2}`]
|
|
249
|
+
r_ice_vol_um : npt.NDArray[np.floating]
|
|
250
|
+
Ice particle volume mean radius, [:math:`\mu m`]
|
|
251
|
+
tau_contrail : npt.NDArray[np.floating]
|
|
252
|
+
Contrail optical depth for each waypoint
|
|
253
|
+
tau_cirrus : npt.NDArray[np.floating]
|
|
254
|
+
Optical depth of numerical weather prediction (NWP) cirrus above the contrail
|
|
255
|
+
sd0 : npt.NDArray[np.floating]
|
|
256
|
+
Solar constant, [:math:`W m^{-2}`]
|
|
257
|
+
sdr : npt.NDArray[np.floating]
|
|
258
|
+
Solar direct radiation, [:math:`W m^{-2}`]
|
|
259
|
+
rsr : npt.NDArray[np.floating]
|
|
260
|
+
Reflected solar radiation, [:math:`W m^{-2}`]
|
|
261
|
+
|
|
262
|
+
Returns
|
|
263
|
+
-------
|
|
264
|
+
npt.NDArray[np.floating]
|
|
265
|
+
Shortwave component of the differential heating rate, [:math:`K s^{-1}`]
|
|
266
|
+
"""
|
|
267
|
+
# short circuit if no waypoints have sdr > 0
|
|
268
|
+
if not np.any(sdr > 0):
|
|
269
|
+
return np.zeros_like(sdr)
|
|
270
|
+
|
|
271
|
+
mue = np.minimum(sdr / sd0, 1.0)
|
|
272
|
+
tau_eff = tau_contrail / (mue + 1.0e-6)
|
|
273
|
+
|
|
274
|
+
return (
|
|
275
|
+
(1 - np.exp(-RAD_HEAT.dqsw * r_ice_vol_um))
|
|
276
|
+
* (RAD_HEAT.dtt * sdr - RAD_HEAT.ddcth * rsr)
|
|
277
|
+
* tau_contrail
|
|
278
|
+
* (-RAD_HEAT.d_gamma_s * tau_contrail + tau_eff)
|
|
279
|
+
* (1 / cp_contrail)
|
|
280
|
+
* (1 - RAD_HEAT.dacth * mue + RAD_HEAT.d_gamma * mue**2 + (RAD_HEAT.dacth3 - 1) * mue**3)
|
|
281
|
+
* np.exp(RAD_HEAT.dbcth * tau_cirrus - RAD_HEAT.dccth * tau_cirrus / (mue + 1e-6))
|
|
282
|
+
* np.exp(-RAD_HEAT.dgalbs * tau_contrail * (1 - mue) ** RAD_HEAT.dexalb)
|
|
283
|
+
* mue**RAD_HEAT.draddsw
|
|
284
|
+
* (1 + RAD_HEAT.dfrsw * (1 - mue) ** 2)
|
|
285
|
+
)
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
def differential_heating_rate_longwave(
|
|
289
|
+
air_temperature: npt.NDArray[np.floating],
|
|
290
|
+
rhi: npt.NDArray[np.floating],
|
|
291
|
+
cp_contrail: npt.NDArray[np.floating],
|
|
292
|
+
r_ice_vol_um: npt.NDArray[np.floating],
|
|
293
|
+
tau_contrail: npt.NDArray[np.floating],
|
|
294
|
+
tau_cirrus: npt.NDArray[np.floating],
|
|
295
|
+
olr: npt.NDArray[np.floating],
|
|
296
|
+
) -> npt.NDArray[np.floating]:
|
|
297
|
+
r"""
|
|
298
|
+
Calculate longwave differential heating rate.
|
|
299
|
+
|
|
300
|
+
Contrails absorb outgoing longwave radiation emitted from the warm surface
|
|
301
|
+
below and heats it up. Therefore, this output will always be a negative value
|
|
302
|
+
(i.e., warmer at the lower contrail edge and cooler at the top). This effect
|
|
303
|
+
is approximated using a parametric model that is calibrated with the
|
|
304
|
+
libRadtran radiative transfer model.
|
|
305
|
+
|
|
306
|
+
Parameters
|
|
307
|
+
----------
|
|
308
|
+
air_temperature : npt.NDArray[np.floating]
|
|
309
|
+
Ambient temperature at each waypoint, [:math:`K`]
|
|
310
|
+
rhi : npt.NDArray[np.floating]
|
|
311
|
+
Relative humidity with respect to ice at each waypoint
|
|
312
|
+
cp_contrail : npt.NDArray[np.floating]
|
|
313
|
+
Contrail heat capacity per unit length and width, [:math:`J K^{-1} m^{-2}`]
|
|
314
|
+
r_ice_vol_um : npt.NDArray[np.floating]
|
|
315
|
+
Ice particle volume mean radius, [:math:`\mu m`]
|
|
316
|
+
tau_contrail : npt.NDArray[np.floating]
|
|
317
|
+
Contrail optical depth for each waypoint
|
|
318
|
+
tau_cirrus : npt.NDArray[np.floating]
|
|
319
|
+
Optical depth of numerical weather prediction (NWP) cirrus above the contrail
|
|
320
|
+
olr : npt.NDArray[np.floating]
|
|
321
|
+
Outgoing longwave radiation at each waypoint, [:math:`W m^{-2}`]
|
|
322
|
+
|
|
323
|
+
Returns
|
|
324
|
+
-------
|
|
325
|
+
npt.NDArray[np.floating]
|
|
326
|
+
Longwave component of the differential heating rate, [:math:`K s^{-1}`]
|
|
327
|
+
"""
|
|
328
|
+
cool = RAD_HEAT.dsigma * air_temperature**RAD_HEAT.dak
|
|
329
|
+
epsc = 1 - np.exp(-RAD_HEAT.ddelta * (tau_contrail + tau_cirrus))
|
|
330
|
+
return (
|
|
331
|
+
-RAD_HEAT.dfrlw
|
|
332
|
+
* (1 / cp_contrail)
|
|
333
|
+
* (olr - cool)
|
|
334
|
+
* (epsc / RAD_HEAT.ddelta)
|
|
335
|
+
* tau_contrail
|
|
336
|
+
* np.exp(-RAD_HEAT.dqlw * tau_cirrus)
|
|
337
|
+
* np.maximum(1 - RAD_HEAT.draddlw * 10 / (r_ice_vol_um + 30), 0.0)
|
|
338
|
+
* (1 - np.exp(-RAD_HEAT.dqrlw * r_ice_vol_um))
|
|
339
|
+
* np.exp(-(rhi - 0.9) * RAD_HEAT.dcrhi)
|
|
340
|
+
)
|
|
341
|
+
|
|
342
|
+
|
|
343
|
+
def heating_rate(
|
|
344
|
+
air_temperature: npt.NDArray[np.floating],
|
|
345
|
+
rhi: npt.NDArray[np.floating],
|
|
346
|
+
rho_air: npt.NDArray[np.floating],
|
|
347
|
+
r_ice_vol: npt.NDArray[np.floating],
|
|
348
|
+
depth_eff: npt.NDArray[np.floating],
|
|
349
|
+
tau_contrail: npt.NDArray[np.floating],
|
|
350
|
+
tau_cirrus: npt.NDArray[np.floating],
|
|
351
|
+
sd0: npt.NDArray[np.floating],
|
|
352
|
+
sdr: npt.NDArray[np.floating],
|
|
353
|
+
rsr: npt.NDArray[np.floating],
|
|
354
|
+
olr: npt.NDArray[np.floating],
|
|
355
|
+
) -> npt.NDArray[np.floating]:
|
|
356
|
+
"""
|
|
357
|
+
Calculate the heating rate affecting the contrail plume.
|
|
358
|
+
|
|
359
|
+
This is the average heating rate over the contrail cirrus layer.
|
|
360
|
+
|
|
361
|
+
Parameters
|
|
362
|
+
----------
|
|
363
|
+
air_temperature : npt.NDArray[np.floating]
|
|
364
|
+
Ambient temperature at each waypoint, [:math:`K`]
|
|
365
|
+
rhi : npt.NDArray[np.floating]
|
|
366
|
+
Relative humidity with respect to ice at each waypoint
|
|
367
|
+
rho_air : npt.NDArray[np.floating]
|
|
368
|
+
Density of air for each waypoint, [:math:`kg m^{-3}`]
|
|
369
|
+
r_ice_vol : npt.NDArray[np.floating]
|
|
370
|
+
Ice particle volume mean radius, [:math:`m`]
|
|
371
|
+
depth_eff : npt.NDArray[np.floating]
|
|
372
|
+
Effective depth of the contrail plume, [:math:`m`]
|
|
373
|
+
tau_contrail : npt.NDArray[np.floating]
|
|
374
|
+
Contrail optical depth for each waypoint
|
|
375
|
+
tau_cirrus : npt.NDArray[np.floating]
|
|
376
|
+
Optical depth of numerical weather prediction (NWP) cirrus above the contrail
|
|
377
|
+
sd0 : npt.NDArray[np.floating]
|
|
378
|
+
Solar constant, [:math:`W m^{-2}`]
|
|
379
|
+
sdr : npt.NDArray[np.floating]
|
|
380
|
+
Solar direct radiation, [:math:`W m^{-2}`]
|
|
381
|
+
rsr : npt.NDArray[np.floating]
|
|
382
|
+
Reflected solar radiation, [:math:`W m^{-2}`]
|
|
383
|
+
olr : npt.NDArray[np.floating]
|
|
384
|
+
Outgoing longwave radiation at each waypoint, [:math:`W m^{-2}`]
|
|
385
|
+
|
|
386
|
+
Returns
|
|
387
|
+
-------
|
|
388
|
+
npt.NDArray[np.floating]
|
|
389
|
+
Heating rate, [:math:`K s^{-1}`]
|
|
390
|
+
"""
|
|
391
|
+
r_ice_vol_um = r_ice_vol * 1e6
|
|
392
|
+
cp_contrail = contrail_heat_capacity(rho_air, depth_eff)
|
|
393
|
+
heat_rate_sw = heating_rate_shortwave(
|
|
394
|
+
cp_contrail, r_ice_vol_um, tau_contrail, tau_cirrus, sd0, sdr, rsr
|
|
395
|
+
)
|
|
396
|
+
heat_rate_lw = heating_rate_longwave(
|
|
397
|
+
air_temperature, rhi, cp_contrail, r_ice_vol_um, tau_contrail, tau_cirrus, olr
|
|
398
|
+
)
|
|
399
|
+
return heat_rate_sw + heat_rate_lw
|
|
400
|
+
|
|
401
|
+
|
|
402
|
+
def heating_rate_shortwave(
|
|
403
|
+
cp_contrail: npt.NDArray[np.floating],
|
|
404
|
+
r_ice_vol_um: npt.NDArray[np.floating],
|
|
405
|
+
tau_contrail: npt.NDArray[np.floating],
|
|
406
|
+
tau_cirrus: npt.NDArray[np.floating],
|
|
407
|
+
sd0: npt.NDArray[np.floating],
|
|
408
|
+
sdr: npt.NDArray[np.floating],
|
|
409
|
+
rsr: npt.NDArray[np.floating],
|
|
410
|
+
) -> npt.NDArray[np.floating]:
|
|
411
|
+
r"""Calculate shortwave heating rate.
|
|
412
|
+
|
|
413
|
+
Parameters
|
|
414
|
+
----------
|
|
415
|
+
cp_contrail : npt.NDArray[np.floating]
|
|
416
|
+
Contrail heat capacity per unit length and width, [:math:`J K^{-1} m^{-2}`]
|
|
417
|
+
r_ice_vol_um : npt.NDArray[np.floating]
|
|
418
|
+
Ice particle volume mean radius, [:math:`\mu m`]
|
|
419
|
+
tau_contrail : npt.NDArray[np.floating]
|
|
420
|
+
Contrail optical depth for each waypoint
|
|
421
|
+
tau_cirrus : npt.NDArray[np.floating]
|
|
422
|
+
Optical depth of numerical weather prediction (NWP) cirrus above the contrail
|
|
423
|
+
sd0 : npt.NDArray[np.floating]
|
|
424
|
+
Solar constant, [:math:`W m^{-2}`]
|
|
425
|
+
sdr : npt.NDArray[np.floating]
|
|
426
|
+
Solar direct radiation, [:math:`W m^{-2}`]
|
|
427
|
+
rsr : npt.NDArray[np.floating]
|
|
428
|
+
Reflected solar radiation, [:math:`W m^{-2}`]
|
|
429
|
+
|
|
430
|
+
Returns
|
|
431
|
+
-------
|
|
432
|
+
npt.NDArray[np.floating]
|
|
433
|
+
Shortwave component of heating rate, [:math:`K s^{-1}`]
|
|
434
|
+
"""
|
|
435
|
+
# short circuit if no waypoints have sdr > 0
|
|
436
|
+
if not np.any(sdr > 0):
|
|
437
|
+
return np.zeros_like(sdr)
|
|
438
|
+
|
|
439
|
+
mue = np.minimum(sdr / sd0, 1.0)
|
|
440
|
+
tau_eff = tau_contrail / (mue + 1.0e-6)
|
|
441
|
+
heat_rate_sw = (
|
|
442
|
+
(1 - np.exp(-RAD_HEAT.q_sw * r_ice_vol_um))
|
|
443
|
+
* (RAD_HEAT.ttt * sdr + RAD_HEAT.dcth * rsr)
|
|
444
|
+
* tau_eff
|
|
445
|
+
* (1 / cp_contrail)
|
|
446
|
+
* (1 - RAD_HEAT.acth * mue + RAD_HEAT.gamma_r * mue**2)
|
|
447
|
+
* np.exp(RAD_HEAT.bcth * tau_cirrus - RAD_HEAT.ccth * tau_cirrus / (mue + 1e-6))
|
|
448
|
+
* np.exp(-tau_contrail * (1 - mue) ** 2)
|
|
449
|
+
* mue
|
|
450
|
+
)
|
|
451
|
+
return np.maximum(heat_rate_sw, 0)
|
|
452
|
+
|
|
453
|
+
|
|
454
|
+
def heating_rate_longwave(
|
|
455
|
+
air_temperature: npt.NDArray[np.floating],
|
|
456
|
+
rhi: npt.NDArray[np.floating],
|
|
457
|
+
cp_contrail: npt.NDArray[np.floating],
|
|
458
|
+
r_ice_vol_um: npt.NDArray[np.floating],
|
|
459
|
+
tau_contrail: npt.NDArray[np.floating],
|
|
460
|
+
tau_cirrus: npt.NDArray[np.floating],
|
|
461
|
+
olr: npt.NDArray[np.floating],
|
|
462
|
+
) -> npt.NDArray[np.floating]:
|
|
463
|
+
r"""Calculate longwave heating rate.
|
|
464
|
+
|
|
465
|
+
Parameters
|
|
466
|
+
----------
|
|
467
|
+
air_temperature : npt.NDArray[np.floating]
|
|
468
|
+
Ambient temperature at each waypoint, [:math:`K`]
|
|
469
|
+
rhi : npt.NDArray[np.floating]
|
|
470
|
+
Relative humidity with respect to ice at each waypoint
|
|
471
|
+
cp_contrail : npt.NDArray[np.floating]
|
|
472
|
+
Contrail heat capacity per unit length and width, [:math:`J K^{-1} m^{-2}`]
|
|
473
|
+
r_ice_vol_um : npt.NDArray[np.floating]
|
|
474
|
+
Ice particle volume mean radius, [:math:`\mu m`]
|
|
475
|
+
tau_contrail : npt.NDArray[np.floating]
|
|
476
|
+
Contrail optical depth for each waypoint
|
|
477
|
+
tau_cirrus : npt.NDArray[np.floating]
|
|
478
|
+
Optical depth of numerical weather prediction (NWP) cirrus above the contrail
|
|
479
|
+
olr : npt.NDArray[np.floating]
|
|
480
|
+
Outgoing longwave radiation at each waypoint, [:math:`W m^{-2}`]
|
|
481
|
+
|
|
482
|
+
Returns
|
|
483
|
+
-------
|
|
484
|
+
npt.NDArray[np.floating]
|
|
485
|
+
Longwave component of heating rate, [:math:`K s^{-1}`]
|
|
486
|
+
"""
|
|
487
|
+
fzlw = np.exp(-(rhi - 0.9) * RAD_HEAT.czlw)
|
|
488
|
+
cool = RAD_HEAT.sigma * air_temperature**RAD_HEAT.ak
|
|
489
|
+
epsc = 1 - np.exp(-RAD_HEAT.delta * (tau_contrail + tau_cirrus))
|
|
490
|
+
heat_rate_lw = (
|
|
491
|
+
np.exp(-(rhi - 0.9) * RAD_HEAT.crhi)
|
|
492
|
+
* RAD_HEAT.fr_lw
|
|
493
|
+
* (1 / cp_contrail)
|
|
494
|
+
* (olr / fzlw - cool * fzlw)
|
|
495
|
+
* (epsc / RAD_HEAT.delta)
|
|
496
|
+
* np.exp(-RAD_HEAT.q_lw * tau_cirrus)
|
|
497
|
+
* (1 + RAD_HEAT.radd_lw / (r_ice_vol_um + 30))
|
|
498
|
+
)
|
|
499
|
+
return np.maximum(heat_rate_lw, 0)
|
|
500
|
+
|
|
501
|
+
|
|
502
|
+
def contrail_heat_capacity(
|
|
503
|
+
rho_air: npt.NDArray[np.floating], depth_eff: npt.NDArray[np.floating]
|
|
504
|
+
) -> npt.NDArray[np.floating]:
|
|
505
|
+
"""
|
|
506
|
+
Calculate contrail heat capacity per unit length and width.
|
|
507
|
+
|
|
508
|
+
Parameters
|
|
509
|
+
----------
|
|
510
|
+
rho_air : npt.NDArray[np.floating]
|
|
511
|
+
density of air for each waypoint, [:math:`kg m^{-3}`]
|
|
512
|
+
depth_eff: npt.NDArray[np.floating]
|
|
513
|
+
Effective depth of the contrail plume, [:math:`m`]
|
|
514
|
+
|
|
515
|
+
Returns
|
|
516
|
+
-------
|
|
517
|
+
npt.NDArray[np.floating]
|
|
518
|
+
Contrail heat capacity per unit length and width, [:math:`J K^{-1} m^{-2}`]
|
|
519
|
+
"""
|
|
520
|
+
return depth_eff * rho_air * constants.c_pd
|