From 03d84e47c4bac8e02b62c311506212baa07189c1 Mon Sep 17 00:00:00 2001 From: Erik van Sebille Date: Fri, 14 Aug 2026 12:04:57 +0200 Subject: [PATCH 1/8] Cleaning up the documentation Fixing linking errors, myST warnings, and removing TODOs --- docs/conf.py | 1 + docs/index.md | 1 - .../examples/explanation_interpolation.md | 38 +++++++++++-------- .../examples/explanation_performance.md | 12 ++++-- .../examples/tutorial_diffusion.ipynb | 10 +---- .../examples/tutorial_interpolation.ipynb | 2 +- .../examples/tutorial_stuck_particles.ipynb | 32 ++++++++-------- .../examples/tutorial_unstuck_Agrid.ipynb | 17 +++++---- .../getting_started/explanation_concepts.md | 2 +- .../getting_started/tutorial_quickstart.md | 4 +- docs/user_guide/index.md | 4 +- docs/v4/index.md | 2 +- 12 files changed, 68 insertions(+), 57 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 45972eef74..369a3799db 100755 --- a/docs/conf.py +++ b/docs/conf.py @@ -522,6 +522,7 @@ def linkcode_resolve(domain, info): nb_execution_excludepatterns = ["jupyter_execute", ".jupyter_cache"] nb_execution_raise_on_error = True nb_execution_timeout = 75 +suppress_warnings = ["mystnb.unknown_mime_type"] # -- Options for autoapi -------------------------------------------------- autoapi_dirs = ["../src/parcels"] diff --git a/docs/index.md b/docs/index.md index f8c0c7e45f..88c95b6e34 100755 --- a/docs/index.md +++ b/docs/index.md @@ -88,7 +88,6 @@ Connect with our community! :hidden: Home -Getting started User guide Community Development diff --git a/docs/user_guide/examples/explanation_interpolation.md b/docs/user_guide/examples/explanation_interpolation.md index de7b80d403..95cc1e852e 100644 --- a/docs/user_guide/examples/explanation_interpolation.md +++ b/docs/user_guide/examples/explanation_interpolation.md @@ -14,7 +14,13 @@ particles.temperature = fieldset.temperature[particles] ````{note} The statement above is shorthand for ```python -particles.temperature = fieldset.temperature[particles.t, particles.z, particles.y, particles.x, particles] +particles.temperature = fieldset.temperature[ + particles.t, + particles.z, + particles.y, + particles.x, + particles +] ``` where the `particles` argument at the end provides the grid search algorithm with a first guess for the element indices to interpolate on. @@ -38,27 +44,29 @@ the requested value at the particles location. The interpolators included in Parcels are designed for common interpolation schemes in Parcels simulations; see the [Using the built-in interpolators tutorial](./tutorial_interpolation.ipynb). -If we want to create a custom interpolation method, we need to look at the interpolator API. Each interpolator is a class that inherits from either the `ScalarInterpolator` or `VectorInterpolator` class. The `ScalarInterpolator` class is used for scalar fields, such as temperature or salinity, while the `VectorInterpolator` class is used for vector fields, such as velocity. An interpolator class than has to have a `.interp()` method with the following signature: +If we want to create a custom interpolation method, we need to look at the interpolator API. Each interpolator is a class that inherits from either the `ScalarInterpolator` or `VectorInterpolator` class. The `ScalarInterpolator` class is used for scalar fields, such as temperature or salinity, while the `VectorInterpolator` class is used for vector fields, such as velocity. + +An interpolator class must have a `.interp()` method with the following signature: ```python - def interp( - self, - particle_positions: dict[str, float | np.ndarray], - grid_positions: dict[ptyping.XgridAxis, dict[str, int | float | np.ndarray]], - field: Field, - ): - ... +def interp( + self, + particle_positions: dict[str, float | np.ndarray], + grid_positions: dict[ptyping.XgridAxis, dict[str, int | float | np.ndarray]], + field: Field, +): + ... ``` The `particle_positions` dictionary contains: -``` -particle_positions = {"t", t, "z", z, "y", y, "x", x} +```python +particle_positions = {"t": t, "z": z, "y": y, "x": x} ``` For structured (`X`) grids, the `grid_positions` dictionary contains: -``` +```python grid_positions = { "T": {"index": ti, "bcoord": tau}, "Z": {"index": zi, "bcoord": zeta}, @@ -71,7 +79,7 @@ where `index` is the grid index in the corresponding dimension, and `bcoord` is For unstructured (`UX`) grids, the same dictionary is defined as: -``` +```python grid_positions = { "T": {"index": ti, "bcoord": tau}, "Z": {"index": zi, "bcoord": zeta}, @@ -79,6 +87,6 @@ grid_positions = { } ``` -The `.interp()` method should return a float (in the case o a `ScalarInterpolator` or a tuple of three floats `(u, v, w)` in the case of a `VectorInterpolator`). +The `.interp()` method should return a float (in the case of a `ScalarInterpolator` or a tuple of three floats `(u, v, w)` in the case of a `VectorInterpolator`). -Writing custom interpolators is not trivial, so we recommend that you have a look at the built-in interpolators in `parcels.interpolators._xinterpolators` or `parcels.interpolators._uxinterpolators` to see how they are implemented. +Writing custom interpolators is not trivial, so we recommend that you have a look at the built-in interpolators in {py:func}`parcels.interpolators._xinterpolators` or {py:func}`parcels.interpolators._uxinterpolators` to see how they are implemented. diff --git a/docs/user_guide/examples/explanation_performance.md b/docs/user_guide/examples/explanation_performance.md index ddbd338eab..03a30e7dd5 100644 --- a/docs/user_guide/examples/explanation_performance.md +++ b/docs/user_guide/examples/explanation_performance.md @@ -1,3 +1,9 @@ +--- +file_format: mystnb +kernelspec: + name: python3 +--- + # 📖 Squeezing performance in Parcels In many Parcels simulations, the bottle-neck in terms of performance is the retrieval of the hydrodynamic field data from disk. This is especially true for simulations with a relatively small number of particles, where the time spent on retrieving the fields can be much larger than the time spent on computing the particle trajectories. @@ -18,7 +24,7 @@ _Uses Parcels Backend: Numpy_ For relatively small Datasets (less than a few GB), it is possible to load the entire FieldSet into memory. This can be done by calling the `load()` method on the `xarray.Dataset` object: -```{code-cell} +```{code-block} python ds = ds.load() ``` @@ -38,7 +44,7 @@ _Uses Parcels Backend: Zarr_ If your Dataset is too large to fit into memory, but your particles are only distributed over a small part of the domain, it could be efficient to use cached zarr files. This can be done by using the (experimental) `zarr.CacheStore` in combination with the `parcels.open_raw_zarr()` function. This will make Parcels only load the chunks that are needed for the particles, and cache these chunks in memory for future use. -```{code-cell} +```{code-block} python source_store = zarr.storage.LocalStore(filenames) cache_store = zarr.storage.MemoryStore() @@ -69,7 +75,7 @@ If your Dataset is so large that it doesn't fit into memory, you can use the `fi The two timeslices (the current and the next) are fully loaded into memory, so this method is especially useful if your particles are distributed over the entire domain, as all data will then have to be accessed anyway. -```{code-cell} +```{code-block} python fieldset.to_windowed_arrays() ``` diff --git a/docs/user_guide/examples/tutorial_diffusion.ipynb b/docs/user_guide/examples/tutorial_diffusion.ipynb index d349dcd492..7879eba2e2 100644 --- a/docs/user_guide/examples/tutorial_diffusion.ipynb +++ b/docs/user_guide/examples/tutorial_diffusion.ipynb @@ -516,19 +516,11 @@ "fields = {\"U\": ds_fields[\"uo\"], \"V\": ds_fields[\"vo\"]}\n", "ds_fset = parcels.convert.copernicusmarine_to_sgrid(fields=fields)\n", "\n", - "# TODO implement zero-dimension support on fieldset dimensions (#2727)\n", - "# ds_fset[\"cell_areas\"] = ([\"lat\", \"lon\"], calc_cell_areas(ds_fields))\n", + "ds_fset[\"cell_areas\"] = ([\"lat\", \"lon\"], calc_cell_areas(ds_fields))\n", "\n", "fieldset = parcels.FieldSet.from_sgrid_conventions(ds_fset)\n", "fieldset.add_context(\"Cs\", 0.1)\n", "\n", - "# TODO remove if previous TODO fixed\n", - "ds_cell_areas = ds_fset[[\"grid\", \"lon\", \"lat\"]]\n", - "ds_cell_areas[\"cell_areas\"] = ([\"lat\", \"lon\"], calc_cell_areas(ds_fields))\n", - "fset2 = parcels.FieldSet.from_sgrid_conventions(ds_cell_areas)\n", - "\n", - "fieldset += fset2\n", - "\n", "# Convert the FieldSet to windowed arrays for better performance\n", "fieldset = fieldset.to_windowed_arrays()" ] diff --git a/docs/user_guide/examples/tutorial_interpolation.ipynb b/docs/user_guide/examples/tutorial_interpolation.ipynb index c5e76825c6..99645ec5d6 100644 --- a/docs/user_guide/examples/tutorial_interpolation.ipynb +++ b/docs/user_guide/examples/tutorial_interpolation.ipynb @@ -245,7 +245,7 @@ "source": [ "### Interpolation at boundaries\n", "In some cases, we need to implement specific boundary conditions, for example to prevent particles from \n", - "getting \"stuck\" near land. [This guide](../examples_v3/documentation_unstuck_Agrid.ipynb) describes \n", + "getting \"stuck\" near land. [This guide](./tutorial_unstuck_Agrid.ipynb) describes \n", "how to implement this in parcels using {py:obj}`parcels.interpolators.XFreeslip` and {py:obj}`parcels.interpolators.XPartialslip`." ] }, diff --git a/docs/user_guide/examples/tutorial_stuck_particles.ipynb b/docs/user_guide/examples/tutorial_stuck_particles.ipynb index 28e6f75f06..204367a868 100644 --- a/docs/user_guide/examples/tutorial_stuck_particles.ipynb +++ b/docs/user_guide/examples/tutorial_stuck_particles.ipynb @@ -25,13 +25,13 @@ "\n", "**Short conclusion: Particles can get stuck on Arakawa A grids and B grids but should not get stuck on C grids.**\n", "\n", - "This tutorial first looks at how velocity fields are structured and what that means for where the ocean-land boundaries are located. Then we look at how particles may end up getting 'stuck' on these boundaries. How to make these particles become 'unstuck' again in Parcels will be discussed in another notebook.\n", + "This tutorial first looks at how velocity fields are structured and what that means for where the ocean-land boundaries are located. Then we look at how particles may end up getting 'stuck' on these boundaries. How to make these particles become 'unstuck' again in Parcels will be discussed in [this notebook](./tutorial_unstuck_Agrid.ipynb).\n", "\n", - "- [Introduction](#Introduction)\n", - "- [A grid interpolated velocity fields](#1.-A-grids)\n", - "- [B grids](#2.-B-grids)\n", - "- [C grid numerical model - NEMO](#3.-C-grids)\n", - "- [Diffusion](#4.-Diffusion)\n" + "- [Introduction](#introduction)\n", + "- [A grid interpolated velocity fields](#a-grids)\n", + "- [B grids](#b-grids)\n", + "- [C grid numerical model - NEMO](#c-grids)\n", + "- [Diffusion](#diffusion)\n" ] }, { @@ -43,7 +43,7 @@ "\n", "Parcels can handle several different types of velocity fields, which makes it widely applicable. This also means that the underlying code and therefore the accuracy of the calculated trajectories can differ, depending on the velocity data input. Even when Parcels runs smoothly with the velocity fields you use, it is good to realize how your velocity fields are structured and how those velocities are generated in the first place.\n", "\n", - "Horizontal velocity data may be structured on a staggered (Arakawa-C) or unstaggered grid (Arakawa-A). The implementation of these grids is covered in this tutorial - _TODO update link to grid tutorial_.\n", + "Horizontal velocity data may be structured on a staggered (Arakawa-C) or unstaggered grid (Arakawa-A). The implementation of these grids is covered in [this explainer](./explanation_grids.ipynb).\n", "\n", "The source of your velocity data will influence how accurate and physically consistent parcels can calculate trajectories. Common sources are **numerical models and data assimilation products**, **interpolations** of those products or **discrete observations**. The staggering of variables determines how the ocean-land boundaries are defined in models and how their boundary conditions can be satisfied. The Parcels interpolation scheme differs per grid configuration and makes some underlying assumptions that determine the trajectory within a grid cell. Whether the source of your velocity data has physically consistent boundary conditions and how well these align with the assumptions made in Parcels determines how accurately the trajectories move within grid cells. This is especially important near ocean-land boundaries, where particles may end up 'stuck' on land.\n", "\n", @@ -63,12 +63,10 @@ "source": [ "from copy import copy\n", "from datetime import timedelta\n", - "from glob import glob\n", "\n", "import matplotlib.gridspec as gridspec\n", "import matplotlib.pyplot as plt\n", "import numpy as np\n", - "import xarray as xr\n", "from matplotlib.colors import ListedColormap\n", "from matplotlib.lines import Line2D\n", "from scipy import interpolate\n", @@ -86,11 +84,13 @@ } }, "source": [ + "\n", + "(a-grids)=\n", "## 1. A grids\n", "\n", "Arakawa A grids are unstaggered grids where the velocities $u$, $v$ (and $w$), pressure and other tracers are defined at the same position (on so-called nodes). In numerical models, these nodes can be interpreted to be located **at the corner _or_ at the center of the grid cells**. This means that the cell boundaries, and therefore the solid-fluid boundaries can either be located at the nodes (**figure 1A**) or at 0.5 dx distance from the nodes (**figure 1B**) respectively.\n", "\n", - "Many ocean models natively run on a C grid, because boundary conditions are easier to implement there (see [C grid](#2.-C-grids)). Sometimes, the C-grid output of these models is interpolated onto an A grid. This is the case for all(?) the data available from [Copernicus Marine Data Store](https://data.marine.copernicus.eu/products), which provide the data on a rectilinear A grid velocity field.\n", + "Many ocean models natively run on a C grid, because boundary conditions are easier to implement there (see [C grid](#c-grids)). Sometimes, the C-grid output of these models is interpolated onto an A grid. This is the case for all(?) the data available from [Copernicus Marine Data Store](https://data.marine.copernicus.eu/products), which provide the data on a rectilinear A grid velocity field.\n", "\n", "To visualize this, in **figure 1** we show the nodes and cells of a coastal region. The ocean cells and nodes are in red and the land cells and nodes are in white.\n" ] @@ -292,10 +292,6 @@ "lat = np.linspace(52.95, 53.2, npart)\n", "X, Y = np.meshgrid(lon, lat)\n", "\n", - "fieldset.models[0].data = fieldset.models[0].data.fillna(\n", - " 0\n", - ") # TODO remove when fillna done in convert.copernicusmarine_to_sgrid\n", - "\n", "pset = parcels.ParticleSet(fieldset=fieldset, x=X, y=Y)\n", "\n", "output_file = parcels.ParticleFile(\n", @@ -427,9 +423,11 @@ "cell_type": "markdown", "metadata": {}, "source": [ + "\n", + "(b-grids)=\n", "## 2. B grids\n", "\n", - "On Arakawa B grids, $u$ and $v$ are at the same location, while $w$ and scalar variables like pressure are staggered. In 2 dimensional flow, Parcels therefore uses the same bilinear interpolation as for [A grids](#1.-A-grids) to find the horizontal velocity, since the $u$ and $v$ components are similarly collocated. This can cause particles to get stuck in the same way as on A grids.\n" + "On Arakawa B grids, $u$ and $v$ are at the same location, while $w$ and scalar variables like pressure are staggered. In 2 dimensional flow, Parcels therefore uses the same bilinear interpolation as for [A grids](#a-grids) to find the horizontal velocity, since the $u$ and $v$ components are similarly collocated. This can cause particles to get stuck in the same way as on A grids.\n" ] }, { @@ -441,6 +439,8 @@ } }, "source": [ + "\n", + "(c-grids)=\n", "## 3. C grids\n" ] }, @@ -771,6 +771,8 @@ "cell_type": "markdown", "metadata": {}, "source": [ + "\n", + "(diffusion)=\n", "## 4. Diffusion\n", "\n", "In many parcels simulations other motions are added. Examples are Brownian motion from a diffusivity field and Stokes drift based on a wind field. These sources of motion will not necessarily consider the same boundaries and, unless they are also based on a C grid, they may also result in particles getting stuck on land. To show how this happens, let us add a random walk to the advection in a C grid velocity field.\n", diff --git a/docs/user_guide/examples/tutorial_unstuck_Agrid.ipynb b/docs/user_guide/examples/tutorial_unstuck_Agrid.ipynb index 89b8cefcc2..7b439f9b99 100644 --- a/docs/user_guide/examples/tutorial_unstuck_Agrid.ipynb +++ b/docs/user_guide/examples/tutorial_unstuck_Agrid.ipynb @@ -17,9 +17,9 @@ "\n", "Common solutions are:\n", "\n", - "1. [Delete the particles](#1.-Particle-deletion)\n", - "2. [Displace the particles when they are within a certain distance of the coast.](#2.-Displacement)\n", - "3. [Implement free-slip or partial-slip boundary conditions](#3.-Slip-boundary-conditions)\n", + "1. [Delete the particles](#particle-deletion)\n", + "2. [Displace the particles when they are within a certain distance of the coast.](#displacement)\n", + "3. [Implement free-slip or partial-slip boundary conditions](#slip-boundary-conditions)\n", "\n", "In the first two of these solutions, kernels are used to modify the trajectories near the coast. The kernels all consist of two parts:\n", "\n", @@ -33,7 +33,7 @@ "1. Flag particles within a specific distance to the shore\n", "2. Flag particles in any gridcell that has a shore edge\n", "\n", - "As argued in the [previous notebook](tutorial_stuck_particles.ipynb), it is important to accurately plot the grid discretization, in order to understand the motion of particles near the boundary. The velocity fields can best be depicted using points or arrows that define the velocity at a single position. Four of these nodes then form gridcells that can be shown using tiles, for example with `matplotlib.pyplot.pcolormesh`.\n" + "As argued in the [previous notebook](./tutorial_stuck_particles.ipynb), it is important to accurately plot the grid discretization, in order to understand the motion of particles near the boundary. The velocity fields can best be depicted using points or arrows that define the velocity at a single position. Four of these nodes then form gridcells that can be shown using tiles, for example with `matplotlib.pyplot.pcolormesh`.\n" ] }, { @@ -59,6 +59,8 @@ "cell_type": "markdown", "metadata": {}, "source": [ + "\n", + "(particle-deletion)=\n", "## 1. Particle deletion\n", "\n", "The simplest way to avoid trajectories that interact with the coastline is to remove them entirely. You can do this for example by a Kernel that samples the velocity field at the particle position and checks whether the particle is on land or not. If it is, the particle is deleted. This is shown in the following example.\n", @@ -76,6 +78,8 @@ "cell_type": "markdown", "metadata": {}, "source": [ + "\n", + "(displacement)=\n", "## 2. Displacement\n", "\n", "A simple concept to avoid particles moving onto shore is displacing them towards the ocean as they get close to shore. This is for example done in [Kaandorp _et al._ (2020)](https://pubs.acs.org/doi/10.1021/acs.est.0c01984) and [Delandmeter and van Sebille (2018)](https://gmd.copernicus.org/articles/12/3571/2019/). To do so, a particle must be 'aware' of where the shore is and displaced accordingly. In Parcels, we can do this by adding a 'displacement' `Field` to the `Fieldset`, which contains vectors pointing away from shore.\n", @@ -95,9 +99,6 @@ "\n", "fields = {\"U\": ds[\"uo\"], \"V\": ds[\"vo\"]}\n", "ds_fset = parcels.convert.copernicusmarine_to_sgrid(fields=fields)\n", - "ds_fset = ds_fset.fillna(\n", - " 0\n", - ") # TODO remove when fillna done in convert.copernicusmarine_to_sgrid\n", "\n", "fieldset = parcels.FieldSet.from_sgrid_conventions(ds_fset)\n", "fieldset = fieldset.to_windowed_arrays()" @@ -827,6 +828,8 @@ "cell_type": "markdown", "metadata": {}, "source": [ + "\n", + "(slip-boundary-conditions)=\n", "## 3. Slip boundary conditions\n", "\n", "The reason trajectories do not neatly follow the coast in A grid velocity fields is that the lack of staggering causes both velocity components to go to zero in the same way towards the cell edge. This no-slip condition can be turned into a free-slip or partial-slip condition by separately considering the cross-shore and along-shore velocity components as in [a staggered C-grid](https://docs.oceanparcels.org/en/latest/examples/documentation_stuck_particles.html#2.-C-grids). Each interpolation of the velocity field must then be corrected with a factor depending on the direction of the boundary.\n", diff --git a/docs/user_guide/getting_started/explanation_concepts.md b/docs/user_guide/getting_started/explanation_concepts.md index a83b229ca8..11a5361561 100644 --- a/docs/user_guide/getting_started/explanation_concepts.md +++ b/docs/user_guide/getting_started/explanation_concepts.md @@ -56,7 +56,7 @@ Each `parcels.Field` is defined on a grid. With Parcels, we can simulate particl ```{admonition} 📖 Read more about grids :class: seealso -- [Grids explanation](../examples/explanation_grids.md) +- [Grids explanation](../examples/explanation_grids.ipynb) ``` ### Interpolation diff --git a/docs/user_guide/getting_started/tutorial_quickstart.md b/docs/user_guide/getting_started/tutorial_quickstart.md index 896d27f092..467063c5ac 100644 --- a/docs/user_guide/getting_started/tutorial_quickstart.md +++ b/docs/user_guide/getting_started/tutorial_quickstart.md @@ -50,9 +50,7 @@ ds_fset = parcels.convert.copernicusmarine_to_sgrid(fields=fields) fieldset = parcels.FieldSet.from_sgrid_conventions(ds_fset) ``` -Now, in order to improve performance, we can convert the `parcels.FieldSet` to windowed arrays. This is especially useful for large datasets with many timeslices, as it allows Parcels to load only the necessary timeslices into memory during the simulation. - -#TODO add link to performance explanation notebook here. +Now, in order to improve performance, we can convert the `parcels.FieldSet` to windowed arrays. This is especially useful for large datasets with many timeslices, as it allows Parcels to load only the necessary timeslices into memory during the simulation. For more information about squeezing performance out of Parcels, see the [performance tutorial](../examples/explanation_performance.md). ```{code-cell} # Convert the FieldSet to windowed arrays for better performance diff --git a/docs/user_guide/index.md b/docs/user_guide/index.md index e79ef81574..c1995fe350 100644 --- a/docs/user_guide/index.md +++ b/docs/user_guide/index.md @@ -120,9 +120,11 @@ examples/tutorial_interaction.ipynb :caption: Other :name: other :titlesonly: +📖 v4 development <../v4/index> 🎓 v3 to v4 migration guide examples/tutorial_stuck_particles.ipynb examples/tutorial_unstuck_Agrid.ipynb examples/tutorial_homepage_animation.md - ``` + + diff --git a/docs/v4/index.md b/docs/v4/index.md index 42c6d197d4..b5591c4e8c 100644 --- a/docs/v4/index.md +++ b/docs/v4/index.md @@ -1,4 +1,4 @@ -# Parcels v4 development +# 📖 Parcels v4 development Supported by funding from the [WarmWorld](https://www.warmworld.de) [ELPHE](https://www.kooperation-international.de/foerderung/projekte/detail/info/warmworld-elphe-ermoeglichung-von-lagranian-particle-tracking-fuer-hochaufloesende-und-unstrukturierte-gitter) project and an [NWO Vici project](https://www.nwo.nl/en/researchprogrammes/nwo-talent-programme/projects-vici/vici-2022), the Parcels team is working on a major update to the Parcels codebase. From 429e74a827eec9cdd77904e6a25e528008d9c7ed Mon Sep 17 00:00:00 2001 From: Erik van Sebille Date: Fri, 14 Aug 2026 12:12:13 +0200 Subject: [PATCH 2/8] More TODO removals --- docs/user_guide/examples/tutorial_diffusion.ipynb | 8 ++------ docs/user_guide/examples/tutorial_nemo.ipynb | 2 +- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/docs/user_guide/examples/tutorial_diffusion.ipynb b/docs/user_guide/examples/tutorial_diffusion.ipynb index 7879eba2e2..e2d9788b5c 100644 --- a/docs/user_guide/examples/tutorial_diffusion.ipynb +++ b/docs/user_guide/examples/tutorial_diffusion.ipynb @@ -74,11 +74,7 @@ "\n", "The extra term in the M1 scheme provides extra accuracy at negligible computational cost.\n", "\n", - "The spatial derivatives in the EM and M1 schemes can be approximated by a central difference. Higher order numerical schemes (see [Gräwe et al., 2012](https://doi.org/10.1007/s10236-012-0523-y)) include higher order derivatives.\n", - "\n", - "```{note}\n", - "TODO: explore higher order derivatives and numerical schemes (using cubic spline interpolation) in v4 \n", - "```\n", + "The spatial derivatives in the EM and M1 schemes can be approximated by a central difference. Higher order numerical schemes (see [Gräwe et al., 2012](https://doi.org/10.1007/s10236-012-0523-y)) include higher order derivatives. It should be possible to also use cubic spline interpolation in Parcels to compute the derivatives, which may be more accurate than finite differences. This is to be explored.\n", "\n", "An overview of numerical approximations for SDEs in a particle tracking setting can be found in [Gräwe (2011)](https://doi.org/10.1016/j.ocemod.2010.10.002).\n", "\n", @@ -621,7 +617,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Parcels:docs (3.14.6)", + "display_name": "Parcels:test (3.14.6)", "language": "python", "name": "python3" }, diff --git a/docs/user_guide/examples/tutorial_nemo.ipynb b/docs/user_guide/examples/tutorial_nemo.ipynb index 3620de50e5..41cd84b7b9 100644 --- a/docs/user_guide/examples/tutorial_nemo.ipynb +++ b/docs/user_guide/examples/tutorial_nemo.ipynb @@ -34,7 +34,7 @@ "Parcels supports [curvilinear grids](https://www.nemo-ocean.eu/doc/node108.html) such as those used in the [NEMO models](https://www.nemo-ocean.eu/).\n", "\n", "```{note}\n", - "TODO: make explicit how Parcels determines rotation\n", + "Parcels assumes that the velocities on curvilinear C-grids are in the `i` and `j` directions of the curvilinear grid, which are not necessarily aligned with the `x` and `y` directions. Parcels will rotate the velocities to the `x` and `y` directions under the hood. On A-grids, on the other hand, the velocities are assumed to be in the `x` and `y` directions.\n", "```\n", "\n", "We will be using the example dataset `NemoCurvilinear_data`. These fields are a purely zonal flow on an aqua-planet (so zonal-velocity is 1 m s-1 and meridional-velocity is 0 m s-1 everywhere, and no land). However, because of the curvilinear grid, the `U` and `V` fields vary for the rotated grid cells north of 20N." From c781dd06a4704afdb95db21aadfa1283ca4497ec Mon Sep 17 00:00:00 2001 From: Erik van Sebille Date: Mon, 17 Aug 2026 07:44:59 +0200 Subject: [PATCH 3/8] Remove {code-block} --- docs/user_guide/examples/explanation_performance.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/user_guide/examples/explanation_performance.md b/docs/user_guide/examples/explanation_performance.md index 03a30e7dd5..0a1fa8d50e 100644 --- a/docs/user_guide/examples/explanation_performance.md +++ b/docs/user_guide/examples/explanation_performance.md @@ -24,7 +24,7 @@ _Uses Parcels Backend: Numpy_ For relatively small Datasets (less than a few GB), it is possible to load the entire FieldSet into memory. This can be done by calling the `load()` method on the `xarray.Dataset` object: -```{code-block} python +```python ds = ds.load() ``` @@ -44,7 +44,7 @@ _Uses Parcels Backend: Zarr_ If your Dataset is too large to fit into memory, but your particles are only distributed over a small part of the domain, it could be efficient to use cached zarr files. This can be done by using the (experimental) `zarr.CacheStore` in combination with the `parcels.open_raw_zarr()` function. This will make Parcels only load the chunks that are needed for the particles, and cache these chunks in memory for future use. -```{code-block} python +```python source_store = zarr.storage.LocalStore(filenames) cache_store = zarr.storage.MemoryStore() @@ -75,7 +75,7 @@ If your Dataset is so large that it doesn't fit into memory, you can use the `fi The two timeslices (the current and the next) are fully loaded into memory, so this method is especially useful if your particles are distributed over the entire domain, as all data will then have to be accessed anyway. -```{code-block} python +```python fieldset.to_windowed_arrays() ``` From 164097ce666ac02ee9e8ef1612af52e39f434e3c Mon Sep 17 00:00:00 2001 From: Erik van Sebille Date: Mon, 17 Aug 2026 07:45:20 +0200 Subject: [PATCH 4/8] Add particlefile_to_v3_zarr to migration guide --- docs/user_guide/v4-migration.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/user_guide/v4-migration.md b/docs/user_guide/v4-migration.md index cd507bf1c5..ac4e687d21 100644 --- a/docs/user_guide/v4-migration.md +++ b/docs/user_guide/v4-migration.md @@ -283,7 +283,7 @@ Use the ParticleSet construc ParticleFiles output is in parquet format
-Read the output with polars.read_parquet or (to automatically handle cftime) parcels.read_particlefile +Read the output with polars.read_parquet() or (to automatically handle cftime) parcels.read_particlefile(). For compatility with old postprocessing codes, convert the new Parquet output to v3-style zarr output using parcels.particlefile_to_v3_zarr()

