pycontrails 0.53.0__cp313-cp313-manylinux_2_17_x86_64.manylinux2014_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.

Files changed (109) hide show
  1. pycontrails/__init__.py +70 -0
  2. pycontrails/_version.py +16 -0
  3. pycontrails/core/__init__.py +30 -0
  4. pycontrails/core/aircraft_performance.py +641 -0
  5. pycontrails/core/airports.py +226 -0
  6. pycontrails/core/cache.py +881 -0
  7. pycontrails/core/coordinates.py +174 -0
  8. pycontrails/core/fleet.py +470 -0
  9. pycontrails/core/flight.py +2312 -0
  10. pycontrails/core/flightplan.py +220 -0
  11. pycontrails/core/fuel.py +140 -0
  12. pycontrails/core/interpolation.py +721 -0
  13. pycontrails/core/met.py +2833 -0
  14. pycontrails/core/met_var.py +307 -0
  15. pycontrails/core/models.py +1181 -0
  16. pycontrails/core/polygon.py +549 -0
  17. pycontrails/core/rgi_cython.cpython-313-x86_64-linux-gnu.so +0 -0
  18. pycontrails/core/vector.py +2191 -0
  19. pycontrails/datalib/__init__.py +12 -0
  20. pycontrails/datalib/_leo_utils/search.py +250 -0
  21. pycontrails/datalib/_leo_utils/static/bq_roi_query.sql +6 -0
  22. pycontrails/datalib/_leo_utils/vis.py +59 -0
  23. pycontrails/datalib/_met_utils/metsource.py +743 -0
  24. pycontrails/datalib/ecmwf/__init__.py +53 -0
  25. pycontrails/datalib/ecmwf/arco_era5.py +527 -0
  26. pycontrails/datalib/ecmwf/common.py +109 -0
  27. pycontrails/datalib/ecmwf/era5.py +538 -0
  28. pycontrails/datalib/ecmwf/era5_model_level.py +482 -0
  29. pycontrails/datalib/ecmwf/hres.py +782 -0
  30. pycontrails/datalib/ecmwf/hres_model_level.py +495 -0
  31. pycontrails/datalib/ecmwf/ifs.py +284 -0
  32. pycontrails/datalib/ecmwf/model_levels.py +79 -0
  33. pycontrails/datalib/ecmwf/static/model_level_dataframe_v20240418.csv +139 -0
  34. pycontrails/datalib/ecmwf/variables.py +256 -0
  35. pycontrails/datalib/gfs/__init__.py +28 -0
  36. pycontrails/datalib/gfs/gfs.py +646 -0
  37. pycontrails/datalib/gfs/variables.py +100 -0
  38. pycontrails/datalib/goes.py +772 -0
  39. pycontrails/datalib/landsat.py +568 -0
  40. pycontrails/datalib/sentinel.py +512 -0
  41. pycontrails/datalib/spire.py +739 -0
  42. pycontrails/ext/bada.py +41 -0
  43. pycontrails/ext/cirium.py +14 -0
  44. pycontrails/ext/empirical_grid.py +140 -0
  45. pycontrails/ext/synthetic_flight.py +426 -0
  46. pycontrails/models/__init__.py +1 -0
  47. pycontrails/models/accf.py +406 -0
  48. pycontrails/models/apcemm/__init__.py +8 -0
  49. pycontrails/models/apcemm/apcemm.py +983 -0
  50. pycontrails/models/apcemm/inputs.py +226 -0
  51. pycontrails/models/apcemm/static/apcemm_yaml_template.yaml +183 -0
  52. pycontrails/models/apcemm/utils.py +437 -0
  53. pycontrails/models/cocip/__init__.py +29 -0
  54. pycontrails/models/cocip/cocip.py +2617 -0
  55. pycontrails/models/cocip/cocip_params.py +299 -0
  56. pycontrails/models/cocip/cocip_uncertainty.py +285 -0
  57. pycontrails/models/cocip/contrail_properties.py +1517 -0
  58. pycontrails/models/cocip/output_formats.py +2261 -0
  59. pycontrails/models/cocip/radiative_forcing.py +1262 -0
  60. pycontrails/models/cocip/radiative_heating.py +520 -0
  61. pycontrails/models/cocip/unterstrasser_wake_vortex.py +403 -0
  62. pycontrails/models/cocip/wake_vortex.py +396 -0
  63. pycontrails/models/cocip/wind_shear.py +120 -0
  64. pycontrails/models/cocipgrid/__init__.py +9 -0
  65. pycontrails/models/cocipgrid/cocip_grid.py +2573 -0
  66. pycontrails/models/cocipgrid/cocip_grid_params.py +138 -0
  67. pycontrails/models/dry_advection.py +486 -0
  68. pycontrails/models/emissions/__init__.py +21 -0
  69. pycontrails/models/emissions/black_carbon.py +594 -0
  70. pycontrails/models/emissions/emissions.py +1353 -0
  71. pycontrails/models/emissions/ffm2.py +336 -0
  72. pycontrails/models/emissions/static/default-engine-uids.csv +239 -0
  73. pycontrails/models/emissions/static/edb-gaseous-v29b-engines.csv +596 -0
  74. pycontrails/models/emissions/static/edb-nvpm-v29b-engines.csv +215 -0
  75. pycontrails/models/humidity_scaling/__init__.py +37 -0
  76. pycontrails/models/humidity_scaling/humidity_scaling.py +1025 -0
  77. pycontrails/models/humidity_scaling/quantiles/era5-model-level-quantiles.pq +0 -0
  78. pycontrails/models/humidity_scaling/quantiles/era5-pressure-level-quantiles.pq +0 -0
  79. pycontrails/models/issr.py +210 -0
  80. pycontrails/models/pcc.py +327 -0
  81. pycontrails/models/pcr.py +154 -0
  82. pycontrails/models/ps_model/__init__.py +17 -0
  83. pycontrails/models/ps_model/ps_aircraft_params.py +376 -0
  84. pycontrails/models/ps_model/ps_grid.py +505 -0
  85. pycontrails/models/ps_model/ps_model.py +1017 -0
  86. pycontrails/models/ps_model/ps_operational_limits.py +540 -0
  87. pycontrails/models/ps_model/static/ps-aircraft-params-20240524.csv +68 -0
  88. pycontrails/models/ps_model/static/ps-synonym-list-20240524.csv +103 -0
  89. pycontrails/models/sac.py +459 -0
  90. pycontrails/models/tau_cirrus.py +168 -0
  91. pycontrails/physics/__init__.py +1 -0
  92. pycontrails/physics/constants.py +116 -0
  93. pycontrails/physics/geo.py +989 -0
  94. pycontrails/physics/jet.py +837 -0
  95. pycontrails/physics/thermo.py +451 -0
  96. pycontrails/physics/units.py +472 -0
  97. pycontrails/py.typed +0 -0
  98. pycontrails/utils/__init__.py +1 -0
  99. pycontrails/utils/dependencies.py +66 -0
  100. pycontrails/utils/iteration.py +13 -0
  101. pycontrails/utils/json.py +188 -0
  102. pycontrails/utils/temp.py +50 -0
  103. pycontrails/utils/types.py +165 -0
  104. pycontrails-0.53.0.dist-info/LICENSE +178 -0
  105. pycontrails-0.53.0.dist-info/METADATA +181 -0
  106. pycontrails-0.53.0.dist-info/NOTICE +43 -0
  107. pycontrails-0.53.0.dist-info/RECORD +109 -0
  108. pycontrails-0.53.0.dist-info/WHEEL +6 -0
  109. pycontrails-0.53.0.dist-info/top_level.txt +3 -0
