|
2 | 2 |
|
3 | 3 | import numpy as np |
4 | 4 | import pytest |
| 5 | +from scipy import stats |
5 | 6 |
|
6 | 7 | from parcels._datasets.structured.generic import simple_UV_dataset |
7 | | -from parcels.application_kernels import DiffusionUniformKh |
| 8 | +from parcels.application_kernels import AdvectionDiffusionEM, AdvectionDiffusionM1, DiffusionUniformKh |
8 | 9 | from parcels.field import Field, VectorField |
9 | 10 | from parcels.fieldset import FieldSet |
10 | 11 | from parcels.particleset import ParticleSet |
@@ -71,3 +72,41 @@ def test_fieldKh_Brownian(mesh_type): |
71 | 72 | assert np.allclose(np.std(pset.lon), expected_std_lon, atol=tol) |
72 | 73 | assert np.allclose(np.mean(pset.lon), 0, atol=tol) |
73 | 74 | assert np.allclose(np.mean(pset.lat), 0, atol=tol) |
| 75 | + |
| 76 | + |
| 77 | +@pytest.mark.parametrize("mesh_type", ["spherical", "flat"]) |
| 78 | +@pytest.mark.parametrize("kernel", [AdvectionDiffusionM1, AdvectionDiffusionEM]) |
| 79 | +def test_fieldKh_SpatiallyVaryingDiffusion(mesh_type, kernel): |
| 80 | + """Test advection-diffusion kernels on a non-uniform diffusivity field with a linear gradient in one direction.""" |
| 81 | + ydim, xdim = 100, 200 |
| 82 | + |
| 83 | + mesh_conversion = 1 / 1852.0 / 60 if mesh_type == "spherical" else 1 |
| 84 | + ds = simple_UV_dataset(dims=(2, 1, ydim, xdim), mesh_type=mesh_type) |
| 85 | + ds["lon"].data = np.linspace(-1e6, 1e6, xdim) |
| 86 | + ds["lat"].data = np.linspace(-1e6, 1e6, ydim) |
| 87 | + grid = XGrid.from_dataset(ds) |
| 88 | + U = Field("U", ds["U"], grid, mesh_type=mesh_type, interp_method=BiLinear) |
| 89 | + V = Field("V", ds["V"], grid, mesh_type=mesh_type, interp_method=BiLinear) |
| 90 | + |
| 91 | + Kh = np.zeros((ydim, xdim), dtype=np.float32) |
| 92 | + for x in range(xdim): |
| 93 | + Kh[:, x] = np.tanh(ds["lon"][x] / ds["lon"][-1] * 10.0) * xdim / 2.0 + xdim / 2.0 + 100.0 |
| 94 | + |
| 95 | + ds["Kh_zonal"] = (["time", "depth", "YG", "XG"], np.full((2, 1, ydim, xdim), Kh)) |
| 96 | + ds["Kh_meridional"] = (["time", "depth", "YG", "XG"], np.full((2, 1, ydim, xdim), Kh)) |
| 97 | + Kh_zonal = Field("Kh_zonal", ds["Kh_zonal"], grid=grid, mesh_type=mesh_type, interp_method=BiLinear) |
| 98 | + Kh_meridional = Field("Kh_meridional", ds["Kh_meridional"], grid=grid, mesh_type=mesh_type, interp_method=BiLinear) |
| 99 | + UV = VectorField("UV", U, V) |
| 100 | + fieldset = FieldSet([U, V, UV, Kh_zonal, Kh_meridional]) |
| 101 | + fieldset.add_constant("dres", ds["lon"][1] - ds["lon"][0]) |
| 102 | + |
| 103 | + npart = 100 |
| 104 | + |
| 105 | + random.seed(1636) |
| 106 | + pset = ParticleSet(fieldset=fieldset, lon=np.zeros(npart), lat=np.zeros(npart)) |
| 107 | + pset.execute(pset.Kernel(kernel), runtime=np.timedelta64(4, "h"), dt=np.timedelta64(1, "h")) |
| 108 | + |
| 109 | + tol = 2000 * mesh_conversion # effectively 2000 m errors (because of low numbers of particles) |
| 110 | + assert np.allclose(np.mean(pset.lon), 0, atol=tol) |
| 111 | + assert np.allclose(np.mean(pset.lat), 0, atol=tol) |
| 112 | + assert stats.skew(pset.lon) > stats.skew(pset.lat) |
0 commit comments