-
Notifications
You must be signed in to change notification settings - Fork 244
api: fix staggered evaluation for add/mul #2782
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
base: main
Are you sure you want to change the base?
Conversation
Codecov Report❌ Patch coverage is 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
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
766cc81 to
a156d3c
Compare
|
Check out this pull request on See visual diffs & provide feedback on Jupyter Notebooks. Powered by ReviewNB |
1a9951a to
dc0e8f5
Compare
FabioLuporini
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Uncontroversial
42588ae to
6c6d45f
Compare
JDBetteridge
left a comment
There was a problem hiding this 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!
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 |
There was a problem hiding this comment.
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): |
There was a problem hiding this comment.
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): |
There was a problem hiding this comment.
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
devito/types/basic.py
Outdated
| # Two indices are aligned if they differ by an Integer*spacing. | ||
| v = (i - j)/d.spacing | ||
| if not i.has(d): | ||
| # Maybe a subdimension |
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
isinstance
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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', {}) |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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
fandf._subs(x, x+.5)would end up with the same_grid_mapwhen the second needs interpolation - using pop so that can just iterate mapper below
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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")
devito/types/basic.py
Outdated
| # 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: |
There was a problem hiding this comment.
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
devito/types/dense.py
Outdated
| except KeyError: | ||
| pass | ||
|
|
||
| if mapper: |
There was a problem hiding this comment.
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
devito/types/dense.py
Outdated
|
|
||
| if mapper: | ||
| return self.subs(mapper) | ||
| return self |
There was a problem hiding this comment.
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): |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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
JDBetteridge
left a comment
There was a problem hiding this 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)" |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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)" |
There was a problem hiding this comment.
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!
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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.
cfcadc9 to
ef1f7d8
Compare
a8d5757 to
7a7fdd1
Compare
7a7fdd1 to
c1544b8
Compare
No description provided.