示例#1
0
    def __init__(self, init, beads, nm, cell, fcomponents, ensemble=None, motion=None, prefix=""):
        """Initialises System class.

        Args:
           init: A class to deal with initializing the system.
           beads: A beads object giving the atom positions.
           cell: A cell object giving the system box.
           fcomponents: A list of force components that are active for each
              replica of the system.
           bcomponents: A list of force components that are considered as bias, and act on each
              replica of the system.
           ensemble: An ensemble object giving the objects necessary for
              producing the correct ensemble.
           nm: A class dealing with path NM operations.
           prefix: A string used to differentiate the output files of different
              systems.
        """

        info(" # Initializing system object ", verbosity.low)
        self.prefix = prefix
        self.init = init
        self.ensemble = ensemble
        self.motion = motion
        self.beads = beads
        self.cell = cell
        self.nm = nm

        self.fcomp = fcomponents
        self.forces = Forces()

        self.properties = Properties()
        self.trajs = Trajectories()
示例#2
0
    def __init__(self, eens=0.0, econs=0.0, temp=None, pext=None, stressext=None, bcomponents=None, bweights=None, hweights=None, time=0.0):
        """Initialises Ensemble.

        Args:
            temp: The temperature.
            fixcom: An optional boolean which decides whether the centre of mass
                motion will be constrained or not. Defaults to False.
        """
        dself = dd(self)

        dself.temp = depend_value(name='temp')
        if temp is not None:
            self.temp = temp
        else:
            self.temp = -1.0

        dself.stressext = depend_array(name='stressext',
                                       value=np.zeros((3, 3), float))
        if stressext is not None:
            self.stressext = np.reshape(np.asarray(stressext), (3, 3))
        else:
            self.stressext = -1.0

        dself.pext = depend_value(name='pext')
        if pext is not None:
            self.pext = pext
        else:
            self.pext = -1.0

        dself.eens = depend_value(name='eens')
        if eens is not None:
            self.eens = eens
        else:
            self.eens = 0.0

        # the bias force contains two bits: explicit biases (that are meant to represent non-physical external biasing potentials)
        # and hamiltonian weights (that will act by scaling different physical components of the force). Both are bound as components
        # of the "bias force" evaluator, but their meaning (and the wiring further down in bind()) differ.

        # these are the additional bias components
        if bcomponents is None:
            bcomponents = []
        self.bcomp = bcomponents
        self.bias = Forces()

        # and their weights
        if bweights is None or len(bweights) == 0:
            bweights = np.ones(len(self.bcomp))

        dself.bweights = depend_array(name="bweights", value=np.asarray(bweights))

        # weights of the Hamiltonian scaling
        if hweights is None:
            hweights = np.ones(0)
        self.hweights = np.asarray(hweights)

        # Internal time counter
        dd(self).time = depend_value(name='time')
        self.time = time
示例#3
0
    def __init__(self,
                 beads,
                 cell,
                 forces,
                 ensemble,
                 prng,
                 outputs,
                 nm,
                 init,
                 step=0,
                 tsteps=1000,
                 ttime=0):
        """Initialises Simulation class.

      Args:
         beads: A beads object giving the atom positions.
         cell: A cell object giving the system box.
         forces: A forcefield object giving the force calculator for each
            replica of the system.
         ensemble: An ensemble object giving the objects necessary for
            producing the correct ensemble.
         prng: A random number object.
         outputs: A list of output objects.
         nm: A class dealing with path NM operations.
         init: A class to deal with initializing the simulation object.
         step: An optional integer giving the current simulation time step.
            Defaults to 0.
         tsteps: An optional integer giving the total number of steps. Defaults
            to 1000.
         ttime: The simulation running time. Used on restart, to keep a
            cumulative total.
      """

        info(" # Initializing simulation object ", verbosity.low)
        self.prng = prng
        self.ensemble = ensemble
        self.beads = beads
        self.cell = cell
        self.nm = nm

        # initialize the configuration of the system
        self.init = init
        init.init_stage1(self)

        self.flist = forces
        self.forces = Forces()
        self.outputs = outputs

        dset(self, "step", depend_value(name="step", value=step))
        self.tsteps = tsteps
        self.ttime = ttime

        self.properties = Properties()
        self.trajs = Trajectories()
        self.chk = None
        self.rollback = True
示例#4
0
文件: system.py 项目: i-pi/i-pi
    def __init__(self, init, beads, nm, cell, fcomponents, ensemble=None, motion=None, prefix=""):
        """Initialises System class.

        Args:
           init: A class to deal with initializing the system.
           beads: A beads object giving the atom positions.
           cell: A cell object giving the system box.
           fcomponents: A list of force components that are active for each
              replica of the system.
           bcomponents: A list of force components that are considered as bias, and act on each
              replica of the system.
           ensemble: An ensemble object giving the objects necessary for
              producing the correct ensemble.
           nm: A class dealing with path NM operations.
           prefix: A string used to differentiate the output files of different
              systems.
        """

        info(" # Initializing system object ", verbosity.low)
        self.prefix = prefix
        self.init = init
        self.ensemble = ensemble
        self.motion = motion
        self.beads = beads
        self.cell = cell
        self.nm = nm

        self.fcomp = fcomponents
        self.forces = Forces()

        self.properties = Properties()
        self.trajs = Trajectories()
示例#5
0
文件: ensembles.py 项目: i-pi/i-pi
    def __init__(self, eens=0.0, econs=0.0, temp=None, pext=None, stressext=None, bcomponents=None, bweights=None, hweights=None, time=0.0):
        """Initialises Ensemble.

        Args:
            temp: The temperature.
            fixcom: An optional boolean which decides whether the centre of mass
                motion will be constrained or not. Defaults to False.
        """
        dself = dd(self)

        dself.temp = depend_value(name='temp')
        if temp is not None:
            self.temp = temp
        else:
            self.temp = -1.0

        dself.stressext = depend_array(name='stressext',
                                       value=np.zeros((3, 3), float))
        if stressext is not None:
            self.stressext = np.reshape(np.asarray(stressext), (3, 3))
        else:
            self.stressext = -1.0

        dself.pext = depend_value(name='pext')
        if pext is not None:
            self.pext = pext
        else:
            self.pext = -1.0

        dself.eens = depend_value(name='eens')
        if eens is not None:
            self.eens = eens
        else:
            self.eens = 0.0

        # the bias force contains two bits: explicit biases (that are meant to represent non-physical external biasing potentials)
        # and hamiltonian weights (that will act by scaling different physical components of the force). Both are bound as components
        # of the "bias force" evaluator, but their meaning (and the wiring further down in bind()) differ.

        # these are the additional bias components
        if bcomponents is None:
            bcomponents = []
        self.bcomp = bcomponents
        self.bias = Forces()

        # and their weights
        if bweights is None or len(bweights) == 0:
            bweights = np.ones(len(self.bcomp))

        dself.bweights = depend_array(name="bweights", value=np.asarray(bweights))

        # weights of the Hamiltonian scaling
        if hweights is None:
            hweights = np.ones(0)
        self.hweights = np.asarray(hweights)


        # Internal time counter
        dd(self).time = depend_value(name='time')
        self.time = time
示例#6
0
   def __init__(self, beads, cell, forces, ensemble, prng, outputs, nm, init, step=0, tsteps=1000, ttime=0):
      """Initialises Simulation class.

      Args:
         beads: A beads object giving the atom positions.
         cell: A cell object giving the system box.
         forces: A forcefield object giving the force calculator for each
            replica of the system.
         ensemble: An ensemble object giving the objects necessary for
            producing the correct ensemble.
         prng: A random number object.
         outputs: A list of output objects.
         nm: A class dealing with path NM operations.
         init: A class to deal with initializing the simulation object.
         step: An optional integer giving the current simulation time step.
            Defaults to 0.
         tsteps: An optional integer giving the total number of steps. Defaults
            to 1000.
         ttime: The simulation running time. Used on restart, to keep a
            cumulative total.
      """

      info(" # Initializing simulation object ", verbosity.low )
      self.prng = prng
      self.ensemble = ensemble
      self.beads = beads
      self.cell = cell
      self.nm = nm

      # initialize the configuration of the system
      self.init = init
      init.init_stage1(self)

      self.flist = forces
      self.forces = Forces()
      self.outputs = outputs

      dset(self, "step", depend_value(name="step", value=step))
      self.tsteps = tsteps
      self.ttime = ttime

      self.properties = Properties()
      self.trajs = Trajectories()
      self.chk = None
      self.rollback = True
示例#7
0
class System(dobject):

    """Physical system object.

    Contains all the physical information. Also handles stepping and output.

    Attributes:
       beads: A beads object giving the atom positions.
       cell: A cell object giving the system box.
       fcomp: A list of force components that must act on each replica
       forces: A Forces object that actually compute energy and forces
       ensemble: An ensemble object giving the objects necessary for producing
          the correct ensemble.
       outputs: A list of output objects that should be printed during the run
       nm:  A helper object dealing with normal modes transformation
       properties: A property object for dealing with property output.
       trajs: A trajectory object for dealing with trajectory output.
       init: A class to deal with initializing the system.
       simul: The parent simulation object.
    """

    def __init__(self, init, beads, nm, cell, fcomponents, ensemble=None, motion=None, prefix=""):
        """Initialises System class.

        Args:
           init: A class to deal with initializing the system.
           beads: A beads object giving the atom positions.
           cell: A cell object giving the system box.
           fcomponents: A list of force components that are active for each
              replica of the system.
           bcomponents: A list of force components that are considered as bias, and act on each
              replica of the system.
           ensemble: An ensemble object giving the objects necessary for
              producing the correct ensemble.
           nm: A class dealing with path NM operations.
           prefix: A string used to differentiate the output files of different
              systems.
        """

        info(" # Initializing system object ", verbosity.low)
        self.prefix = prefix
        self.init = init
        self.ensemble = ensemble
        self.motion = motion
        self.beads = beads
        self.cell = cell
        self.nm = nm

        self.fcomp = fcomponents
        self.forces = Forces()

        self.properties = Properties()
        self.trajs = Trajectories()

    def bind(self, simul):
        """Calls the bind routines for all the objects in the system."""

        self.simul = simul  # keeps a handle to the parent simulation object

        # binds important computation engines
        print "NOW BINDING THE FORCES.... "
        self.forces.bind(self.beads, self.cell, self.fcomp, self.simul.fflist,open_paths=self.nm.open_paths)
        self.nm.bind(self.ensemble, self.motion, beads=self.beads, forces=self.forces)
        self.ensemble.bind(self.beads, self.nm, self.cell, self.forces, self.simul.fflist)
        self.motion.bind(self.ensemble, self.beads, self.nm, self.cell, self.forces, self.prng, simul.output_maker)

        dpipe(dd(self.nm).omegan2, dd(self.forces).omegan2)

        self.init.init_stage2(self)

        # binds output management objects
        self._propertylock = threading.Lock()
        self.properties.bind(self)
        self.trajs.bind(self)
示例#8
0
class Simulation(dobject):
   """Main simulation object.

   Contains all the references and the main dynamics loop. Also handles the
   initialization and output.

   Attributes:
      beads: A beads object giving the atom positions.
      cell: A cell object giving the system box.
      prng: A random number generator object.
      flist: A list of forcefield objects giving different ways to partially
         calculate the forces.
      forces: A Forces object for calculating the total force for all the
         replicas.
      ensemble: An ensemble object giving the objects necessary for producing
         the correct ensemble.
      tsteps: The total number of steps.
      ttime: The wall clock time (in seconds).
      format: A string specifying both the format and the extension of traj
         output.
      outputs: A list of output objects that should be printed during the run
      nm:  A helper object dealing with normal modes transformation
      properties: A property object for dealing with property output.
      trajs: A trajectory object for dealing with trajectory output.
      chk: A checkpoint object for dealing with checkpoint output.
      rollback: If set to true, the state of the simulation at the start
         of the step will be output to a restart file rather than
         the current state of the simulation. This is because we cannot
         restart from half way through a step, only from the beginning of a
         step, so this is necessary for the trajectory to be continuous.

   Depend objects:
      step: The current simulation step.
   """

   def __init__(self, beads, cell, forces, ensemble, prng, outputs, nm, init, step=0, tsteps=1000, ttime=0):
      """Initializes Simulation class.

      Args:
         beads: A beads object giving the atom positions.
         cell: A cell object giving the system box.
         forces: A forcefield object giving the force calculator for each
            replica of the system.
         ensemble: An ensemble object giving the objects necessary for
            producing the correct ensemble.
         prng: A random number object.
         outputs: A list of output objects.
         nm: A class dealing with path NM operations.
         init: A class to deal with initializing the simulation object.
         step: An optional integer giving the current simulation time step.
            Defaults to 0.
         tsteps: An optional integer giving the total number of steps. Defaults
            to 1000.
         ttime: The simulation running time. Used on restart, to keep a
            cumulative total.
      """

      info(" # Initializing simulation object ", verbosity.low )
      self.prng = prng
      self.ensemble = ensemble
      self.beads = beads
      self.cell = cell
      self.nm = nm

      # initialize the configuration of the system
      self.init = init
      init.init_stage1(self)

      self.flist = forces
      self.forces = Forces()
      self.outputs = outputs

      dset(self, "step", depend_value(name="step", value=step))
      self.tsteps = tsteps
      self.ttime = ttime

      self.properties = Properties()
      self.trajs = Trajectories()
      self.chk = None
      self.rollback = True

   def bind(self):
      """Calls the bind routines for all the objects in the simulation."""

      # binds important computation engines
      self.nm.bind(self.beads, self.ensemble)
      self.forces.bind(self.beads, self.cell, self.flist)
      self.ensemble.bind(self.beads, self.nm, self.cell, self.forces, self.prng)
      self.init.init_stage2(self)

      # binds output management objects
      self.properties.bind(self)
      self.trajs.bind(self)
      for o in self.outputs:
         o.bind(self)

      self.chk = CheckpointOutput("RESTART", 1, True, 0)
      self.chk.bind(self)

      # registers the softexit routine
      softexit.register(self.softexit)

   def softexit(self):
      """Deals with a soft exit request.

      Tries to ensure that a consistent restart checkpoint is
      written out.
      """

      if self.step < self.tsteps:
         self.step += 1
      if not self.rollback:
         self.chk.store()
      self.chk.write(store=False)

      self.forces.stop()

   def run(self):
      """Runs the simulation.

      Does all the simulation steps, and outputs data to the appropriate files
      when necessary. Also deals with starting and cleaning up the threads used
      in the communication between the driver and the PIMD code.
      """

      self.forces.run()

      # prints initial configuration -- only if we are not restarting
      if (self.step == 0):
         self.step = -1
         for o in self.outputs:
            o.write()
         self.step = 0

      steptime = 0.0
      simtime =  time.time()

      cstep = 0
      tptime = 0.0
      tqtime = 0.0
      tttime = 0.0
      ttot = 0.0
      # main MD loop
      for self.step in range(self.step,self.tsteps):
         # stores the state before doing a step.
         # this is a bit time-consuming but makes sure that we can honor soft
         # exit requests without screwing the trajectory

         steptime = -time.time()
         self.chk.store()

         self.ensemble.step()

         for o in self.outputs:
            o.write()

         if os.path.exists("EXIT"): # soft-exit
            self.rollback = False
            softexit.trigger()

         steptime += time.time()
         ttot += steptime
         tptime += self.ensemble.ptime
         tqtime += self.ensemble.qtime
         tttime += self.ensemble.ttime
         cstep += 1

         if verbosity.high or (verbosity.medium and self.step%100 == 0) or (verbosity.low and self.step%1000 == 0):
            info(" # Average timings at MD step % 7d. t/step: %10.5e [p: %10.5e  q: %10.5e  t: %10.5e]" %
               ( self.step, ttot/cstep, tptime/cstep, tqtime/cstep, tttime/cstep ) )
            cstep = 0
            tptime = 0.0
            tqtime = 0.0
            tttime = 0.0
            ttot = 0.0
            info(" # MD diagnostics: V: %10.5e    Kcv: %10.5e   Ecns: %10.5e" %
               (self.properties["potential"], self.properties["kinetic_cv"], self.properties["conserved"] ) )

         if (self.ttime > 0 and time.time() - simtime > self.ttime):
            info(" # Wall clock time expired! Bye bye!", verbosity.low )
            break

      info(" # Simulation ran successfully for the prescribed total_step! Bye bye!", verbosity.low )
      self.rollback = False
      softexit.trigger()
