Skip to content

Commit 02aee73

Browse files
merge conflict fixed
2 parents 57a9c3b + 4d31dbb commit 02aee73

File tree

5 files changed

+40
-110
lines changed

5 files changed

+40
-110
lines changed

docs/examples/tutorial_diffusion.ipynb

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,9 @@
118118
"import trajan as ta\n",
119119
"import xarray as xr\n",
120120
"\n",
121-
"import parcels"
121+
"import parcels\n",
122+
"from parcels.grid import GridType\n",
123+
"from parcels.tools.converters import Geographic, GeographicPolar, UnitConverter"
122124
]
123125
},
124126
{
@@ -471,8 +473,40 @@
471473
"x = fieldset.U.grid.lon\n",
472474
"y = fieldset.U.grid.lat\n",
473475
"\n",
476+
"\n",
477+
"def calc_cell_edge_sizes(grid):\n",
478+
" \"\"\"Calculate cell sizes based on numpy.gradient method.\n",
479+
"\n",
480+
" Currently only works for Rectilinear Grids. Operates in place adding a `cell_edge_sizes`\n",
481+
" attribute to the grid.\n",
482+
" \"\"\"\n",
483+
" assert grid._gtype in (GridType.RectilinearZGrid, GridType.RectilinearSGrid), (\n",
484+
" f\"_cell_edge_sizes() not implemented for {grid._gtype} grids. \"\n",
485+
" \"You can provide cell_edge_sizes yourself by in, e.g., \"\n",
486+
" \"NEMO using the e1u fields etc from the mesh_mask.nc file.\"\n",
487+
" )\n",
488+
"\n",
489+
" cell_edge_sizes_x = np.zeros((grid.ydim, grid.xdim), dtype=np.float32)\n",
490+
" cell_edge_sizes_y = np.zeros((grid.ydim, grid.xdim), dtype=np.float32)\n",
491+
"\n",
492+
" x_conv = GeographicPolar() if grid.mesh == \"spherical\" else UnitConverter()\n",
493+
" y_conv = Geographic() if grid.mesh == \"spherical\" else UnitConverter()\n",
494+
" for y, (lat, dy) in enumerate(zip(grid.lat, np.gradient(grid.lat), strict=False)):\n",
495+
" for x, (lon, dx) in enumerate(\n",
496+
" zip(grid.lon, np.gradient(grid.lon), strict=False)\n",
497+
" ):\n",
498+
" cell_edge_sizes_x[y, x] = x_conv.to_source(dx, grid.depth[0], lat, lon)\n",
499+
" cell_edge_sizes_y[y, x] = y_conv.to_source(dy, grid.depth[0], lat, lon)\n",
500+
" return cell_edge_sizes_x, cell_edge_sizes_y\n",
501+
"\n",
502+
"\n",
503+
"def calc_cell_areas(grid):\n",
504+
" cell_edge_sizes_x, cell_edge_sizes_y = calc_cell_edge_sizes(grid)\n",
505+
" return cell_edge_sizes_x * cell_edge_sizes_y\n",
506+
"\n",
507+
"\n",
474508
"cell_areas = parcels.Field(\n",
475-
" name=\"cell_areas\", data=fieldset.U.cell_areas(), lon=x, lat=y\n",
509+
" name=\"cell_areas\", data=calc_cell_areas(fieldset.U.grid), lon=x, lat=y\n",
476510
")\n",
477511
"fieldset.add_field(cell_areas)\n",
478512
"\n",
@@ -580,7 +614,7 @@
580614
],
581615
"metadata": {
582616
"kernelspec": {
583-
"display_name": "parcels",
617+
"display_name": "parcels-dev",
584618
"language": "python",
585619
"name": "python3"
586620
},
@@ -594,7 +628,7 @@
594628
"name": "python",
595629
"nbconvert_exporter": "python",
596630
"pygments_lexer": "ipython3",
597-
"version": "3.12.3"
631+
"version": "3.10.15"
598632
}
599633
},
600634
"nbformat": 4,

parcels/field.py

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@
4949
DeferredNetcdfFileBuffer,
5050
NetcdfFileBuffer,
5151
)
52-
from .grid import Grid, GridType, _calc_cell_areas
52+
from .grid import Grid, GridType
5353

5454
if TYPE_CHECKING:
5555
from parcels.fieldset import FieldSet
@@ -337,10 +337,6 @@ def depth(self):
337337
"""Depth defined on the Grid object"""
338338
return self.grid.depth
339339

