Example #1
0
def test_randomvonmises(mode, mu, kappa, npart=10000):
    fieldset = zeros_fieldset()

    # Parameters for random.vonmisesvariate
    fieldset.mu = mu
    fieldset.kappa = kappa

    # Set random seed
    ParcelsRandom.seed(1234)

    class AngleParticle(ptype[mode]):
        angle = Variable('angle')

    pset = ParticleSet(fieldset=fieldset,
                       pclass=AngleParticle,
                       lon=np.zeros(npart),
                       lat=np.zeros(npart),
                       depth=np.zeros(npart))

    def vonmises(particle, fieldset, time):
        particle.angle = ParcelsRandom.vonmisesvariate(fieldset.mu,
                                                       fieldset.kappa)

    pset.execute(vonmises, runtime=1, dt=1)

    angles = np.array([p.angle for p in pset])

    assert np.allclose(np.mean(angles), mu, atol=.1)
    scipy_mises = stats.vonmises.rvs(kappa, loc=mu, size=10000)
    assert np.allclose(np.mean(angles), np.mean(scipy_mises), atol=.1)
    assert np.allclose(np.std(angles), np.std(scipy_mises), atol=.1)
def test_recursive_errorhandling(mode, xdim=2, ydim=2):
    """Example script to show how recursaive error handling can work.

    In this example, a set of Particles is started at Longitude 0.5.
    These are run through a Kernel that throws an error if the
    Longitude is smaller than 0.7.
    The error Kernel then draws a new random number between 0 and 1

    Importantly, the 'normal' Kernel and Error Kernel keep iterating
    until a particle does have a longitude larger than 0.7.

    This behaviour can be useful if particles need to be 'pushed out'
    from e.g. land. Note however that current under-the-hood
    implementation is not extremely efficient, so code could be slow."""

    dimensions = {'lon': np.linspace(0., 1., xdim, dtype=np.float32),
                  'lat': np.linspace(0., 1., ydim, dtype=np.float32)}
    data = {'U': np.zeros((ydim, xdim), dtype=np.float32),
            'V': np.zeros((ydim, xdim), dtype=np.float32)}
    fieldset = FieldSet.from_data(data, dimensions, mesh='flat')

    # Set minimum value for valid longitudes (i.e. all longitudes < minlon are 'land')
    fieldset.add_constant('minlon', 0.7)

    # create a ParticleSet with all particles starting at centre of Field
    pset = ParticleSet.from_line(fieldset=fieldset, pclass=ptype[mode],
                                 start=(0.5, 0.5), finish=(0.5, 0.5), size=10)

    def TestLon(particle, fieldset, time):
        """Kernel to check whether a longitude is larger than fieldset.minlon.
        If not, the Kernel throws an error"""
        if particle.lon <= fieldset.minlon:
            return ErrorCode.Error

    def Error_RandomiseLon(particle, fieldset, time):
        """Error handling kernel that draws a new longitude.
        Note that this new longitude can be smaller than fieldset.minlon"""
        particle.lon = ParcelsRandom.uniform(0., 1.)

    ParcelsRandom.seed(123456)

    # The .execute below is only run for one timestep. Yet the
    # recovery={ErrorCode.Error: Error_RandomiseLon} assures Parcels keeps
    # attempting to move all particles beyond 0.7 longitude
    pset.execute(pset.Kernel(TestLon), runtime=1, dt=1,
                 recovery={ErrorCode.Error: Error_RandomiseLon})

    assert (pset.lon > fieldset.minlon).all()