示例#9
0
class Ensemble(dobject):
    """Base ensemble class.

    Defines the thermodynamic state of the system.

    Depend objects:
        temp: The system's temperature.
        pext: The systems's pressure
        stressext: The system's stress tensor
        bias: Explicit bias forces
    """
    def __init__(self,
                 eens=0.0,
                 econs=0.0,
                 temp=None,
                 pext=None,
                 stressext=None,
                 bcomponents=None,
                 bweights=None,
                 hweights=None,
                 time=0.0):
        """Initialises Ensemble.

        Args:
            temp: The temperature.
            fixcom: An optional boolean which decides whether the centre of mass
                motion will be constrained or not. Defaults to False.
        """
        dself = dd(self)

        dself.temp = depend_value(name='temp')
        if temp is not None:
            self.temp = temp
        else:
            self.temp = -1.0

        dself.stressext = depend_array(name='stressext',
                                       value=np.zeros((3, 3), float))
        if stressext is not None:
            self.stressext = np.reshape(np.asarray(stressext), (3, 3))
        else:
            self.stressext = -1.0

        dself.pext = depend_value(name='pext')
        if pext is not None:
            self.pext = pext
        else:
            self.pext = -1.0

        dself.eens = depend_value(name='eens')
        if eens is not None:
            self.eens = eens
        else:
            self.eens = 0.0

        # the bias force contains two bits: explicit biases (that are meant to represent non-physical external biasing potentials)
        # and hamiltonian weights (that will act by scaling different physical components of the force). Both are bound as components
        # of the "bias force" evaluator, but their meaning (and the wiring further down in bind()) differ.

        # these are the additional bias components
        if bcomponents is None:
            bcomponents = []
        self.bcomp = bcomponents
        self.bias = Forces()

        # and their weights
        if bweights is None or len(bweights) == 0:
            bweights = np.ones(len(self.bcomp))

        dself.bweights = depend_array(name="bweights",
                                      value=np.asarray(bweights))

        # weights of the Hamiltonian scaling
        if hweights is None:
            hweights = np.ones(0)
        self.hweights = np.asarray(hweights)

        # Internal time counter
        dd(self).time = depend_value(name='time')
        self.time = time

    def copy(self):
        return Ensemble(eens=self.eens,
                        econs=0.0,
                        temp=self.temp,
                        pext=self.pext,
                        stressext=dstrip(self.stressext).copy(),
                        bcomponents=self.bcomp,
                        bweights=dstrip(self.bweights).copy(),
                        hweights=dstrip(self.hweights).copy(),
                        time=self.time)

    def bind(self,
             beads,
             nm,
             cell,
             bforce,
             fflist,
             elist=[],
             xlpot=[],
             xlkin=[]):
        self.beads = beads
        self.cell = cell
        self.forces = bforce
        self.nm = nm
        dself = dd(self)

        # this binds just the explicit bias forces
        self.bias.bind(self.beads,
                       self.cell,
                       self.bcomp,
                       fflist,
                       open_paths=nm.open_paths)

        dself.econs = depend_value(name='econs', func=self.get_econs)
        # dependencies of the conserved quantity
        dself.econs.add_dependency(dd(self.nm).kin)
        dself.econs.add_dependency(dd(self.forces).pot)
        dself.econs.add_dependency(dd(self.bias).pot)
        dself.econs.add_dependency(dd(self.nm).vspring)
        dself.econs.add_dependency(dself.eens)

        # pipes the weights to the list of weight vectors
        i = 0
        for fc in self.bias.mforces:
            if fc.weight != 1:
                warning(
                    "The weight given to forces used in an ensemble bias are given a weight determined by bias_weight"
                )
            dpipe(dself.bweights, dd(fc).weight, i)
            i += 1

        # add Hamiltonian REM bias components
        if len(self.hweights) == 0:
            self.hweights = np.ones(len(self.forces.mforces))

        dself.hweights = depend_array(name="hweights",
                                      value=np.asarray(self.hweights))

        # we use ScaledForceComponents to replicate the physical forces without (hopefully) them being actually recomputed
        for ic in range(len(self.forces.mforces)):
            sfc = ScaledForceComponent(self.forces.mforces[ic], 1.0)
            self.bias.add_component(self.forces.mbeads[ic],
                                    self.forces.mrpc[ic], sfc)
            dd(sfc).scaling._func = lambda i=ic: self.hweights[i] - 1
            dd(sfc).scaling.add_dependency(dself.hweights)

        self._elist = []

        for e in elist:
            self.add_econs(e)

        dself.lpens = depend_value(name='lpens',
                                   func=self.get_lpens,
                                   dependencies=[dself.temp])
        dself.lpens.add_dependency(dd(self.nm).kin)
        dself.lpens.add_dependency(dd(self.forces).pot)
        dself.lpens.add_dependency(dd(self.bias).pot)
        dself.lpens.add_dependency(dd(self.nm).vspring)

        # extended Lagrangian terms for the ensemble
        self._xlpot = []
        for p in xlpot:
            self.add_xlpot(p)

        self._xlkin = []
        for k in xlkin:
            self.add_xlkin(k)

    def add_econs(self, e):
        self._elist.append(e)
        dd(self).econs.add_dependency(e)

    def add_xlpot(self, p):
        self._xlpot.append(p)
        dd(self).lpens.add_dependency(p)

    def add_xlkin(self, k):
        self._xlkin.append(k)
        dd(self).lpens.add_dependency(k)

    def get_econs(self):
        """Calculates the conserved energy quantity for constant energy
        ensembles.
        """

        eham = self.nm.vspring + self.nm.kin + self.forces.pot

        eham += self.bias.pot  # bias

        for e in self._elist:
            eham += e.get()

        return eham + self.eens

    def get_lpens(self):
        """Returns the ensemble probability (modulo the partition function)
        for the ensemble.
        """

        lpens = (self.forces.pot + self.bias.pot + self.nm.kin +
                 self.nm.vspring)

        # inlcude terms associated with an extended Lagrangian integrator of some sort
        for p in self._xlpot:
            lpens += p.get()
        for k in self._xlkin:
            lpens += k.get()

        lpens *= -1.0 / (Constants.kb * self.temp * self.beads.nbeads)
        return lpens
示例#10
0
class Simulation(dobject):
   """Main simulation object.

   Contains all the references and the main dynamics loop. Also handles the
   initialisation and output.

   Attributes:
      beads: A beads object giving the atom positions.
      cell: A cell object giving the system box.
      prng: A random number generator object.
      flist: A list of forcefield objects giving different ways to partially
         calculate the forces.
      forces: A Forces object for calculating the total force for all the
         replicas.
      ensemble: An ensemble object giving the objects necessary for producing
         the correct ensemble.
      tsteps: The total number of steps.
      ttime: The wall clock time (in seconds).
      format: A string specifying both the format and the extension of traj
         output.
      outputs: A list of output objects that should be printed during the run
      nm:  A helper object dealing with normal modes transformation
      properties: A property object for dealing with property output.
      trajs: A trajectory object for dealing with trajectory output.
      chk: A checkpoint object for dealing with checkpoint output.
      rollback: If set to true, the state of the simulation at the start
         of the step will be output to a restart file rather than
         the current state of the simulation. This is because we cannot
         restart from half way through a step, only from the beginning of a
         step, so this is necessary for the trajectory to be continuous.

   Depend objects:
      step: The current simulation step.
   """

   def __init__(self, beads, cell, forces, ensemble, prng, outputs, nm, init, step=0, tsteps=1000, ttime=0):
      """Initialises Simulation class.

      Args:
         beads: A beads object giving the atom positions.
         cell: A cell object giving the system box.
         forces: A forcefield object giving the force calculator for each
            replica of the system.
         ensemble: An ensemble object giving the objects necessary for
            producing the correct ensemble.
         prng: A random number object.
         outputs: A list of output objects.
         nm: A class dealing with path NM operations.
         init: A class to deal with initializing the simulation object.
         step: An optional integer giving the current simulation time step.
            Defaults to 0.
         tsteps: An optional integer giving the total number of steps. Defaults
            to 1000.
         ttime: The simulation running time. Used on restart, to keep a
            cumulative total.
      """

      info(" # Initializing simulation object ", verbosity.low )
      self.prng = prng
      self.ensemble = ensemble
      self.beads = beads
      self.cell = cell
      self.nm = nm

      # initialize the configuration of the system
      self.init = init
      init.init_stage1(self)

      self.flist = forces
      self.forces = Forces()
      self.outputs = outputs

      dset(self, "step", depend_value(name="step", value=step))
      self.tsteps = tsteps
      self.ttime = ttime

      self.properties = Properties()
      self.trajs = Trajectories()
      self.chk = None
      self.rollback = True

   def bind(self):
      """Calls the bind routines for all the objects in the simulation."""

      # binds important computation engines
      self.nm.bind(self.beads, self.ensemble)
      self.forces.bind(self.beads, self.cell, self.flist)
      self.ensemble.bind(self.beads, self.nm, self.cell, self.forces, self.prng)
      self.init.init_stage2(self)

      # binds output management objects
      self.properties.bind(self)
      self.trajs.bind(self)
      for o in self.outputs:
         o.bind(self)

      self.chk = CheckpointOutput("RESTART", 1, True, 0)
      self.chk.bind(self)

      # registers the softexit routine
      softexit.register(self.softexit)

   def softexit(self):
      """Deals with a soft exit request.

      Tries to ensure that a consistent restart checkpoint is
      written out.
      """

      if self.step < self.tsteps:
         self.step += 1
      if not self.rollback:
         self.chk.store()
      self.chk.write(store=False)

      self.forces.stop()

   def run(self):
      """Runs the simulation.

      Does all the simulation steps, and outputs data to the appropriate files
      when necessary. Also deals with starting and cleaning up the threads used
      in the communication between the driver and the PIMD code.
      """

      self.forces.run()

      # prints inital configuration -- only if we are not restarting
      if (self.step == 0):
         self.step = -1
         for o in self.outputs:
            o.write()
         self.step = 0

      steptime = 0.0
      simtime =  time.time()

      cstep = 0
      tptime = 0.0
      tqtime = 0.0
      tttime = 0.0
      ttot = 0.0
      # main MD loop
      for self.step in range(self.step,self.tsteps):
         # stores the state before doing a step.
         # this is a bit time-consuming but makes sure that we can honor soft
         # exit requests without screwing the trajectory

         steptime = -time.time()
         self.chk.store()

         self.ensemble.step()

         for o in self.outputs:
            o.write()

         if os.path.exists("EXIT"): # soft-exit
            self.rollback = False
            softexit.trigger()

         steptime += time.time()
         ttot += steptime
         tptime += self.ensemble.ptime
         tqtime += self.ensemble.qtime
         tttime += self.ensemble.ttime
         cstep += 1

         if verbosity.high or (verbosity.medium and self.step%100 == 0) or (verbosity.low and self.step%1000 == 0):
            info(" # Average timings at MD step % 7d. t/step: %10.5e [p: %10.5e  q: %10.5e  t: %10.5e]" %
               ( self.step, ttot/cstep, tptime/cstep, tqtime/cstep, tttime/cstep ) )
            cstep = 0
            tptime = 0.0
            tqtime = 0.0
            tttime = 0.0
            ttot = 0.0
            info(" # MD diagnostics: V: %10.5e    Kcv: %10.5e   Ecns: %10.5e" %
               (self.properties["potential"], self.properties["kinetic_cv"], self.properties["conserved"] ) )

         if (self.ttime > 0 and time.time() - simtime > self.ttime):
            info(" # Wall clock time expired! Bye bye!", verbosity.low )
            break

      info(" # Simulation ran successfully for the prescribed total_step! Bye bye!", verbosity.low )
      self.rollback = False
      softexit.trigger()
