pycontrails 0.54.2__cp310-cp310-win_amd64.whl → 0.54.4__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.

Files changed (68) hide show
  1. pycontrails/__init__.py +2 -2
  2. pycontrails/_version.py +2 -2
  3. pycontrails/core/__init__.py +1 -1
  4. pycontrails/core/aircraft_performance.py +75 -61
  5. pycontrails/core/cache.py +7 -7
  6. pycontrails/core/fleet.py +25 -21
  7. pycontrails/core/flight.py +215 -301
  8. pycontrails/core/interpolation.py +56 -56
  9. pycontrails/core/met.py +48 -39
  10. pycontrails/core/models.py +25 -11
  11. pycontrails/core/polygon.py +15 -15
  12. pycontrails/core/rgi_cython.cp310-win_amd64.pyd +0 -0
  13. pycontrails/core/vector.py +22 -22
  14. pycontrails/datalib/_met_utils/metsource.py +8 -5
  15. pycontrails/datalib/ecmwf/__init__.py +14 -14
  16. pycontrails/datalib/ecmwf/common.py +1 -1
  17. pycontrails/datalib/ecmwf/era5.py +7 -7
  18. pycontrails/datalib/ecmwf/hres.py +3 -3
  19. pycontrails/datalib/ecmwf/ifs.py +1 -1
  20. pycontrails/datalib/ecmwf/variables.py +1 -0
  21. pycontrails/datalib/gfs/__init__.py +6 -6
  22. pycontrails/datalib/gfs/gfs.py +2 -2
  23. pycontrails/datalib/goes.py +5 -5
  24. pycontrails/datalib/landsat.py +5 -8
  25. pycontrails/datalib/sentinel.py +7 -11
  26. pycontrails/ext/bada.py +3 -2
  27. pycontrails/ext/empirical_grid.py +1 -1
  28. pycontrails/ext/synthetic_flight.py +3 -2
  29. pycontrails/models/accf.py +40 -19
  30. pycontrails/models/apcemm/apcemm.py +5 -4
  31. pycontrails/models/cocip/__init__.py +2 -2
  32. pycontrails/models/cocip/cocip.py +16 -17
  33. pycontrails/models/cocip/cocip_params.py +2 -11
  34. pycontrails/models/cocip/cocip_uncertainty.py +24 -18
  35. pycontrails/models/cocip/contrail_properties.py +331 -316
  36. pycontrails/models/cocip/output_formats.py +53 -53
  37. pycontrails/models/cocip/radiative_forcing.py +135 -131
  38. pycontrails/models/cocip/radiative_heating.py +135 -135
  39. pycontrails/models/cocip/unterstrasser_wake_vortex.py +90 -87
  40. pycontrails/models/cocip/wake_vortex.py +92 -92
  41. pycontrails/models/cocip/wind_shear.py +8 -8
  42. pycontrails/models/cocipgrid/cocip_grid.py +118 -107
  43. pycontrails/models/dry_advection.py +59 -58
  44. pycontrails/models/emissions/__init__.py +2 -2
  45. pycontrails/models/emissions/black_carbon.py +108 -108
  46. pycontrails/models/emissions/emissions.py +85 -85
  47. pycontrails/models/emissions/ffm2.py +35 -35
  48. pycontrails/models/humidity_scaling/humidity_scaling.py +23 -23
  49. pycontrails/models/ps_model/__init__.py +3 -2
  50. pycontrails/models/ps_model/ps_aircraft_params.py +11 -6
  51. pycontrails/models/ps_model/ps_grid.py +256 -60
  52. pycontrails/models/ps_model/ps_model.py +18 -21
  53. pycontrails/models/ps_model/ps_operational_limits.py +58 -69
  54. pycontrails/models/tau_cirrus.py +8 -1
  55. pycontrails/physics/geo.py +216 -67
  56. pycontrails/physics/jet.py +220 -90
  57. pycontrails/physics/static/iata-cargo-load-factors-20241115.csv +71 -0
  58. pycontrails/physics/static/iata-passenger-load-factors-20241115.csv +71 -0
  59. pycontrails/physics/units.py +14 -14
  60. pycontrails/utils/json.py +1 -2
  61. pycontrails/utils/types.py +12 -7
  62. {pycontrails-0.54.2.dist-info → pycontrails-0.54.4.dist-info}/METADATA +10 -10
  63. {pycontrails-0.54.2.dist-info → pycontrails-0.54.4.dist-info}/NOTICE +1 -1
  64. pycontrails-0.54.4.dist-info/RECORD +111 -0
  65. {pycontrails-0.54.2.dist-info → pycontrails-0.54.4.dist-info}/WHEEL +1 -1
  66. pycontrails-0.54.2.dist-info/RECORD +0 -109
  67. {pycontrails-0.54.2.dist-info → pycontrails-0.54.4.dist-info}/LICENSE +0 -0
  68. {pycontrails-0.54.2.dist-info → pycontrails-0.54.4.dist-info}/top_level.txt +0 -0
