pycontrails 0.54.11__cp310-cp310-win_amd64.whl → 0.55.0__cp310-cp310-win_amd64.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/_version.py +16 -3
- pycontrails/core/rgi_cython.cp310-win_amd64.pyd +0 -0
- pycontrails/datalib/ecmwf/hres.py +1 -0
- pycontrails/datalib/goes.py +3 -3
- pycontrails/models/cocip/cocip.py +30 -13
- pycontrails/models/cocip/cocip_params.py +9 -3
- pycontrails/models/cocip/cocip_uncertainty.py +4 -4
- pycontrails/models/cocip/contrail_properties.py +27 -27
- pycontrails/models/cocip/radiative_forcing.py +4 -4
- pycontrails/models/cocip/unterstrasser_wake_vortex.py +5 -5
- pycontrails/models/cocip/wake_vortex.py +6 -6
- pycontrails/models/cocipgrid/cocip_grid.py +60 -32
- pycontrails/models/dry_advection.py +2 -2
- pycontrails/models/extended_k15.py +1327 -0
- pycontrails/models/issr.py +1 -1
- pycontrails/models/pcr.py +1 -1
- pycontrails/models/sac.py +5 -22
- pycontrails/physics/constants.py +1 -1
- pycontrails/physics/geo.py +3 -3
- pycontrails/physics/thermo.py +121 -21
- pycontrails/utils/types.py +3 -10
- {pycontrails-0.54.11.dist-info → pycontrails-0.55.0.dist-info}/METADATA +1 -1
- {pycontrails-0.54.11.dist-info → pycontrails-0.55.0.dist-info}/RECORD +27 -26
- {pycontrails-0.54.11.dist-info → pycontrails-0.55.0.dist-info}/WHEEL +0 -0
- {pycontrails-0.54.11.dist-info → pycontrails-0.55.0.dist-info}/licenses/LICENSE +0 -0
- {pycontrails-0.54.11.dist-info → pycontrails-0.55.0.dist-info}/licenses/NOTICE +0 -0
- {pycontrails-0.54.11.dist-info → pycontrails-0.55.0.dist-info}/top_level.txt +0 -0
pycontrails/_version.py
CHANGED
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
# file generated by setuptools-scm
|
|
2
2
|
# don't change, don't track in version control
|
|
3
3
|
|
|
4
|
-
__all__ = [
|
|
4
|
+
__all__ = [
|
|
5
|
+
"__version__",
|
|
6
|
+
"__version_tuple__",
|
|
7
|
+
"version",
|
|
8
|
+
"version_tuple",
|
|
9
|
+
"__commit_id__",
|
|
10
|
+
"commit_id",
|
|
11
|
+
]
|
|
5
12
|
|
|
6
13
|
TYPE_CHECKING = False
|
|
7
14
|
if TYPE_CHECKING:
|
|
@@ -9,13 +16,19 @@ if TYPE_CHECKING:
|
|
|
9
16
|
from typing import Union
|
|
10
17
|
|
|
11
18
|
VERSION_TUPLE = Tuple[Union[int, str], ...]
|
|
19
|
+
COMMIT_ID = Union[str, None]
|
|
12
20
|
else:
|
|
13
21
|
VERSION_TUPLE = object
|
|
22
|
+
COMMIT_ID = object
|
|
14
23
|
|
|
15
24
|
version: str
|
|
16
25
|
__version__: str
|
|
17
26
|
__version_tuple__: VERSION_TUPLE
|
|
18
27
|
version_tuple: VERSION_TUPLE
|
|
28
|
+
commit_id: COMMIT_ID
|
|
29
|
+
__commit_id__: COMMIT_ID
|
|
19
30
|
|
|
20
|
-
__version__ = version = '0.
|
|
21
|
-
__version_tuple__ = version_tuple = (0,
|
|
31
|
+
__version__ = version = '0.55.0'
|
|
32
|
+
__version_tuple__ = version_tuple = (0, 55, 0)
|
|
33
|
+
|
|
34
|
+
__commit_id__ = commit_id = 'g113bce45e'
|
|
Binary file
|
|
@@ -155,6 +155,7 @@ class HRES(ECMWFAPI):
|
|
|
155
155
|
- "scda" = short cut-off high resolution forecast, atmospheric fields,
|
|
156
156
|
run at hours 06Z and 18Z
|
|
157
157
|
- "enfo" = ensemble forecast, atmospheric fields, run at hours 00Z, 06Z, 12Z, and 18Z
|
|
158
|
+
|
|
158
159
|
Defaults to "oper" (HRES).
|
|
159
160
|
If the stream is incompatible with a provided forecast_time, a ``ValueError`` is raised.
|
|
160
161
|
See the `ECMWF documentation <https://confluence.ecmwf.int/display/DAC/ECMWF+open+data%3A+real-time+forecasts+from+IFS+and+AIFS>`_
|
pycontrails/datalib/goes.py
CHANGED
|
@@ -593,10 +593,10 @@ class GOES:
|
|
|
593
593
|
da = da_dict.popitem()[1]
|
|
594
594
|
elif "C02" in da_dict:
|
|
595
595
|
da2 = da_dict.pop("C02")
|
|
596
|
-
|
|
597
|
-
da = _concat_c02(
|
|
596
|
+
da = xr.concat(da_dict.values(), dim="band_id", coords="different", compat="equals")
|
|
597
|
+
da = _concat_c02(da, da2)
|
|
598
598
|
else:
|
|
599
|
-
da = xr.concat(da_dict.values(), dim="band_id")
|
|
599
|
+
da = xr.concat(da_dict.values(), dim="band_id", coords="different", compat="equals")
|
|
600
600
|
|
|
601
601
|
else:
|
|
602
602
|
ds = _load_via_tempfile(data)
|
|
@@ -27,7 +27,7 @@ from pycontrails.core.met_var import MetVariable
|
|
|
27
27
|
from pycontrails.core.models import Model, interpolate_met
|
|
28
28
|
from pycontrails.core.vector import GeoVectorDataset, VectorDataDict
|
|
29
29
|
from pycontrails.datalib import ecmwf, gfs
|
|
30
|
-
from pycontrails.models import sac, tau_cirrus
|
|
30
|
+
from pycontrails.models import extended_k15, sac, tau_cirrus
|
|
31
31
|
from pycontrails.models.cocip import (
|
|
32
32
|
contrail_properties,
|
|
33
33
|
radiative_forcing,
|
|
@@ -58,7 +58,7 @@ class Cocip(Model):
|
|
|
58
58
|
rad : MetDataset
|
|
59
59
|
Single level dataset containing top of atmosphere radiation fluxes.
|
|
60
60
|
See *Notes* for variable names by data source.
|
|
61
|
-
params : dict[str, Any], optional
|
|
61
|
+
params : dict[str, Any] | None, optional
|
|
62
62
|
Override Cocip model parameters with dictionary.
|
|
63
63
|
See :class:`CocipFlightParams` for model parameters.
|
|
64
64
|
**params_kwargs : Any
|
|
@@ -411,7 +411,7 @@ class Cocip(Model):
|
|
|
411
411
|
|
|
412
412
|
Returns
|
|
413
413
|
-------
|
|
414
|
-
Flight | list[Flight]
|
|
414
|
+
Flight | list[Flight]
|
|
415
415
|
Flight(s) with updated Contrail data. The model parameter "verbose_outputs"
|
|
416
416
|
determines the variables on the return flight object.
|
|
417
417
|
|
|
@@ -489,7 +489,7 @@ class Cocip(Model):
|
|
|
489
489
|
|
|
490
490
|
Returns
|
|
491
491
|
-------
|
|
492
|
-
tuple[MetVariable]
|
|
492
|
+
tuple[MetVariable, ...]
|
|
493
493
|
List of model-agnostic variants of required variables
|
|
494
494
|
"""
|
|
495
495
|
available = set(met_var.MET_VARIABLES)
|
|
@@ -501,7 +501,7 @@ class Cocip(Model):
|
|
|
501
501
|
|
|
502
502
|
Returns
|
|
503
503
|
-------
|
|
504
|
-
tuple[MetVariable]
|
|
504
|
+
tuple[MetVariable, ...]
|
|
505
505
|
List of ECMWF-specific variants of required variables
|
|
506
506
|
"""
|
|
507
507
|
available = set(ecmwf.ECMWF_VARIABLES)
|
|
@@ -513,7 +513,7 @@ class Cocip(Model):
|
|
|
513
513
|
|
|
514
514
|
Returns
|
|
515
515
|
-------
|
|
516
|
-
tuple[MetVariable]
|
|
516
|
+
tuple[MetVariable, ...]
|
|
517
517
|
List of GFS-specific variants of required variables
|
|
518
518
|
"""
|
|
519
519
|
available = set(gfs.GFS_VARIABLES)
|
|
@@ -981,6 +981,30 @@ class Cocip(Model):
|
|
|
981
981
|
)
|
|
982
982
|
iwc_1 = contrail_properties.iwc_post_wake_vortex(iwc, iwc_ad)
|
|
983
983
|
|
|
984
|
+
if self.params["vpm_activation"]:
|
|
985
|
+
# We can add a Cocip parameter for T_exhaust, vpm_ei_n, and particles
|
|
986
|
+
aei = extended_k15.droplet_apparent_emission_index(
|
|
987
|
+
specific_humidity=specific_humidity,
|
|
988
|
+
T_ambient=air_temperature,
|
|
989
|
+
T_exhaust=self.source.attrs.get("T_exhaust", extended_k15.DEFAULT_EXHAUST_T),
|
|
990
|
+
air_pressure=air_pressure,
|
|
991
|
+
nvpm_ei_n=nvpm_ei_n,
|
|
992
|
+
vpm_ei_n=self.source.attrs.get("vpm_ei_n", extended_k15.DEFAULT_VPM_EI_N),
|
|
993
|
+
G=self._sac_flight["G"],
|
|
994
|
+
)
|
|
995
|
+
min_aei = None # don't clip
|
|
996
|
+
|
|
997
|
+
else:
|
|
998
|
+
f_activation = contrail_properties.ice_particle_activation_rate(
|
|
999
|
+
air_temperature, T_critical_sac
|
|
1000
|
+
)
|
|
1001
|
+
aei = nvpm_ei_n * f_activation
|
|
1002
|
+
min_aei = self.params["min_ice_particle_number_nvpm_ei_n"]
|
|
1003
|
+
|
|
1004
|
+
n_ice_per_m_0 = contrail_properties.initial_ice_particle_number(
|
|
1005
|
+
aei=aei, fuel_dist=fuel_dist, min_aei=min_aei
|
|
1006
|
+
)
|
|
1007
|
+
|
|
984
1008
|
if self.params["unterstrasser_ice_survival_fraction"]:
|
|
985
1009
|
wingspan = self._sac_flight.get_data_or_attr("wingspan")
|
|
986
1010
|
rhi_0 = thermo.rhi(specific_humidity, air_temperature, air_pressure)
|
|
@@ -997,13 +1021,6 @@ class Cocip(Model):
|
|
|
997
1021
|
else:
|
|
998
1022
|
f_surv = contrail_properties.ice_particle_survival_fraction(iwc, iwc_1)
|
|
999
1023
|
|
|
1000
|
-
n_ice_per_m_0 = contrail_properties.initial_ice_particle_number(
|
|
1001
|
-
nvpm_ei_n=nvpm_ei_n,
|
|
1002
|
-
fuel_dist=fuel_dist,
|
|
1003
|
-
air_temperature=air_temperature,
|
|
1004
|
-
T_crit_sac=T_critical_sac,
|
|
1005
|
-
min_ice_particle_number_nvpm_ei_n=self.params["min_ice_particle_number_nvpm_ei_n"],
|
|
1006
|
-
)
|
|
1007
1024
|
n_ice_per_m_1 = n_ice_per_m_0 * f_surv
|
|
1008
1025
|
|
|
1009
1026
|
# Check for persistent initial_contrails
|
|
@@ -195,8 +195,8 @@ class CocipParams(AdvectionBuffers):
|
|
|
195
195
|
nvpm_ei_n_enhancement_factor: float = 1.0
|
|
196
196
|
|
|
197
197
|
#: Lower bound for ``nvpm_ei_n`` to account for ambient aerosol
|
|
198
|
-
#: particles for newer engines, [:math:`kg^{-1}`]
|
|
199
|
-
min_ice_particle_number_nvpm_ei_n: float = 1e13
|
|
198
|
+
#: particles for newer engines, [:math:`kg^{-1}`]. Set to None to disable.
|
|
199
|
+
min_ice_particle_number_nvpm_ei_n: float | None = 1e13
|
|
200
200
|
|
|
201
201
|
#: Upper bound for contrail plume depth, constraining it to realistic values.
|
|
202
202
|
#: CoCiP only uses the ambient conditions at the mid-point of the Gaussian plume,
|
|
@@ -223,11 +223,17 @@ class CocipParams(AdvectionBuffers):
|
|
|
223
223
|
#: .. versionadded:: 0.28.9
|
|
224
224
|
radiative_heating_effects: bool = False
|
|
225
225
|
|
|
226
|
+
#: Experimental. Apply the extended K15 model to account for vPM activation.
|
|
227
|
+
#: See the preprint `<https://doi.org/10.5194/egusphere-2025-1717>`_ for details.
|
|
228
|
+
#:
|
|
229
|
+
#: .. versionadded:: 0.55.0
|
|
230
|
+
vpm_activation: bool = False
|
|
231
|
+
|
|
226
232
|
#: Experimental. Radiative effects due to contrail-contrail overlapping
|
|
227
233
|
#: Account for change in local contrail shortwave and longwave radiative forcing
|
|
228
234
|
#: due to contrail-contrail overlapping.
|
|
229
235
|
#:
|
|
230
|
-
#: .. versionadded:: 0.45
|
|
236
|
+
#: .. versionadded:: 0.45.0
|
|
231
237
|
contrail_contrail_overlapping: bool = False
|
|
232
238
|
|
|
233
239
|
#: Experimental. Contrail-contrail overlapping altitude interval
|
|
@@ -40,9 +40,9 @@ class habit_dirichlet(rv_frozen):
|
|
|
40
40
|
|
|
41
41
|
Parameters
|
|
42
42
|
----------
|
|
43
|
-
*args
|
|
43
|
+
*args : Any
|
|
44
44
|
Used to create a number of habit distributions
|
|
45
|
-
**kwds
|
|
45
|
+
**kwds : Any
|
|
46
46
|
Passed through to :func:`scipy.stats.dirichlet.rvs()`
|
|
47
47
|
|
|
48
48
|
Returns
|
|
@@ -190,7 +190,7 @@ class CocipUncertaintyParams(CocipParams):
|
|
|
190
190
|
|
|
191
191
|
Returns
|
|
192
192
|
-------
|
|
193
|
-
dict[str,
|
|
193
|
+
dict[str, rv_frozen]
|
|
194
194
|
Uncertainty parameters and values
|
|
195
195
|
"""
|
|
196
196
|
# handle these differently starting in version 0.27.0
|
|
@@ -230,7 +230,7 @@ class CocipUncertaintyParams(CocipParams):
|
|
|
230
230
|
|
|
231
231
|
Returns
|
|
232
232
|
-------
|
|
233
|
-
dict[str,
|
|
233
|
+
dict[str, np.float64 | npt.NDArray[np.floating]]
|
|
234
234
|
Dictionary of random parameters. Dictionary keys consists of names of parameters in
|
|
235
235
|
`CocipParams` to be overridden by random value.
|
|
236
236
|
|
|
@@ -202,32 +202,32 @@ def iwc_post_wake_vortex(
|
|
|
202
202
|
|
|
203
203
|
|
|
204
204
|
def initial_ice_particle_number(
|
|
205
|
-
|
|
205
|
+
aei: npt.NDArray[np.floating],
|
|
206
206
|
fuel_dist: npt.NDArray[np.floating],
|
|
207
|
-
|
|
208
|
-
T_crit_sac: npt.NDArray[np.floating],
|
|
209
|
-
min_ice_particle_number_nvpm_ei_n: float,
|
|
207
|
+
min_aei: float | None,
|
|
210
208
|
) -> npt.NDArray[np.floating]:
|
|
211
209
|
"""Calculate the initial number of ice particles per distance after the wake vortex phase.
|
|
212
210
|
|
|
213
|
-
The initial number of ice particle per distance is calculated from the
|
|
214
|
-
|
|
215
|
-
Note that a lower bound for ``
|
|
211
|
+
The initial number of ice particle per distance is calculated from the activated apparent
|
|
212
|
+
emissions index ``aei`` and fuel burn per distance ``fuel_dist``.
|
|
213
|
+
Note that a lower bound for ``aei`` is set at ``1e13`` :math:`kg^{-1}` to account
|
|
216
214
|
for the activation of ambient aerosol particles and organic volatile particles.
|
|
217
215
|
|
|
216
|
+
.. versionchanged:: 0.55
|
|
217
|
+
|
|
218
|
+
The signature of this function has changed. The parameter ``aei`` is now
|
|
219
|
+
expected to be the previous ``npvm_ei_n`` multiplied by the activation
|
|
220
|
+
fraction ``f_activation``.
|
|
221
|
+
|
|
218
222
|
Parameters
|
|
219
223
|
----------
|
|
220
|
-
|
|
221
|
-
|
|
224
|
+
aei : npt.NDArray[np.floating]
|
|
225
|
+
Apparent contrail emissions index, [:math:`kg^{-1}`]
|
|
222
226
|
fuel_dist : npt.NDArray[np.floating]
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
estimated Schmidt-Appleman temperature threshold for contrail formation, [:math:`K`]
|
|
228
|
-
min_ice_particle_number_nvpm_ei_n : float
|
|
229
|
-
lower bound for nvpm_ei_n to account for ambient aerosol particles for
|
|
230
|
-
newer engines [:math:`kg^{-1}`]
|
|
227
|
+
Fuel consumption of the flight segment per distance traveled, [:math:`kg m^{-1}`]
|
|
228
|
+
min_aei : float | None
|
|
229
|
+
Lower bound for ``aei`` to account for ambient aerosol particles for
|
|
230
|
+
newer engines [:math:`kg^{-1}`]. If None, no clipping is applied.
|
|
231
231
|
|
|
232
232
|
Returns
|
|
233
233
|
-------
|
|
@@ -235,9 +235,9 @@ def initial_ice_particle_number(
|
|
|
235
235
|
The initial number of ice particles per distance before the wake vortex
|
|
236
236
|
phase, [:math:`# m^{-1}`]
|
|
237
237
|
"""
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
return fuel_dist *
|
|
238
|
+
if min_aei is not None:
|
|
239
|
+
aei = np.clip(aei, min=min_aei) # type: ignore[arg-type,call-overload]
|
|
240
|
+
return fuel_dist * aei
|
|
241
241
|
|
|
242
242
|
|
|
243
243
|
def ice_particle_activation_rate(
|
|
@@ -462,9 +462,9 @@ def _within_range(
|
|
|
462
462
|
----------
|
|
463
463
|
val : np.ndarray
|
|
464
464
|
value of selected contrail property
|
|
465
|
-
max :
|
|
465
|
+
max : float | np.timedelta64 | None, optional
|
|
466
466
|
Upper bound. If None, no upper bound is imposed. None by default.
|
|
467
|
-
min :
|
|
467
|
+
min : float | np.timedelta64 | None, optional
|
|
468
468
|
Lower bound. If None, no lower bound is imposed. None by default.
|
|
469
469
|
|
|
470
470
|
Returns
|
|
@@ -585,9 +585,9 @@ def contrail_vertices(
|
|
|
585
585
|
|
|
586
586
|
Returns
|
|
587
587
|
-------
|
|
588
|
-
tuple
|
|
588
|
+
tuple
|
|
589
589
|
(lon_1, lat_1, lon_2, lat_2, lon_3, lat_3, lon_4, lat_4) degrees
|
|
590
|
-
"""
|
|
590
|
+
"""
|
|
591
591
|
dlon_width = units.m_to_longitude_distance(width * sin_a * 0.5, lat)
|
|
592
592
|
dlat_width = units.m_to_latitude_distance(width * cos_a * 0.5)
|
|
593
593
|
|
|
@@ -888,9 +888,9 @@ def vertical_diffusivity(
|
|
|
888
888
|
Temperature gradient with respect to altitude (dz), [:math:`K m^{-1}`]
|
|
889
889
|
depth_eff : npt.NDArray[np.floating]
|
|
890
890
|
Effective depth of the contrail plume, [:math:`m`]
|
|
891
|
-
terminal_fall_speed : npt.NDArray[np.floating]
|
|
891
|
+
terminal_fall_speed : npt.NDArray[np.floating] | float
|
|
892
892
|
Terminal fall speed of contrail ice particles, [:math:`m s^{-1}`]
|
|
893
|
-
sedimentation_impact_factor : float
|
|
893
|
+
sedimentation_impact_factor : npt.NDArray[np.floating] | float
|
|
894
894
|
Enhancement parameter denoted by `f_T` in eq. (35) Schumann (2012).
|
|
895
895
|
eff_heat_rate: npt.NDArray[np.floating] | None
|
|
896
896
|
Effective heating rate, i.e., rate of which the contrail plume
|
|
@@ -1506,7 +1506,7 @@ def mean_energy_flux_per_m(
|
|
|
1506
1506
|
rad_flux_per_m : npt.NDArray[np.floating]
|
|
1507
1507
|
Mean radiative flux between time steps for waypoint, [:math:`W m^{-1}`].
|
|
1508
1508
|
See :func:`mean_radiative_flux_per_m`.
|
|
1509
|
-
dt : npt.NDArray[np.timedelta64]
|
|
1509
|
+
dt : npt.NDArray[np.timedelta64] | np.timedelta64
|
|
1510
1510
|
timedelta of integration timestep for each waypoint.
|
|
1511
1511
|
|
|
1512
1512
|
Returns
|
|
@@ -241,7 +241,7 @@ def habit_weight_regime_idx(
|
|
|
241
241
|
|
|
242
242
|
def effective_radius_by_habit(
|
|
243
243
|
r_vol_um: npt.NDArray[np.floating], habit_idx: npt.NDArray[np.intp]
|
|
244
|
-
) -> np.
|
|
244
|
+
) -> npt.NDArray[np.floating]:
|
|
245
245
|
r"""Calculate the effective radius ``r_eff_um`` via the mean ice particle radius and habit type.
|
|
246
246
|
|
|
247
247
|
The ``habit_idx`` corresponds to the habit types in ``rf_const.habits``.
|
|
@@ -479,7 +479,7 @@ def longwave_radiative_forcing(
|
|
|
479
479
|
habit_weights_ : npt.NDArray[np.floating]
|
|
480
480
|
Weights to different ice particle habits for each waypoint,
|
|
481
481
|
``n_waypoints x 8`` (habit) columns, [:math:`[0 - 1]`]
|
|
482
|
-
r_eff_um : npt.NDArray[np.floating], optional
|
|
482
|
+
r_eff_um : npt.NDArray[np.floating] | None, optional
|
|
483
483
|
Provide effective radius corresponding to elements in ``r_vol_um``, [:math:`\mu m`].
|
|
484
484
|
Defaults to None, which means the effective radius will be calculated using ``r_vol_um``
|
|
485
485
|
and habit types in :func:`effective_radius_by_habit`.
|
|
@@ -583,7 +583,7 @@ def shortwave_radiative_forcing(
|
|
|
583
583
|
habit_weights_ : npt.NDArray[np.floating]
|
|
584
584
|
Weights to different ice particle habits for each waypoint,
|
|
585
585
|
``n_waypoints x 8`` (habit) columns, [:math:`[0 - 1]`]
|
|
586
|
-
r_eff_um : npt.NDArray[np.floating], optional
|
|
586
|
+
r_eff_um : npt.NDArray[np.floating] | None, optional
|
|
587
587
|
Provide effective radius corresponding to elements in ``r_vol_um``, [:math:`\mu m`].
|
|
588
588
|
Defaults to None, which means the effective radius will be calculated using ``r_vol_um``
|
|
589
589
|
and habit types in :func:`effective_radius_by_habit`.
|
|
@@ -923,7 +923,7 @@ def contrail_contrail_overlap_radiative_effects(
|
|
|
923
923
|
min_altitude_m : float
|
|
924
924
|
Minimum altitude domain in simulation, [:math:`m`]
|
|
925
925
|
See :attr:`CocipParams.min_altitude_m`
|
|
926
|
-
max_altitude_m
|
|
926
|
+
max_altitude_m : float
|
|
927
927
|
Maximum altitude domain in simulation, [:math:`m`]
|
|
928
928
|
See :attr:`CocipParams.min_altitude_m`
|
|
929
929
|
dz_overlap_m : float
|
|
@@ -284,7 +284,7 @@ def z_emit_length_scale_analytical(
|
|
|
284
284
|
|
|
285
285
|
Parameters
|
|
286
286
|
----------
|
|
287
|
-
rho_emit : npt.NDArray[np.floating]
|
|
287
|
+
rho_emit : npt.NDArray[np.floating]
|
|
288
288
|
Aircraft-emitted water vapour concentration in the plume, [:math:`kg m^{-3}`]
|
|
289
289
|
air_temperature : npt.NDArray[np.floating]
|
|
290
290
|
ambient temperature for each waypoint, [:math:`K`]
|
|
@@ -317,7 +317,7 @@ def z_emit_length_scale_numerical(
|
|
|
317
317
|
|
|
318
318
|
Parameters
|
|
319
319
|
----------
|
|
320
|
-
rho_emit : npt.NDArray[np.floating]
|
|
320
|
+
rho_emit : npt.NDArray[np.floating]
|
|
321
321
|
Aircraft-emitted water vapour concentration in the plume, [:math:`kg m^{-3}`]
|
|
322
322
|
air_temperature : npt.NDArray[np.floating]
|
|
323
323
|
ambient temperature for each waypoint, [:math:`K`]
|
|
@@ -365,7 +365,7 @@ def plume_area(wingspan: npt.NDArray[np.floating] | float) -> npt.NDArray[np.flo
|
|
|
365
365
|
|
|
366
366
|
Returns
|
|
367
367
|
-------
|
|
368
|
-
float
|
|
368
|
+
npt.NDArray[np.floating] | float
|
|
369
369
|
Area of two wake-vortex plumes, [:math:`m^{2}`]
|
|
370
370
|
|
|
371
371
|
Notes
|
|
@@ -396,7 +396,7 @@ def z_desc_length_scale(
|
|
|
396
396
|
pressure altitude at each waypoint, [:math:`Pa`]
|
|
397
397
|
true_airspeed : npt.NDArray[np.floating]
|
|
398
398
|
true airspeed for each waypoint, [:math:`m s^{-1}`]
|
|
399
|
-
aircraft_mass : npt.NDArray[np.floating]
|
|
399
|
+
aircraft_mass : npt.NDArray[np.floating]
|
|
400
400
|
aircraft mass for each waypoint, [:math:`kg`]
|
|
401
401
|
dT_dz : npt.NDArray[np.floating]
|
|
402
402
|
potential temperature gradient, [:math:`K m^{-1}`]
|
|
@@ -436,7 +436,7 @@ def _initial_wake_vortex_circulation(
|
|
|
436
436
|
pressure altitude at each waypoint, [:math:`Pa`]
|
|
437
437
|
true_airspeed : npt.NDArray[np.floating]
|
|
438
438
|
true airspeed for each waypoint, [:math:`m s^{-1}`]
|
|
439
|
-
aircraft_mass : npt.NDArray[np.floating]
|
|
439
|
+
aircraft_mass : npt.NDArray[np.floating]
|
|
440
440
|
aircraft mass for each waypoint, [:math:`kg`]
|
|
441
441
|
|
|
442
442
|
Returns
|
|
@@ -39,7 +39,7 @@ def max_downward_displacement(
|
|
|
39
39
|
ds_dz: npt.NDArray[np.floating],
|
|
40
40
|
air_pressure: npt.NDArray[np.floating],
|
|
41
41
|
effective_vertical_resolution: float,
|
|
42
|
-
wind_shear_enhancement_exponent:
|
|
42
|
+
wind_shear_enhancement_exponent: npt.NDArray[np.floating] | float,
|
|
43
43
|
) -> npt.NDArray[np.floating]:
|
|
44
44
|
"""
|
|
45
45
|
Calculate the maximum contrail downward displacement after the wake vortex phase.
|
|
@@ -117,11 +117,11 @@ def effective_time_scale(
|
|
|
117
117
|
|
|
118
118
|
Parameters
|
|
119
119
|
----------
|
|
120
|
-
wingspan : npt.NDArray[np.floating]
|
|
120
|
+
wingspan : npt.NDArray[np.floating] | float
|
|
121
121
|
aircraft wingspan, [:math:`m`]
|
|
122
122
|
true_airspeed : npt.NDArray[np.floating]
|
|
123
123
|
true airspeed for each waypoint, [:math:`m \ s^{-1}`]
|
|
124
|
-
aircraft_mass : npt.NDArray[np.floating]
|
|
124
|
+
aircraft_mass : npt.NDArray[np.floating] | float
|
|
125
125
|
aircraft mass for each waypoint, [:math:`kg`]
|
|
126
126
|
rho_air : npt.NDArray[np.floating]
|
|
127
127
|
density of air for each waypoint, [:math:`kg \ m^{-3}`]
|
|
@@ -260,7 +260,7 @@ def wake_vortex_separation(
|
|
|
260
260
|
|
|
261
261
|
Returns
|
|
262
262
|
-------
|
|
263
|
-
npt.NDArray[np.floating]
|
|
263
|
+
npt.NDArray[np.floating] | float
|
|
264
264
|
wake vortex separation, [:math:`m`]
|
|
265
265
|
"""
|
|
266
266
|
return (np.pi * wingspan) / 4.0
|
|
@@ -320,9 +320,9 @@ def normalized_dissipation_rate(
|
|
|
320
320
|
aircraft wingspan, [:math:`m`]
|
|
321
321
|
true_airspeed : npt.NDArray[np.floating]
|
|
322
322
|
true airspeed for each waypoint, [:math:`m s^{-1}`]
|
|
323
|
-
aircraft_mass : npt.NDArray[np.floating]
|
|
323
|
+
aircraft_mass : npt.NDArray[np.floating] | float
|
|
324
324
|
aircraft mass for each waypoint, [:math:`kg`]
|
|
325
|
-
rho_air : npt.NDArray[np.floating]
|
|
325
|
+
rho_air : npt.NDArray[np.floating] | float
|
|
326
326
|
density of air for each waypoint, [:math:`kg m^{-3}`]
|
|
327
327
|
|
|
328
328
|
Returns
|
|
@@ -16,7 +16,7 @@ import pycontrails
|
|
|
16
16
|
from pycontrails.core import models
|
|
17
17
|
from pycontrails.core.met import MetDataset, maybe_downselect_mds
|
|
18
18
|
from pycontrails.core.vector import GeoVectorDataset, VectorDataset
|
|
19
|
-
from pycontrails.models import humidity_scaling, sac
|
|
19
|
+
from pycontrails.models import extended_k15, humidity_scaling, sac
|
|
20
20
|
from pycontrails.models.cocip import cocip, contrail_properties, wake_vortex, wind_shear
|
|
21
21
|
from pycontrails.models.cocipgrid.cocip_grid_params import CocipGridParams
|
|
22
22
|
from pycontrails.models.emissions import Emissions
|
|
@@ -36,13 +36,15 @@ class CocipGrid(models.Model):
|
|
|
36
36
|
|
|
37
37
|
Parameters
|
|
38
38
|
----------
|
|
39
|
-
met
|
|
39
|
+
met : MetDataset
|
|
40
40
|
CoCiP-specific met data to interpolate against
|
|
41
|
-
|
|
41
|
+
rad : MetDataset
|
|
42
|
+
CoCiP-specific radiation data to interpolate against
|
|
43
|
+
params : dict[str, Any] | None, optional
|
|
42
44
|
Override :class:`CocipGridParams` defaults. Most notably, the model is highly
|
|
43
45
|
dependent on the parameter ``dt_integration``. Memory usage is also affected by
|
|
44
46
|
parameters ``met_slice_dt`` and ``target_split_size``.
|
|
45
|
-
|
|
47
|
+
**params_kwargs : Any
|
|
46
48
|
Override CocipGridParams defaults with arbitrary keyword arguments.
|
|
47
49
|
|
|
48
50
|
Notes
|
|
@@ -126,10 +128,7 @@ class CocipGrid(models.Model):
|
|
|
126
128
|
raise NotImplementedError(msg)
|
|
127
129
|
|
|
128
130
|
if self.params["unterstrasser_ice_survival_fraction"]:
|
|
129
|
-
msg =
|
|
130
|
-
"Parameter 'unterstrasser_ice_survival_fraction' is not "
|
|
131
|
-
"yet implemented in CocipGrid"
|
|
132
|
-
)
|
|
131
|
+
msg = "Parameter 'unterstrasser_ice_survival_fraction' is not implemented in CocipGrid"
|
|
133
132
|
raise NotImplementedError(msg)
|
|
134
133
|
|
|
135
134
|
self._target_dtype = np.result_type(*self.met.data.values())
|
|
@@ -767,20 +766,26 @@ class CocipGrid(models.Model):
|
|
|
767
766
|
|
|
768
767
|
Parameters
|
|
769
768
|
----------
|
|
770
|
-
level :
|
|
769
|
+
level : npt.NDArray[np.floating] | list[float] | float
|
|
771
770
|
Pressure levels for gridded cocip.
|
|
772
771
|
To avoid interpolating outside of the passed ``met`` and ``rad`` data, this
|
|
773
772
|
parameter should avoid the extreme values of the ``met`` and `rad` levels.
|
|
774
773
|
If ``met`` is already defined, a good choice for ``level`` is
|
|
775
774
|
``met.data['level'].values[1: -1]``.
|
|
776
|
-
time: npt.NDArray[np.datetime64 | list[np.datetime64] | np.datetime64
|
|
775
|
+
time : npt.NDArray[np.datetime64] | list[np.datetime64] | np.datetime64
|
|
777
776
|
One or more time values for gridded cocip.
|
|
778
|
-
longitude
|
|
779
|
-
Longitude
|
|
777
|
+
longitude : npt.NDArray[np.floating] | list[float] | None, optional
|
|
778
|
+
Longitude array, by default None. If not specified, values of
|
|
779
|
+
``lon_step`` and ``lat_step`` are used to define ``longitude`` and ``latitude``.
|
|
780
|
+
latitude : npt.NDArray[np.floating] | list[float] | None, optional
|
|
781
|
+
Latitude array, by default None. If not specified, values of
|
|
780
782
|
``lon_step`` and ``lat_step`` are used to define ``longitude`` and ``latitude``.
|
|
781
|
-
lon_step
|
|
782
|
-
Longitude
|
|
783
|
-
Only used if parameter ``longitude``
|
|
783
|
+
lon_step : float, optional
|
|
784
|
+
Longitude resolution, by default 1.0.
|
|
785
|
+
Only used if parameter ``longitude`` not specified.
|
|
786
|
+
lat_step : float, optional
|
|
787
|
+
Latitude resolution, by default 1.0.
|
|
788
|
+
Only used if parameter ``latitude`` not specified.
|
|
784
789
|
|
|
785
790
|
Returns
|
|
786
791
|
-------
|
|
@@ -899,14 +904,16 @@ def run_interpolators(
|
|
|
899
904
|
----------
|
|
900
905
|
vector : GeoVectorDataset
|
|
901
906
|
Grid points.
|
|
902
|
-
met
|
|
903
|
-
CoCiP met
|
|
907
|
+
met : MetDataset
|
|
908
|
+
CoCiP met slices. See :class:`CocipGrid`.
|
|
909
|
+
rad : MetDataset | None, optional
|
|
910
|
+
CoCiP rad slices. If ``keys`` is not None, this parameter must be None.
|
|
904
911
|
dz_m : float | None, optional
|
|
905
912
|
Difference in altitude between top and bottom layer for stratification calculations (m).
|
|
906
913
|
Must be specified if ``keys`` is None.
|
|
907
914
|
humidity_scaling : humidity_scaling.HumidityScaling | None, optional
|
|
908
915
|
Specific humidity scaling scheme. Must be specified if ``keys`` is None.
|
|
909
|
-
keys :
|
|
916
|
+
keys : Sequence[str] | None, optional
|
|
910
917
|
Only run interpolators for select keys from ``met``
|
|
911
918
|
**interp_kwargs : Any
|
|
912
919
|
Interpolation keyword arguments
|
|
@@ -1067,8 +1074,10 @@ def _evolve_vector(
|
|
|
1067
1074
|
----------
|
|
1068
1075
|
vector : GeoVectorDataset
|
|
1069
1076
|
Contrail points that have been initialized and are ready for evolution.
|
|
1070
|
-
met
|
|
1071
|
-
CoCiP met
|
|
1077
|
+
met : MetDataset
|
|
1078
|
+
CoCiP met slices. See :class:`CocipGrid`.
|
|
1079
|
+
rad : MetDataset
|
|
1080
|
+
CoCiP rad slices. See :class:`CocipGrid`.
|
|
1072
1081
|
params : dict[str, Any]
|
|
1073
1082
|
CoCiP model parameters. See :class:`CocipGrid`.
|
|
1074
1083
|
t : np.datetime64
|
|
@@ -1124,8 +1133,10 @@ def _run_downwash(
|
|
|
1124
1133
|
----------
|
|
1125
1134
|
vector : GeoVectorDataset
|
|
1126
1135
|
Grid values
|
|
1127
|
-
met
|
|
1128
|
-
CoCiP met
|
|
1136
|
+
met : MetDataset
|
|
1137
|
+
CoCiP met slices. See :class:`CocipGrid`.
|
|
1138
|
+
rad : MetDataset
|
|
1139
|
+
CoCiP rad slices. See :class:`CocipGrid`.
|
|
1129
1140
|
params : dict[str, Any]
|
|
1130
1141
|
CoCiP model parameters. See :class:`CocipGrid`.
|
|
1131
1142
|
|
|
@@ -1297,6 +1308,8 @@ def find_initial_contrail_regions(
|
|
|
1297
1308
|
# which is why we compute it here
|
|
1298
1309
|
T_crit_sac = sac.T_critical_sac(t_sat_liq[filt], rh[filt], G[filt])
|
|
1299
1310
|
filtered_vector["T_crit_sac"] = T_crit_sac
|
|
1311
|
+
if params["vpm_activation"]:
|
|
1312
|
+
filtered_vector["G"] = G[filt] # only used in vpm_activation
|
|
1300
1313
|
return filtered_vector, pd.Series(data=sac_, index=vector["index"])
|
|
1301
1314
|
|
|
1302
1315
|
|
|
@@ -1487,14 +1500,29 @@ def find_initial_persistent_contrails(
|
|
|
1487
1500
|
air_pressure_1=air_pressure_1,
|
|
1488
1501
|
)
|
|
1489
1502
|
iwc_1 = contrail_properties.iwc_post_wake_vortex(iwc, iwc_ad)
|
|
1490
|
-
|
|
1503
|
+
|
|
1504
|
+
if params["vpm_activation"]:
|
|
1505
|
+
# We can add a Cocip parameter for T_exhaust, vpm_ei_n, and particles
|
|
1506
|
+
aei = extended_k15.droplet_apparent_emission_index(
|
|
1507
|
+
specific_humidity=specific_humidity,
|
|
1508
|
+
T_ambient=air_temperature,
|
|
1509
|
+
T_exhaust=vector.attrs.get("T_exhaust", extended_k15.DEFAULT_EXHAUST_T),
|
|
1510
|
+
air_pressure=air_pressure,
|
|
1511
|
+
nvpm_ei_n=nvpm_ei_n,
|
|
1512
|
+
vpm_ei_n=vector.attrs.get("vpm_ei_n", extended_k15.DEFAULT_VPM_EI_N),
|
|
1513
|
+
G=vector["G"],
|
|
1514
|
+
)
|
|
1515
|
+
min_aei = None
|
|
1516
|
+
else:
|
|
1517
|
+
f_activ = contrail_properties.ice_particle_activation_rate(air_temperature, T_crit_sac)
|
|
1518
|
+
aei = nvpm_ei_n * f_activ
|
|
1519
|
+
min_aei = params["min_ice_particle_number_nvpm_ei_n"]
|
|
1520
|
+
|
|
1491
1521
|
n_ice_per_m_0 = contrail_properties.initial_ice_particle_number(
|
|
1492
|
-
|
|
1493
|
-
fuel_dist=fuel_dist,
|
|
1494
|
-
air_temperature=air_temperature,
|
|
1495
|
-
T_crit_sac=T_crit_sac,
|
|
1496
|
-
min_ice_particle_number_nvpm_ei_n=params["min_ice_particle_number_nvpm_ei_n"],
|
|
1522
|
+
aei=aei, fuel_dist=fuel_dist, min_aei=min_aei
|
|
1497
1523
|
)
|
|
1524
|
+
|
|
1525
|
+
f_surv = contrail_properties.ice_particle_survival_fraction(iwc, iwc_1)
|
|
1498
1526
|
n_ice_per_m_1 = n_ice_per_m_0 * f_surv
|
|
1499
1527
|
|
|
1500
1528
|
# The logic below corresponds to Cocip._create_downwash_contrail (roughly)
|
|
@@ -2131,7 +2159,7 @@ def result_to_metdataset(
|
|
|
2131
2159
|
result : VectorDataset | None
|
|
2132
2160
|
Aggregated data arising from contrail evolution. Expected to contain keys:
|
|
2133
2161
|
``index``, ``age``, ``ef``.
|
|
2134
|
-
verbose_dict : dict[str, npt.NDArray[np.floating]]
|
|
2162
|
+
verbose_dict : dict[str, npt.NDArray[np.floating]]
|
|
2135
2163
|
Verbose outputs to attach to results.
|
|
2136
2164
|
source : MetDataset
|
|
2137
2165
|
:attr:`CocipGrid.`source` data on which to attach results.
|
|
@@ -2366,11 +2394,11 @@ def _check_coverage(
|
|
|
2366
2394
|
|
|
2367
2395
|
Parameters
|
|
2368
2396
|
----------
|
|
2369
|
-
met_array :
|
|
2397
|
+
met_array : npt.NDArray[_T]
|
|
2370
2398
|
Coordinate on met data
|
|
2371
|
-
grid_array :
|
|
2399
|
+
grid_array : npt.NDArray[_T]
|
|
2372
2400
|
Coordinate on grid data
|
|
2373
|
-
coord :
|
|
2401
|
+
coord : str
|
|
2374
2402
|
Name of coordinate. Only used for warning message.
|
|
2375
2403
|
name : str
|
|
2376
2404
|
Name of met dataset. Only used for warning message.
|
|
@@ -137,14 +137,14 @@ class DryAdvection(models.Model):
|
|
|
137
137
|
|
|
138
138
|
Parameters
|
|
139
139
|
----------
|
|
140
|
-
source : GeoVectorDataset
|
|
140
|
+
source : GeoVectorDataset | None
|
|
141
141
|
Arbitrary points to advect. A :class:`Flight` instance is not treated any
|
|
142
142
|
differently than a :class:`GeoVectorDataset`. In particular, the user must
|
|
143
143
|
explicitly set ``flight["azimuth"] = flight.segment_azimuth()`` if they
|
|
144
144
|
want to use wind shear effects for a flight.
|
|
145
145
|
In the current implementation, any existing meteorological variables in the ``source``
|
|
146
146
|
are ignored. The ``source`` will be interpolated against the :attr:`met` dataset.
|
|
147
|
-
params : Any
|
|
147
|
+
**params : Any
|
|
148
148
|
Overwrite model parameters defined in ``__init__``.
|
|
149
149
|
|
|
150
150
|
Returns
|