Example #3
0
def test_brownian_example(mode, mesh, npart=3000):
    fieldset = FieldSet.from_data({
        'U': 0,
        'V': 0
    }, {
        'lon': 0,
        'lat': 0
    },
                                  mesh=mesh)

    # Set diffusion constants.
    kh_zonal = 100  # in m^2/s
    kh_meridional = 100  # in m^2/s

    # Create field of constant Kh_zonal and Kh_meridional
    fieldset.add_field(Field('Kh_zonal', kh_zonal, lon=0, lat=0, mesh=mesh))
    fieldset.add_field(
        Field('Kh_meridional', kh_meridional, lon=0, lat=0, mesh=mesh))

    # Set random seed
    ParcelsRandom.seed(123456)

    runtime = delta(days=1)

    ParcelsRandom.seed(1234)
    pset = ParticleSet(fieldset=fieldset,
                       pclass=ptype[mode],
                       lon=np.zeros(npart),
                       lat=np.zeros(npart))
    pset.execute(pset.Kernel(DiffusionUniformKh),
                 runtime=runtime,
                 dt=delta(hours=1))

    expected_std_x = np.sqrt(2 * kh_zonal * runtime.total_seconds())
    expected_std_y = np.sqrt(2 * kh_meridional * runtime.total_seconds())

    ys = pset.lat * mesh_conversion(mesh)
    xs = pset.lon * mesh_conversion(
        mesh
    )  # since near equator, we do not need to care about curvature effect

    tol = 200  # 200m tolerance
    assert np.allclose(np.std(xs), expected_std_x, atol=tol)
    assert np.allclose(np.std(ys), expected_std_y, atol=tol)
    assert np.allclose(np.mean(xs), 0, atol=tol)
    assert np.allclose(np.mean(ys), 0, atol=tol)
Example #4
0
def test_fieldKh_Brownian(mesh,
                          mode,
                          xdim=200,
                          ydim=100,
                          kh_zonal=100,
                          kh_meridional=50):
    mesh_conversion = 1 / 1852. / 60 if mesh == 'spherical' else 1
    fieldset = zeros_fieldset(mesh=mesh,
                              xdim=xdim,
                              ydim=ydim,
                              mesh_conversion=mesh_conversion)

    vec = np.linspace(-1e5 * mesh_conversion, 1e5 * mesh_conversion, 2)
    grid = RectilinearZGrid(lon=vec, lat=vec, mesh=mesh)

    fieldset.add_field(Field('Kh_zonal', kh_zonal * np.ones((2, 2)),
                             grid=grid))
    fieldset.add_field(
        Field('Kh_meridional', kh_meridional * np.ones((2, 2)), grid=grid))

    npart = 1000
    runtime = delta(days=1)

    ParcelsRandom.seed(1234)
    pset = ParticleSet(fieldset=fieldset,
                       pclass=ptype[mode],
                       lon=np.zeros(npart),
                       lat=np.zeros(npart))
    pset.execute(pset.Kernel(DiffusionUniformKh),
                 runtime=runtime,
                 dt=delta(hours=1))

    expected_std_lon = np.sqrt(2 * kh_zonal * mesh_conversion**2 *
                               runtime.total_seconds())
    expected_std_lat = np.sqrt(2 * kh_meridional * mesh_conversion**2 *
                               runtime.total_seconds())

    lats = pset.lat
    lons = pset.lon

    tol = 200 * mesh_conversion  # effectively 200 m errors
    assert np.allclose(np.std(lats), expected_std_lat, atol=tol)
    assert np.allclose(np.std(lons), expected_std_lon, atol=tol)
    assert np.allclose(np.mean(lons), 0, atol=tol)
    assert np.allclose(np.mean(lats), 0, atol=tol)
Example #5
0
def test_fieldKh_Brownian(mesh,
                          mode,
                          pset_mode,
                          xdim=200,
                          ydim=100,
                          kh_zonal=100,
                          kh_meridional=50):
    mesh_conversion = 1 / 1852. / 60 if mesh == 'spherical' else 1
    fieldset = zeros_fieldset(mesh=mesh,
                              xdim=xdim,
                              ydim=ydim,
                              mesh_conversion=mesh_conversion)

    fieldset.add_constant_field("Kh_zonal", kh_zonal, mesh=mesh)
    fieldset.add_constant_field("Kh_meridional", kh_meridional, mesh=mesh)

    npart = 1000
    runtime = delta(days=1)

    ParcelsRandom.seed(1234)
    pset = pset_type[pset_mode]['pset'](fieldset=fieldset,
                                        pclass=ptype[mode],
                                        lon=np.zeros(npart),
                                        lat=np.zeros(npart))
    pset.execute(pset.Kernel(DiffusionUniformKh),
                 runtime=runtime,
                 dt=delta(hours=1))

    expected_std_lon = np.sqrt(2 * kh_zonal * mesh_conversion**2 *
                               runtime.total_seconds())
    expected_std_lat = np.sqrt(2 * kh_meridional * mesh_conversion**2 *
                               runtime.total_seconds())

    lats = pset.lat
    lons = pset.lon

    tol = 200 * mesh_conversion  # effectively 200 m errors
    assert np.allclose(np.std(lats), expected_std_lat, atol=tol)
    assert np.allclose(np.std(lons), expected_std_lon, atol=tol)
    assert np.allclose(np.mean(lons), 0, atol=tol)
    assert np.allclose(np.mean(lats), 0, atol=tol)