@@ -155,34 +155,34 @@ def max_available_thrust_coefficient(
155
155
 
156
156
 
157
157
  def get_excess_thrust_available(
158
- mach_number: float | npt.NDArray[np.float64],
159
- air_temperature: float | npt.NDArray[np.float64],
160
- air_pressure: float | npt.NDArray[np.float64],
161
- aircraft_mass: float | npt.NDArray[np.float64],
162
- theta: float | npt.NDArray[np.float64],
158
+ mach_number: ArrayOrFloat,
159
+ air_temperature: ArrayOrFloat,
160
+ air_pressure: ArrayOrFloat,
161
+ aircraft_mass: ArrayOrFloat,
162
+ theta: ArrayOrFloat,
163
163
  atyp_param: PSAircraftEngineParams,
164
- ) -> float | npt.NDArray[np.float64]:
164
+ ) -> ArrayOrFloat:
165
165
  r"""
166
166
  Calculate the excess thrust coefficient available at specified operation condition.
167
167
 
168
168
  Parameters
169
169
  ----------
170
- mach_number : float | npt.NDArray[np.float64]
170
+ mach_number : ArrayOrFloat
171
171
  Mach number at each waypoint
172
- air_temperature : float | npt.NDArray[np.float64]
172
+ air_temperature : ArrayOrFloat
173
173
  Ambient temperature at each waypoint, [:math:`K`]
174
- air_pressure : float | npt.NDArray[np.float64]
174
+ air_pressure : ArrayOrFloat
175
175
  Ambient pressure, [:math:`Pa`]
176
- aircraft_mass : float | npt.NDArray[np.float64]
176
+ aircraft_mass : ArrayOrFloat
177
177
  Aircraft mass at each waypoint, [:math:`kg`]
178
- theta : float | npt.NDArray[np.float64]
178
+ theta : ArrayOrFloat
179
179
  Climb (positive value) or descent (negative value) angle, [:math:`\deg`]
180
180
  atyp_param : PSAircraftEngineParams
181
181
  Extracted aircraft and engine parameters.
182
182
 
183
183
  Returns
184
184
  -------
185
- float | npt.NDArray[np.float64]
185
+ ArrayOrFloat
186
186
  The difference between the maximum rated thrust coefficient and the thrust coefficient
187
187
  required to maintain the current mach_number.
188
188
  """
@@ -217,7 +217,7 @@ def get_excess_thrust_available(
217
217
  )
218
218
 
219
219
  tas = units.mach_number_to_tas(mach_number, air_temperature)
220
- req_thrust_coeff = required_thrust_coefficient(c_lift, c_drag, tas)
220
+ req_thrust_coeff = required_thrust_coefficient(c_lift, c_drag, tas) # type: ignore[type-var]
221
221
 
