|
2 | 2 | import xarray as xr |
3 | 3 |
|
4 | 4 |
|
5 | | -def generate_grid_parameters(bathy_data: xr.DataArray) -> dict: |
| 5 | +def generate_grid_parameters( |
| 6 | + bathy_data: xr.DataArray, |
| 7 | + alpc: float = 0, |
| 8 | + xpc: float = None, |
| 9 | + ypc: float = None, |
| 10 | + xlenc: float = None, |
| 11 | + ylenc: float = None, |
| 12 | + buffer_distance: float = None, |
| 13 | +) -> dict: |
6 | 14 | """ |
7 | | - Generate the grid parameters for the SWAN model. |
| 15 | + Generate grid parameters for the SWAN model based on bathymetry. |
8 | 16 |
|
9 | 17 | Parameters |
10 | 18 | ---------- |
11 | 19 | bathy_data : xr.DataArray |
12 | | - Bathymetry data. |
| 20 | + Bathymetry data. |
13 | 21 | Must have the following dimensions: |
14 | | - - lon: longitude |
15 | | - - lat: latitude |
| 22 | + - lon/x: longitude or x coordinate |
| 23 | + - lat/y: latitude or y coordinate |
| 24 | + alpc: float |
| 25 | + Computational Grid Rotation angle in degrees. |
| 26 | + xpc: float |
| 27 | + X origin. |
| 28 | + ypc: float |
| 29 | + Y origin. |
16 | 30 |
|
17 | 31 | Returns |
18 | 32 | ------- |
19 | 33 | dict |
20 | | - Grid parameters for the SWAN model. |
21 | | -
|
22 | | - Contact @bellidog on GitHub for more information. |
| 34 | + Dictionary with grid configuration for SWAN input. |
23 | 35 | """ |
24 | 36 |
|
25 | | - return { |
26 | | - "xpc": int(np.nanmin(bathy_data.lon)), # x origin |
27 | | - "ypc": int(np.nanmin(bathy_data.lat)), # y origin |
28 | | - "alpc": 0, # x-axis direction |
29 | | - "xlenc": int( |
30 | | - np.nanmax(bathy_data.lon) - np.nanmin(bathy_data.lon) |
31 | | - ), # grid length in x |
32 | | - "ylenc": int( |
33 | | - np.nanmax(bathy_data.lat) - np.nanmin(bathy_data.lat) |
34 | | - ), # grid length in y |
35 | | - "mxc": len(bathy_data.lon) - 1, # number mesh x, una menos pq si no SWAN peta |
36 | | - "myc": len(bathy_data.lat) - 1, # number mesh y, una menos pq si no SWAN peta |
37 | | - "xpinp": np.nanmin(bathy_data.lon), # x origin |
38 | | - "ypinp": np.nanmin(bathy_data.lat), # y origin |
39 | | - "alpinp": 0, # x-axis direction |
40 | | - "mxinp": len(bathy_data.lon) - 1, # number mesh x |
41 | | - "myinp": len(bathy_data.lat) - 1, # number mesh y |
42 | | - "dxinp": abs( |
43 | | - bathy_data.lon[1].values - bathy_data.lon[0].values |
44 | | - ), # size mesh x (resolution in x) |
45 | | - "dyinp": abs( |
46 | | - bathy_data.lat[1].values - bathy_data.lat[0].values |
47 | | - ), # size mesh y (resolution in y) |
48 | | - } |
| 37 | + # Determine coordinate system based on coordinate names |
| 38 | + coord_names = list(bathy_data.coords) |
| 39 | + |
| 40 | + # Get coordinate variables |
| 41 | + if any(name in ["lon", "longitude"] for name in coord_names): |
| 42 | + x_coord = next(name for name in coord_names if name in ["lon", "longitude"]) |
| 43 | + y_coord = next(name for name in coord_names if name in ["lat", "latitude"]) |
| 44 | + else: |
| 45 | + x_coord = next( |
| 46 | + name for name in coord_names if name in ["x", "X", "cx", "easting"] |
| 47 | + ) |
| 48 | + y_coord = next( |
| 49 | + name for name in coord_names if name in ["y", "Y", "cy", "northing"] |
| 50 | + ) |
| 51 | + |
| 52 | + # Get resolution from cropped data |
| 53 | + grid_resolution_x = abs( |
| 54 | + bathy_data[x_coord][1].values - bathy_data[x_coord][0].values |
| 55 | + ) |
| 56 | + grid_resolution_y = abs( |
| 57 | + bathy_data[y_coord][1].values - bathy_data[y_coord][0].values |
| 58 | + ) |
| 59 | + |
| 60 | + if alpc != 0: |
| 61 | + angle_rad = np.radians(alpc) |
| 62 | + # Create rotation matrix |
| 63 | + R = np.array( |
| 64 | + [ |
| 65 | + [np.cos(angle_rad), -np.sin(angle_rad)], |
| 66 | + [np.sin(angle_rad), np.cos(angle_rad)], |
| 67 | + ] |
| 68 | + ) |
| 69 | + |
| 70 | + # Create unrotated rectangle corners |
| 71 | + dx = np.array([0, xlenc, xlenc, 0, 0]) |
| 72 | + dy = np.array([0, 0, ylenc, ylenc, 0]) |
| 73 | + points = np.column_stack([dx, dy]) |
| 74 | + |
| 75 | + # Rotate points |
| 76 | + rotated = np.dot(points, R.T) |
| 77 | + |
| 78 | + # Translate to corner position |
| 79 | + x = rotated[:, 0] + xpc |
| 80 | + y = rotated[:, 1] + ypc |
| 81 | + corners = np.column_stack([x, y]) |
| 82 | + |
| 83 | + x_min = np.min(x) - buffer_distance |
| 84 | + x_max = np.max(x) + buffer_distance |
| 85 | + y_min = np.min(y) - buffer_distance |
| 86 | + y_max = np.max(y) + buffer_distance |
| 87 | + |
| 88 | + print(f"Cropping bounds: x=[{x_min}, {x_max}], y=[{y_min}, {y_max}]") |
| 89 | + |
| 90 | + # Crop bathymetry |
| 91 | + cropped = bathy_data.sel( |
| 92 | + { |
| 93 | + x_coord: slice(x_min, x_max), |
| 94 | + y_coord: slice(y_max, y_min), |
| 95 | + } # Note: slice from max to min for descending coordinates |
| 96 | + ) |
| 97 | + |
| 98 | + grid_parameters = { |
| 99 | + "xpc": xpc, |
| 100 | + "ypc": ypc, |
| 101 | + "alpc": alpc, |
| 102 | + "xlenc": xlenc, |
| 103 | + "ylenc": ylenc, |
| 104 | + "mxc": int(np.round(xlenc / grid_resolution_x) - 1), |
| 105 | + "myc": int(np.round(ylenc / grid_resolution_y) - 1), |
| 106 | + "xpinp": np.nanmin(cropped[x_coord]), # x origin from cropped data |
| 107 | + "ypinp": np.nanmin(cropped[y_coord]), # y origin from cropped data |
| 108 | + "alpinp": 0, # x-axis direction |
| 109 | + "mxinp": len(cropped[x_coord]) - 1, # number mesh x from cropped data |
| 110 | + "myinp": len(cropped[y_coord]) - 1, # number mesh y from cropped data |
| 111 | + "dxinp": grid_resolution_x, # resolution from cropped data |
| 112 | + "dyinp": grid_resolution_y, # resolution from cropped data |
| 113 | + } |
| 114 | + return grid_parameters, cropped, corners |
| 115 | + |
| 116 | + else: |
| 117 | + # Compute parameters from full bathymetry |
| 118 | + grid_parameters = { |
| 119 | + "xpc": float(np.nanmin(bathy_data[x_coord])), # origin x |
| 120 | + "ypc": float(np.nanmin(bathy_data[y_coord])), # origin y |
| 121 | + "alpc": alpc, # x-axis direction |
| 122 | + "xlenc": float( |
| 123 | + np.nanmax(bathy_data[x_coord]) - np.nanmin(bathy_data[x_coord]) |
| 124 | + ), # grid length x |
| 125 | + "ylenc": float( |
| 126 | + np.nanmax(bathy_data[y_coord]) - np.nanmin(bathy_data[y_coord]) |
| 127 | + ), # grid length y |
| 128 | + "mxc": len(bathy_data[x_coord]) - 1, # num mesh x |
| 129 | + "myc": len(bathy_data[y_coord]) - 1, # num mesh y |
| 130 | + "xpinp": float(np.nanmin(bathy_data[x_coord])), # origin x |
| 131 | + "ypinp": float(np.nanmin(bathy_data[y_coord])), # origin y |
| 132 | + "alpinp": 0, # x-axis direction |
| 133 | + "mxinp": len(bathy_data[x_coord]) - 1, # num mesh x |
| 134 | + "myinp": len(bathy_data[y_coord]) - 1, # num mesh y |
| 135 | + "dxinp": float( |
| 136 | + abs(bathy_data[x_coord][1].values - bathy_data[x_coord][0].values) |
| 137 | + ), # resolution x |
| 138 | + "dyinp": float( |
| 139 | + abs(bathy_data[y_coord][1].values - bathy_data[y_coord][0].values) |
| 140 | + ), # resolution y |
| 141 | + } |
| 142 | + return grid_parameters |
0 commit comments