-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathwind.qmd
More file actions
149 lines (101 loc) · 5.15 KB
/
wind.qmd
File metadata and controls
149 lines (101 loc) · 5.15 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
# 🌪️ Wind optimal flights
Flight trajectory optimization considering wind conditions is crucial for efficient flight planning. Wind can significantly impact flight time, fuel consumption, and overall flight efficiency. For example, a favorable tailwind can help reduce flight time and fuel burn, while headwinds can have the opposite effect.
There are two main approaches to incorporate wind data when using `opentop` trajectory optimization:
1. The first approach uses the FastMeteo API to access ERA meteorological data stored in cloud-optimized Zarr format on Google Cloud Storage. This method provides efficient access to wind data through API calls without requiring large local datasets. It's particularly suitable for single flight optimizations where direct data access is preferred.
2. The second approach works with pre-downloaded GRIB files from ECMWF or GFS sources. This method is more suitable for batch processing number of flights with larger RAM resources, though it requires downloading and storing weather data files locally.
## Obtaining wind with fastmeteo
It is also possible to include 3D or 4D wind data in the optimization. The following code provides an example of such a use case. Note that the wind data is obtained using `fastmeteo` library in this example.
```{python}
import numpy as np
import pandas as pd
import openap
from fastmeteo.source import ArcoEra5
import opentop as top
import warnings
warnings.filterwarnings("ignore")
```
```{python}
actype = "A320"
origin = "EHAM"
destination = "LGAV"
m0 = 0.85
```
Next, we need to get an example wind field data using the `fastmeteo` library. Note the selected ERA5 data will be cached temporarily at `/tmp/era5-zarr`.
```{python}
# get the boundary of the wind field
o = openap.nav.airport(origin)
d = openap.nav.airport(destination)
latmin = round(min(o["lat"], d["lat"])) - 2
latmax = round(max(o["lat"], d["lat"])) + 2
lonmin = round(min(o["lon"], d["lon"])) - 4
lonmax = round(max(o["lon"], d["lon"])) + 4
# create the and flatten the wind grid
latitudes = np.arange(latmin, latmax, 0.5)
longitudes = np.arange(lonmin, lonmax, 1)
altitudes = np.arange(1000, 46000, 2000)
timestamps = pd.date_range("2021-05-01 08:00:00", "2021-05-01 11:00:00", freq="1h")
latitudes, longitudes, altitudes, times = np.meshgrid(
latitudes, longitudes, altitudes, timestamps
)
grid = pd.DataFrame().assign(
latitude=latitudes.flatten(),
longitude=longitudes.flatten(),
altitude=altitudes.flatten(),
timestamp=times.flatten(),
)
# obtain the wind based on the grid
fmg = ArcoEra5(local_store="/tmp/era5-zarr")
meteo_data = fmg.interpolate(grid)
```
Let's take a look at the meteorological data we got:
```{python}
meteo_data.head()
```
Before passing this wind field to the optimizer, we need to format it correctly. The wind data needs to be in `pandas.DataFrame` with the following columns:
- `ts`: timestamp in seconds, with `0` representing the time of departure of the flight
- `latitude`: latitude of all the grid points
- `longitude`: longitude of all the grid points
- `h`: height of the grid points, in meters
- `u`: u component of the wind for each grid point, in m/s
- `v`: v component of the wind for each grid point, in m/s
```{python}
wind = (
meteo_data.rename(
columns={
"u_component_of_wind": "u",
"v_component_of_wind": "v",
}
)
.assign(ts=lambda x: (x.timestamp - x.timestamp.iloc[0]).dt.total_seconds())
.eval("h=altitude * 0.3048")
)[["ts", "latitude", "longitude", "h", "u", "v"]]
wind.head()
```
Last, we can run the optimization with the wind field and visulize the result:
```{python}
import matplotlib.pyplot as plt
optimizer = top.CompleteFlight(actype, origin, destination, m0)
optimizer.enable_wind(wind)
flight = optimizer.trajectory(objective="fuel")
top.vis.trajectory(flight, windfield=wind, barb_steps=15)
plt.show()
```
If you only want to visualize the map:
```{python}
top.vis.map(flight, windfield=wind, barb_steps=15)
plt.show()
```
## Using grid wind files
You can also optimize the trajectory with grid atmospheric data, for example, `grib` or `nc` files downloaded from the ECMWF or GFS. In `TOP`, there is a built-in function `top.tools.read_grids()` that can be used to process grid data files into a `DataFrame` for the optimizer.
```{python}
#| eval: false
# read the downloaded ERA5 grib data, the arguments can be a list of files.
wind = top.tools.read_grids("tmp/era5_2021-05-01_0800.grib")
optimizer = top.CompleteFlight(actype, origin, destination, m0)
optimizer.enable_wind(wind)
flight = optimizer.trajectory(objective="fuel")
top.vis.trajectory(flight, windfield=wind, barb_steps=25)
plt.show()
```
Since the grib data from a similar time frame was downloaded, we can observe that the result is similar to the one from the previous section. The advantage is that the code is relatively simple compared to the previous example, which used `fastmeteo` to download data that covers the region of the flights.
However, this approach requires a large quantity of grid data to be downloaded first. The `read_grids()` function also loads the entire grid files into RAM, which can be memory intensive if many grid files are loaded.