|
| 1 | +## Argo float benchmark |
| 2 | + |
| 3 | +from datetime import timedelta |
| 4 | + |
| 5 | +import numpy as np |
| 6 | + |
| 7 | +from parcels import AdvectionRK4, FieldSet, JITParticle, ParticleSet, ScipyParticle, StatusCode, Variable |
| 8 | + |
| 9 | +def ArgoVerticalMovement(particle, fieldset, time): |
| 10 | + driftdepth = 1000 # maximum depth in m |
| 11 | + maxdepth = 2000 # maximum depth in m |
| 12 | + vertical_speed = 0.10 # sink and rise speed in m/s |
| 13 | + cycletime = 10 * 86400 # total time of cycle in seconds |
| 14 | + drifttime = 9 * 86400 # time of deep drift in seconds |
| 15 | + |
| 16 | + if particle.cycle_phase == 0: |
| 17 | + # Phase 0: Sinking with vertical_speed until depth is driftdepth |
| 18 | + particle_ddepth += vertical_speed * particle.dt |
| 19 | + if particle.depth + particle_ddepth >= driftdepth: |
| 20 | + particle_ddepth = driftdepth - particle.depth |
| 21 | + particle.cycle_phase = 1 |
| 22 | + |
| 23 | + elif particle.cycle_phase == 1: |
| 24 | + # Phase 1: Drifting at depth for drifttime seconds |
| 25 | + particle.drift_age += particle.dt |
| 26 | + if particle.drift_age >= drifttime: |
| 27 | + particle.drift_age = 0 # reset drift_age for next cycle |
| 28 | + particle.cycle_phase = 2 |
| 29 | + |
| 30 | + elif particle.cycle_phase == 2: |
| 31 | + # Phase 2: Sinking further to maxdepth |
| 32 | + particle_ddepth += vertical_speed * particle.dt |
| 33 | + if particle.depth + particle_ddepth >= maxdepth: |
| 34 | + particle_ddepth = maxdepth - particle.depth |
| 35 | + particle.cycle_phase = 3 |
| 36 | + |
| 37 | + elif particle.cycle_phase == 3: |
| 38 | + # Phase 3: Rising with vertical_speed until at surface |
| 39 | + particle_ddepth -= vertical_speed * particle.dt |
| 40 | + # particle.temp = fieldset.temp[time, particle.depth, particle.lat, particle.lon] # if fieldset has temperature |
| 41 | + if particle.depth + particle_ddepth <= fieldset.mindepth: |
| 42 | + particle_ddepth = fieldset.mindepth - particle.depth |
| 43 | + # particle.temp = 0./0. # reset temperature to NaN at end of sampling cycle |
| 44 | + particle.cycle_phase = 4 |
| 45 | + |
| 46 | + elif particle.cycle_phase == 4: |
| 47 | + # Phase 4: Transmitting at surface until cycletime is reached |
| 48 | + if particle.cycle_age > cycletime: |
| 49 | + particle.cycle_phase = 0 |
| 50 | + particle.cycle_age = 0 |
| 51 | + |
| 52 | + if particle.state == StatusCode.Evaluate: |
| 53 | + particle.cycle_age += particle.dt # update cycle_age |
| 54 | + |
| 55 | +class ArgoFloatJIT: |
| 56 | + def setup(self): |
| 57 | + xdim = ydim = zdim = 2 |
| 58 | + |
| 59 | + dimensions = { |
| 60 | + "lon": "lon", |
| 61 | + "lat": "lat", |
| 62 | + "depth": "depth", |
| 63 | + } |
| 64 | + data = { |
| 65 | + "U": np.ones((xdim, ydim, zdim), dtype=np.float32), |
| 66 | + "V": np.zeros((xdim, ydim, zdim), dtype=np.float32), |
| 67 | + } |
| 68 | + data["U"][:, :, 0] = 0.0 |
| 69 | + fieldset = FieldSet.from_data(data, dimensions, mesh="flat", transpose=True) |
| 70 | + fieldset.mindepth = fieldset.U.depth[0] |
| 71 | + |
| 72 | + # Define a new Particle type including extra Variables |
| 73 | + self.ArgoParticle = JITParticle.add_variables( |
| 74 | + [ |
| 75 | + # Phase of cycle: |
| 76 | + # init_descend=0, |
| 77 | + # drift=1, |
| 78 | + # profile_descend=2, |
| 79 | + # profile_ascend=3, |
| 80 | + # transmit=4 |
| 81 | + Variable("cycle_phase", dtype=np.int32, initial=0.0), |
| 82 | + Variable("cycle_age", dtype=np.float32, initial=0.0), |
| 83 | + Variable("drift_age", dtype=np.float32, initial=0.0), |
| 84 | + # if fieldset has temperature |
| 85 | + # Variable('temp', dtype=np.float32, initial=np.nan), |
| 86 | + ] |
| 87 | + ) |
| 88 | + |
| 89 | + self.pset=ParticleSet( |
| 90 | + fieldset=fieldset, |
| 91 | + pclass=ArgoParticle, |
| 92 | + lon=[0], |
| 93 | + lat=[0], |
| 94 | + depth=[0] |
| 95 | + ) |
| 96 | + |
| 97 | + # combine Argo vertical movement kernel with built-in Advection kernel |
| 98 | + self.kernels = [ArgoVerticalMovement, AdvectionRK4] |
| 99 | + |
| 100 | + def time_run_single_timestep(self): |
| 101 | + self.pset.execute(AdvectionRK4, runtime=timedelta(seconds=1 * 30), dt=timedelta(seconds=30)) |
| 102 | + |
| 103 | + |
| 104 | + |
0 commit comments