Example #6
0
def test_fieldKh_SpatiallyVaryingDiffusion(mesh,
                                           mode,
                                           pset_mode,
                                           kernel,
                                           xdim=200,
                                           ydim=100):
    """Test advection-diffusion kernels on a non-uniform diffusivity field
    with a linear gradient in one direction"""
    mesh_conversion = 1 / 1852. / 60 if mesh == 'spherical' else 1
    fieldset = zeros_fieldset(mesh=mesh,
                              xdim=xdim,
                              ydim=ydim,
                              mesh_conversion=mesh_conversion)

    Kh = np.zeros((ydim, xdim), dtype=np.float32)
    for x in range(xdim):
        Kh[:, x] = np.tanh(fieldset.U.lon[x] / fieldset.U.lon[-1] *
                           10.) * xdim / 2. + xdim / 2. + 100.

    grid = RectilinearZGrid(lon=fieldset.U.lon, lat=fieldset.U.lat, mesh=mesh)
    fieldset.add_field(Field('Kh_zonal', Kh, grid=grid))
    fieldset.add_field(Field('Kh_meridional', Kh, grid=grid))
    fieldset.add_constant('dres', fieldset.U.lon[1] - fieldset.U.lon[0])

    npart = 100
    runtime = delta(days=1)

    ParcelsRandom.seed(1636)
    pset = pset_type[pset_mode]['pset'](fieldset=fieldset,
                                        pclass=ptype[mode],
                                        lon=np.zeros(npart),
                                        lat=np.zeros(npart))
    pset.execute(pset.Kernel(kernel), runtime=runtime, dt=delta(hours=1))

    lats = pset.lat
    lons = pset.lon
    tol = 2000 * mesh_conversion  # effectively 2000 m errors (because of low numbers of particles)
    assert np.allclose(np.mean(lons), 0, atol=tol)
    assert np.allclose(np.mean(lats), 0, atol=tol)
    assert (stats.skew(lons) > stats.skew(lats))
Example #7
0
def test_randomexponential(mode, lambd, npart=1000):
    fieldset = zeros_fieldset()

    # Rate parameter for random.expovariate
    fieldset.lambd = lambd

    # Set random seed
    ParcelsRandom.seed(1234)

    pset = ParticleSet(fieldset=fieldset,
                       pclass=ptype[mode],
                       lon=np.zeros(npart),
                       lat=np.zeros(npart),
                       depth=np.zeros(npart))

    def vertical_randomexponential(particle, fieldset, time):
        # Kernel for random exponential variable in depth direction
        particle.depth = ParcelsRandom.expovariate(fieldset.lambd)

    pset.execute(vertical_randomexponential, runtime=1, dt=1)

    depth = pset.depth
    expected_mean = 1. / fieldset.lambd
    assert np.allclose(np.mean(depth), expected_mean, rtol=.1)
Example #8
0
# ADD THE PERIODIC BOUNDARY
fieldset.add_constant('halo_west', -180.)
fieldset.add_constant('halo_east', 180.)
fieldset.add_periodic_halo(zonal=True)

# ADD DIFFUSION
if param['Kh']:
    fieldset.add_constant_field('Kh_zonal', param['Kh'], mesh='spherical')
    fieldset.add_constant_field('Kh_meridional', param['Kh'], mesh='spherical')

# ADD MAXIMUM PARTICLE AGE (IF LIMITED AGE)
fieldset.add_constant('max_age', param['max_age'])

# SET SEED
ParcelsRandom.seed(690)

##############################################################################
# PARTICLE CLASS #############################################################
##############################################################################


class debris(JITParticle):

    ##########################################################################
    # TEMPORARY VARIABLES FOR TRACKING PARTICLE POSITION/STATUS ##############
    ##########################################################################

    # ISO code of current cell (>0 if in any coastal cell)
    iso = Variable('iso', dtype=np.int32, initial=0, to_write=False)