Skip to content

parcels.FieldSet.from_croco() has issues with Fields that have multiple times #1831

@andrew-s28

Description

@andrew-s28

Parcels version

3.1.1

Description

There seems to be an issue with the parcels.FieldSet.from_croco() function when using it with a file with multiple times. This first occurred when trying to run Parcels on regional CROCO fields that I am using from a collaborator (note I am not a CROCO expert by any means). Of course, this could have just been something funky with my model files, so I investigated a bit further, and can report what I think is an issue with the way Parcels is handling the Cs_w parameter when loading fields with multiple times.

The example runs just fine, but this example uses a file with a single time and allow_time_extrapolation=True. I then used the example file and created a new file with 10 times, each with the exact same data as the original file, which one would think would provide the same results. However, this results in the error shown below. This was all done in a fresh environment with v3.1.1 of Parcels, following the basic installation in the docs. Worth noting that a similar error occurs in the Field.py file if using multiple times and multiple files (e.g., one file per time), but it is a different error, and that deferred_load=True creates a slightly different error as well, but I believe they are all related. Happy to provide minimal example for these too (but it's very similar to below).

I have taken some stabs at fixing it locally. One attempt that seemed to make progress was adding an additional condition in parcels.Field.computeTimeChunk() that attempts to account for the fact that Cs_w only has dimensions of depth and reshaping it to match other fields:

# field.py
# lines 1898-1899
if len(buffer_data.shape) == 1 and g.zdim > 1:
    buffer_data = lib.reshape(buffer_data, sum(((1,), buffer_data.shape, (1, 1,)), ()))

but it just seemed to result in another error cropping up down the road, so I got to the point that I thought it was worth some discussion here.

One question before diving any deeper is: has anyone ran this function with files containing multiple times with success?

Code sample

import os

import numpy as np
import parcels
import xarray as xr

# create and save new dataset with multiple times
example_dataset_folder = parcels.download_example_dataset("CROCOidealized_data")
file = os.path.join(example_dataset_folder, "CROCO_idealized.nc")
ds = xr.open_dataset(file)

time = ds.time.values
time = [time[0]*x + time[0] for x in np.arange(10)]
ds_list = []
for t in time:
    ds_copy = ds.copy()
    ds_copy["time"] = [t]
    ds_list.append(ds_copy)
xr.concat(ds_list, dim="time").to_netcdf("./CROCO_idealized-extended.nc")

# rerun example with new dataset
file = "./CROCO_idealized-extended.nc"

variables = {"U": "u", "V": "v", "W": "w", "H": "h", "Zeta": "zeta", "Cs_w": "Cs_w"}

lon_rho = "x_rho"  # Note, this would be "lon_rho" for a dataset on a spherical grid
lat_rho = "y_rho"  # Note ,this would be "lat_rho" for a dataset on a spherical grid

dimensions = {
    "U": {"lon": lon_rho, "lat": lat_rho, "depth": "s_w", "time": "time"},
    "V": {"lon": lon_rho, "lat": lat_rho, "depth": "s_w", "time": "time"},
    "W": {"lon": lon_rho, "lat": lat_rho, "depth": "s_w", "time": "time"},
    "H": {"lon": lon_rho, "lat": lat_rho},
    "Zeta": {"lon": lon_rho, "lat": lat_rho, "time": "time"},
    "Cs_w": {"depth": "s_w"},
}

fieldset = parcels.FieldSet.from_croco(
    file,
    variables,
    dimensions,
    hc=xr.open_dataset(
        file
    ).hc.values,
    allow_time_extrapolation=False,  # same error happens with True or False
    mesh="flat", 
)

X, Z, T = np.meshgrid(
    [40e3, 80e3, 120e3],
    [100, -10, -130, -250, -400, -850, -1400, -1550],
    [19200],   # added time to release particles as well
)

Y = np.ones(X.size) * 10e3

def DeleteParticle(particle, fieldset, time):
    if particle.state >= 50:
        particle.delete()


pset = parcels.ParticleSet(
    fieldset=fieldset, pclass=parcels.JITParticle, lon=X, lat=Y, depth=Z, time=T
)

outputfile = pset.ParticleFile(name="croco_particles3D.zarr", outputdt=5000)

pset.execute(
    [parcels.AdvectionRK4_3D, DeleteParticle],
    runtime=5e4,
    dt=100,
    output_file=outputfile,
)

Traceback (most recent call last):
  File "~/code/test.py", line 38, in <module>
    fieldset = parcels.FieldSet.from_croco(
        file,
    ...<6 lines>...
        mesh="flat",
    )
  File "~/miniconda3/envs/parcels3/lib/python3.13/site-packages/parcels/fieldset.py", line 779, in from_croco
    fieldset = cls.from_netcdf(
        filenames,
    ...<9 lines>...
        **kwargs,
    )
  File "~/miniconda3/envs/parcels3/lib/python3.13/site-packages/parcels/fieldset.py", line 528, in from_netcdf
    fields[var] = Field.from_netcdf(
                  ~~~~~~~~~~~~~~~~~^
        paths,
        ^^^^^^
    ...<12 lines>...
        **kwargs,
        ^^^^^^^^^
    )
    ^
  File "~/miniconda3/envs/parcels3/lib/python3.13/site-packages/parcels/field.py", line 760, in from_netcdf
    data_list.append(buffer_data.reshape(sum(((len(tslice), 1), buffer_data.shape[1:]), ())))
                              ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
ValueError: cannot reshape array of size 31110 into shape (1,1,51,61)

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    Status

    Done

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions