-
Notifications
You must be signed in to change notification settings - Fork 142
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fixing an inconsistency in vertical index search between JIT and Scipy #1834
Fixing an inconsistency in vertical index search between JIT and Scipy #1834
Conversation
Would you mind elaborating on 762d911 ? Does the first search get the wrong |
In some very rare cases, the |
There's a failing mypy check; should I worry about that? Do you want to have a look for a fix, or can I merge? |
Feel free to merge. The mypy checks can be worried about another time |
I was doing some testing in #1816, and it looks like we're still getting failures on I have pushed a commit to def test_scipy_vs_jit(interp_method):
"""Test that the scipy and JIT versions of the interpolation are the same."""
variables = {"U": "U", "V": "V", "W": "W"}
dimensions = {"time": "time", "lon": "lon", "lat": "lat", "depth": "depth"}
fieldset = FieldSet.from_xarray_dataset(create_interpolation_data_with_land(), variables, dimensions, mesh="flat")
for field in [fieldset.U, fieldset.V, fieldset.W]: # Set a land point (for testing freeslip)
field.interp_method = interp_method
x, y, z = np.meshgrid(np.linspace(0, 1, 7), np.linspace(0, 1, 13), np.linspace(0, 1, 5))
TestP = ScipyParticle.add_variable("pid", dtype=np.int32, initial=0)
pset_scipy = ParticleSet(fieldset, pclass=TestP, lon=x, lat=y, depth=z, pid=np.arange(x.size))
pset_jit = ParticleSet(fieldset, pclass=JITParticle, lon=x, lat=y, depth=z)
def DeleteParticle(particle, fieldset, time):
if particle.state >= 50:
particle.delete()
for pset in [pset_scipy, pset_jit]:
pset.execute([AdvectionRK4_3D, DeleteParticle], runtime=4e-3, dt=1e-3)
tol = 1e-6
+ count = 0
for i in range(len(pset_scipy)):
# Check that the Scipy and JIT particles are at the same location
assert np.isclose(pset_scipy[i].lon, pset_jit[i].lon, atol=tol)
assert np.isclose(pset_scipy[i].lat, pset_jit[i].lat, atol=tol)
assert np.isclose(pset_scipy[i].depth, pset_jit[i].depth, atol=tol)
# Check that the Scipy and JIT particles have moved
assert not np.isclose(pset_scipy[i].lon, x.flatten()[pset_scipy.pid[i]], atol=tol)
assert not np.isclose(pset_scipy[i].lat, y.flatten()[pset_scipy.pid[i]], atol=tol)
- assert not np.isclose(pset_scipy[i].depth, z.flatten()[pset_scipy.pid[i]], atol=tol)
+ if np.isclose(pset_scipy[i].depth, z.flatten()[pset_scipy.pid[i]], atol=tol):
+ count += 1
+ print(f"{count}/{len(pset_scipy)} particles are at the same depth as the initial condition.") And the outcome is - x, y, z = np.meshgrid(np.linspace(0, 1, 7), np.linspace(0, 1, 13), np.linspace(0, 1, 5))
+ dx = 0.2
+ x, y, z = np.meshgrid(
+ np.linspace(0 + dx, 1 - dx, 7), np.linspace(0 + dx, 1 - dx, 13), np.linspace(0 + dx, 1 - dx, 5)
+ ) Any thoughts as to what is going on here @erikvansebille ? |
Hmm, not sure what is going on here. I'll investigate in the coming days! |
I found the bug, just fixed it in bb275c3. The issue was with the 'land point' we created in the unit test. That set |
I see! I'm a bit surprised that that caused it (since we're not using "nearest" interpolation), but at the same time I don't have a feel like I have a great intuition for this scenario |
While working on #1816, we found a small inconsistency between the JIT and Scipy implementation of the vertical index search. This meant that a particle that was exactly at the top of a cell in JIT (
zi=k, zeta=1
) would be located at the bottom of the overlying cell in Scipy (zi=k+1, zeta=0
).While this does not matter for linear or nearest interpolation (the particle will get the velocities at the cell interface anyways), it does matter for C-grid interpolation because the horizontal velocities are vertically uniform over a cell; so the horizontal velocities would be different in JIT and Scipy for a particle located exactly at a depth level.
This PR makes the Scipy index-search consistent with what was already the JIT version. I think(?) it's arbitrary whether the upper (
k+1
) or lower (k
) cell is chosen when a particle is at a depth level, and because JIT is used much more widely and in production, I decided to use the JIT-implementation also for Scipy.