From bf60e4462c9a24f298de45783e3d8c8b4991bf6a Mon Sep 17 00:00:00 2001 From: Aart Stuurman Date: Fri, 5 Jul 2024 13:14:02 +0200 Subject: [PATCH 1/5] argo float test start --- .../{test_argo.py => test_argo_float.py} | 10 +++++++--- virtual_ship/instruments/argo_float.py | 19 +++++++++---------- virtual_ship/sailship.py | 2 +- 3 files changed, 17 insertions(+), 14 deletions(-) rename tests/instruments/{test_argo.py => test_argo_float.py} (86%) diff --git a/tests/instruments/test_argo.py b/tests/instruments/test_argo_float.py similarity index 86% rename from tests/instruments/test_argo.py rename to tests/instruments/test_argo_float.py index 1b6493ea..4d4e5145 100644 --- a/tests/instruments/test_argo.py +++ b/tests/instruments/test_argo_float.py @@ -3,13 +3,14 @@ from datetime import timedelta import numpy as np +import py from parcels import FieldSet from virtual_ship import Location, Spacetime from virtual_ship.instruments.argo_float import ArgoFloat, simulate_argo_floats -def test_simulate_argo_floats() -> None: +def test_simulate_argo_floats(tmpdir: py.path.LocalPath) -> None: DRIFT_DEPTH = -1000 MAX_DEPTH = -2000 VERTICAL_SPEED = -0.10 @@ -39,9 +40,12 @@ def test_simulate_argo_floats() -> None: ) ] + # perform simulation + out_path = tmpdir.join("out.zarr") + simulate_argo_floats( - argo_floats=argo_floats, fieldset=fieldset, - out_file_name="test", + out_path=out_path, + argo_floats=argo_floats, outputdt=timedelta(minutes=5), ) diff --git a/virtual_ship/instruments/argo_float.py b/virtual_ship/instruments/argo_float.py index cd014671..2cb0791c 100644 --- a/virtual_ship/instruments/argo_float.py +++ b/virtual_ship/instruments/argo_float.py @@ -5,6 +5,7 @@ from datetime import timedelta import numpy as np +import py from parcels import ( AdvectionRK4, FieldSet, @@ -115,19 +116,21 @@ def _check_error(particle, fieldset, time): def simulate_argo_floats( - argo_floats: list[ArgoFloat], fieldset: FieldSet, - out_file_name: str, + out_path: str | py.path.LocalPath, + argo_floats: list[ArgoFloat], outputdt: timedelta, ) -> None: """ Use parcels to simulate a set of Argo floats in a fieldset. - :param argo_floats: A list of Argo floats to simulate. :param fieldset: The fieldset to simulate the Argo floats in. - :param out_file_name: The file to write the results to. + :param out_path: The path to write the results to. + :param argo_floats: A list of Argo floats to simulate. :param outputdt: Interval which dictates the update frequency of file output during simulation """ + DT = 10.0 # dt of Argo float simulation integrator + lon = [argo.spacetime.location.lon for argo in argo_floats] lat = [argo.spacetime.location.lat for argo in argo_floats] time = [argo.spacetime.time for argo in argo_floats] @@ -149,11 +152,7 @@ def simulate_argo_floats( ) # define output file for the simulation - out_file = argo_float_particleset.ParticleFile( - name=out_file_name, - outputdt=outputdt, - chunks=(1, 500), - ) + out_file = argo_float_particleset.ParticleFile(name=out_path, outputdt=outputdt) # get time when the fieldset ends fieldset_endtime = fieldset.time_origin.fulltime(fieldset.U.grid.time_full[-1]) @@ -167,6 +166,6 @@ def simulate_argo_floats( _check_error, ], endtime=fieldset_endtime, - dt=outputdt, + dt=DT, output_file=out_file, ) diff --git a/virtual_ship/sailship.py b/virtual_ship/sailship.py index d9dc4a85..3677c6b0 100644 --- a/virtual_ship/sailship.py +++ b/virtual_ship/sailship.py @@ -239,9 +239,9 @@ def sailship(config: VirtualShipConfiguration): print("Simulating argo floats") simulate_argo_floats( + out_path=os.path.join("results", "argo_floats.zarr"), argo_floats=argo_floats, fieldset=config.argo_float_fieldset, - out_file_name=os.path.join("results", "argo_floats.zarr"), outputdt=timedelta(minutes=5), ) From d75524e54f0156fe8f63667c4f9d006d15479594 Mon Sep 17 00:00:00 2001 From: Aart Stuurman Date: Fri, 5 Jul 2024 13:21:45 +0200 Subject: [PATCH 2/5] end time --- tests/instruments/test_argo_float.py | 1 + virtual_ship/instruments/argo_float.py | 25 +++++++++++++++---------- virtual_ship/sailship.py | 1 + 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/tests/instruments/test_argo_float.py b/tests/instruments/test_argo_float.py index 4d4e5145..c3e518b6 100644 --- a/tests/instruments/test_argo_float.py +++ b/tests/instruments/test_argo_float.py @@ -48,4 +48,5 @@ def test_simulate_argo_floats(tmpdir: py.path.LocalPath) -> None: out_path=out_path, argo_floats=argo_floats, outputdt=timedelta(minutes=5), + endtime=None, ) diff --git a/virtual_ship/instruments/argo_float.py b/virtual_ship/instruments/argo_float.py index 2cb0791c..8475306e 100644 --- a/virtual_ship/instruments/argo_float.py +++ b/virtual_ship/instruments/argo_float.py @@ -2,7 +2,7 @@ import math from dataclasses import dataclass -from datetime import timedelta +from datetime import timedelta, datetime import numpy as np import py @@ -120,6 +120,7 @@ def simulate_argo_floats( out_path: str | py.path.LocalPath, argo_floats: list[ArgoFloat], outputdt: timedelta, + endtime: datetime | None, ) -> None: """ Use parcels to simulate a set of Argo floats in a fieldset. @@ -128,21 +129,18 @@ def simulate_argo_floats( :param out_path: The path to write the results to. :param argo_floats: A list of Argo floats to simulate. :param outputdt: Interval which dictates the update frequency of file output during simulation + :param endtime: Stop at this time, or if None, continue until the end of the fieldset. """ DT = 10.0 # dt of Argo float simulation integrator - lon = [argo.spacetime.location.lon for argo in argo_floats] - lat = [argo.spacetime.location.lat for argo in argo_floats] - time = [argo.spacetime.time for argo in argo_floats] - # define parcel particles argo_float_particleset = ParticleSet( fieldset=fieldset, pclass=_ArgoParticle, - lon=lon, - lat=lat, + lat=[argo.spacetime.location.lat for argo in argo_floats], + lon=[argo.spacetime.location.lon for argo in argo_floats], depth=[argo.min_depth for argo in argo_floats], - time=time, + time=[argo.spacetime.time for argo in argo_floats], min_depth=[argo.min_depth for argo in argo_floats], max_depth=[argo.max_depth for argo in argo_floats], drift_depth=[argo.drift_depth for argo in argo_floats], @@ -154,8 +152,15 @@ def simulate_argo_floats( # define output file for the simulation out_file = argo_float_particleset.ParticleFile(name=out_path, outputdt=outputdt) - # get time when the fieldset ends + # get earliest between fieldset end time and provide end time fieldset_endtime = fieldset.time_origin.fulltime(fieldset.U.grid.time_full[-1]) + if endtime is None: + actual_endtime = fieldset_endtime + elif endtime > fieldset_endtime: + print("WARN: Requested end time later than fieldset end time.") + actual_endtime = fieldset_endtime + else: + actual_endtime = np.timedelta64(endtime) # execute simulation argo_float_particleset.execute( @@ -165,7 +170,7 @@ def simulate_argo_floats( _keep_at_surface, _check_error, ], - endtime=fieldset_endtime, + endtime=actual_endtime, dt=DT, output_file=out_file, ) diff --git a/virtual_ship/sailship.py b/virtual_ship/sailship.py index 3677c6b0..b0eb3d6c 100644 --- a/virtual_ship/sailship.py +++ b/virtual_ship/sailship.py @@ -243,6 +243,7 @@ def sailship(config: VirtualShipConfiguration): argo_floats=argo_floats, fieldset=config.argo_float_fieldset, outputdt=timedelta(minutes=5), + endtime=None, ) # convert CTD data to CSV From f3cafab8f15a84f7e47b8138268ec361fcfe0d18 Mon Sep 17 00:00:00 2001 From: Aart Stuurman Date: Fri, 5 Jul 2024 13:27:44 +0200 Subject: [PATCH 3/5] some cleanup --- tests/instruments/test_argo_float.py | 2 ++ virtual_ship/instruments/argo_float.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/instruments/test_argo_float.py b/tests/instruments/test_argo_float.py index c3e518b6..15333fc8 100644 --- a/tests/instruments/test_argo_float.py +++ b/tests/instruments/test_argo_float.py @@ -50,3 +50,5 @@ def test_simulate_argo_floats(tmpdir: py.path.LocalPath) -> None: outputdt=timedelta(minutes=5), endtime=None, ) + + # TODO test output diff --git a/virtual_ship/instruments/argo_float.py b/virtual_ship/instruments/argo_float.py index 8475306e..e890b30f 100644 --- a/virtual_ship/instruments/argo_float.py +++ b/virtual_ship/instruments/argo_float.py @@ -51,7 +51,7 @@ class ArgoFloat: def _argo_float_vertical_movement(particle, fieldset, time): if particle.cycle_phase == 0: # Phase 0: Sinking with vertical_speed until depth is drift_depth - particle_ddepth += ( # noqa See comment above about particle_* variables. + particle_ddepth += ( # noqa Parcels defines particle_* variables, which code checkers cannot know. particle.vertical_speed * particle.dt ) if particle.depth + particle_ddepth <= particle.drift_depth: From 546dbe07a44bb0483d65c57859321aa823d8ba90 Mon Sep 17 00:00:00 2001 From: Aart Stuurman Date: Fri, 5 Jul 2024 13:38:18 +0200 Subject: [PATCH 4/5] argo test output --- tests/instruments/test_argo_float.py | 38 ++++++++++++++++++++------ virtual_ship/instruments/argo_float.py | 1 + 2 files changed, 30 insertions(+), 9 deletions(-) diff --git a/tests/instruments/test_argo_float.py b/tests/instruments/test_argo_float.py index 15333fc8..0738722d 100644 --- a/tests/instruments/test_argo_float.py +++ b/tests/instruments/test_argo_float.py @@ -1,6 +1,6 @@ """Test the simulation of Argo floats.""" -from datetime import timedelta +from datetime import timedelta, datetime import numpy as np import py @@ -8,30 +8,44 @@ from virtual_ship import Location, Spacetime from virtual_ship.instruments.argo_float import ArgoFloat, simulate_argo_floats +import xarray as xr def test_simulate_argo_floats(tmpdir: py.path.LocalPath) -> None: + # arbitrary time offset for the dummy fieldset + base_time = datetime.strptime("1950-01-01", "%Y-%m-%d") + DRIFT_DEPTH = -1000 MAX_DEPTH = -2000 VERTICAL_SPEED = -0.10 CYCLE_DAYS = 10 DRIFT_DAYS = 9 + CONST_TEMPERATURE = 1.0 # constant temperature in fieldset + CONST_SALINITY = 1.0 # constant salinity in fieldset + + v = np.full((2, 2, 2), 1.0) + u = np.full((2, 2, 2), 1.0) + t = np.full((2, 2, 2), CONST_TEMPERATURE) + s = np.full((2, 2, 2), CONST_SALINITY) + fieldset = FieldSet.from_data( - {"U": 0, "V": 0, "T": 0, "S": 0}, + {"V": v, "U": u, "T": t, "S": s}, { - "lon": 0, - "lat": 0, - "time": [np.datetime64("1950-01-01") + np.timedelta64(632160, "h")], + "lon": np.array([0.0, 10.0]), + "lat": np.array([0.0, 10.0]), + "time": [ + np.datetime64(base_time + timedelta(seconds=0)), + np.datetime64(base_time + timedelta(hours=4)), + ], }, ) - min_depth = -fieldset.U.depth[0] - + # argo floats to deploy argo_floats = [ ArgoFloat( spacetime=Spacetime(location=Location(latitude=0, longitude=0), time=0), - min_depth=min_depth, + min_depth=0.0, max_depth=MAX_DEPTH, drift_depth=DRIFT_DEPTH, vertical_speed=VERTICAL_SPEED, @@ -51,4 +65,10 @@ def test_simulate_argo_floats(tmpdir: py.path.LocalPath) -> None: endtime=None, ) - # TODO test output + # test if output is as expected + results = xr.open_zarr(out_path) + + # check the following variables are in the dataset + assert len(results.trajectory) == len(argo_floats) + for var in ["lon", "lat", "z", "temperature", "salinity"]: + assert var in results, f"Results don't contain {var}" diff --git a/virtual_ship/instruments/argo_float.py b/virtual_ship/instruments/argo_float.py index e890b30f..bd362ef5 100644 --- a/virtual_ship/instruments/argo_float.py +++ b/virtual_ship/instruments/argo_float.py @@ -173,4 +173,5 @@ def simulate_argo_floats( endtime=actual_endtime, dt=DT, output_file=out_file, + verbose_progress=False, ) From 621bb781a91e87a37eeccc981c414aeddd354326 Mon Sep 17 00:00:00 2001 From: Aart Stuurman Date: Fri, 5 Jul 2024 13:41:34 +0200 Subject: [PATCH 5/5] done --- tests/instruments/test_argo_float.py | 4 ++-- virtual_ship/instruments/argo_float.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/instruments/test_argo_float.py b/tests/instruments/test_argo_float.py index 0738722d..b25e80e7 100644 --- a/tests/instruments/test_argo_float.py +++ b/tests/instruments/test_argo_float.py @@ -1,14 +1,14 @@ """Test the simulation of Argo floats.""" -from datetime import timedelta, datetime +from datetime import datetime, timedelta import numpy as np import py +import xarray as xr from parcels import FieldSet from virtual_ship import Location, Spacetime from virtual_ship.instruments.argo_float import ArgoFloat, simulate_argo_floats -import xarray as xr def test_simulate_argo_floats(tmpdir: py.path.LocalPath) -> None: diff --git a/virtual_ship/instruments/argo_float.py b/virtual_ship/instruments/argo_float.py index bd362ef5..031c8309 100644 --- a/virtual_ship/instruments/argo_float.py +++ b/virtual_ship/instruments/argo_float.py @@ -2,7 +2,7 @@ import math from dataclasses import dataclass -from datetime import timedelta, datetime +from datetime import datetime, timedelta import numpy as np import py