222
222
  c_t_eta_b = thrust_coefficient_at_max_efficiency(
223
223
  mach_number, atyp_param.m_des, atyp_param.c_t_des
@@ -226,7 +226,7 @@ def get_excess_thrust_available(
226
226
  air_temperature, mach_number, c_t_eta_b, atyp_param
227
227
  )
228
228
 
229
- return max_thrust_coeff - req_thrust_coeff
229
+ return max_thrust_coeff - req_thrust_coeff # type: ignore[return-value]
230
230
 
231
231
 
232
232
  def _normalised_max_throttle_parameter(
@@ -350,49 +350,47 @@ def max_usable_lift_coefficient(
350
350
 
351
351
 
352
352
  def minimum_mach_num(
353
- air_pressure: float,
354
- aircraft_mass: float,
353
+ air_pressure: ArrayOrFloat,
354
+ aircraft_mass: ArrayOrFloat,
355
355
  atyp_param: PSAircraftEngineParams,
356
- ) -> float:
356
+ ) -> ArrayOrFloat:
357
357
  """
358
358
  Calculate minimum mach number to avoid stall.
359
359
 
360
360
  Parameters
361
361
  ----------
362
- air_pressure : float
362
+ air_pressure : ArrayOrFloat
363
363
  Ambient pressure, [:math:`Pa`]
364
- aircraft_mass : float
364
+ aircraft_mass : ArrayOrFloat
365
365
  Aircraft mass at each waypoint, [:math:`kg`]
366
366
  atyp_param : PSAircraftEngineParams
367
367
  Extracted aircraft and engine parameters.
368
368
 
369
369
  Returns
370
370
  -------
371
- float
372
- Maximum usable lift coefficient.
371
+ ArrayOrFloat
372
+ Minimum mach number to avoid stall.
373
373
  """
374
374
 
375
375
  def excess_mass(
376
- mach_number: float,
377
- air_pressure: float,
378
- aircraft_mass: float,
376
+ mach_number: ArrayOrFloat,
377
+ air_pressure: ArrayOrFloat,
378
+ aircraft_mass: ArrayOrFloat,
379
379
  mach_num_des: float,
380
380
  c_l_do: float,
381
381
  wing_surface_area: float,
382
- ) -> float:
382
+ ) -> ArrayOrFloat:
383
383
  amass_max = max_allowable_aircraft_mass(
384
384
  air_pressure,
385
385
  mach_number,
386
386
  mach_num_des,
387
387
  c_l_do,
388
388
  wing_surface_area,
389
- 1e10,
389
+ 1e10, # clipped to this value which we want to ignore
390
390
  )
391
- if amass_max < 0:
392
- return np.nan
393
391
  return amass_max - aircraft_mass
394
392
 
395
- m = scipy.optimize.root_scalar(
393
+ m = scipy.optimize.newton(
396
394
  excess_mass,
397
395
  args=(
398
396
  air_pressure,
@@ -401,21 +399,22 @@ def minimum_mach_num(
401
399
  atyp_param.c_l_do,
402
400
  atyp_param.wing_surface_area,
403
401
  ),
404
- x0=0.5,
405
- x1=0.6,
406
- ).root
402
+ x0=np.full_like(air_pressure, 0.4),
403
+ x1=np.full_like(air_pressure, 0.5),
404
+ tol=1e-4,
405
+ )
407
406
 
408
407
  return m
409
408
 
410
409
 
411
410
  def maximum_mach_num(
412
- altitude_ft: float,
413
- air_pressure: float,
414
- aircraft_mass: float,
415
- air_temperature: float,
416
- theta: float,
411
+ altitude_ft: ArrayOrFloat,
412
+ air_pressure: ArrayOrFloat,
413
+ aircraft_mass: ArrayOrFloat,
414
+ air_temperature: ArrayOrFloat,
415
+ theta: ArrayOrFloat,
417
416
  atyp_param: PSAircraftEngineParams,
418
- ) -> float:
417
+ ) -> ArrayOrFloat:
419
418
  r"""
420
419
  Return the maximum mach number at the current operating conditions.
421
420
 
@@ -424,23 +423,23 @@ def maximum_mach_num(
424
423
 
425
424
  Parameters
426
425
  ----------
427
- altitude_ft : float
426
+ altitude_ft : ArrayOrFloat
428
427
  Altitude, [:math:`ft`]
429
- air_pressure : float
428
+ air_pressure : ArrayOrFloat
430
429
  Ambient pressure, [:math:`Pa`]
431
- aircraft_mass : float
430
+ aircraft_mass : ArrayOrFloat
432
431
  Aircraft mass at each waypoint, [:math:`kg`]
433
- air_temperature : npt.NDArray[np.float64]
432
+ air_temperature : ArrayOrFloat
434
433
  Array of ambient temperature, [:math: `K`]
435
- theta : float | npt.NDArray[np.float64]
434
+ theta : ArrayOrFloat
436
435
  Climb (positive value) or descent (negative value) angle, [:math:`\deg`]
437
436
  atyp_param : PSAircraftEngineParams
438
437
  Extracted aircraft and engine parameters.
439
438
 
440
439
  Returns
441
440
  -------
442
- float
443
- Maximum usable lift coefficient.
441
+ ArrayOrFloat
442
+ Maximum mach number given thrust limiations.
444
443
  """
445
444
  # Max speed ignoring thrust limits
446
445
  mach_num_op_lim = max_mach_number_by_altitude(
@@ -451,27 +450,15 @@ def maximum_mach_num(
451
450
  atyp_param.p_inf_co,
452
451
  )
453
452
 
454
- # If the max mach number ignoring thrust limits is possible, return that value
455
- if (
456
- get_excess_thrust_available(
457
- mach_num_op_lim, air_temperature, air_pressure, aircraft_mass, theta, atyp_param
458
- )
459
- > 0
460
- ):
461
- return mach_num_op_lim
462
-
463
- # Numerically solve for the speed where drag == max thrust
464
- try:
465
- m_max = scipy.optimize.root_scalar(
466
- get_excess_thrust_available,
467
- args=(air_temperature, air_pressure, aircraft_mass, theta, atyp_param),
468
- x0=mach_num_op_lim,
469
- x1=mach_num_op_lim - 0.05,
470
- ).root
471
- except ValueError:
472
- return np.nan
453
+ max_mach = scipy.optimize.newton(
454
+ func=get_excess_thrust_available,
455
+ args=(air_temperature, air_pressure, aircraft_mass, theta, atyp_param),
456
+ x0=mach_num_op_lim,
457
+ x1=mach_num_op_lim - 0.01,
458
+ tol=1e-4,
459
+ ).clip(max=mach_num_op_lim)
473
460
 
474
- return m_max
461
+ return max_mach
475
462
 
476
463
 
477
464
  # ----------------
@@ -479,7 +466,9 @@ def maximum_mach_num(
479
466
  # ----------------
480
467
 
481
468
 
482
- def fuel_flow_idle(fuel_flow_idle_sls: float, altitude_ft: ArrayOrFloat) -> npt.NDArray[np.float64]:
469
+ def fuel_flow_idle(
470
+ fuel_flow_idle_sls: float, altitude_ft: ArrayOrFloat
471
+ ) -> npt.NDArray[np.floating]:
483
472
  r"""Calculate minimum fuel mass flow rate at flight idle conditions.
484
473
 
485
474
  Parameters
@@ -491,7 +480,7 @@ def fuel_flow_idle(fuel_flow_idle_sls: float, altitude_ft: ArrayOrFloat) -> npt.
491
480
 
492
481
  Returns
493
482
  -------
494
- npt.NDArray[np.float64]
483
+ npt.NDArray[np.floating]
495
484
  Fuel mass flow rate at flight idle conditions, [:math:`kg \ s^{-1}`]
496
485
  """
497
486
  x = altitude_ft / 10000.0
@@ -504,7 +493,7 @@ def max_fuel_flow(
504
493
  mach_number: ArrayOrFloat,
505
494
  fuel_flow_max_sls: float,
506
495
  flight_phase: npt.NDArray[np.uint8] | flight.FlightPhase,
507
- ) -> npt.NDArray[np.float64]:
496
+ ) -> npt.NDArray[np.floating]:
508
497
  r"""Correct maximum fuel mass flow rate that can be supplied by the engine.
509
498
 
510
499
  Parameters
@@ -522,7 +511,7 @@ def max_fuel_flow(
522
511
 
523
512
  Returns
524
513
  -------
525
- npt.NDArray[np.float64]
514
+ npt.NDArray[np.floating]
526
515
  Maximum allowable fuel mass flow rate, [:math:`kg \ s^{-1}`]
527
516
  """
528
517
  ff_max = jet.equivalent_fuel_flow_rate_at_cruise(
@@ -80,7 +80,14 @@ def tau_cirrus(met: MetDataset) -> xr.DataArray:
80
80
  met.data["air_pressure"],
81
81
  )
82
82
 
83
- dz = -dask.array.gradient(geopotential_height, axis=geopotential_height.get_axis_num("level"))
83
+ # dask.array.gradient expects at least 2 elements in each chunk
84
+ level_axis = geopotential_height.get_axis_num("level")
85
+ if geopotential_height.chunks:
86
+ level_chunks = geopotential_height.chunks[level_axis] # type: ignore[call-overload, index]
87
+ if any(chunk < 2 for chunk in level_chunks):
88
+ geopotential_height = geopotential_height.chunk(level=-1)
89
+
90
+ dz = -dask.array.gradient(geopotential_height, axis=level_axis)
84
91
  dz = xr.DataArray(dz, dims=geopotential_height.dims)
85
92
 
86
93
  da = beta_e * dz