340-
@property
341-
def cell_edge_sizes(self):
342-
return self.grid.cell_edge_sizes
343-
344340
@property
345341
def interp_method(self):
346342
return self._interp_method
@@ -870,13 +866,6 @@ def set_depth_from_field(self, field):
870866
if self.grid != field.grid:
871867
field.grid.depth_field = field
872868

873-
def cell_areas(self):
874-
"""Method to calculate cell sizes based on cell_edge_sizes.
875-
876-
Only works for Rectilinear Grids
877-
"""
878-
return _calc_cell_areas(self.grid)
879-
880869
def _search_indices(self, time, z, y, x, particle=None, search2D=False):
881870
tau, ti = self._time_index(time)
882871

parcels/grid.py

Lines changed: 1 addition & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import numpy.typing as npt
77

88
from parcels._typing import Mesh, UpdateStatus, assert_valid_mesh
9-
from parcels.tools.converters import Geographic, GeographicPolar, TimeConverter, UnitConverter
9+
from parcels.tools.converters import TimeConverter
1010
from parcels.tools.warnings import FieldSetWarning
1111

1212
__all__ = [
@@ -67,7 +67,6 @@ def __init__(
6767
assert isinstance(self.time_origin, TimeConverter), "time_origin needs to be a TimeConverter object"
6868
assert_valid_mesh(mesh)
6969
self._mesh = mesh
70-
self._cell_edge_sizes: dict[str, npt.NDArray] = {}
7170
self._zonal_periodic = False
7271
self._zonal_halo = 0
7372
self._meridional_halo = 0
@@ -136,10 +135,6 @@ def zonal_halo(self):
136135
def defer_load(self):
137136
return self._defer_load
138137

139-
@property
140-
def cell_edge_sizes(self):
141-
return self._cell_edge_sizes
142-
143138
@staticmethod
144139
def create_grid(
145140
lon: npt.ArrayLike,
@@ -633,34 +628,3 @@ def __init__(
633628
@property
634629
def zdim(self):
635630
return self.depth.shape[-3]
636-
637-
638-
def _calc_cell_edge_sizes(grid: RectilinearGrid) -> None:
639-
"""Method to calculate cell sizes based on numpy.gradient method.
640-
641-
Currently only works for Rectilinear Grids. Operates in place adding a `cell_edge_sizes`
642-
attribute to the grid.
643-
"""
644-
if not grid.cell_edge_sizes:
645-
if grid._gtype in (GridType.RectilinearZGrid, GridType.RectilinearSGrid): # type: ignore[attr-defined]
646-
grid.cell_edge_sizes["x"] = np.zeros((grid.ydim, grid.xdim), dtype=np.float32)
647-
grid.cell_edge_sizes["y"] = np.zeros((grid.ydim, grid.xdim), dtype=np.float32)
648-
649-
x_conv = GeographicPolar() if grid.mesh == "spherical" else UnitConverter()
650-
y_conv = Geographic() if grid.mesh == "spherical" else UnitConverter()
651-
for y, (lat, dy) in enumerate(zip(grid.lat, np.gradient(grid.lat), strict=False)):
652-
for x, (lon, dx) in enumerate(zip(grid.lon, np.gradient(grid.lon), strict=False)):
653-
grid.cell_edge_sizes["x"][y, x] = x_conv.to_source(dx, grid.depth[0], lat, lon)
654-
grid.cell_edge_sizes["y"][y, x] = y_conv.to_source(dy, grid.depth[0], lat, lon)
655-
else:
656-
raise ValueError(
657-
f"_cell_edge_sizes() not implemented for {grid._gtype} grids. " # type: ignore[attr-defined]
658-
"You can provide Field.grid.cell_edge_sizes yourself by in, e.g., "
659-
"NEMO using the e1u fields etc from the mesh_mask.nc file."
660-
)
661-
662-
663-
def _calc_cell_areas(grid: RectilinearGrid) -> np.ndarray:
664-
if not grid.cell_edge_sizes:
665-
_calc_cell_edge_sizes(grid)
666-
return grid.cell_edge_sizes["x"] * grid.cell_edge_sizes["y"]

tests/test_fieldset.py

Lines changed: 0 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -423,22 +423,6 @@ def test_fieldset_samegrids_from_data():
423423
assert fieldset1.U.grid == fieldset1.B.grid
424424

425425

426-
@pytest.mark.parametrize("dx, dy", [("e1u", "e2u"), ("e1v", "e2v")])
427-
def test_fieldset_celledgesizes_curvilinear(dx, dy):
428-
fname = str(TEST_DATA / "mask_nemo_cross_180lon.nc")
429-
filenames = {"dx": fname, "dy": fname, "mesh_mask": fname}
430-
variables = {"dx": dx, "dy": dy}
431-
dimensions = {"dx": {"lon": "glamu", "lat": "gphiu"}, "dy": {"lon": "glamu", "lat": "gphiu"}}
432-
fieldset = FieldSet.from_nemo(filenames, variables, dimensions)
433-
434-
# explicitly setting cell_edge_sizes from e1u and e2u etc
435-
fieldset.dx.grid.cell_edge_sizes["x"] = fieldset.dx.data
436-
fieldset.dx.grid.cell_edge_sizes["y"] = fieldset.dy.data
437-
438-
A = fieldset.dx.cell_areas()
439-
assert np.allclose(A, fieldset.dx.data * fieldset.dy.data)
440-
441-
442426
def test_fieldset_write_curvilinear(tmpdir):
443427
fname = str(TEST_DATA / "mask_nemo_cross_180lon.nc")
444428
filenames = {"dx": fname, "mesh_mask": fname}
@@ -472,21 +456,6 @@ def test_curv_fieldset_add_periodic_halo():
472456
fieldset.add_periodic_halo(zonal=3, meridional=2)
473457

474458

475-
@pytest.mark.parametrize("mesh", ["flat", "spherical"])
476-
def test_fieldset_cellareas(mesh):
477-
data, dimensions = generate_fieldset_data(10, 7)
478-
fieldset = FieldSet.from_data(data, dimensions, mesh=mesh)
479-
cell_areas = fieldset.V.cell_areas()
480-
if mesh == "flat":
481-
assert np.allclose(cell_areas.flatten(), cell_areas[0, 0], rtol=1e-3)
482-
else:
483-
assert all(
484-
(np.gradient(cell_areas, axis=0) < 0).flatten()
485-
) # areas should decrease with latitude in spherical mesh
486-
for y in range(cell_areas.shape[0]):
487-
assert np.allclose(cell_areas[y, :], cell_areas[y, 0], rtol=1e-3)
488-
489-
490459
def addConst(particle, fieldset, time): # pragma: no cover
491460
particle.lon = particle.lon + fieldset.movewest + fieldset.moveeast
492461

tests/test_grids.py

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,6 @@
1919
UnitConverter,
2020
Variable,
2121
)
22-
from parcels.grid import Grid, _calc_cell_edge_sizes
23-
from parcels.tools.converters import TimeConverter
2422
from tests.utils import TEST_DATA
2523

2624

@@ -975,27 +973,3 @@ def VelocityInterpolator(particle, fieldset, time): # pragma: no cover
975973
assert np.allclose(pset.Wvel[0], 0, atol=1e-9)
976974
else:
977975
assert np.allclose(pset.Wvel[0], -w * convfactor)
978-
979-
980-
@pytest.mark.parametrize(
981-
"lon, lat",
982-
[
983-
(np.arange(0.0, 20.0, 1.0), np.arange(0.0, 10.0, 1.0)),
984-
],
985-
)
986-
@pytest.mark.parametrize("mesh", ["flat", "spherical"])
987-
def test_grid_celledgesizes(lon, lat, mesh):
988-
grid = Grid.create_grid(
989-
lon=lon, lat=lat, depth=np.array([0]), time=np.array([0]), time_origin=TimeConverter(0), mesh=mesh
990-
)
991-
992-
_calc_cell_edge_sizes(grid)
993-
D_meridional = grid.cell_edge_sizes["y"]
994-
D_zonal = grid.cell_edge_sizes["x"]
995-
assert np.allclose(
996-
D_meridional.flatten(), D_meridional[0, 0]
997-
) # all meridional distances should be the same in either mesh
998-
if mesh == "flat":
999-
assert np.allclose(D_zonal.flatten(), D_zonal[0, 0]) # all zonal distances should be the same in flat mesh
1000-
else:
1001-
assert all((np.gradient(D_zonal, axis=0) < 0).flatten()) # zonal distances should decrease in spherical mesh

0 commit comments

Comments
 (0)