@@ -743,51 +743,52 @@ def generateSomdConfig(
743743 # Get the report and restart intervals.
744744 report_interval = self ._report_interval
745745 restart_interval = self ._restart_interval
746- runtime = self .protocol .getRunTime ()
747746
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 )
761754
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+ )
767760
768761 # 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
770763
771764 # Work out whether we need to adjust the buffer frequency.
772765 buffer_freq = 0
773766 if cycles_per_frame < 1 :
774- buffer_freq = cycles_per_frame * restart_interval
767+ buffer_freq = restart_interval
775768 cycles_per_frame = 1
776- self ._buffer_freq = buffer_freq
777769 else :
778770 cycles_per_frame = _math .floor (cycles_per_frame )
779771
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+
780779 # For free energy simulations, the buffer frequency must be an integer
781780 # 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.
783782 if isinstance (self .protocol , _Protocol ._FreeEnergyMixin ):
784783 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+ )
786787
787788 # The number of SOMD cycles.
788- protocol_dict ["ncycles" ] = int ( ncycles )
789+ protocol_dict ["ncycles" ] = ncycles
789790 # The number of moves per cycle.
790- protocol_dict ["nmoves" ] = report_interval
791+ protocol_dict ["nmoves" ] = moves_per_cycle
791792 # Cycles per trajectory write.
792793 protocol_dict ["ncycles_per_snap" ] = cycles_per_frame
793794 # Buffering frequency.
@@ -862,7 +863,7 @@ def generateSomdConfig(
862863 "hbonds-notperturbed" # Handle hydrogen perturbations.
863864 )
864865 protocol_dict ["energy frequency" ] = (
865- 250 # Write gradients every 250 steps .
866+ report_interval # Write gradients at report interval .
866867 )
867868
868869 protocol = [str (x ) for x in self .protocol .getLambdaValues ()]
0 commit comments