Skip to content

Commit d309f4a

Browse files
authored
Merge pull request #108 from GeoOcean/88-document-and-test-greensurge-and-ocsmesh
[EJP] add function vortex2delft_3D_FM_nc
2 parents c8d8bac + 5b4ca44 commit d309f4a

File tree

2 files changed

+149
-1
lines changed

2 files changed

+149
-1
lines changed

bluemath_tk/core/plotting/utils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ def join_colormaps(
105105

106106
bounds1 = np.linspace(value_range1[0], value_range1[1], 129)
107107
bounds2 = np.linspace(value_range2[0], value_range2[1], 129)
108-
all_bounds = np.concatenate([bounds1[:-1], bounds2])
108+
all_bounds = np.sort(np.concatenate([bounds1[:-1], bounds2]))
109109

110110
norm = BoundaryNorm(boundaries=all_bounds, ncolors=len(newcolors))
111111

bluemath_tk/tcs/vortex.py

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
1+
from datetime import datetime
2+
from os import path as op
3+
14
import numpy as np
25
import pandas as pd
36
import xarray as xr
7+
from scipy.interpolate import RegularGridInterpolator
48

59
from ..core.geo import geo_distance_cartesian, geodesic_distance
610

@@ -209,3 +213,147 @@ def vortex_model_grid(
209213
},
210214
coords={ylab: cg_lat, xlab: cg_lon, "time": times},
211215
)
216+
217+
218+
def vortex2delft_3D_FM_nc(
219+
mesh: xr.Dataset,
220+
ds_vortex: xr.Dataset,
221+
path_output: str,
222+
ds_name: str = "forcing_Tonga_vortex.nc",
223+
fotcing_ext: str = "GreenSurge_GFDcase_wind.ext",
224+
) -> None:
225+
"""
226+
Convert the vortex dataset to a Delft3D FM compatible netCDF forcing file.
227+
228+
Parameters
229+
----------
230+
mesh : xarray.Dataset
231+
The mesh dataset containing the node coordinates.
232+
ds_vortex : xarray.Dataset
233+
The vortex dataset containing wind speed and pressure data.
234+
path_output : str
235+
The output path where the netCDF file will be saved.
236+
ds_name : str
237+
The name of the output netCDF file, default is "forcing_Tonga_vortex.nc".
238+
forcing_ext : str
239+
The extension for the forcing file, default is "GreenSurge_GFDcase_wind.ext".
240+
"""
241+
longitude = mesh.mesh2d_node_x.values
242+
latitude = mesh.mesh2d_node_y.values
243+
n_time = ds_vortex.time.size
244+
245+
lat_interp = xr.DataArray(latitude, dims="node")
246+
lon_interp = xr.DataArray(longitude, dims="node")
247+
248+
angle = np.deg2rad((270 - ds_vortex.Dir.values) % 360)
249+
W = ds_vortex.W.values
250+
251+
ds_vortex_interp = ds_vortex.drop_vars(["Dir", "W"])
252+
253+
ds_vortex_interp["windx"] = (
254+
(
255+
"lat",
256+
"lon",
257+
"time",
258+
),
259+
(W * np.cos(angle)).astype(np.float32),
260+
)
261+
ds_vortex_interp["windy"] = (
262+
("lat", "lon", "time"),
263+
(W * np.sin(angle)).astype(np.float32),
264+
)
265+
266+
ds_vortex_interp = ds_vortex_interp.rename(
267+
{
268+
"p": "airpressure",
269+
"lon": "longitude",
270+
"lat": "latitude",
271+
}
272+
)
273+
274+
forcing_dataset = ds_vortex_interp.interp(
275+
latitude=lat_interp, longitude=lon_interp
276+
).transpose("time", "node")
277+
forcing_dataset["time"] = np.arange(n_time)
278+
279+
reference_date_str = (
280+
ds_vortex.time.values[0]
281+
.astype("M8[ms]")
282+
.astype(datetime)
283+
.strftime("%Y-%m-%d %H:%M:%S")
284+
)
285+
286+
forcing_dataset["windx"].attrs = {
287+
"coordinates": "time node",
288+
"long_name": "Wind speed in x direction",
289+
"standard_name": "windx",
290+
"units": "m s-1",
291+
}
292+
forcing_dataset["windy"].attrs = {
293+
"coordinates": "time node",
294+
"long_name": "Wind speed in y direction",
295+
"standard_name": "windy",
296+
"units": "m s-1",
297+
}
298+
299+
forcing_dataset["airpressure"].attrs = {
300+
"coordinates": "time node",
301+
"long_name": "Atmospheric Pressure",
302+
"standard_name": "air_pressure",
303+
"units": "Pa",
304+
}
305+
306+
forcing_dataset["time"].attrs = {
307+
"standard_name": "time",
308+
"long_name": f"Time - hours since {reference_date_str} +00:00",
309+
"time_origin": f"{reference_date_str}",
310+
"units": f"hours since {reference_date_str} +00:00",
311+
"calendar": "gregorian",
312+
"description": "Time definition for the forcing data",
313+
}
314+
315+
forcing_dataset["longitude"].attrs = {
316+
"description": "Longitude of each mesh node of the computational grid",
317+
"standard_name": "longitude",
318+
"long_name": "longitude",
319+
"units": "degrees_east",
320+
}
321+
forcing_dataset["latitude"].attrs = {
322+
"description": "Latitude of each mesh node of the computational grid",
323+
"standard_name": "latitude",
324+
"long_name": "latitude",
325+
"units": "degrees_north",
326+
}
327+
328+
forcing_dataset.to_netcdf(
329+
op.join(path_output, ds_name),
330+
"w",
331+
"NETCDF3_CLASSIC",
332+
unlimited_dims="time",
333+
)
334+
335+
texte = f"""QUANTITY=windx
336+
FILENAME={ds_name}
337+
VARNAME =windx
338+
FILETYPE=11
339+
METHOD=3
340+
OPERAND=O
341+
342+
QUANTITY=windy
343+
FILENAME={ds_name}
344+
VARNAME =windy
345+
FILETYPE=11
346+
METHOD=3
347+
OPERAND=O
348+
349+
QUANTITY=airpressure
350+
FILENAME={ds_name}
351+
VARNAME =airpressure
352+
FILETYPE=11
353+
METHOD=3
354+
OPERAND=O"""
355+
356+
with open(
357+
op.join(path_output, fotcing_ext), "w", encoding="utf-8"
358+
) as f:
359+
f.write(texte)

0 commit comments

Comments
 (0)