-
Notifications
You must be signed in to change notification settings - Fork 238
dsl: Superstep #2658
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
dsl: Superstep #2658
Conversation
Check out this pull request on See visual diffs & provide feedback on Jupyter Notebooks. Powered by ReviewNB |
View / edit / reply to this conversation on ReviewNB EdCaunt commented on 2025-07-04T10:14:01Z "In Nemeth et al k=30 is chosen." |
View / edit / reply to this conversation on ReviewNB EdCaunt commented on 2025-07-04T10:14:01Z Line #3. src_term = source.inject(field=u.forward, expr=source*velocity*velocity*dt*dt)
|
View / edit / reply to this conversation on ReviewNB EdCaunt commented on 2025-07-04T10:14:02Z Typo: arguemnts
"the size of the superstep: k in the paper,
"Written in maths:" <- odd phrasing, reconsider |
View / edit / reply to this conversation on ReviewNB EdCaunt commented on 2025-07-04T10:14:03Z Line #1. # Should the timer context be removed??? Leftover? JDBetteridge commented on 2025-08-19T12:37:51Z More a question for the reviewer, I guess the answer is: Yes, remove it |
View / edit / reply to this conversation on ReviewNB EdCaunt commented on 2025-07-04T10:14:03Z Line #7. # Fetch and setup the Set up the what? JDBetteridge commented on 2025-08-19T12:39:44Z yes EdCaunt commented on 2025-08-20T10:48:20Z This comment is still missing a noun |
View / edit / reply to this conversation on ReviewNB EdCaunt commented on 2025-07-04T10:14:04Z "we would have to redefine much of what we have done above." What would need redefining? JDBetteridge commented on 2025-08-19T12:42:21Z I'll double check, I'm fairly sure something was unstable JDBetteridge commented on 2025-08-19T12:57:03Z Apparently nothing, I'll update to use a different EdCaunt commented on 2025-08-20T10:49:30Z Note: this is still in the notebook |
View / edit / reply to this conversation on ReviewNB EdCaunt commented on 2025-07-04T10:14:05Z x10^-4 JDBetteridge commented on 2025-08-19T12:43:29Z Technically 10^4 isn't wrong... EdCaunt commented on 2025-08-20T10:52:35Z It is misleading though and not how most people would interpret that statement |
devito/timestepping/superstep.py
Outdated
# New fields, for vector formulation both current and previous timestep are needed | ||
name = field.name | ||
grid = field.grid | ||
u = TimeFunction(name=f'{name}_ss', grid=grid, time_order=2, space_order=2*k) |
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 presume the space_order=2*k
is to ensure the halo is sufficiently wide for the operators? Would taking the space order from the original fields and using padding here be strictly more correct?
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 needs to use ._rebuild
(or .func
) to make sure it's consistent with field
u = field._rebuild(name=f'{name}_ss', space_order=2*k)
u_prev = field._rebuild(name=f'{name}_ss', space_order=2*k)
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.
So, something is fundamentally different about doing it the way you suggest @mloubout.
Seems to be an off by k
error
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.
Yeah actually ran into that in something else. _rebuild
keeps halo
from the original func so the order is right but the halo is too short so it leads to issues unless the new halo is specified as well.
''' | ||
# Placeholder fields for forming the superstep | ||
grid = u.grid | ||
a_tmp = Function(name="a_tmp", grid=grid, space_order=2*k) |
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.
Are these Function
s just used as symbolic objects? If so, why not just use Symbol
?
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 doesn't work, trying TempFunction
although I have no idea if it's the correct type to try
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.
TempFunction
also doesn't work, I'm honestly not sure what using a different object gains you here. These temporaries are never used, so should never be allocated any memory. Unless I'm misunderstanding something?
data = acoustic_model(model, step=step, snapshots=m) | ||
time = np.linspace(model.t1, model.t2, (m - 1)//step + 1) | ||
idx = 0 | ||
for ii, ax in enumerate(ax_row): |
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 would set up a separate plotting function for the contents of this loop to improve readability
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 plotting isn't really the bulk of this, its mainly setting different axis properties for different iteration counts. I can try and refactor it further
devito/timestepping/superstep.py
Outdated
# New fields, for vector formulation both current and previous timestep are needed | ||
name = field.name | ||
grid = field.grid | ||
u = TimeFunction(name=f'{name}_ss', grid=grid, time_order=2, space_order=2*k) |
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 needs to use ._rebuild
(or .func
) to make sure it's consistent with field
u = field._rebuild(name=f'{name}_ss', space_order=2*k)
u_prev = field._rebuild(name=f'{name}_ss', space_order=2*k)
|
||
|
||
def marmousi(grid, step=0): | ||
# Grab dataset from pwd or download |
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 should just throw a warning/erro people should git clone the data repo
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.
And it's a preset in the Model as well so this should be reusing the examples
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 might try making a more generic function in examples, but this really needs to go in a separate PR as it's unrelated to this work.
return u_save.data | ||
|
||
|
||
layered_model = model( |
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.
USe existing preset
@@ -0,0 +1,114 @@ | |||
''' Script that demonstrates the functionality of the superstep in 2D |
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.
That's a lot of duplicate from the 1D case, can probably be merged into one file with 1d/2d as input
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.
Pull Request Overview
This PR introduces superstep functionality to Devito, enabling multi-step time advancement with larger effective time steps while maintaining stability. The implementation includes both iterative and binary decomposition algorithms for generating superstep operators.
- Adds core superstep generation functionality with two algorithmic approaches
- Provides comprehensive examples demonstrating 1D and 2D wave propagation scenarios
- Updates test configuration to support higher-order spatial discretizations
Reviewed Changes
Copilot reviewed 5 out of 7 changed files in this pull request and generated 4 comments.
Show a summary per file
File | Description |
---|---|
devito/timestepping/superstep.py | Core superstep implementation with generator functions and solution transfer utilities |
examples/timestepping/superstep_1d.py | 1D wave equation example demonstrating superstep functionality |
examples/timestepping/superstep_2d.py | 2D ripple simulation example with visualization |
examples/timestepping/acoustic_superstep_2d.py | Advanced 2D acoustic modeling with source injection and velocity models |
tests/test_pickle.py | Updates space_order from 2 to 4 for derivative testing |
Comments suppressed due to low confidence (2)
examples/timestepping/superstep_1d.py:49
- [nitpick] Variable name 'newu' is inconsistent with the naming convention used elsewhere in the codebase. Consider using 'new_u' to match the pattern used in line 55 and other files.
newu = u
examples/timestepping/acoustic_superstep_2d.py:28
- Class name 'model' should follow Python naming conventions and be capitalized as 'Model'.
class model:
))) | ||
ax.set_xlim(model.origin[0], model.origin[0] + model.extent[0]) | ||
yticks = ax.get_yticks() | ||
ax.set_yticks(np.concat(((model.origin[1],), yticks[2::2]))) |
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.
[nitpick] Using np.concat with nested tuples is unnecessarily complex. Consider using np.concatenate([model.origin[1:2], yticks[2::2]]) or np.hstack for better readability.
ax.set_yticks(np.concat(((model.origin[1],), yticks[2::2]))) | |
ax.set_yticks(np.concatenate([model.origin[1:2], yticks[2::2]])) |
Copilot uses AI. Check for mistakes.
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.
np.concat
and np.concatenate
are the same function! 🙄
4fb9198
to
1268740
Compare
438a601
to
b1b0846
Compare
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #2658 +/- ##
=======================================
Coverage 82.94% 82.94%
=======================================
Files 248 248
Lines 50022 50022
Branches 4402 4402
=======================================
Hits 41492 41492
Misses 7776 7776
Partials 754 754
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:
|
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.
Somewhere, add a docstring referencing Tamas 's paper? or have I missed it?
Perhaps add it to a short README to examples/timestepping, which would also help navigating the directory?
solve, | ||
) | ||
from devito.timestepping.superstep import superstep_generator | ||
from scipy.interpolate import interpn |
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.
imports from third-parties should go in between those from the stdlin and the devito ones
see here https://github.com/devitocodes/devito/blob/main/CONTRIBUTING.md#coding-guidelines
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.
Cheers.
Any reason that this file isn't linked in either the readme or the wiki?
Can I suggest moving to ruff
again, or if we don't like ruff
, just using isort
? Lots of the existing "Devito style" nitpicks could quite easily be caught by the linter.
devito/timestepping/superstep.py
Outdated
new.data[0, :] = old.data[idx - 1] | ||
new.data[1, :] = old.data[idx] | ||
new_p.data[0, :] = old.data[idx - 2] | ||
new_p.data[1, :] = old.data[idx - 1] |
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, this is very suspicious...
However, you may as well throw a warning for now
devito/timestepping/superstep.py
Outdated
def superstep_generator_iterative(field, stencil, k, tn=0): | ||
''' Generate superstep iteratively: | ||
Aʲ⁺¹ = A·Aʲ | ||
''' | ||
# New fields, for vector formulation both current and previous timestep are needed | ||
name = field.name | ||
grid = field.grid | ||
u = TimeFunction(name=f'{name}_ss', grid=grid, time_order=2, space_order=2*k) | ||
u_prev = TimeFunction(name=f'{name}_ss_p', grid=grid, time_order=2, space_order=2*k) | ||
|
||
superstep_solution_transfer(field, u, u_prev, tn) | ||
|
||
# Substitute new fields into stencil | ||
ss_stencil = stencil.subs({field: u, field.backward: u_prev}, postprocess=False) | ||
ss_stencil = ss_stencil.expand().expand(add=True, nest=True) | ||
current = ss_stencil | ||
|
||
# Placeholder fields for forming the superstep | ||
a_tmp = Function(name="a_tmp", grid=grid, space_order=2*k) | ||
b_tmp = Function(name="b_tmp", grid=grid, space_order=2*k) | ||
|
||
if k >= 2: | ||
for _ in range(k - 2): | ||
current = current.subs( | ||
{u: a_tmp, u_prev: b_tmp}, postprocess=False).subs( | ||
{a_tmp: ss_stencil, b_tmp: u}, postprocess=False | ||
) | ||
current = current.expand().expand(add=True, nest=True) | ||
else: | ||
current = u | ||
|
||
stencil_next = current.subs( | ||
{u: a_tmp, u_prev: b_tmp}, postprocess=False).subs( | ||
{a_tmp: ss_stencil, b_tmp: u}, postprocess=False | ||
) | ||
stencil_next = stencil_next.expand().expand(add=True, nest=True) | ||
return u, u_prev, Eq(u.forward, stencil_next), Eq(u_prev.forward, current) | ||
|
||
|
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.
def superstep_generator_iterative(field, stencil, k, tn=0): | |
''' Generate superstep iteratively: | |
Aʲ⁺¹ = A·Aʲ | |
''' | |
# New fields, for vector formulation both current and previous timestep are needed | |
name = field.name | |
grid = field.grid | |
u = TimeFunction(name=f'{name}_ss', grid=grid, time_order=2, space_order=2*k) | |
u_prev = TimeFunction(name=f'{name}_ss_p', grid=grid, time_order=2, space_order=2*k) | |
superstep_solution_transfer(field, u, u_prev, tn) | |
# Substitute new fields into stencil | |
ss_stencil = stencil.subs({field: u, field.backward: u_prev}, postprocess=False) | |
ss_stencil = ss_stencil.expand().expand(add=True, nest=True) | |
current = ss_stencil | |
# Placeholder fields for forming the superstep | |
a_tmp = Function(name="a_tmp", grid=grid, space_order=2*k) | |
b_tmp = Function(name="b_tmp", grid=grid, space_order=2*k) | |
if k >= 2: | |
for _ in range(k - 2): | |
current = current.subs( | |
{u: a_tmp, u_prev: b_tmp}, postprocess=False).subs( | |
{a_tmp: ss_stencil, b_tmp: u}, postprocess=False | |
) | |
current = current.expand().expand(add=True, nest=True) | |
else: | |
current = u | |
stencil_next = current.subs( | |
{u: a_tmp, u_prev: b_tmp}, postprocess=False).subs( | |
{a_tmp: ss_stencil, b_tmp: u}, postprocess=False | |
) | |
stencil_next = stencil_next.expand().expand(add=True, nest=True) | |
return u, u_prev, Eq(u.forward, stencil_next), Eq(u_prev.forward, current) |
Drop this before merge. I don't think there's much utility to having both methods present
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 anyone should write code like this and no longer think this is a good example. I may just have to remove it if I can't refactor it into something presentable
More a question for the reviewer, I guess the answer is: Yes, remove it View entire conversation on ReviewNB |
yes View entire conversation on ReviewNB |
I'll double check, I'm fairly sure something was unstable View entire conversation on ReviewNB |
28865f3
to
a43feb7
Compare
Currently a PR into #2559 as the diff is smaller
Adds superstep functionality as well as example scripts and notebook