diff --git a/doc/source/changelog.rst b/doc/source/changelog.rst index e2676c9e8..77bd94c11 100644 --- a/doc/source/changelog.rst +++ b/doc/source/changelog.rst @@ -17,6 +17,10 @@ organisation on `GitHub `__. * Please add an item to this CHANGELOG for any new features or bug fixes when creating a PR. +* Run each ``Dynamics.run()`` block through to the next frame or energy save rather than + in fixed blocks of 50 steps, which cost a force evaluation and a GPU sync each. The 50 + step blocks are kept when a progress bar is shown, since they only exist to update it. + `2026.2.0 `__ - September 2026 ---------------------------------------------------------------------------------------------- diff --git a/src/sire/base/_progressbar.py b/src/sire/base/_progressbar.py index 219c05781..870234fde 100644 --- a/src/sire/base/_progressbar.py +++ b/src/sire/base/_progressbar.py @@ -3,6 +3,7 @@ from ..legacy.Base import ProgressBar as _ProgressBar _cached_in_notebook = None +_is_silent = False def _in_notebook(): @@ -113,4 +114,10 @@ def set_theme(theme): @staticmethod def set_silent(): + global _is_silent + _is_silent = True _ProgressBar.set_silent() + + @staticmethod + def is_silent(): + return _is_silent diff --git a/src/sire/mol/_dynamics.py b/src/sire/mol/_dynamics.py index 383300078..545d14090 100644 --- a/src/sire/mol/_dynamics.py +++ b/src/sire/mol/_dynamics.py @@ -1405,35 +1405,31 @@ class NeedsMinimiseError(Exception): with ThreadPoolExecutor() as pool: while completed < steps_to_run: - block_size = 50 + # Each block ends at the next frame or energy save, or the end + # of the run. Shorter blocks are only needed to update the + # progress bar, and cost a GPU sync each. + block_size = steps_to_run - completed + if not ProgressBar.is_silent(): + block_size = min(block_size, 50) steps_till_frame = self._next_save_frame - ( completed + nsteps_before_run ) - if steps_till_frame <= 0 or ( - steps_till_frame <= block_size - and steps_till_frame <= steps_to_run - completed - ): - save_frame = True - self._next_save_frame += frame_frequency_steps - if frame_frequency_steps < block_size: - block_size = frame_frequency_steps - else: - save_frame = False - steps_till_energy = self._next_save_energy - ( completed + nsteps_before_run ) - if steps_till_energy <= 0 or ( - steps_till_energy <= block_size - and steps_till_energy <= steps_to_run - completed - ): - save_energy = True + if 0 < steps_till_frame < block_size: + block_size = steps_till_frame + if 0 < steps_till_energy < block_size: + block_size = steps_till_energy + + save_frame = steps_till_frame <= block_size + if save_frame: + self._next_save_frame += frame_frequency_steps + + save_energy = steps_till_energy <= block_size + if save_energy: self._next_save_energy += energy_frequency_steps - if energy_frequency_steps < block_size: - block_size = energy_frequency_steps - else: - save_energy = False # save the last frame if we're about to exit and the user # has requested it