Skip to content

Commit 345d114

Browse files
authored
Merge pull request #13 from FESOM/latlon_support
Add support for lat-lon grids. Fix installation bugs
2 parents dedda40 + ce183e4 commit 345d114

16 files changed

Lines changed: 1247 additions & 14 deletions

examples/lat_long_grid_example.ipynb

Lines changed: 786 additions & 0 deletions
Large diffs are not rendered by default.

pyproject.toml

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,4 @@ platforms = ["any"]
4141
zip-safe = false
4242
include-package-data = true
4343

44-
[tool.setuptools.packages.find]
45-
where = ["implicit_filter"]
46-
include = ["implicit_filter*"]
47-
4844

readme.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,10 @@
77
[![arXiv](https://img.shields.io/badge/arXiv-2404.07398-b31b1b.svg)](https://arxiv.org/abs/2404.07398)
88

99
The Implicit Filter Python Package provides a collection of classes for filtering data using implicit filtering techniques.
10-
Currently FESOM and NEMO meshes are supported.
10+
Currently FESOM, NEMO and longitude-latitude meshes are supported.
11+
12+
For ICON please use this [fork](https://github.com/wienkers/implicit_filter_ICON) made by Aaron Wienkers.
13+
In the future it will be integrated into the main repository.
1114

1215
For optimal performance usage of Nvidia GPU is highly recommended.
1316

Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
from .jax_filter import JaxFilter
22
from .numpy_filter import NumpyFilter
33
from .nemo_filter import NemoNumpyFilter
4+
from .latlon_filter import LatLonNumpyFilter
45
from ._auxiliary import make_tri, convert_to_wavenumbers
56

6-
# If CuPy is not installed this class won't be imported
7+
# If CuPy isn't installed, this classes won't be imported
78
try:
89
from .cupy_filter import CuPyFilter
910
from .nemo_cupy_filter import NemoCupyFilter
11+
from .latlon_cupy_filter import LatLonCupyFilter
1012
except ModuleNotFoundError:
1113
pass
Lines changed: 209 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -154,12 +154,12 @@ def calculate_global_nemo_neighbourhood(e2d: int, nx: int, ny: int, north_adj: p
154154
xc = nx # Number of cells in x axis
155155

156156
# Fill ee_pos, arrangement is W;N;E;S
157-
ee_pos[:, 0] = np.array([xc * (yc - 1), 1, yc, 0]) # Corner
157+
ee_pos[:, 0] = np.array([yc * (xc - 1), 1, yc, 0]) # Corner
158158
# print(f"x: {0} y: {0} ni: {0}")
159159
# ids.add(0)
160160
nza += 3
161161
for m in range(1, yc - 1):
162-
ee_pos[:, m] = [xc * (yc - 1) + m, m + 1, m + yc, m - 1] # Left border
162+
ee_pos[:, m] = [yc * (xc - 1) + m, m + 1, m + yc, m - 1] # Left border
163163
# ids.add(m)
164164
# print(f"x: {0} y: {m} ni: {m}")
165165
nza += 4
@@ -188,7 +188,7 @@ def calculate_global_nemo_neighbourhood(e2d: int, nx: int, ny: int, north_adj: p
188188
nza += 4
189189

190190
# print("Top border")
191-
# ni = no + (yc - 1)
191+
ni = no + (yc - 1)
192192
# print(f"Northern neighbour of {n + 1} is {north_adj[n + 1]}")
193193
ee_pos[:, ni] = [ni - yc, north_adj[n + 1] * yc - 1, ni + yc, ni - 1]
194194

@@ -221,3 +221,209 @@ def calculate_global_nemo_neighbourhood(e2d: int, nx: int, ny: int, north_adj: p
221221
nza += e2d
222222

223223
return ee_pos, nza
224+
225+
226+
def calculate_global_regular_neighbourhood(e2d: int, nx: int, ny: int) -> Tuple[np.ndarray, int]:
227+
"""
228+
Calculate the neighbourhood of each cell in regular global mesh.
229+
The Northern border is ignored
230+
231+
Parameters:
232+
----------
233+
e2d : int
234+
The total number of cells (elements) in the mesh.
235+
236+
nx : int
237+
Number of cells in X direction.
238+
239+
ny : int
240+
Number of cells in Y direction.
241+
242+
Returns:
243+
-------
244+
ee_pos : np.ndarray
245+
2D NumPy array of shape (4, e2d) containing indexes of neighboring cells.
246+
247+
nza : int
248+
The total number of unique elements in ee_pos.
249+
"""
250+
251+
ee_pos = np.zeros((4, e2d), dtype=np.int32)
252+
# ids = set()
253+
# Initialize nza
254+
nza = 0
255+
256+
yc = ny # Numer of cells in y axis
257+
xc = nx # Number of cells in x axis
258+
259+
# Fill ee_pos, arrangement is W;N;E;S
260+
ee_pos[:, 0] = np.array([yc * (xc - 1), 1, yc, 0]) # Corner
261+
# print(f"x: {0} y: {0} ni: {0}")
262+
# ids.add(0)
263+
nza += 3
264+
for m in range(1, yc - 1):
265+
ee_pos[:, m] = [yc * (xc - 1) + m, m + 1, m + yc, m - 1] # Left border
266+
# ids.add(m)
267+
# print(f"x: {0} y: {m} ni: {m}")
268+
nza += 4
269+
# print("Left")
270+
m = yc - 1
271+
# print(f"Northern neighbour of {1} is {north_adj[1]}")
272+
ee_pos[:, m] = [xc * yc - 1, m, m + yc, m - 1] # Second corner
273+
# ids.add(m)
274+
# print(f"x: {0} y: {m} ni: {ni}")
275+
nza += 3
276+
277+
for n in range(1, xc - 1): # Center
278+
# print("Bottom border")
279+
no = yc * n
280+
ni = no
281+
ee_pos[:, ni] = [ni - yc, ni + 1, ni + yc, ni]
282+
# if not ni in ids: ids.add(ni)
283+
# print(f"x: {n} y: {0} ni: {ni}")
284+
nza += 3
285+
# print("Inner center")
286+
for m in range(1, yc - 1):
287+
ni = no + m
288+
ee_pos[:, ni] = [ni - yc, ni + 1, ni + yc, ni - 1]
289+
# if not ni in ids: ids.add(ni)
290+
# print(f"x: {n} y: {m} ni: {ni}")
291+
nza += 4
292+
293+
# print("Top border")
294+
ni = no + (yc - 1)
295+
# print(f"Northern neighbour of {n + 1} is {north_adj[n + 1]}")
296+
ee_pos[:, ni] = [ni - yc, ni, ni + yc, ni - 1]
297+
298+
# if not ni in ids: ids.add(ni)
299+
# print(f"x: {n} y: {yc-1} ni: {ni}")
300+
nza += 3
301+
302+
no = yc * (xc - 1)
303+
ni = no
304+
ee_pos[:, ni] = [ni - yc, ni + 1, 0, ni] # Third corner
305+
# if not ni in ids: ids.add(ni)
306+
# print(f"x: {xc-1} y: {0} ni: {ni}")
307+
nza += 3
308+
# print("Right")
309+
for m in range(1, yc - 1): # Right border
310+
ni = no + m
311+
ee_pos[:, ni] = [ni - yc, ni + 1, m, ni - 1]
312+
# if not ni in ids: ids.add(ni)
313+
# print(f"x: {xc-1} y: {m} ni: {ni}")
314+
nza += 4
315+
316+
ni = no + (yc - 1)
317+
# print(f"Northern neighbour of {xc} is {north_adj[xc]}")
318+
ee_pos[:, ni] = [ni - yc, ni, yc - 1, ni - 1] # Fourth border
319+
# if not ni in ids: ids.add(ni)
320+
# print(f"x: {xc-1} y: {yc-1} ni: {ni}")
321+
nza += 3
322+
323+
# Final adjustment for nza
324+
nza += e2d
325+
326+
return ee_pos, nza
327+
328+
329+
def calculate_local_regular_neighbourhood(e2d: int, nx: int, ny: int) -> Tuple[np.ndarray, int]:
330+
"""
331+
Calculate the neighbourhood of each cell in regular local mesh.
332+
All periodic neighbours are ignored
333+
334+
Parameters:
335+
----------
336+
e2d : int
337+
The total number of cells (elements) in the mesh.
338+
339+
nx : int
340+
Number of cells in X direction.
341+
342+
ny : int
343+
Number of cells in Y direction.
344+
345+
Returns:
346+
-------
347+
ee_pos : np.ndarray
348+
2D NumPy array of shape (4, e2d) containing indexes of neighboring cells.
349+
350+
nza : int
351+
The total number of unique elements in ee_pos.
352+
"""
353+
354+
ee_pos = np.zeros((4, e2d), dtype=np.int32)
355+
# ids = set()
356+
# Initialize nza
357+
nza = 0
358+
359+
yc = ny # Numer of cells in y axis
360+
xc = nx # Number of cells in x axis
361+
362+
# Fill ee_pos, arrangement is W;N;E;S
363+
ee_pos[:, 0] = np.array([0, 1, yc, 0]) # Corner
364+
# print(f"x: {0} y: {0} ni: {0}")
365+
# ids.add(0)
366+
nza += 2
367+
for m in range(1, yc - 1):
368+
ee_pos[:, m] = [m, m + 1, m + yc, m - 1] # Left border
369+
# ids.add(m)
370+
# print(f"x: {0} y: {m} ni: {m}")
371+
nza += 3
372+
# print("Left")
373+
m = yc - 1
374+
# print(f"Northern neighbour of {1} is {north_adj[1]}")
375+
ee_pos[:, m] = [m, m, m + yc, m - 1] # Second corner
376+
# ids.add(m)
377+
# print(f"x: {0} y: {m} ni: {ni}")
378+
nza += 2
379+
380+
for n in range(1, xc - 1): # Center
381+
# print("Bottom border")
382+
no = yc * n
383+
ni = no
384+
ee_pos[:, ni] = [ni - yc, ni + 1, ni + yc, ni]
385+
# if not ni in ids: ids.add(ni)
386+
# print(f"x: {n} y: {0} ni: {ni}")
387+
nza += 3
388+
# print("Inner center")
389+
for m in range(1, yc - 1):
390+
ni = no + m
391+
ee_pos[:, ni] = [ni - yc, ni + 1, ni + yc, ni - 1]
392+
# if not ni in ids: ids.add(ni)
393+
# print(f"x: {n} y: {m} ni: {ni}")
394+
nza += 4
395+
396+
# print("Top border")
397+
ni = no + (yc - 1)
398+
# print(f"Northern neighbour of {n + 1} is {north_adj[n + 1]}")
399+
ee_pos[:, ni] = [ni - yc, ni, ni + yc, ni - 1]
400+
401+
# if not ni in ids: ids.add(ni)
402+
# print(f"x: {n} y: {yc-1} ni: {ni}")
403+
nza += 3
404+
405+
no = yc * (xc - 1)
406+
ni = no
407+
ee_pos[:, ni] = [ni - yc, ni + 1, ni, ni] # Third corner
408+
# if not ni in ids: ids.add(ni)
409+
# print(f"x: {xc-1} y: {0} ni: {ni}")
410+
nza += 2
411+
# print("Right")
412+
for m in range(1, yc - 1): # Right border
413+
ni = no + m
414+
ee_pos[:, ni] = [ni - yc, ni + 1, ni, ni - 1]
415+
# if not ni in ids: ids.add(ni)
416+
# print(f"x: {xc-1} y: {m} ni: {ni}")
417+
nza += 3
418+
419+
ni = no + (yc - 1)
420+
# print(f"Northern neighbour of {xc} is {north_adj[xc]}")
421+
ee_pos[:, ni] = [ni - yc, ni, ni, ni - 1] # Fourth border
422+
# if not ni in ids: ids.add(ni)
423+
# print(f"x: {xc-1} y: {yc-1} ni: {ni}")
424+
nza += 2
425+
426+
# Final adjustment for nza
427+
nza += e2d
428+
429+
return ee_pos, nza

0 commit comments

Comments
 (0)