|
27 | 27 | from parcels.particle import JITParticle, Variable |
28 | 28 | from parcels.particledata import ParticleData, ParticleDataIterator |
29 | 29 | from parcels.particlefile import ParticleFile |
30 | | -from parcels.tools._helpers import deprecated, deprecated_made_private, particleset_repr |
| 30 | +from parcels.tools._helpers import deprecated, deprecated_made_private, particleset_repr, timedelta_to_float |
31 | 31 | from parcels.tools.converters import _get_cftime_calendars, convert_to_flat_array |
32 | 32 | from parcels.tools.global_statics import get_package_dir |
33 | 33 | from parcels.tools.loggers import logger |
@@ -189,12 +189,13 @@ def ArrayClass_init(self, *args, **kwargs): |
189 | 189 | lon.size == kwargs[kwvar].size |
190 | 190 | ), f"{kwvar} and positions (lon, lat, depth) don't have the same lengths." |
191 | 191 |
|
192 | | - self.repeatdt = repeatdt.total_seconds() if isinstance(repeatdt, timedelta) else repeatdt |
| 192 | + self.repeatdt = timedelta_to_float(repeatdt) if repeatdt is not None else None |
| 193 | + |
193 | 194 | if self.repeatdt: |
194 | 195 | if self.repeatdt <= 0: |
195 | | - raise "Repeatdt should be > 0" |
| 196 | + raise ValueError("Repeatdt should be > 0") |
196 | 197 | if time[0] and not np.allclose(time, time[0]): |
197 | | - raise "All Particle.time should be the same when repeatdt is not None" |
| 198 | + raise ValueError("All Particle.time should be the same when repeatdt is not None") |
198 | 199 | self._repeatpclass = pclass |
199 | 200 | self._repeatkwargs = kwargs |
200 | 201 | self._repeatkwargs.pop("partition_function", None) |
@@ -986,13 +987,13 @@ def execute( |
986 | 987 | pyfunc=AdvectionRK4, |
987 | 988 | pyfunc_inter=None, |
988 | 989 | endtime=None, |
989 | | - runtime=None, |
990 | | - dt=1.0, |
| 990 | + runtime: float | timedelta | np.timedelta64 | None = None, |
| 991 | + dt: float | timedelta | np.timedelta64 = 1.0, |
991 | 992 | output_file=None, |
992 | 993 | verbose_progress=True, |
993 | 994 | postIterationCallbacks=None, |
994 | | - callbackdt=None, |
995 | | - delete_cfiles=True, |
| 995 | + callbackdt: float | timedelta | np.timedelta64 | None = None, |
| 996 | + delete_cfiles: bool = True, |
996 | 997 | ): |
997 | 998 | """Execute a given kernel function over the particle set for multiple timesteps. |
998 | 999 |
|
@@ -1072,22 +1073,23 @@ def execute( |
1072 | 1073 | if self.time_origin.calendar is None: |
1073 | 1074 | raise NotImplementedError("If fieldset.time_origin is not a date, execution endtime must be a double") |
1074 | 1075 | endtime = self.time_origin.reltime(endtime) |
1075 | | - if isinstance(runtime, timedelta): |
1076 | | - runtime = runtime.total_seconds() |
1077 | | - if isinstance(dt, timedelta): |
1078 | | - dt = dt.total_seconds() |
| 1076 | + |
| 1077 | + if runtime is not None: |
| 1078 | + runtime = timedelta_to_float(runtime) |
| 1079 | + |
| 1080 | + dt = timedelta_to_float(dt) |
| 1081 | + |
1079 | 1082 | if abs(dt) <= 1e-6: |
1080 | 1083 | raise ValueError("Time step dt is too small") |
1081 | 1084 | if (dt * 1e6) % 1 != 0: |
1082 | 1085 | raise ValueError("Output interval should not have finer precision than 1e-6 s") |
1083 | | - outputdt = output_file.outputdt if output_file else np.inf |
1084 | | - if isinstance(outputdt, timedelta): |
1085 | | - outputdt = outputdt.total_seconds() |
1086 | | - if outputdt is not None: |
| 1086 | + outputdt = timedelta_to_float(output_file.outputdt) if output_file else np.inf |
| 1087 | + |
| 1088 | + if np.isfinite(outputdt): |
1087 | 1089 | _warn_outputdt_release_desync(outputdt, self.particledata.data["time_nextloop"]) |
1088 | 1090 |
|
1089 | | - if isinstance(callbackdt, timedelta): |
1090 | | - callbackdt = callbackdt.total_seconds() |
| 1091 | + if callbackdt is not None: |
| 1092 | + callbackdt = timedelta_to_float(callbackdt) |
1091 | 1093 |
|
1092 | 1094 | assert runtime is None or runtime >= 0, "runtime must be positive" |
1093 | 1095 | assert outputdt is None or outputdt >= 0, "outputdt must be positive" |
@@ -1240,7 +1242,7 @@ def execute( |
1240 | 1242 |
|
1241 | 1243 | def _warn_outputdt_release_desync(outputdt: float, release_times: Iterable[float]): |
1242 | 1244 | """Gives the user a warning if the release time isn't a multiple of outputdt.""" |
1243 | | - if any(t % outputdt != 0 for t in release_times): |
| 1245 | + if any((np.isfinite(t) and t % outputdt != 0) for t in release_times): |
1244 | 1246 | warnings.warn( |
1245 | 1247 | "Some of the particles have a start time that is not a multiple of outputdt. " |
1246 | 1248 | "This could cause the first output to be at a different time than expected.", |
|
0 commit comments