示例#11
0
文件: system.py 项目: i-pi/i-pi
class System(dobject):

    """Physical system object.

    Contains all the physical information. Also handles stepping and output.

    Attributes:
       beads: A beads object giving the atom positions.
       cell: A cell object giving the system box.
       fcomp: A list of force components that must act on each replica
       forces: A Forces object that actually compute energy and forces
       ensemble: An ensemble object giving the objects necessary for producing
          the correct ensemble.
       outputs: A list of output objects that should be printed during the run
       nm:  A helper object dealing with normal modes transformation
       properties: A property object for dealing with property output.
       trajs: A trajectory object for dealing with trajectory output.
       init: A class to deal with initializing the system.
       simul: The parent simulation object.
    """

    def __init__(self, init, beads, nm, cell, fcomponents, ensemble=None, motion=None, prefix=""):
        """Initialises System class.

        Args:
           init: A class to deal with initializing the system.
           beads: A beads object giving the atom positions.
           cell: A cell object giving the system box.
           fcomponents: A list of force components that are active for each
              replica of the system.
           bcomponents: A list of force components that are considered as bias, and act on each
              replica of the system.
           ensemble: An ensemble object giving the objects necessary for
              producing the correct ensemble.
           nm: A class dealing with path NM operations.
           prefix: A string used to differentiate the output files of different
              systems.
        """

        info(" # Initializing system object ", verbosity.low)
        self.prefix = prefix
        self.init = init
        self.ensemble = ensemble
        self.motion = motion
        self.beads = beads
        self.cell = cell
        self.nm = nm

        self.fcomp = fcomponents
        self.forces = Forces()

        self.properties = Properties()
        self.trajs = Trajectories()

    def bind(self, simul):
        """Calls the bind routines for all the objects in the system."""

        self.simul = simul  # keeps a handle to the parent simulation object

        # binds important computation engines
        self.forces.bind(self.beads, self.cell, self.fcomp, self.simul.fflist)
        self.nm.bind(self.ensemble, self.motion, beads=self.beads, forces=self.forces)
        self.ensemble.bind(self.beads, self.nm, self.cell, self.forces, self.simul.fflist)
        self.motion.bind(self.ensemble, self.beads, self.nm, self.cell, self.forces, self.prng, simul.output_maker)

        dpipe(dd(self.nm).omegan2, dd(self.forces).omegan2)

        self.init.init_stage2(self)

        # binds output management objects
        self._propertylock = threading.Lock()
        self.properties.bind(self)
        self.trajs.bind(self)
