Skip to content

Conversation

@mloubout
Copy link
Contributor

No description provided.

@mloubout mloubout added the API api (symbolics, types, ...) label Oct 31, 2025
@codecov
Copy link

codecov bot commented Oct 31, 2025

Codecov Report

❌ Patch coverage is 83.18584% with 19 lines in your changes missing coverage. Please review.
✅ Project coverage is 83.01%. Comparing base (59c357b) to head (37af191).

Files with missing lines Patch % Lines
devito/passes/clusters/implicit.py 0.00% 10 Missing ⚠️
devito/types/dense.py 71.42% 3 Missing and 1 partial ⚠️
devito/finite_differences/differentiable.py 72.72% 2 Missing and 1 partial ⚠️
devito/passes/iet/parpragma.py 0.00% 1 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2782      +/-   ##
==========================================
- Coverage   83.02%   83.01%   -0.01%     
==========================================
  Files         248      248              
  Lines       50804    50851      +47     
  Branches     4479     4484       +5     
==========================================
+ Hits        42180    42216      +36     
- Misses       7857     7866       +9     
- Partials      767      769       +2     
Flag Coverage Δ
pytest-gpu-aomp-amdgpuX 68.50% <61.84%> (-0.04%) ⬇️
pytest-gpu-nvc-nvidiaX 69.02% <61.84%> (-0.03%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@mloubout mloubout force-pushed the fd-eval-add branch 2 times, most recently from 766cc81 to a156d3c Compare October 31, 2025 16:05
@review-notebook-app
Copy link

Check out this pull request on  ReviewNB

See visual diffs & provide feedback on Jupyter Notebooks.


Powered by ReviewNB

@mloubout mloubout force-pushed the fd-eval-add branch 2 times, most recently from 1a9951a to dc0e8f5 Compare November 3, 2025 13:01
Copy link
Contributor

@FabioLuporini FabioLuporini left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Uncontroversial

@mloubout mloubout force-pushed the fd-eval-add branch 7 times, most recently from 42588ae to 6c6d45f Compare November 4, 2025 04:17
Copy link
Contributor

@JDBetteridge JDBetteridge left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A lot of the norms in the tests and notebooks have changed significantly, how do we know these are now the "right values". And is the test really valuable if we do not know what the true value is?

One could suggest that these are in some sense "regression tests", but then we definitely should not be changing the values!

@mloubout
Copy link
Contributor Author

mloubout commented Nov 6, 2025

A lot of the norms in the tests and notebooks have changed significantly

The one norm that changed a lot in test_mpi.py .... was indeed because of a bug introduced, made me find it so thanks, the rest is small changes due to a few extra interpolation but within tolerance



class DiffDerivative(IndexDerivative, DifferentiableOp):
pass
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

drop pass now

class DiffDerivative(IndexDerivative, DifferentiableOp):
pass

def _eval_at(self, func):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isn't it the case of IndexDerivative too?

kwargs.pop('is_commutative', None)
return self.func(*args, **kwargs)

def _eval_at(self, func):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpicking: Perhaps could be moved into a mixin class from which all *Derivative class inherit

# Two indices are aligned if they differ by an Integer*spacing.
v = (i - j)/d.spacing
if not i.has(d):
# Maybe a subdimension
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpicking, SubDimension

v = (i - j)/d.spacing
if not i.has(d):
# Maybe a subdimension
dims = {sd for sd in i.free_symbols if getattr(sd, 'is_Dimension', False)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isinstance

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

avoids circular (so local) import using getattr

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's just a hack to avoid a hack in that case?

anyway, u just reminded me that unless i is a Number or a Dimension w/o an offset, it will be of type AffineIndexAccessFunction https://github.com/devitocodes/devito/blob/main/devito/types/dimension.py#L1822

so all you have to here is

try:
    sds, = i.sds
except (AttributeError, ValueError):
    # Expected exactly one StencilDimension
    continue

btw should we not raise a NotImplementedError if len(sds) > 1 instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't think it's better. You have to check all three of i.sds, i.d, o.ofs and see if one is a sbdimensions it doesn't make it cleaner or simpler.

btw should we not raise a NotImplementedError if len(sds) > 1 instead?

No if there is multiple dimensions it's considered that the user decided to specifiy its own indices and to be valid ones. Would lead to a lot of breakign cases to raise and error here

for the compiler.
"""
mapper = self._grid_map
subs = mapper.pop('subs', {})
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since _grid_map is (must be) a cached_property, use .get() instead of .pop()

In fact, _grid_map, now that you make me think twice about it, should return a frozendict to be pedantic

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • I should not be cached no, that would break all of the FD since f and f._subs(x, x+.5) would end up with the same _grid_map when the second needs interpolation
  • using pop so that can just iterate mapper below

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh that's because we still have that crazy hack that makes every instance of f(x,y,z) reference the same __dict__ as the "origin" Function?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No this is because this is based on indices. Every f.subs is the same f with different indices (and has too or it would get really nasty with data/.....) and this checks if those specific indices are on the grid given the reference index (staggered "dim")

# Evaluate. Since we used `self.function` it will be on the grid when
# evaluate is called again within FD
retval = retval._evaluate(**kwargs)
if subs:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this if is needed, .subs should take O(1) when subs is empty by returning immediately

except KeyError:
pass

if mapper:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpicking, but same as before. We can reduce verbosity by avoiding these if since they practically speaking won't improve performance


if mapper:
return self.subs(mapper)
return self
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpicking, perhaps a blank line

eqne = eqn.evaluate.rhs
assert simplify(eqne - (p._subs(y, yp).evaluate * f).dx(x0=xp).evaluate) == 0

def test_param_stagg_add(self):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

quite a few changes have been made, and it seems weird that only one new test was required?

were they all fixing the same exact (set of) thing(s), which is entirely captured by this test? if so, OK

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the only "change" that is tested. Everything else isadjustments from removing is_Parameter and using subs in eval_for_fd instead of explicit derivatives

Copy link
Contributor

@JDBetteridge JDBetteridge left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just flagging a couple of other big changes that might need investigation (or given they are just in the notebooks, maybe re-running after your bug fix)

"source": [
"from devito import norm\n",
"assert np.isclose(norm(u), norm(U[0]), rtol=1e-5, atol=0)"
"assert np.isclose(norm(u), norm(U[0]), rtol=1e-2, atol=0)"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is 3 orders of magnitude change in the difference between two values that are notionally the same

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The numpy implementation is techinically wrong, as it does staggering but does not interpolate u/v where needed so there is some difference now because forcing the devito equation to be the same would be tricky since "incorrect"

"outputs": [],
"source": [
"assert np.isclose(np.linalg.norm(rec.data), 4263.511, atol=0, rtol=1e-4)"
"assert np.isclose(np.linalg.norm(rec.data), 3640.584, atol=0, rtol=1e-4)"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This jump is also pretty big!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Likely some parameters interpolation that were not being processed due to the SubDimensions. Will double check

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, basically comes from parameters (damp, ro, ...) being properly interpolated now.

@mloubout mloubout force-pushed the fd-eval-add branch 5 times, most recently from cfcadc9 to ef1f7d8 Compare November 12, 2025 15:06
@mloubout mloubout force-pushed the fd-eval-add branch 7 times, most recently from a8d5757 to 7a7fdd1 Compare November 18, 2025 14:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

API api (symbolics, types, ...)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants