def bind(self, beads=None, atoms=None, pm=None, nm=None, prng=None, fixdof=None): """Binds the appropriate degrees of freedom to the thermostat. This takes an object with degrees of freedom, and makes their momentum and mass vectors members of the thermostat. It also then creates the objects that will hold the data needed in the thermostat algorithms and the dependency network. Args: beads: An optional beads object to take the mass and momentum vectors from. atoms: An optional atoms object to take the mass and momentum vectors from. pm: An optional tuple containing a single momentum value and its conjugate mass. prng: An optional pseudo random number generator object. Defaults to Random(). fixdof: An optional integer which can specify the number of constraints applied to the system. Defaults to zero. Raises: TypeError: Raised if no appropriate degree of freedom or object containing a momentum vector is specified for the thermostat to couple to. """ super(ThermoGLE, self).bind(beads=beads, atoms=atoms, pm=pm, prng=prng, fixdof=fixdof) dself = dd(self) # allocates, initializes or restarts an array of s's if self.s.shape != (self.ns + 1, len(dself.m)): if len(self.s) > 0: warning( "Mismatch in GLE s array size on restart, will reinitialise to free particle.", verbosity.low, ) self.s = np.zeros((self.ns + 1, len(dself.m))) # Initializes the s vector in the free-particle limit info( " GLE additional DOFs initialised to the free-particle limit.", verbosity.low, ) SC = stab_cholesky(self.C * Constants.kb) self.s[:] = np.dot(SC, self.prng.gvec(self.s.shape)) else: info("GLE additional DOFs initialised from input.", verbosity.medium)
def bind(self, beads=None, atoms=None, pm=None, nm=None, prng=None, fixdof=None): """Binds the appropriate degrees of freedom to the thermostat. This takes an object with degrees of freedom, and makes their momentum and mass vectors members of the thermostat. It also then creates the objects that will hold the data needed in the thermostat algorithms and the dependency network. Args: beads: An optional beads object to take the mass and momentum vectors from. atoms: An optional atoms object to take the mass and momentum vectors from. pm: An optional tuple containing a single momentum value and its conjugate mass. prng: An optional pseudo random number generator object. Defaults to Random(). fixdof: An optional integer which can specify the number of constraints applied to the system. Defaults to zero. Raises: TypeError: Raised if no appropriate degree of freedom or object containing a momentum vector is specified for the thermostat to couple to. """ super(ThermoGLE, self).bind(beads=beads, atoms=atoms, pm=pm, prng=prng, fixdof=fixdof) dself = dd(self) # allocates, initializes or restarts an array of s's if self.s.shape != (self.ns + 1, len(dself.m)): if len(self.s) > 0: warning("Mismatch in GLE s array size on restart, will reinitialise to free particle.", verbosity.low) self.s = np.zeros((self.ns + 1, len(dself.m))) # Initializes the s vector in the free-particle limit info(" GLE additional DOFs initialised to the free-particle limit.", verbosity.low) SC = stab_cholesky(self.C * Constants.kb) self.s[:] = np.dot(SC, self.prng.gvec(self.s.shape)) else: info("GLE additional DOFs initialised from input.", verbosity.medium)
def bind(self, beads=None, atoms=None, pm=None, nm=None, prng=None, fixdof=None): """Binds the appropriate degrees of freedom to the thermostat. This takes an object with degrees of freedom, and makes their momentum and mass vectors members of the thermostat. It also then creates the objects that will hold the data needed in the thermostat algorithms and the dependency network. Actually, this specific thermostat requires being called on a beads object. Args: nm: An optional normal modes object to take the mass and momentum vectors from. prng: An optional pseudo random number generator object. Defaults to Random(). fixdof: An optional integer which can specify the number of constraints applied to the system. Defaults to zero. Raises: TypeError: Raised if no beads object is specified for the thermostat to couple to. """ dself = dd(self) if nm is None or not type(nm) is NormalModes: raise TypeError( "ThermoNMGLE.bind expects a NormalModes argument to bind to") if prng is None: self.prng = Random() else: self.prng = prng if nm.nbeads != self.nb: raise IndexError( "The parameters in nm_gle options correspond to a bead number " + str(self.nb) + " which does not match the number of beads in the path" + str(nm.nbeads)) # allocates, initializes or restarts an array of s's if self.s.shape != (self.nb, self.ns + 1, nm.natoms * 3): if len(self.s) > 0: warning( "Mismatch in GLE s array size on restart, will reinitialise to free particle.", verbosity.low, ) self.s = np.zeros((self.nb, self.ns + 1, nm.natoms * 3)) # Initializes the s vector in the free-particle limit info( " GLE additional DOFs initialised to the free-particle limit.", verbosity.low, ) for b in range(self.nb): SC = stab_cholesky(self.C[b] * Constants.kb) self.s[b] = np.dot(SC, self.prng.gvec(self.s[b].shape)) else: info("GLE additional DOFs initialised from input.", verbosity.medium) prev_ethermo = self.ethermo # creates a set of thermostats to be applied to individual normal modes self._thermos = [ ThermoGLE(temp=1, dt=1, A=self.A[b], C=self.C[b]) for b in range(self.nb) ] # must pipe all the dependencies in such a way that values for the nm # thermostats are automatically updated based on the "master" thermostat def make_Agetter(k): return lambda: self.A[k] def make_Cgetter(k): return lambda: self.C[k] it = 0 for t in self._thermos: t.s = self.s[it] # gets the s's as a slice of self.s t.bind( pm=(nm.pnm[it, :], nm.dynm3[it, :]), prng=self.prng) # bind thermostat t to the it-th normal mode # pipes temp and dt dpipe(dself.temp, dd(t).temp) dpipe(dself.dt, dd(t).dt) # here we pipe the A and C of individual NM to the "master" arrays dd(t).A.add_dependency(dself.A) dd(t).A._func = make_Agetter(it) dd(t).C.add_dependency(dself.C) dd(t).C._func = make_Cgetter(it) dself.ethermo.add_dependency(dd(t).ethermo) it += 1 # since the ethermo will be "delegated" to the normal modes thermostats, # one has to split # any previously-stored value between the sub-thermostats for t in self._thermos: t.ethermo = prev_ethermo / self.nb dself.ethermo._func = self.get_ethermo
def bind(self, nm=None, prng=None, fixdof=None): """Binds the appropriate degrees of freedom to the thermostat. This takes an object with degrees of freedom, and makes their momentum and mass vectors members of the thermostat. It also then creates the objects that will hold the data needed in the thermostat algorithms and the dependency network. Actually, this specific thermostat requires being called on a beads object. Args: nm: An optional normal modes object to take the mass and momentum vectors from. prng: An optional pseudo random number generator object. Defaults to Random(). fixdof: An optional integer which can specify the number of constraints applied to the system. Defaults to zero. Raises: TypeError: Raised if no beads object is specified for the thermostat to couple to. """ if nm is None or not type(nm) is NormalModes: raise TypeError("ThermoNMGLE.bind expects a NormalModes argument to bind to") if prng is None: self.prng = Random() else: self.prng = prng if (nm.nbeads != self.nb): raise IndexError("The parameters in nm_gle options correspond to a bead number "+str(self.nb)+ " which does not match the number of beads in the path" + str(nm.nbeads) ) # allocates, initializes or restarts an array of s's if self.s.shape != (self.nb, self.ns + 1, nm.natoms *3) : if len(self.s) > 0: warning("Mismatch in GLE s array size on restart, will reinitialise to free particle.", verbosity.low) self.s = np.zeros((self.nb, self.ns + 1, nm.natoms*3)) # Initializes the s vector in the free-particle limit info(" GLE additional DOFs initialised to the free-particle limit.", verbosity.low) for b in range(self.nb): SC = stab_cholesky(self.C[b]*Constants.kb) self.s[b] = np.dot(SC, self.prng.gvec(self.s[b].shape)) else: info("GLE additional DOFs initialised from input.", verbosity.medium) prev_ethermo = self.ethermo # creates a set of thermostats to be applied to individual normal modes self._thermos = [ThermoGLE(temp=1, dt=1, A=self.A[b], C=self.C[b]) for b in range(self.nb)] # must pipe all the dependencies in such a way that values for the nm # thermostats are automatically updated based on the "master" thermostat def make_Agetter(k): return lambda: self.A[k] def make_Cgetter(k): return lambda: self.C[k] it = 0 for t in self._thermos: t.s = self.s[it] # gets the s's as a slice of self.s t.bind(pm=(nm.pnm[it,:],nm.dynm3[it,:]), prng=self.prng) # bind thermostat t to the it-th normal mode # pipes temp and dt deppipe(self,"temp", t, "temp") deppipe(self,"dt", t, "dt") # here we pipe the A and C of individual NM to the "master" arrays dget(t,"A").add_dependency(dget(self,"A")) dget(t,"A")._func = make_Agetter(it) dget(t,"C").add_dependency(dget(self,"C")) dget(t,"C")._func = make_Cgetter(it) dget(self,"ethermo").add_dependency(dget(t,"ethermo")) it += 1 # since the ethermo will be "delegated" to the normal modes thermostats, # one has to split # any previously-stored value between the sub-thermostats for t in self._thermos: t.ethermo = prev_ethermo/self.nb dget(self,"ethermo")._func = self.get_ethermo;