示例#12
0
文件: ensembles.py 项目: i-pi/i-pi
class Ensemble(dobject):

    """Base ensemble class.

    Defines the thermodynamic state of the system.

    Depend objects:
        temp: The system's temperature.
        pext: The systems's pressure
        stressext: The system's stress tensor
        bias: Explicit bias forces
    """

    def __init__(self, eens=0.0, econs=0.0, temp=None, pext=None, stressext=None, bcomponents=None, bweights=None, hweights=None, time=0.0):
        """Initialises Ensemble.

        Args:
            temp: The temperature.
            fixcom: An optional boolean which decides whether the centre of mass
                motion will be constrained or not. Defaults to False.
        """
        dself = dd(self)

        dself.temp = depend_value(name='temp')
        if temp is not None:
            self.temp = temp
        else:
            self.temp = -1.0

        dself.stressext = depend_array(name='stressext',
                                       value=np.zeros((3, 3), float))
        if stressext is not None:
            self.stressext = np.reshape(np.asarray(stressext), (3, 3))
        else:
            self.stressext = -1.0

        dself.pext = depend_value(name='pext')
        if pext is not None:
            self.pext = pext
        else:
            self.pext = -1.0

        dself.eens = depend_value(name='eens')
        if eens is not None:
            self.eens = eens
        else:
            self.eens = 0.0

        # the bias force contains two bits: explicit biases (that are meant to represent non-physical external biasing potentials)
        # and hamiltonian weights (that will act by scaling different physical components of the force). Both are bound as components
        # of the "bias force" evaluator, but their meaning (and the wiring further down in bind()) differ.

        # these are the additional bias components
        if bcomponents is None:
            bcomponents = []
        self.bcomp = bcomponents
        self.bias = Forces()

        # and their weights
        if bweights is None or len(bweights) == 0:
            bweights = np.ones(len(self.bcomp))

        dself.bweights = depend_array(name="bweights", value=np.asarray(bweights))

        # weights of the Hamiltonian scaling
        if hweights is None:
            hweights = np.ones(0)
        self.hweights = np.asarray(hweights)


        # Internal time counter
        dd(self).time = depend_value(name='time')
        self.time = time


    def bind(self, beads, nm, cell, bforce, fflist, elist=[], xlpot=[], xlkin=[]):
        self.beads = beads
        self.cell = cell
        self.forces = bforce
        self.nm = nm
        dself = dd(self)
        dself.econs = depend_value(name='econs', func=self.get_econs)

        # this binds just the explicit bias forces
        self.bias.bind(self.beads, self.cell, self.bcomp, fflist)

        dself.econs = depend_value(name='econs', func=self.get_econs)
        # dependencies of the conserved quantity
        dself.econs.add_dependency(dd(self.nm).kin)
        dself.econs.add_dependency(dd(self.forces).pot)
        dself.econs.add_dependency(dd(self.bias).pot)
        dself.econs.add_dependency(dd(self.nm).vspring)
        dself.econs.add_dependency(dself.eens)

        # pipes the weights to the list of weight vectors
        i = 0
        for fc in self.bias.mforces:
            if fc.weight != 1:
                warning("The weight given to forces used in an ensemble bias are given a weight determined by bias_weight")
            dpipe(dself.bweights, dd(fc).weight, i)
            i += 1

        # add Hamiltonian REM bias components
        if len(self.hweights) == 0:
            self.hweights = np.ones(len(self.forces.mforces))

        dself.hweights = depend_array(name="hweights", value=np.asarray(self.hweights))

        # we use ScaledForceComponents to replicate the physical forces without (hopefully) them being actually recomputed
        for ic in xrange(len(self.forces.mforces)):
            sfc = ScaledForceComponent(self.forces.mforces[ic], 1.0)
            self.bias.add_component(self.forces.mbeads[ic], self.forces.mrpc[ic], sfc)
            dd(sfc).scaling._func = lambda i=ic: self.hweights[i] - 1
            dd(sfc).scaling.add_dependency(dself.hweights)

        self._elist = []

        for e in elist:
            self.add_econs(e)

        dself.lpens = depend_value(name='lpens', func=self.get_lpens,
                                   dependencies=[dself.temp])
        dself.lpens.add_dependency(dd(self.nm).kin)
        dself.lpens.add_dependency(dd(self.forces).pot)
        dself.lpens.add_dependency(dd(self.bias).pot)
        dself.lpens.add_dependency(dd(self.nm).vspring)

        # extended Lagrangian terms for the ensemble
        self._xlpot = []
        for p in xlpot:
            self.add_xlpot(p)

        self._xlkin = []
        for k in xlkin:
            self.add_xlkin(k)

    def add_econs(self, e):
        self._elist.append(e)
        dd(self).econs.add_dependency(e)

    def add_xlpot(self, p):
        self._xlpot.append(p)
        dd(self).lpens.add_dependency(p)

    def add_xlkin(self, k):
        self._xlkin.append(k)
        dd(self).lpens.add_dependency(k)

    def get_econs(self):
        """Calculates the conserved energy quantity for constant energy
        ensembles.
        """

        eham = self.nm.vspring + self.nm.kin + self.forces.pot

        eham += self.bias.pot   # bias

        for e in self._elist:
            eham += e.get()

        return eham + self.eens

    def get_lpens(self):
        """Returns the ensemble probability (modulo the partition function)
        for the ensemble.
        """

        lpens = (self.forces.pot + self.bias.pot + self.nm.kin + self.nm.vspring);

        # inlcude terms associated with an extended Lagrangian integrator of some sort
        for p in self._xlpot:
            lpens += p.get()
        for k in self._xlkin:
            lpens += k.get()

        lpens *= -1.0 / (Constants.kb * self.temp * self.beads.nbeads)
        return lpens