@@ -743,51 +743,52 @@ def generateSomdConfig(
743
743
# Get the report and restart intervals.
744
744
report_interval = self ._report_interval
745
745
restart_interval = self ._restart_interval
746
- runtime = self .protocol .getRunTime ()
747
746
748
- # Get the timestep.
749
- timestep = self .protocol ._timestep
750
-
751
- # Work out the number of cycles.
752
- ncycles = (runtime / timestep ) / report_interval
753
-
754
- # If the number of cycles isn't integer valued, adjust the report
755
- # interval so that we match specified the run time.
756
- if ncycles - _math .floor (ncycles ) != 0 :
757
- ncycles = _math .floor (ncycles )
758
- if ncycles == 0 :
759
- ncycles = 1
760
- report_interval = _math .ceil ((runtime / timestep ) / ncycles )
747
+ # Work out the number of cycles. We want one per nanosecond of simulation.
748
+ if self .protocol .getRunTime ().nanoseconds ().value () < 2 :
749
+ ncycles = 1
750
+ moves_per_cycle = self ._steps
751
+ else :
752
+ ncycles = _math .ceil (self .protocol .getRunTime ().nanoseconds ().value ())
753
+ moves_per_cycle = _math .ceil (self ._steps / ncycles )
761
754
762
- # For free energy simulations, the report interval must be a multiple
763
- # of the energy frequency which is 250 steps.
764
- if isinstance ( self . protocol , _Protocol . _FreeEnergyMixin ):
765
- if report_interval % 250 != 0 :
766
- report_interval = 250 * _math . ceil ( report_interval / 250 )
755
+ # The number of moves needs to be multiple of the report interval.
756
+ if moves_per_cycle % report_interval != 0 :
757
+ moves_per_cycle = (
758
+ _math . ceil ( moves_per_cycle / report_interval ) * report_interval
759
+ )
767
760
768
761
# Work out the number of cycles per frame.
769
- cycles_per_frame = restart_interval / report_interval
762
+ cycles_per_frame = restart_interval / moves_per_cycle
770
763
771
764
# Work out whether we need to adjust the buffer frequency.
772
765
buffer_freq = 0
773
766
if cycles_per_frame < 1 :
774
- buffer_freq = cycles_per_frame * restart_interval
767
+ buffer_freq = restart_interval
775
768
cycles_per_frame = 1
776
- self ._buffer_freq = buffer_freq
777
769
else :
778
770
cycles_per_frame = _math .floor (cycles_per_frame )
779
771
772
+ # Make sure that we aren't buffering more than 1000 frames per cycle.
773
+ if buffer_freq > 0 and moves_per_cycle / buffer_freq > 1000 :
774
+ _warnings .warn (
775
+ "Trajectory buffering will exceed limit. Reducing buffer frequency."
776
+ )
777
+ buffer_freq = moves_per_cycle / 1000
778
+
780
779
# For free energy simulations, the buffer frequency must be an integer
781
780
# multiple of the frequency at which free energies are written, which
782
- # is 250 steps . Round down to the closest multiple.
781
+ # is report interval . Round down to the closest multiple.
783
782
if isinstance (self .protocol , _Protocol ._FreeEnergyMixin ):
784
783
if buffer_freq > 0 :
785
- buffer_freq = 250 * _math .floor (buffer_freq / 250 )
784
+ buffer_freq = report_interval * _math .floor (
785
+ buffer_freq / report_interval
786
+ )
786
787
787
788
# The number of SOMD cycles.
788
- protocol_dict ["ncycles" ] = int ( ncycles )
789
+ protocol_dict ["ncycles" ] = ncycles
789
790
# The number of moves per cycle.
790
- protocol_dict ["nmoves" ] = report_interval
791
+ protocol_dict ["nmoves" ] = moves_per_cycle
791
792
# Cycles per trajectory write.
792
793
protocol_dict ["ncycles_per_snap" ] = cycles_per_frame
793
794
# Buffering frequency.
@@ -862,7 +863,7 @@ def generateSomdConfig(
862
863
"hbonds-notperturbed" # Handle hydrogen perturbations.
863
864
)
864
865
protocol_dict ["energy frequency" ] = (
865
- 250 # Write gradients every 250 steps .
866
+ report_interval # Write gradients at report interval .
866
867
)
867
868
868
869
protocol = [str (x ) for x in self .protocol .getLambdaValues ()]
0 commit comments