From aa652651965c3f66773322986621e7e120378d76 Mon Sep 17 00:00:00 2001 From: Erik van Sebille Date: Mon, 17 Aug 2026 07:55:54 +0200 Subject: [PATCH 5/8] Using capital P in Parcels throughout the code --- docs/conf.py | 2 +- docs/development/maintainer.md | 2 +- .../user_guide/examples/tutorial_interpolation.ipynb | 2 +- docs/user_guide/examples/tutorial_sampling.ipynb | 4 ++-- .../examples/tutorial_stuck_particles.ipynb | 12 ++++++------ .../getting_started/explanation_concepts.md | 4 ++-- .../user_guide/getting_started/tutorial_output.ipynb | 8 ++++---- pyproject.toml | 2 +- src/parcels/_compat.py | 2 +- src/parcels/_core/field.py | 2 +- src/parcels/_core/fieldset.py | 2 +- src/parcels/_core/model.py | 2 +- tests/sgrid/test_accessor.py | 2 +- tests/utils/test_time.py | 2 +- tools/numpydoc-public-api.py | 2 +- 15 files changed, 25 insertions(+), 25 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 369a3799db..64bf04f4ff 100755 --- a/docs/conf.py +++ b/docs/conf.py @@ -1,5 +1,5 @@ """autoSphinx configuration file for Parcels documentation.""" -# parcels documentation build configuration file, created by +# Parcels documentation build configuration file, created by # sphinx-quickstart on Tue Oct 20 09:58:20 2015. # # This file is execfile()d with the current directory set to its diff --git a/docs/development/maintainer.md b/docs/development/maintainer.md index c357dca700..95785aaf9d 100644 --- a/docs/development/maintainer.md +++ b/docs/development/maintainer.md @@ -29,4 +29,4 @@ - Parcels development status - Check feature tiles - (once package is available on conda) Re-build the Binder -- Ask for the shared parcels environment on [Lorenz](https://github.com/IMAU-oceans/Lorenz) to be updated +- Ask for the shared Parcels environment on [Lorenz](https://github.com/IMAU-oceans/Lorenz) to be updated diff --git a/docs/user_guide/examples/tutorial_interpolation.ipynb b/docs/user_guide/examples/tutorial_interpolation.ipynb index 99645ec5d6..d706a5109e 100644 --- a/docs/user_guide/examples/tutorial_interpolation.ipynb +++ b/docs/user_guide/examples/tutorial_interpolation.ipynb @@ -246,7 +246,7 @@ "### Interpolation at boundaries\n", "In some cases, we need to implement specific boundary conditions, for example to prevent particles from \n", "getting \"stuck\" near land. [This guide](./tutorial_unstuck_Agrid.ipynb) describes \n", - "how to implement this in parcels using {py:obj}`parcels.interpolators.XFreeslip` and {py:obj}`parcels.interpolators.XPartialslip`." + "how to implement this in Parcels using {py:obj}`parcels.interpolators.XFreeslip` and {py:obj}`parcels.interpolators.XPartialslip`." ] }, { diff --git a/docs/user_guide/examples/tutorial_sampling.ipynb b/docs/user_guide/examples/tutorial_sampling.ipynb index a2db9f2ade..13ec953966 100644 --- a/docs/user_guide/examples/tutorial_sampling.ipynb +++ b/docs/user_guide/examples/tutorial_sampling.ipynb @@ -22,7 +22,7 @@ "source": [ "## Basic sampling\n", "\n", - "We import both the packages that we need to set up the simulation, as well as the parcels package." + "We import both the packages that we need to set up the simulation, as well as the Parcels package." ] }, { @@ -47,7 +47,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Suppose we want to study the environmental temperature for plankton drifting in the Agulhas current. We have a CopernicusMarine dataset with surface ocean velocities and the corresponding potential temperature (\"thetao\") stored in netcdf files in the [parcels example dataset repository](https://github.com/OceanParcels/parcels-data). Loading in the FieldSet, parcels detects U and V because they have CF standard names and tells us that they are assumed as the velocity fields to be used in the simulation.\n" + "Suppose we want to study the environmental temperature for plankton drifting in the Agulhas current. We have a CopernicusMarine dataset with surface ocean velocities and the corresponding potential temperature (\"thetao\") stored in netcdf files in the [Parcels example dataset repository](https://github.com/Parcels-code/parcels-data). Loading in the FieldSet, Parcels detects U and V because they have CF standard names and tells us that they are assumed as the velocity fields to be used in the simulation.\n" ] }, { diff --git a/docs/user_guide/examples/tutorial_stuck_particles.ipynb b/docs/user_guide/examples/tutorial_stuck_particles.ipynb index 204367a868..10711cdb8a 100644 --- a/docs/user_guide/examples/tutorial_stuck_particles.ipynb +++ b/docs/user_guide/examples/tutorial_stuck_particles.ipynb @@ -45,9 +45,9 @@ "\n", "Horizontal velocity data may be structured on a staggered (Arakawa-C) or unstaggered grid (Arakawa-A). The implementation of these grids is covered in [this explainer](./explanation_grids.ipynb).\n", "\n", - "The source of your velocity data will influence how accurate and physically consistent parcels can calculate trajectories. Common sources are **numerical models and data assimilation products**, **interpolations** of those products or **discrete observations**. The staggering of variables determines how the ocean-land boundaries are defined in models and how their boundary conditions can be satisfied. The Parcels interpolation scheme differs per grid configuration and makes some underlying assumptions that determine the trajectory within a grid cell. Whether the source of your velocity data has physically consistent boundary conditions and how well these align with the assumptions made in Parcels determines how accurately the trajectories move within grid cells. This is especially important near ocean-land boundaries, where particles may end up 'stuck' on land.\n", + "The source of your velocity data will influence how accurate and physically consistent Parcels can calculate trajectories. Common sources are **numerical models and data assimilation products**, **interpolations** of those products or **discrete observations**. The staggering of variables determines how the ocean-land boundaries are defined in models and how their boundary conditions can be satisfied. The Parcels interpolation scheme differs per grid configuration and makes some underlying assumptions that determine the trajectory within a grid cell. Whether the source of your velocity data has physically consistent boundary conditions and how well these align with the assumptions made in Parcels determines how accurately the trajectories move within grid cells. This is especially important near ocean-land boundaries, where particles may end up 'stuck' on land.\n", "\n", - "Here we will look at two examples of velocity fields in parcels. We visualize the structure of the velocity field, briefly discuss the Parcels implementation and look at how particles get stuck. Then we shortly discuss Arakawa B grids and additional sources of movement that may not respect the ocean-land boundary, such as particle diffusion using a random walk.\n" + "Here we will look at two examples of velocity fields in Parcels. We visualize the structure of the velocity field, briefly discuss the Parcels implementation and look at how particles get stuck. Then we shortly discuss Arakawa B grids and additional sources of movement that may not respect the ocean-land boundary, such as particle diffusion using a random walk.\n" ] }, { @@ -266,7 +266,7 @@ "source": [ "### 1.1 Parcels bilinear interpolation\n", "\n", - "On Arakawa A grids, Parcels uses a simple bilinear interpolation to find the particle velocity at a specific location in a cell. It finds the four nearest velocity components in a 2D field and interpolates between those. This means that the velocity field is essentially divided into cells by parcels as in **figure 1A**. The boundaries of cells in this case are located between the nodes of the velocity field and therefore the ocean-land boundary lies in between the nodes of the land. Since both velocity components are defined at all four corner nodes, they equally persist in the limit toward the boundary as they go to zero." + "On Arakawa A grids, Parcels uses a simple bilinear interpolation to find the particle velocity at a specific location in a cell. It finds the four nearest velocity components in a 2D field and interpolates between those. This means that the velocity field is essentially divided into cells by Parcels as in **figure 1A**. The boundaries of cells in this case are located between the nodes of the velocity field and therefore the ocean-land boundary lies in between the nodes of the land. Since both velocity components are defined at all four corner nodes, they equally persist in the limit toward the boundary as they go to zero." ] }, { @@ -276,7 +276,7 @@ "source": [ "### 1.2 How do particles get stuck?\n", "\n", - "Here we create a parcels simulation of trajectories of particles released near and on the _land_ cells in the velocity field and see how the bilinear interpolation causes particles to get stuck.\n" + "Here we create a Parcels simulation of trajectories of particles released near and on the _land_ cells in the velocity field and see how the bilinear interpolation causes particles to get stuck.\n" ] }, { @@ -617,7 +617,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "There are different options for the along-boundary velocity in NEMO: a free-slip condition, a partial-slip condition and a no-slip condition. Since the tangential velocity is not defined at the boundary, this boundary condition is defined by a Neumann boundary condition: the normal derivative of the along-boundary velocity is specified. This derivative is schematically represented by a \"ghost\" velocity on the adjacent land node. The specified derivative is equivalent to what would result from the central difference between the along-boundary velocity at the nearest ocean cell and this \"ghost\" velocity. The type of boundary condition defines the direction and magnitude of this \"ghost\" velocity relative to the along-boundary velocity in the fluid domain. In Parcels, these \"ghost\" velocities may be used to determine how the velocity should be interpolated near the coast. By default, parcels interpolates piecewise-constant in the direction normal to the velocity component. This means that the along-boundary velocity is the same for any distance away from the boundary and therefore equivalent to the free-slip boundary condition shown in subfigure **(a)** below.\n", + "There are different options for the along-boundary velocity in NEMO: a free-slip condition, a partial-slip condition and a no-slip condition. Since the tangential velocity is not defined at the boundary, this boundary condition is defined by a Neumann boundary condition: the normal derivative of the along-boundary velocity is specified. This derivative is schematically represented by a \"ghost\" velocity on the adjacent land node. The specified derivative is equivalent to what would result from the central difference between the along-boundary velocity at the nearest ocean cell and this \"ghost\" velocity. The type of boundary condition defines the direction and magnitude of this \"ghost\" velocity relative to the along-boundary velocity in the fluid domain. In Parcels, these \"ghost\" velocities may be used to determine how the velocity should be interpolated near the coast. By default, Parcels interpolates piecewise-constant in the direction normal to the velocity component. This means that the along-boundary velocity is the same for any distance away from the boundary and therefore equivalent to the free-slip boundary condition shown in subfigure **(a)** below.\n", "\n", "\n" ] @@ -775,7 +775,7 @@ "(diffusion)=\n", "## 4. Diffusion\n", "\n", - "In many parcels simulations other motions are added. Examples are Brownian motion from a diffusivity field and Stokes drift based on a wind field. These sources of motion will not necessarily consider the same boundaries and, unless they are also based on a C grid, they may also result in particles getting stuck on land. To show how this happens, let us add a random walk to the advection in a C grid velocity field.\n", + "In many Parcels simulations other motions are added. Examples are Brownian motion from a diffusivity field and Stokes drift based on a wind field. These sources of motion will not necessarily consider the same boundaries and, unless they are also based on a C grid, they may also result in particles getting stuck on land. To show how this happens, let us add a random walk to the advection in a C grid velocity field.\n", "\n", "This random walk can be added using a diffusion kernel, as documented in [this notebook](tutorial_diffusion.ipynb). Since the particles will move randomly through the domain, without awareness of the solid-fluid boundaries in the velocity field, we cannot define stuck particles as having moved less than a tolerance value and we will instead check whether particles find themselves on land or not. To do this, we sample the local velocities.\n" ] diff --git a/docs/user_guide/getting_started/explanation_concepts.md b/docs/user_guide/getting_started/explanation_concepts.md index 11a5361561..39a9d256c7 100644 --- a/docs/user_guide/getting_started/explanation_concepts.md +++ b/docs/user_guide/getting_started/explanation_concepts.md @@ -28,7 +28,7 @@ Parcels concepts diagram with key classes in blue boxes ## 1. FieldSet -Parcels provides a framework to simulate particles **within a set of fields**, such as flow velocities and temperature. To start a parcels simulation we must define this dataset with the **`parcels.FieldSet`** class. +Parcels provides a framework to simulate particles **within a set of fields**, such as flow velocities and temperature. To start a Parcels simulation we must define this dataset with the **`parcels.FieldSet`** class. The input dataset from which to create a `parcels.FieldSet` can be an [`xarray.Dataset`](https://docs.xarray.dev/en/stable/user-guide/data-structures.html#dataset) with output from a hydrodynamic model or reanalysis. Such a dataset usually contains a number of gridded variables (e.g. `"U"`), which in Parcels become `parcels.Field` objects. A list of `parcels.Field` objects is stored in a `parcels.FieldSet` in an analoguous way to how `xarray.DataArray` objects combine to make an `xarray.Dataset`. @@ -44,7 +44,7 @@ fieldset = parcels.FieldSet.from_sgrid_conventions(ds_fset) In some cases, we might want to combine fields from different sources in the same `parcels.FieldSet`, such as ocean currents from one dataset and Stokes drift from another. This is possible in Parcels by creating multiple `parcels.FieldSet` objects and combining them into a single `parcels.FieldSet`: ```python -dataset2 = xr.dataset("insert_stokes_data_files.nc") +dataset2 = xr.open_dataset("insert_stokes_data_files.nc") fields2 = {"Ustokes": ds_fields["ustokes"], "Vstokes": ds_fields["vstokes"]} ds_fset = parcels.convert.copernicusmarine_to_sgrid(fields=fields2) fieldset += parcels.FieldSet.from_sgrid_conventions(ds_fset, vector_fields={"UVstokes": ["Ustokes", "Vstokes"]}) diff --git a/docs/user_guide/getting_started/tutorial_output.ipynb b/docs/user_guide/getting_started/tutorial_output.ipynb index ea311a2877..6bcb0ebf74 100644 --- a/docs/user_guide/getting_started/tutorial_output.ipynb +++ b/docs/user_guide/getting_started/tutorial_output.ipynb @@ -13,7 +13,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "This tutorial covers the format of the trajectory output exported by Parcels. **Parcels does not include advanced analysis or plotting functionality**, which users are suggested to write themselves to suit their research goals. Here we provide some starting points to explore the parcels output files yourself.\n", + "This tutorial covers the format of the trajectory output exported by Parcels. **Parcels does not include advanced analysis or plotting functionality**, which users are suggested to write themselves to suit their research goals. Here we provide some starting points to explore the Parcels output files yourself.\n", "\n", "- [**Reading the output file**](#reading-the-output-file)\n", "- [**Trajectory data structure**](#trajectory-data-structure)\n", @@ -45,7 +45,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "First we need to create some parcels output to analyze. We simulate a set of particles using the setup described in the [Delay start tutorial](https://docs.oceanparcels.org/en/latest/examples/tutorial_delaystart.html). We will also add some user defined metadata to the output file." + "First we need to create some Parcels output to analyze. We simulate a set of particles using the setup described in the [Delay start tutorial](https://docs.oceanparcels.org/en/latest/examples/tutorial_delaystart.html). We will also add some user defined metadata to the output file." ] }, { @@ -247,7 +247,7 @@ "source": [ "## Plotting trajectories\n", "\n", - "Parcels output consists of particle trajectories through time and space. An important way to explore patterns in this information is to draw the trajectories in space. The [**trajan**](https://opendrift.github.io/trajan/index.html) package can be used to quickly plot parcels results, but users are encouraged to create their own figures, for example by using the comprehensive [**matplotlib**](https://matplotlib.org/) library. Here we show a basic setup on how to process the parcels output into trajectory plots and animations.\n", + "Parcels output consists of particle trajectories through time and space. An important way to explore patterns in this information is to draw the trajectories in space. The [**trajan**](https://opendrift.github.io/trajan/index.html) package can be used to quickly plot Parcels results, but users are encouraged to create their own figures, for example by using the comprehensive [**matplotlib**](https://matplotlib.org/) library. Here we show a basic setup on how to process the Parcels output into trajectory plots and animations.\n", "\n", "```{warning}\n", "Trajan is not yet compatible with the `parquet` output format, but we are working on a solution to this.\n", @@ -384,7 +384,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Trajectory plots like the ones above can become very cluttered for large sets of particles. To better see patterns, it's a good idea to create an animation in time and space. To do this, matplotlib offers an [animation package](https://matplotlib.org/stable/api/animation_api.html). Here we show how to use the [**FuncAnimation**](https://matplotlib.org/3.3.2/api/_as_gen/matplotlib.animation.FuncAnimation.html#matplotlib.animation.FuncAnimation) class to animate parcels trajectory data.\n" + "Trajectory plots like the ones above can become very cluttered for large sets of particles. To better see patterns, it's a good idea to create an animation in time and space. To do this, matplotlib offers an [animation package](https://matplotlib.org/stable/api/animation_api.html). Here we show how to use the [**FuncAnimation**](https://matplotlib.org/3.3.2/api/_as_gen/matplotlib.animation.FuncAnimation.html#matplotlib.animation.FuncAnimation) class to animate Parcels trajectory data.\n" ] }, { diff --git a/pyproject.toml b/pyproject.toml index 71afa62dc4..13f443b312 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -96,7 +96,7 @@ select = [ "YTT", # checks for misuse of sys.version or sys.version_info # "FBT", # checks for boolean traps (which result in poor function API) # "A", # check for python builtins being used as variables or parameters - # "T20", # disallows printing in code - parcels source code should not have dev debugging statements, or should use logging statements instead of prints + # "T20", # disallows printing in code - Parcels source code should not have dev debugging statements, or should use logging statements instead of prints "NPY201", # numpy 2 deprecations ] diff --git a/src/parcels/_compat.py b/src/parcels/_compat.py index f3273dbc61..a5643903fc 100644 --- a/src/parcels/_compat.py +++ b/src/parcels/_compat.py @@ -1,7 +1,7 @@ """Import helpers for compatability between installations.""" -# for compat with v3 of parcels when users provide `initial=attrgetter("...")` to a Variable +# for compat with v3 of Parcels when users provide `initial=attrgetter("...")` to a Variable # so that particle initial state matches another variable class _AttrgetterHelper: """ diff --git a/src/parcels/_core/field.py b/src/parcels/_core/field.py index 22f9bdc1fa..0cff9adb2c 100644 --- a/src/parcels/_core/field.py +++ b/src/parcels/_core/field.py @@ -90,7 +90,7 @@ def __init__( # TODO PR: Enable isinstance check once ModelData is moved to abc.ModelData # if not isinstance(model, "ModelData"): # raise ValueError( - # f"Expected `model` to be a parcels ModelData object. Got {type(model)}." + # f"Expected `model` to be a Parcels ModelData object. Got {type(model)}." # ) _assert_str_and_python_varname(name) diff --git a/src/parcels/_core/fieldset.py b/src/parcels/_core/fieldset.py index 481e5d3ee1..11a1b86caf 100644 --- a/src/parcels/_core/fieldset.py +++ b/src/parcels/_core/fieldset.py @@ -377,7 +377,7 @@ def _warn_if_fields_use_different_meshes(fields: Iterable[Field | VectorField]): ) -class CalendarError(Exception): # TODO: Move to a parcels errors module +class CalendarError(Exception): # TODO: Move to a Parcels errors module """Exception raised when the calendar of a field is not compatible with the rest of the Fields. The user should ensure that they only add fields to a FieldSet that have compatible CFtime calendars.""" diff --git a/src/parcels/_core/model.py b/src/parcels/_core/model.py index 6fa8c998c2..270723a97e 100644 --- a/src/parcels/_core/model.py +++ b/src/parcels/_core/model.py @@ -323,7 +323,7 @@ def __init__(self, data: ux.UxDataset, grid: UxGrid, vector_field_components: pt raise ValueError(f"Expected `data` to be an uxarray.UxDataset . Got {type(data)}") if not isinstance(grid, UxGrid): - raise ValueError(f"Expected `grid` to be a parcels UxGrid object. Got {type(grid)}.") + raise ValueError(f"Expected `grid` to be a Parcels UxGrid object. Got {type(grid)}.") self.data = data self.grid = grid diff --git a/tests/sgrid/test_accessor.py b/tests/sgrid/test_accessor.py index a5acb19304..1f3423ad03 100644 --- a/tests/sgrid/test_accessor.py +++ b/tests/sgrid/test_accessor.py @@ -16,7 +16,7 @@ def grid_and_dataset(draw) -> tuple[sgrid.SGrid2DMetadata, xr.Dataset]: # used only for test_metadata - for all other tests we can simply do `ds.sgrid.metadata` to get the metadata metadata_2d = draw( pst.sgrid.grid_metadata.filter( - # parcels can only generate 2D Sgrid datasets, that also have coordinates + # Parcels can only generate 2D Sgrid datasets, that also have coordinates lambda meta: isinstance(meta, sgrid.SGrid2DMetadata) and meta.node_coordinates is not None ) ) diff --git a/tests/utils/test_time.py b/tests/utils/test_time.py index 3b1329414a..180bc3102f 100644 --- a/tests/utils/test_time.py +++ b/tests/utils/test_time.py @@ -7,7 +7,7 @@ from cftime import datetime as cftime_datetime from hypothesis import given -import parcels._strategies as pst # parcels strategies +import parcels._strategies as pst # Parcels strategies from parcels._core.utils.time import ( TimeInterval, _get_cf_attrs, diff --git a/tools/numpydoc-public-api.py b/tools/numpydoc-public-api.py index 70fc6d41e6..85f668af53 100644 --- a/tools/numpydoc-public-api.py +++ b/tools/numpydoc-public-api.py @@ -27,7 +27,7 @@ # full list of numpydoc error codes: https://numpydoc.readthedocs.io/en/latest/validation.html SKIP_ERRORS = [ - "GL01", # parcels is fine with the summary line starting directly after `"""`, or on the next line. + "GL01", # Parcels is fine with the summary line starting directly after `"""`, or on the next line. "SA01", # Parcels doesn't require the "See also" section "SA04", # "ES01", # We don't require the extended summary for all docstrings From c76aa97ed6dd037805afee3280062d5669c1b314 Mon Sep 17 00:00:00 2001 From: Erik van Sebille Date: Mon, 17 Aug 2026 07:57:17 +0200 Subject: [PATCH 6/8] Revert "Remove {code-block}" This reverts commit c781dd06a4704afdb95db21aadfa1283ca4497ec. --- docs/user_guide/examples/explanation_performance.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/user_guide/examples/explanation_performance.md b/docs/user_guide/examples/explanation_performance.md index 0a1fa8d50e..03a30e7dd5 100644 --- a/docs/user_guide/examples/explanation_performance.md +++ b/docs/user_guide/examples/explanation_performance.md @@ -24,7 +24,7 @@ _Uses Parcels Backend: Numpy_ For relatively small Datasets (less than a few GB), it is possible to load the entire FieldSet into memory. This can be done by calling the `load()` method on the `xarray.Dataset` object: -```python +```{code-block} python ds = ds.load() ``` @@ -44,7 +44,7 @@ _Uses Parcels Backend: Zarr_ If your Dataset is too large to fit into memory, but your particles are only distributed over a small part of the domain, it could be efficient to use cached zarr files. This can be done by using the (experimental) `zarr.CacheStore` in combination with the `parcels.open_raw_zarr()` function. This will make Parcels only load the chunks that are needed for the particles, and cache these chunks in memory for future use. -```python +```{code-block} python source_store = zarr.storage.LocalStore(filenames) cache_store = zarr.storage.MemoryStore() @@ -75,7 +75,7 @@ If your Dataset is so large that it doesn't fit into memory, you can use the `fi The two timeslices (the current and the next) are fully loaded into memory, so this method is especially useful if your particles are distributed over the entire domain, as all data will then have to be accessed anyway. -```python +```{code-block} python fieldset.to_windowed_arrays() ``` From 99a4f0d4a2ddf5a50222d6a5a8e3cd2522ef0526 Mon Sep 17 00:00:00 2001 From: Erik van Sebille Date: Mon, 17 Aug 2026 08:00:10 +0200 Subject: [PATCH 7/8] changing oceanparcels to parcels-code --- .github/PULL_REQUEST_TEMPLATE.md | 2 +- docs/user_guide/examples/tutorial_croco_3D.ipynb | 2 +- docs/user_guide/examples/tutorial_delaystart.ipynb | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 09799239b6..1ce7c39614 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -10,7 +10,7 @@ ### AI Disclosure - + - [ ] This PR contains AI-generated content. - [ ] I have tested any AI-generated content in my PR. diff --git a/docs/user_guide/examples/tutorial_croco_3D.ipynb b/docs/user_guide/examples/tutorial_croco_3D.ipynb index a393739f17..d2ba42130c 100644 --- a/docs/user_guide/examples/tutorial_croco_3D.ipynb +++ b/docs/user_guide/examples/tutorial_croco_3D.ipynb @@ -65,7 +65,7 @@ "metadata": {}, "source": [ "```{note}\n", - "In the code below, we use the `w` velocity field for vertical velocity. However, it is unclear whether this is always the right choice. CROCO (and ROMS) also output an `omega` field, which may be more appropriate to use. The idealised simulation below only works when using `w`, though. In other simulations, it is recommended to test whether `omega` provides more realistic results. See https://github.com/OceanParcels/Parcels/discussions/1728 for more information.\n", + "In the code below, we use the `w` velocity field for vertical velocity. However, it is unclear whether this is always the right choice. CROCO (and ROMS) also output an `omega` field, which may be more appropriate to use. The idealised simulation below only works when using `w`, though. In other simulations, it is recommended to test whether `omega` provides more realistic results. See https://github.com/Parcels-code/Parcels/discussions/1728 for more information.\n", "```" ] }, diff --git a/docs/user_guide/examples/tutorial_delaystart.ipynb b/docs/user_guide/examples/tutorial_delaystart.ipynb index 8c5df112e3..c404f425d5 100644 --- a/docs/user_guide/examples/tutorial_delaystart.ipynb +++ b/docs/user_guide/examples/tutorial_delaystart.ipynb @@ -193,7 +193,7 @@ "source": [ "
\n", "\n", - "Note that the `repeatdt` argument in `parcels.ParticleSet` used in previous versions of parcels is no longer supported as of v4\n", + "Note that the `repeatdt` argument in `parcels.ParticleSet` used in previous versions of Parcels is no longer supported as of v4\n", "
" ] }, From c3a011d68db3ead48046f0649277c29c4a0b035d Mon Sep 17 00:00:00 2001 From: Vecko <36369090+VeckoTheGecko@users.noreply.github.com> Date: Mon, 17 Aug 2026 14:16:44 +0800 Subject: [PATCH 8/8] Update SPHINXOPTS Basing them off the ones in Xarray https://github.com/pydata/xarray/blob/af3dad69b7ee7b95fb4510e40bcd25405cdc64a5/doc/Makefile#L5 . e.g., failing on warning --- docs/Makefile | 2 +- pixi.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/Makefile b/docs/Makefile index 613a264a44..8de2df1011 100755 --- a/docs/Makefile +++ b/docs/Makefile @@ -2,7 +2,7 @@ # # You can set these variables from the command line. -SPHINXOPTS = +SPHINXOPTS = --show-traceback --fail-on-warning --keep-going --jobs auto SPHINXBUILD = sphinx-build SPHINXATUOBUILD = sphinx-autobuild PAPER = diff --git a/pixi.toml b/pixi.toml index b9b2713142..4b699435b1 100644 --- a/pixi.toml +++ b/pixi.toml @@ -123,7 +123,7 @@ parcels = { path = "." } numpydoc = "*" myst-nb = "*" ipython = "*" -sphinx = "*" +sphinx = ">=9.0.0" pandoc = "*" pydata-sphinx-theme = "*" sphinx-autobuild = "*"