def __init__(self, mode, syslist, fflist, outputs, prng, paratemp, step=0, tsteps=1000, ttime=0): """Initialises Simulation class. Args: mode: What kind of simulation is this syslist: A list of system objects fflist: A list of forcefield objects prng: A random number object. paratemp: A parallel tempering helper class. outputs: A list of output objects. 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.mode = mode self.syslist = syslist for s in syslist: s.prng = self.prng # bind the system's prng to self prng s.init.init_stage1(s) if self.mode == "md" and len(syslist) > 1: warning("Multiple systems will evolve independently in a '" + self.mode + "' simulation.") self.fflist = {} for f in fflist: self.fflist[f.name] = f self.outtemplate = outputs dset(self, "step", depend_value(name="step", value=step)) self.tsteps = tsteps self.ttime = ttime self.paratemp = paratemp self.chk = None self.rollback = True
def __init__(self, timestep, mode="nve", thermostat=None, barostat=None, fixcom=False, fixatoms=None, nmts=None): """Initialises a "dynamics" motion object. Args: dt: The timestep of the simulation algorithms. fixcom: An optional boolean which decides whether the centre of mass motion will be constrained or not. Defaults to False. """ super(Dynamics, self).__init__(fixcom=fixcom, fixatoms=fixatoms) dset(self, "dt", depend_value(name='dt', value=timestep)) if thermostat is None: self.thermostat = Thermostat() else: self.thermostat = thermostat if barostat is None: self.barostat = Barostat() else: self.barostat = barostat if nmts is None: self.nmts = np.asarray([1], int) else: self.nmts = np.asarray(nmts) self.enstype = mode if self.enstype == "nve": self.integrator = NVEIntegrator() elif self.enstype == "nvt": self.integrator = NVTIntegrator() elif self.enstype == "npt": self.integrator = NPTIntegrator() elif self.enstype == "nst": self.integrator = NSTIntegrator() elif self.enstype == "mts": self.integrator = MTSIntegrator() else: self.integrator = DummyIntegrator() self.fixcom = fixcom if fixatoms is None: self.fixatoms = np.zeros(0, int) else: self.fixatoms = fixatoms
def bind(self, motion): """ Reference all the variables for simpler access.""" self.beads = motion.beads self.bias = motion.bias self.ensemble = motion.ensemble self.forces = motion.forces self.prng = motion.prng self.nm = motion.nm self.thermostat = motion.thermostat self.barostat = motion.barostat self.fixcom = motion.fixcom self.fixatoms = motion.fixatoms dset(self, "dt", dget(motion, "dt")) if motion.enstype == "mts": self.nmts = motion.nmts
def __init__(self, fixcom=False, fixatoms=None): """Initialises Motion object. Args: fixcom: An optional boolean which decides whether the centre of mass motion will be constrained or not. Defaults to False. fixatoms: A list of atoms that should be held fixed to their initial positions. """ dset(self, "dt", depend_value(name="dt", value=0.0)) self.fixcom = fixcom if fixatoms is None: self.fixatoms = np.zeros(0, int) else: self.fixatoms = fixatoms
def bind(self, ens, beads, nm, cell, bforce, prng): """Binds ensemble beads, cell, bforce, and prng to the dynamics. This takes a beads object, a cell object, a forcefield object and a random number generator object and makes them members of the ensemble. It also then creates the objects that will hold the data needed in the ensemble algorithms and the dependency network. Note that the conserved quantity is defined in the init, but as each ensemble has a different conserved quantity the dependencies are defined in bind. Args: beads: The beads object from whcih the bead positions are taken. nm: A normal modes object used to do the normal modes transformation. cell: The cell object from which the system box is taken. bforce: The forcefield object from which the force and virial are taken. prng: The random number generator object which controls random number generation. """ super(Dynamics, self).bind(ens, beads, nm, cell, bforce, prng) # Binds integrators self.integrator.bind(self) # n times the temperature (for path integral partition function) dset( self, "ntemp", depend_value(name='ntemp', func=self.get_ntemp, dependencies=[dget(self.ensemble, "temp")])) self.integrator.pconstraints() fixdof = len(self.fixatoms) * 3 * self.beads.nbeads if self.fixcom: fixdof += 3 # first makes sure that the thermostat has the correct temperature, then proceed with binding it. deppipe(self, "ntemp", self.thermostat, "temp") deppipe(self, "dt", self.thermostat, "dt") # the free ring polymer propagator is called in the inner loop, so propagation time should be redefined accordingly. if self.enstype == "mts": self.inmts = 1 for mk in self.nmts: self.inmts *= mk dset( self, "deltat", depend_value(name="deltat", func=(lambda: self.dt / self.inmts), dependencies=[dget(self, "dt")])) deppipe(self, "deltat", self.nm, "dt") # depending on the kind, the thermostat might work in the normal mode or the bead representation. self.thermostat.bind(beads=self.beads, nm=self.nm, prng=prng, fixdof=fixdof) deppipe(self, "ntemp", self.barostat, "temp") deppipe(self, "dt", self.barostat, "dt") deppipe(self.ensemble, "pext", self.barostat, "pext") deppipe(self.ensemble, "stressext", self.barostat, "stressext") self.barostat.bind(beads, nm, cell, bforce, prng=prng, fixdof=fixdof) self.ensemble.add_econs(dget(self.thermostat, "ethermo")) self.ensemble.add_econs(dget(self.barostat, "ebaro")) #!TODO THOROUGH CLEAN-UP AND CHECK #if self.enstype in ["nvt", "npt", "nst"]: if self.enstype == "nvt" or self.enstype == "npt" or self.enstype == "nst": if self.ensemble.temp < 0: raise ValueError( "Negative or unspecified temperature for a constant-T integrator" ) if self.enstype == "npt": if type(self.barostat) is Barostat: raise ValueError( "The barostat and its mode have to be specified for constant-p integrators" ) if self.ensemble.pext < 0: raise ValueError( "Negative or unspecified pressure for a constant-p integrator" ) elif self.enstype == "nst": print "STRESS:", np.trace(self.ensemble.stressext) if np.trace(self.ensemble.stressext) < 0: raise ValueError( "Negative or unspecified stress for a constant-s integrator" )