-
Notifications
You must be signed in to change notification settings - Fork 195
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
CFL-limited adaptive timestepping for electrostatic solver #5176
CFL-limited adaptive timestepping for electrostatic solver #5176
Conversation
Marking as ready for review. Ran a long simulation over the weekend using this feature at two different CFL numbers and encountered no issues. |
Addressed most of the comments. Remaining open issues concern the hybrid solver. If we think that will work OK with this timestepping method, then we can use it for all non-EM solver cases. I also want to add a test case or two. Would modifying one of the existing ES test cases to not use a constant dt be sufficient, or should I add an extra test? |
…n ES simulation enabled
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 really cool! I do worry a bit that the need to pass dt_next
to so many functions for which it usually is not needed tangles things up in a way that could make it hard to maintain in the future, so I wonder if there is a way to avoid this. Said another way, I wonder if this new algorithm can be added without touching as many functions that are used by other algorithms as well.
For example, to get adaptive time stepping in the ES scheme one could run a simulation for a small number of steps and create a checkpoint (during which particle positions and velocities are synchronized), and then restart that simulation with a different timestep. Could we do this in a way that doesn't require actually checkpointing and restarting? The WarpX evolve loop includes a check for whether positions and velocities are synchronized (is_synchronized
) and moves the momentum back half a timestep if it is. Could this algorithm instead re-synchronize the positions and velocities every time the timestep is changed (setting is_synchronized = True
)? At the next loop the momentum would then be moved back based on the new timestep and the push should work as usual. Does that make sense? What do you think?
Python/pywarpx/picmi.py
Outdated
|
||
warpx_max_dt: float, optional | ||
The maximum allowable timestep when using adaptive timestepping (only available for non-electromagnetic solvers) |
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.
Seeing as this is specific to the Poisson solver I think it would make more sense to put this argument in ElectrostaticSolver
.
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.
Sure, that makes sense
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 the adaptive time stepping would be particularly useful for the hybrid code since the allowable timestep in that model is set by the frequency of Whistler waves at the smallest wavelength the grid can support rather than a particle CFL condition.
That's a neat idea! I'll see if I can implement that instead. |
Ok, I refactored according to your suggestion. I think it's much cleaner now. |
I could use a bit of help with the last failing test. It's this one, in cartesian2D:
I don't do anything to the restarts at all, so I'm unsure why this would be off. Here's the test output:
|
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.
Thanks for updating the implementation! I just have a few minor comments.
As for the test that is suddenly failing, I'd have to guess it is due to the timestep in that simulation having slightly changed since the logic to set it is subtly (and slightly) different. Before it would have been:
deltat = cfl * std::min(dx[0], dx[1]) / PhysConst::c;
whereas now it is
deltat = cfl / PhysConst::c * std::min({AMREX_D_DECL(x[0], x[1], x[2])});
I'm guessing something in that, probably the order of operations, caused a floating point change in deltat
which broke the test.
That's what I was thinking, but the weird part is it's only the restart that fails. The regular |
Ok, looks like tests pass now, yay! Also addressed the most recent round of comments. |
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.
Looks good! Thanks for adding this feature!
This PR implements CFL-limited adaptive timestepping for the electrostatic and magnetostatic solvers. This relies on #5169 (edit: now merged!) and would help fix a lot of the problems in #5113.
The algorithm is pretty simple. At the end of each simulation step, the timestep is updated to be CFL * min(dx,dy,dz) / max_v, where max_v is the maximum speed of any particle in the simulation. For accuracy using leapfrog-like methods where position and velocity are stored at different times, we store both the current and next timestep indt
anddt_next
, respectively. During a particle push, the position is pushed bydt
and the momentum bydt/2 + dt_next/2
. Then, dt is set to dt_next and dt_next is computed using the formula above. I found this approach demonstrated in Chen et al, which included a helpful diagram, although their time centering is offset from oursEDIT: After some feedback from @roelof-groenewald, we now set the timestep at user-defined intervals as opposed to every step. When the timestep is updated, we first synchronize position and velocity. We then set the timestep according to CFL * min(dx,dy,dz) / max_v, where max_v is the maximum speed of any particle in the simulation. We then push the velocity backward one half step and continue using the new timestep.
For PICMI, the cfl number for electrostatic simulations is now controlled by the
warpx_cfl
parameter in theElectrostaticSolver
class. Users may also specify awarpx.max_dt
andwarpx.dt_update_interval
. The former parameter specifies the maximum allowable timestep and additionally sets the initial timestep. The latter determines how often the timestep is updated. Adaptive timestepping is disabled if this parameter is <= 0.TODO