@@ -0,0 +1,17 @@
1
+ """Support for the Poll-Schumann (PS) aircraft performance model."""
2
+
3
+ from pycontrails.models.ps_model.ps_aircraft_params import (
4
+ PSAircraftEngineParams,
5
+ load_aircraft_engine_params,
6
+ )
7
+ from pycontrails.models.ps_model.ps_grid import PSGrid, ps_nominal_grid
8
+ from pycontrails.models.ps_model.ps_model import PSFlight, PSFlightParams
9
+
10
+ __all__ = [
11
+ "PSFlight",
12
+ "PSFlightParams",
13
+ "PSAircraftEngineParams",
14
+ "PSGrid",
15
+ "load_aircraft_engine_params",
16
+ "ps_nominal_grid",
17
+ ]
@@ -0,0 +1,376 @@
1
+ """Simple dataclasses for working with PS aircraft performance data."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import dataclasses
6
+ import functools
7
+ import pathlib
8
+ from collections.abc import Mapping
9
+ from typing import Any
10
+
11
+ import numpy as np
12
+ import pandas as pd
13
+
14
+ from pycontrails.physics import constants as c
15
+
16
+ #: Path to the Poll-Schumann aircraft parameters CSV file.
17
+ PS_FILE_PATH = pathlib.Path(__file__).parent / "static" / "ps-aircraft-params-20240524.csv"
18
+
19
+
20
+ @dataclasses.dataclass(frozen=True)
21
+ class PSAircraftEngineParams:
22
+ """Store extracted aircraft and engine parameters for each aircraft type.
23
+
24
+ -------------------------------------
25
+ AIRCRAFT INFORMATION
26
+ -------------------------------------
27
+ - ``manufacturer`` Aircraft manufacturer name
28
+ - ``aircraft_type`` Specific aircraft type variant
29
+ - ``n_engine`` Number of engines
30
+ - ``winglets`` Does the aircraft type contain winglets? (True/False)
31
+
32
+ -------------------------------------
33
+ AIRCRAFT MASS PARAMETERS
34
+ -------------------------------------
35
+ - ``amass_mtow`` Aircraft maximum take-off weight, [:math:`kg`]
36
+ - ``amass_mlw`` Aircraft maximum landing weight, [:math:`kg`]
37
+ - ``amass_mzfw`` Aircraft maximum zero fuel weight, [:math:`kg`]
38
+ - ``amass_oew`` Aircraft operating empty weight, [:math:`kg`]
39
+ - ``amass_mpl`` Aircraft maximum payload, [:math:`kg`]
40
+
41
+ -------------------------------------
42
+ AIRCRAFT GEOMETRY
43
+ -------------------------------------
44
+ - ``wing_surface_area`` Reference wing surface area, [:math:`m^{2}`]
45
+ - ``wing_span`` Wing span, [:math:`m`]
46
+ - ``fuselage_width`` Aircraft fuselage width, [:math:`m`]
47
+ - ``delta_2`` Induced drag wing-fuselage interference factor
48
+ - ``cos_sweep`` Cosine of wing sweep angle measured at the 1/4 chord line
49
+ - ``wing_aspect_ratio`` Wing aspect ratio, ``wing_span**2 / wing_surface_area``
50
+
51
+ -------------------------------------
52
+ AERODYNAMIC PARAMETERS
53
+ -------------------------------------
54
+ - ``psi_0`` Aircraft geometry drag parameter
55
+ - ``x_ref`` Threshold condition where the terminating shockwave moves onto
56
+ the rear part of the wing
57
+ - ``wing_constant`` A constant used in the wave drag model, capturing the aerofoil
58
+ technology factor and wing geometry
59
+ - ``j_1`` Wave drag parameter 1
60
+ - ``j_2`` Wave drag parameter 2
61
+ - ``j_3`` Wave drag parameter 3
62
+ - ``c_l_do`` Design optimum lift coefficient
63
+
64
+ -------------------------------------
65
+ ENGINE PARAMETERS
66
+ -------------------------------------
67
+ - ``f_00`` Maximum thrust force that can be supplied by the engine at sea level static
68
+ conditions, summed over all engines, [:math:`N`].
69
+ - ``ff_max_sls`` Fuel mass flow rate at take-off and sea level static conditions, summed
70
+ over all engines, [:math:`kg s^{-1}`]
71
+ - ``ff_idle_sls`` Fuel mass flow rate under engine idle and sea level static conditions,
72
+ summed over all engines, [:math:`kg s^{-1}`]
73
+ - ``m_des`` Design optimum Mach number where the fuel mass flow rate is at a minimum.
74
+ - ``c_t_des`` Design optimum engine thrust coefficient where the fuel mass flow rate is
75
+ at a minimum.
76
+ - ``eta_1`` Multiplier for maximum overall propulsion efficiency model
77
+ - ``eta_2`` Exponent for maximum overall propulsion efficiency model
78
+ - ``tr_ec`` Engine characteristic ratio of total turbine-entry-temperature to
79
+ the total freestream temperature for maximum overall efficiency.
80
+ - ``m_ec`` Engine characteristic Mach number associated with `tr_ec`.
81
+ - ``tet_mto`` Turbine entry temperature at maximum take-off rating, [:math:`K`]
82
+ - ``tet_mcc`` Turbine entry temperature at maximum continuous climb rating, [:math:`K`]
83
+ - ``nominal_opr`` Nominal engine operating pressure ratio.
84
+ - ``nominal_bpr`` Nominal engine bypass ratio.
85
+ - ``nominal_fpr`` Nominal engine fan pressure ratio.
86
+
87
+ -------------------------------------
88
+ HEIGHT AND SPEED LIMITS
89
+ -------------------------------------
90
+ - ``fl_max`` Maximum flight level
91
+ - ``max_mach_num`` Maximum operational Mach number
92
+ - ``p_i_max`` Maximum operational impact pressure, [:math:`Pa`]
93
+ - ``p_inf_co`` Crossover pressure altitude, [:math:`Pa`]
94
+ """
95
+
96
+ manufacturer: str
97
+ aircraft_type: str
98
+ n_engine: int
99
+ winglets: bool
100
+
101
+ amass_mtow: float
102
+ amass_mlw: float
103
+ amass_mzfw: float
104
+ amass_oew: float
105
+ amass_mpl: float
106
+
107
+ wing_surface_area: float
108
+ wing_span: float
109
+ fuselage_width: float
110
+ delta_2: float
111
+ cos_sweep: float
112
+ wing_aspect_ratio: float
113
+
114
+ psi_0: float
115
+ x_ref: float
116
+ wing_constant: float
117
+ j_1: float
118
+ j_2: float
119
+ j_3: float
120
+ c_l_do: float
121
+
122
+ f_00: float
123
+ ff_max_sls: float
124
+ ff_idle_sls: float
125
+ m_des: float
126
+ c_t_des: float
127
+ eta_1: float
128
+ eta_2: float
129
+ tr_ec: float
130
+ m_ec: float
131
+ tet_mto: float
132
+ tet_mcc: float
133
+ nominal_opr: float
134
+ nominal_bpr: float
135
+ nominal_fpr: float
136
+
137
+ fl_max: float
138
+ max_mach_num: float
139
+ p_i_max: float
140
+ p_inf_co: float
141
+
142
+
143
+ def _row_to_aircraft_engine_params(tup: Any) -> tuple[str, PSAircraftEngineParams]:
144
+ icao = tup.ICAO
145
+ wing_aspect_ratio = tup.AR
146
+ amass_mtow = tup.MTOM_kg
147
+ tet_mto = turbine_entry_temperature_at_max_take_off(tup.Year_of_first_flight)
148
+ p_i_max = impact_pressure_max_operating_limits(tup.MMO)
149
+ params = PSAircraftEngineParams(
150
+ manufacturer=tup.Manufacturer,
151
+ aircraft_type=tup.Type,
152
+ n_engine=tup.n_engine,
153
+ winglets=tup.winglets == "yes",
154
+ amass_mtow=amass_mtow,
155
+ amass_mlw=tup.MLM_kg,
156
+ amass_mzfw=tup.MZFM_kg,
157
+ amass_oew=tup.OEM_i_kg,
158
+ amass_mpl=tup.MPM_i_kg,
159
+ wing_surface_area=tup.Sref_m2,
160
+ wing_span=tup.span_m,
161
+ fuselage_width=tup.bf_m,
162
+ delta_2=tup.delta_2,
163
+ cos_sweep=tup.cos_sweep,
164
+ wing_aspect_ratio=wing_aspect_ratio,
165
+ psi_0=tup.psi_0,
166
+ x_ref=tup.Xo,
167
+ wing_constant=tup.wing_constant,
168
+ j_1=tup.j_1,
169
+ j_2=tup.j_2,
170
+ j_3=70.0, # use constant value for now, may be updated in the future
171
+ c_l_do=tup.CL_do,
172
+ f_00=tup.nominal_F00_ISA_kn * 1000.0,
173
+ ff_max_sls=tup.mf_max_T_O_SLS_kg_s,
174
+ ff_idle_sls=tup.mf_idle_SLS_kg_s,
175
+ m_des=tup.M_des,
176
+ c_t_des=tup.CT_des,
177
+ eta_1=tup.eta_1,
178
+ eta_2=tup.eta_2,
179
+ tr_ec=tup.Tec,
180
+ m_ec=tup.Mec,
181
+ tet_mto=tet_mto,
182
+ tet_mcc=turbine_entry_temperature_at_max_continuous_climb(tet_mto),
183
+ nominal_opr=tup.nominal_opr,
184
+ nominal_bpr=tup.nominal_bpr,
185
+ nominal_fpr=tup.nominal_fpr,
186
+ fl_max=tup.FL_max,
187
+ max_mach_num=tup.MMO,
188
+ p_i_max=p_i_max,
189
+ p_inf_co=crossover_pressure_altitude(tup.MMO, p_i_max),
190
+ )
191
+ return icao, params
192
+
193
+
194
+ @functools.cache
195
+ def load_aircraft_engine_params(
196
+ engine_deterioration_factor: float = 0.025,
197
+ ) -> Mapping[str, PSAircraftEngineParams]:
198
+ """
199
+ Extract aircraft-engine parameters for each aircraft type supported by the PS model.
200
+
201
+ Parameters
202
+ ----------
203
+ engine_deterioration_factor: float
204
+ Account for "in-service" engine deterioration between maintenance cycles.
205
+ Default value reduces `eta_1` by 2.5%, which increases the fuel flow estimates by 2.5%.
206
+
207
+ Returns
208
+ -------
209
+ Mapping[str, PSAircraftEngineParams]
210
+ Aircraft-engine parameters for each aircraft type supported by the PS model.
211
+ """
212
+ dtypes = {
213
+ "ICAO": object,
214
+ "Manufacturer": object,
215
+ "Type": object,
216
+ "Year_of_first_flight": float,
217
+ "n_engine": int,
218
+ "winglets": object,
219
+ "WV": object,
220
+ "MTOM_kg": float,
221
+ "MLM_kg": float,
222
+ "MZFM_kg": float,
223
+ "OEM_i_kg": float,
224
+ "MPM_i_kg": float,
225
+ "MZFM_MTOM": float,
226
+ "OEM_i_MTOM": float,
227
+ "MPM_i_MTOM": float,
228
+ "Sref_m2": float,
229
+ "span_m": float,
230
+ "bf_m": float,
231
+ "delta_2": float,
232
+ "cos_sweep": float,
233
+ "AR": float,
234
+ "psi_0": float,
235
+ "Xo": float,
236
+ "wing_constant": float,
237
+ "j_2": float,
238
+ "j_1": float,
239
+ "CL_do": float,
240
+ "nominal_F00_ISA_kn": float,
241
+ "mf_max_T_O_SLS_kg_s": float,
242
+ "mf_idle_SLS_kg_s": float,
243
+ "M_des": float,
244
+ "CT_des": float,
245
+ "eta_1": float,
246
+ "eta_2": float,
247
+ "Mec": float,
248
+ "Tec": float,
249
+ "FL_max": float,
250
+ "MMO": float,
251
+ "nominal_opr": float,
252
+ "nominal_bpr": float,
253
+ "nominal_fpr": float,
254
+ }
255
+
256
+ df = pd.read_csv(PS_FILE_PATH, dtype=dtypes)
257
+ df["eta_1"] = df["eta_1"] * (1.0 - engine_deterioration_factor)
258
+
259
+ return dict(_row_to_aircraft_engine_params(tup) for tup in df.itertuples(index=False))
260
+
261
+
262
+ def turbine_entry_temperature_at_max_take_off(first_flight: float) -> float:
263
+ """
264
+ Calculate turbine entry temperature at maximum take-off rating.
265
+
266
+ Parameters
267
+ ----------
268
+ first_flight: float
269
+ Year of first flight
270
+
271
+ Returns
272
+ -------
273
+ float
274
+ Turbine entry temperature at maximum take-off rating, ``tet_mto``, [:math:`K`]
275
+
276
+ Notes
277
+ -----
278
+ The turbine entry temperature at max take-off is approximated based on the year of first flight
279
+ for the specific aircraft type. This approximation captures the historical trends of
280
+ improvements in turbine cooling technology level. The uncertainty of this estimate is ±75 K.
281
+
282
+ References
283
+ ----------
284
+ - :cite:`cumpstyJetPropulsion2015`
285
+ """
286
+ return 2000.0 * (1 - np.exp(62.8 - 0.0325 * first_flight))
287
+
288
+
289
+ def turbine_entry_temperature_at_max_continuous_climb(tet_mto: float) -> float:
290
+ """
291
+ Calculate turbine entry temperature at maximum continuous climb rating.
292
+
293
+ Parameters
294
+ ----------
295
+ tet_mto: float
296
+ Turbine entry temperature at maximum take-off rating, `tet_mto`, [:math:`K`]
297
+
298
+ Returns
299
+ -------
300
+ float
301
+ Turbine entry temperature at maximum continuous climb rating, `tet_mcc`, [:math:`K`]
302
+ """
303
+ return 0.92 * tet_mto
304
+
305
+
306
+ def impact_pressure_max_operating_limits(max_mach_num: float) -> float:
307
+ """
308
+ Calculate maximum permitted operational impact pressure.
309
+
310
+ Parameters
311
+ ----------
312
+ max_mach_num: float
313
+ Maximum permitted operational Mach number for aircraft type.
314
+
315
+ Returns
316
+ -------
317
+ float
318
+ Maximum permitted operational impact pressure for aircraft type, ``p_i_max``, [:math:`Pa`]
319
+
320
+ Notes
321
+ -----
322
+ The impact pressure is the difference between the free stream total pressure ``p_0`` and the
323
+ atmospheric static pressure ``p_inf``. By definition, the calibrated airspeed, ``v_cas``, is
324
+ the speed at sea level in the ISA that has the same impact pressure.
325
+ """
326
+ v_cas_mo_over_c_msl = max_calibrated_airspeed_over_speed_of_sound(max_mach_num)
327
+ return c.p_surface * (
328
+ (1.0 + 0.5 * (c.kappa - 1.0) * v_cas_mo_over_c_msl**2) ** (c.kappa / (c.kappa - 1.0)) - 1.0
329
+ )
330
+
331
+
332
+ def max_calibrated_airspeed_over_speed_of_sound(max_mach_num: float) -> float:
333
+ """
334
+ Calculate max calibrated airspeed over the speed of sound at ISA mean sea level.
335
+
336
+ Parameters
337
+ ----------
338
+ max_mach_num: float
339
+ Maximum permitted operational Mach number for aircraft type.
340
+
341
+ Returns
342
+ -------
343
+ float
344
+ Ratio of maximum operating limits of the calibrated airspeed (CAS) over the speed of sound
345
+ at mean sea level (MSL) in standard atmosphere (ISA), ``v_cas_mo_over_c_msl``
346
+ """
347
+ return 0.57 * (max_mach_num + 0.10)
348
+
349
+
350
+ def crossover_pressure_altitude(max_mach_num: float, p_i_max: float) -> float:
351
+ """
352
+ Calculate crossover pressure altitude.
353
+
354
+ Parameters
355
+ ----------
356
+ max_mach_num: float
357
+ Maximum permitted operational Mach number for aircraft type.
358
+ p_i_max : float
359
+ Maximum permitted operational impact pressure for aircraft type, [:math:`Pa`]
360
+
361
+ Returns
362
+ -------
363
+ float
364
+ Crossover pressure altitude, ``p_inf_co``, [:math:`Pa`]
365
+
366
+ Notes
367
+ -----
368
+ At low altitudes, the calibrated airspeed (CAS) is used to determine the maximum aircraft
369
+ operational speed. However, the ambient temperature drops as altitude increases, which causes
370
+ the Mach number to increase even when the CAS remains constant. This can cause the Mach number
371
+ to exceed the maximum permitted operational Mach number. Therefore, above the crossover
372
+ altitude, the maximum operational speed is determined by the Mach number instead of CAS.
373
+ """
374
+ return p_i_max / (
375
+ 0.5 * c.kappa * max_mach_num**2 * (1.0 + (max_mach_num**2 / 4.0) + (max_mach_num**4 / 40.0))
376
+ )