def main(prefix, suffix="pos", unitconv="1.0"): ipos = [] imode = [] for filename in sorted(glob.glob(prefix + "." + suffix + "*")): imode.append(filename.split(".")[-1]) ipos.append(open(filename, "r")) nbeads = len(ipos) natoms = 0 ifr = 0 while True: try: for i in range(nbeads): ret = read_file(imode[i], ipos[i]) pos = ret["atoms"] cell = ret["cell"] if natoms == 0: natoms = pos.natoms beads = Beads(natoms, nbeads) cell.h *= float(unitconv) beads[i].q = pos.q * float(unitconv) beads.names = pos.names except EOFError: # finished reading files sys.exit(0) print_file_path("pdb", beads, cell) ifr += 1
def main(prefix, temp): temp = unit_to_internal("energy","kelvin",float(temp)) ipos=[] for filename in sorted(glob.glob(prefix+".pos*")): ipos.append(open(filename,"r")) ifor=[] for filename in sorted(glob.glob(prefix+".for*")): ifor.append(open(filename,"r")) ikin=open(prefix+".kin.xyz","w") ikod=open(prefix+".kod.xyz","w") nbeads = len(ipos) if (nbeads!=len(ifor)): raise ValueError("Mismatch between number of output files for forces and positions") natoms = 0 ifr = 0 while True: try: for i in range(nbeads): pos = read_xyz(ipos[i]) force = read_xyz(ifor[i]) if natoms == 0: natoms = pos.natoms beads = Beads(natoms,nbeads) forces = Beads(natoms,nbeads) kcv = np.zeros((natoms,6),float) beads[i].q = pos.q forces[i].q = force.q except EOFError: # finished reading files sys.exit(0) q = depstrip(beads.q) f = depstrip(forces.q) qc = depstrip(beads.qc) kcv[:]=0 for j in range(nbeads): for i in range(natoms): kcv[i,0] += (q[j,i*3+0]-qc[i*3+0])*f[j,i*3+0] kcv[i,1] += (q[j,i*3+1]-qc[i*3+1])*f[j,i*3+1] kcv[i,2] += (q[j,i*3+2]-qc[i*3+2])*f[j,i*3+2] kcv[i,3] += (q[j,i*3+0]-qc[i*3+0])*f[j,i*3+1] + (q[j,i*3+1]-qc[i*3+1])*f[j,i*3+0] kcv[i,4] += (q[j,i*3+0]-qc[i*3+0])*f[j,i*3+2] + (q[j,i*3+2]-qc[i*3+2])*f[j,i*3+0] kcv[i,5] += (q[j,i*3+1]-qc[i*3+1])*f[j,i*3+2] + (q[j,i*3+2]-qc[i*3+2])*f[j,i*3+1] kcv*=-0.5/nbeads kcv[:,0:3]+=0.5*Constants.kb*temp kcv[:,3:6]*=0.5 ikin.write("%d\n# Centroid-virial kinetic energy estimator [a.u.] - diagonal terms: xx yy zz\n" % (natoms)) ikod.write("%d\n# Centroid-virial kinetic energy estimator [a.u.] - off-diag terms: xy xz yz\n" % (natoms)) for i in range(natoms): ikin.write("%8s %12.5e %12.5e %12.5e\n" % (pos.names[i], kcv[i,0], kcv[i,1], kcv[i,2])) ikod.write("%8s %12.5e %12.5e %12.5e\n" % (pos.names[i], kcv[i,3], kcv[i,4], kcv[i,5])) ifr+=1
def init_beads(iif, nbeads): """A file to initialize a beads object from an appropriate initializer object. Args: iif: An Initializer object which has information on the bead positions. nbeads: The number of beads. Raises: ValueError: If called using an Initializer object with a 'manual' mode. """ mode = iif.mode value = iif.value if mode == "xyz" or mode == "pdb": if mode == "xyz": ratoms = init_xyz(value) if mode == "pdb": ratoms = init_pdb(value)[0] rbeads = Beads(ratoms[0].natoms, len(ratoms)) for i in range(len(ratoms)): rbeads[i] = ratoms[i] elif mode == "chk": rbeads = init_chk(value)[0] elif mode == "manual": raise ValueError("Cannot initialize manually a whole beads object.") return rbeads
def init_beads(iif, nbeads, dimension="length", units="automatic", cell_units="automatic"): """Initializes a beads object from an appropriate initializer object. Args: iif: An Initializer object which has information on the bead positions. nbeads: The number of beads. Raises: ValueError: If called using an Initializer object with a 'manual' mode. """ mode = iif.mode value = iif.value if mode == "chk": rbeads = init_chk(value)[0] elif mode == "manual": raise ValueError("Cannot initialize manually a whole beads object.") else: ret = init_file(mode, value, dimension, units, cell_units) ratoms = ret[0] rbeads = Beads(ratoms[0].natoms, len(ratoms)) for i in range(len(ratoms)): rbeads[i] = ratoms[i] return rbeads
def bind(self, dumop, discretization): self.temp = dumop.temp self.fix = Fix(dumop.beads.natoms, dumop.fixatoms, dumop.beads.nbeads) self.dbeads = Beads(dumop.beads.natoms - len(dumop.fixatoms), dumop.beads.nbeads) self.dbeads.q[:] = self.fix.get_active_vector(dumop.beads.copy().q, 1) self.dbeads.m[:] = self.fix.get_active_vector(dumop.beads.copy().m, 0) self.dbeads.names[:] = self.fix.get_active_vector(dumop.beads.copy().names, 0) self.set_coef(discretization) if dumop.options["mode"] == 'rate': self.omega2 = (self.temp * (2 * self.dbeads.nbeads) * units.Constants.kb / units.Constants.hbar) ** 2 elif dumop.options["mode"] == 'splitting': self.omega2 = (self.temp * self.dbeads.nbeads * units.Constants.kb / units.Constants.hbar) ** 2 if dumop.options["opt"] == 'nichols' or dumop.options["opt"] == 'NR' or dumop.options["opt"] == 'lanczos': self.h = self.spring_hessian(natoms=self.dbeads.natoms, nbeads=self.dbeads.nbeads, m3=self.dbeads.m3[0], omega2=self.omega2, coef=self.coef)
def init_stage1(self, simul): """Initializes the simulation -- first stage. Takes a simulation object, and uses all the data in the initialization queue to fill up the beads and cell data needed to run the simulation. Args: simul: A simulation object to be initialized. Raises: ValueError: Raised if there is a problem with the initialization, if something that should have been has not been, or if the objects that have been specified are not compatible with each other. """ if simul.beads.nbeads == 0: fpos = fmom = fmass = flab = fcell = False # we don't have an explicitly defined beads object yet else: fpos = fmom = fmass = flab = fcell = True for (k, v) in self.queue: info(" # Initializer (stage 1) parsing " + str(k) + " object.", verbosity.high) if k == "cell": if fcell: warning("Overwriting previous cell parameters", verbosity.medium) if v.mode == "pdb": rh = init_pdb(v.value)[1].h elif v.mode == "chk": rh = init_chk(v.value)[1].h else: rh = v.value.reshape((3, 3)) rh *= unit_to_internal("length", v.units, 1.0) simul.cell.h = rh if simul.cell.V == 0.0: ValueError("Cell provided has zero volume") fcell = True elif k == "masses": if simul.beads.nbeads == 0: raise ValueError( "Cannot initialize the masses before the size of the system is known" ) if fmass: warning("Overwriting previous atomic masses", verbosity.medium) if v.mode == "manual": rm = v.value else: rm = init_beads(v, self.nbeads).m rm *= unit_to_internal("mass", v.units, 1.0) if v.bead < 0: # we are initializing the path if (fmom and fmass): warning( "Rescaling momenta to make up for changed mass", verbosity.medium) simul.beads.p /= simul.beads.sm3 # go to mass-scaled momenta, that are mass-invariant if v.index < 0: simul.beads.m = rm else: # we are initializing a specific atom simul.beads.m[v.index:v.index + 1] = rm if (fmom and fmass): # finishes correcting the momenta simul.beads.p *= simul.beads.sm3 # back to normal momenta else: raise ValueError("Cannot change the mass of a single bead") fmass = True elif k == "labels": if simul.beads.nbeads == 0: raise ValueError( "Cannot initialize the labels before the size of the system is known" ) if flab: warning("Overwriting previous atomic labels", verbosity.medium) if v.mode == "manual": rn = v.value else: rn = init_beads(v, self.nbeads).names if v.bead < 0: # we are initializing the path if v.index < 0: simul.beads.names = rn else: # we are initializing a specific atom simul.beads.names[v.index:v.index + 1] = rn else: raise ValueError( "Cannot change the label of a single bead") flab = True elif k == "positions": if fpos: warning("Overwriting previous atomic positions", verbosity.medium) # read the atomic positions as a vector rq = init_vector(v, self.nbeads) rq *= unit_to_internal("length", v.units, 1.0) (nbeads, natoms) = rq.shape natoms /= 3 # check if we must initialize the simulation beads if simul.beads.nbeads == 0: if v.index >= 0: raise ValueError( "Cannot initialize single atoms before the size of the system is known" ) simul.beads.resize(natoms, self.nbeads) set_vector(v, simul.beads.q, rq) fpos = True elif ( k == "velocities" or k == "momenta" ) and v.mode == "thermal": # intercept here thermal initialization, so we don't need to check further down if fmom: warning("Overwriting previous atomic momenta", verbosity.medium) if simul.beads.natoms == 0: raise ValueError( "Cannot initialize momenta before the size of the system is known." ) if not fmass: raise ValueError( "Trying to resample velocities before having masses.") rtemp = v.value * unit_to_internal("temperature", v.units, 1.0) if rtemp <= 0: warning( "Using the simulation temperature to resample velocities", verbosity.low) rtemp = simul.ensemble.temp else: info( " # Resampling velocities at temperature %s %s" % (v.value, v.units), verbosity.low) # pull together a mock initialization to get NM masses right #without too much code duplication if v.bead >= 0: raise ValueError("Cannot thermalize a single bead") if v.index >= 0: rnatoms = 1 else: rnatoms = simul.beads.natoms rbeads = Beads(rnatoms, simul.beads.nbeads) if v.index < 0: rbeads.m[:] = simul.beads.m else: rbeads.m[:] = simul.beads.m[v.index] rnm = NormalModes(mode=simul.nm.mode, transform_method=simul.nm.transform_method, freqs=simul.nm.nm_freqs) rens = Ensemble(dt=simul.ensemble.dt, temp=simul.ensemble.temp) rnm.bind(rbeads, rens) # then we exploit the sync magic to do a complicated initialization # in the NM representation # with (possibly) shifted-frequencies NM rnm.pnm = simul.prng.gvec( (rbeads.nbeads, 3 * rbeads.natoms)) * np.sqrt( rnm.dynm3) * np.sqrt( rbeads.nbeads * rtemp * Constants.kb) if v.index < 0: simul.beads.p = rbeads.p else: simul.beads.p[:, 3 * v.index:3 * (v.index + 1)] = rbeads.p fmom = True elif k == "momenta": if fmom: warning("Overwriting previous atomic momenta", verbosity.medium) # read the atomic momenta as a vector rp = init_vector(v, self.nbeads, momenta=True) rp *= unit_to_internal("momentum", v.units, 1.0) (nbeads, natoms) = rp.shape natoms /= 3 # checks if we must initialize the simulation beads if simul.beads.nbeads == 0: if v.index >= 0: raise ValueError( "Cannot initialize single atoms before the size of the system is known" ) simul.beads.resize(natoms, self.nbeads) rp *= np.sqrt(self.nbeads / nbeads) set_vector(v, simul.beads.p, rp) fmom = True elif k == "velocities": if fmom: warning("Overwriting previous atomic momenta", verbosity.medium) # read the atomic velocities as a vector rv = init_vector(v, self.nbeads) rv *= unit_to_internal("velocity", v.units, 1.0) (nbeads, natoms) = rv.shape natoms /= 3 # checks if we must initialize the simulation beads if simul.beads.nbeads == 0 or not fmass: ValueError( "Cannot initialize velocities before the masses of the atoms are known" ) simul.beads.resize(natoms, self.nbeads) warning( "Initializing from velocities uses the previously defined masses -- not the masses inferred from the file -- to build momenta", verbosity.low) if v.index >= 0: rv *= simul.beads.m[v.index] elif v.bead >= 0: rv *= simul.beads.m3[0] else: rv *= simul.beads.m3 rv *= np.sqrt(self.nbeads / nbeads) set_vector(v, simul.beads.p, rv) fmom = True elif k == "thermostat": pass # thermostats must be initialized in a second stage if simul.beads.natoms == 0: raise ValueError( "Initializer could not initialize the atomic positions") if simul.cell.V == 0: raise ValueError("Initializer could not initialize the cell") for i in range(simul.beads.natoms): if simul.beads.m[i] <= 0: raise ValueError("Initializer could not initialize the masses") if simul.beads.names[i] == "": raise ValueError( "Initializer could not initialize the atom labels") if not fmom: warning( "Momenta not specified in initialize. Will start with zero velocity if they are not specified in beads.", verbosity.low)
def init_stage1(self, simul): """Initializes the simulation -- first stage. Takes a simulation object, and uses all the data in the initialization queue to fill up the beads and cell data needed to run the simulation. Args: simul: A simulation object to be initialized. Raises: ValueError: Raised if there is a problem with the initialization, if something that should have been has not been, or if the objects that have been specified are not compatible with each other. """ if simul.beads.nbeads == 0: fpos = fmom = fmass = flab = fcell = False # we don't have an explicitly defined beads object yet else: fpos = fmom = fmass = flab = fcell = True for (k, v) in self.queue: info(" # Initializer (stage 1) parsing " + str(k) + " object.", verbosity.high) if k == "cell": if v.mode == "manual": rh = v.value.reshape((3, 3)) * unit_to_internal("length", v.units, 1.0) elif v.mode == "chk": rh = init_chk(v.value)[1].h elif init_file(v.mode, v.value)[1].h.trace() == -3: # In case the file do not contain any # + cell parameters, the diagonal elements of the cell will be # +set to -1 from the io_units and nothing is read here. continue else: rh = init_file(v.mode, v.value, cell_units=v.units)[1].h if fcell: warning("Overwriting previous cell parameters", verbosity.low) simul.cell.h = rh if simul.cell.V == 0.0: ValueError("Cell provided has zero volume") fcell = True elif k == "masses": if simul.beads.nbeads == 0: raise ValueError("Cannot initialize the masses before the size of the system is known") if fmass: warning("Overwriting previous atomic masses", verbosity.medium) if v.mode == "manual": rm = v.value * unit_to_internal("mass", v.units, 1.0) else: rm = init_beads(v, self.nbeads).m if v.bead < 0: # we are initializing the path if (fmom and fmass): warning("Rescaling momenta to make up for changed mass", verbosity.medium) simul.beads.p /= simul.beads.sm3 # go to mass-scaled momenta, that are mass-invariant if v.index < 0: simul.beads.m = rm else: # we are initializing a specific atom simul.beads.m[v.index:v.index + 1] = rm if (fmom and fmass): # finishes correcting the momenta simul.beads.p *= simul.beads.sm3 # back to normal momenta else: raise ValueError("Cannot change the mass of a single bead") fmass = True elif k == "labels": if simul.beads.nbeads == 0: raise ValueError("Cannot initialize the labels before the size of the system is known") if flab: warning("Overwriting previous atomic labels", verbosity.medium) if v.mode == "manual": rn = v.value else: rn = init_beads(v, self.nbeads).names if v.bead < 0: # we are initializing the path if v.index < 0: simul.beads.names = rn else: # we are initializing a specific atom simul.beads.names[v.index:v.index + 1] = rn else: raise ValueError("Cannot change the label of a single bead") flab = True elif k == "positions": if fpos: warning("Overwriting previous atomic positions", verbosity.medium) # read the atomic positions as a vector rq = init_vector(v, self.nbeads, dimension="length", units=v.units) nbeads, natoms = rq.shape natoms /= 3 # check if we must initialize the simulation beads if simul.beads.nbeads == 0: if v.index >= 0: raise ValueError("Cannot initialize single atoms before the size of the system is known") simul.beads.resize(natoms, self.nbeads) set_vector(v, simul.beads.q, rq) fpos = True elif (k == "velocities" or k == "momenta") and v.mode == "thermal": # intercept here thermal initialization, so we don't need to check further down if fmom: warning("Overwriting previous atomic momenta", verbosity.medium) if simul.beads.natoms == 0: raise ValueError("Cannot initialize momenta before the size of the system is known.") if not fmass: raise ValueError("Trying to resample velocities before having masses.") rtemp = v.value * unit_to_internal("temperature", v.units, 1.0) if rtemp <= 0: warning("Using the simulation temperature to resample velocities", verbosity.low) rtemp = simul.ensemble.temp else: info(" # Resampling velocities at temperature %s %s" % (v.value, v.units), verbosity.low) # pull together a mock initialization to get NM masses right # without too much code duplication if v.bead >= 0: raise ValueError("Cannot thermalize a single bead") if v.index >= 0: rnatoms = 1 else: rnatoms = simul.beads.natoms rbeads = Beads(rnatoms, simul.beads.nbeads) if v.index < 0: rbeads.m[:] = simul.beads.m else: rbeads.m[:] = simul.beads.m[v.index] rnm = NormalModes(mode=simul.nm.mode, transform_method=simul.nm.transform_method, freqs=simul.nm.nm_freqs) rens = Ensemble(temp=simul.ensemble.temp) rmv = Motion() rnm.bind(rens, rmv, rbeads) # then we exploit the sync magic to do a complicated initialization # in the NM representation # with (possibly) shifted-frequencies NM rnm.pnm = simul.prng.gvec((rbeads.nbeads, 3 * rbeads.natoms)) * np.sqrt(rnm.dynm3) * np.sqrt(rbeads.nbeads * rtemp * Constants.kb) if v.index < 0: simul.beads.p = rbeads.p else: simul.beads.p[:, 3 * v.index:3 * (v.index + 1)] = rbeads.p fmom = True elif k == "momenta": if fmom: warning("Overwriting previous atomic momenta", verbosity.medium) # read the atomic momenta as a vector rp = init_vector(v, self.nbeads, momenta=True, dimension="momentum", units=v.units) nbeads, natoms = rp.shape natoms /= 3 # checks if we must initialize the simulation beads if simul.beads.nbeads == 0: if v.index >= 0: raise ValueError("Cannot initialize single atoms before the size of the system is known") simul.beads.resize(natoms, self.nbeads) rp *= np.sqrt(self.nbeads / nbeads) set_vector(v, simul.beads.p, rp) fmom = True elif k == "velocities": if fmom: warning("Overwriting previous atomic momenta", verbosity.medium) # read the atomic velocities as a vector rv = init_vector(v, self.nbeads, dimension="velocity", units=v.units) nbeads, natoms = rv.shape natoms /= 3 # checks if we must initialize the simulation beads if simul.beads.nbeads == 0 or not fmass: ValueError("Cannot initialize velocities before the masses of the atoms are known") simul.beads.resize(natoms, self.nbeads) warning("Initializing from velocities uses the previously defined masses -- not the masses inferred from the file -- to build momenta", verbosity.low) if v.index >= 0: rv *= simul.beads.m[v.index] else: for ev in rv: ev *= simul.beads.m3[0] rv *= np.sqrt(self.nbeads / nbeads) set_vector(v, simul.beads.p, rv) fmom = True elif k == "gle": pass # thermostats must be initialised in a second stage if simul.beads.natoms == 0: raise ValueError("Initializer could not initialize the atomic positions") if simul.cell.V == 0: raise ValueError("Initializer could not initialize the cell") for i in range(simul.beads.natoms): if simul.beads.m[i] <= 0: raise ValueError("Initializer could not initialize the masses") if simul.beads.names[i] == "": raise ValueError("Initializer could not initialize the atom labels") if not fmom: warning("Momenta not specified in initialize. Will start with zero velocity if they are not specified in beads.", verbosity.low)
def bind(self, beads, cell, fcomponents, fflist): """Binds beads, cell and forces to the forcefield. Args: beads: Beads object from which the bead positions are taken. cell: Cell object from which the system box is taken. fcomponents: A list of different objects for each force type. For example, if ring polymer contraction is being used, then there may be separate forces for the long and short range part of the potential. fflist: A list of forcefield objects to use to calculate the potential, forces and virial for each force type. To clarify: fcomponents are the names and parameters of forcefields that are active for a certain system. fflist contains the overall list of force providers, and one typically has just one per force kind. """ self.natoms = beads.natoms self.nbeads = beads.nbeads self.beads = beads self.cell = cell self.bound = True self.nforces = len(fcomponents) self.fcomp = fcomponents self.ff = fflist # fflist should be a dictionary of forcefield objects self.mforces = [] self.mbeads = [] self.mrpc = [] dself = dd(self) # a "function factory" to generate functions to automatically update # contracted paths def make_rpc(rpc, beads): return lambda: rpc.b1tob2(dstrip(beads.q)) # creates new force objects, possibly acting on contracted path # representations for fc in self.fcomp: # creates an automatically-updated contracted beads object newb = fc.nbeads # if the number of beads for this force component is unspecified, # assume full force evaluation if newb == 0 or newb > beads.nbeads: newb = beads.nbeads newforce = ForceComponent(ffield=fc.ffield, name=fc.name, nbeads=newb, weight=fc.weight, mts_weights=fc.mts_weights, epsilon=fc.epsilon) newbeads = Beads(beads.natoms, newb) newrpc = nm_rescale(beads.nbeads, newb) # the beads positions for this force components are obtained # automatically, when needed, as a contraction of the full beads dd(newbeads).q._func = make_rpc(newrpc, beads) for b in newbeads: # must update also indirect access to the beads coordinates dd(b).q._func = dd(newbeads).q._func # makes newbeads.q depend from beads.q dd(beads).q.add_dependant(dd(newbeads).q) # now we create a new forcecomponent which is bound to newbeads! newforce.bind(newbeads, cell, fflist) # adds information we will later need to the appropriate lists. self.mbeads.append(newbeads) self.mforces.append(newforce) self.mrpc.append(newrpc) # now must expose an interface that gives overall forces dself.f = depend_array(name="f", value=np.zeros((self.nbeads, 3 * self.natoms)), func=self.f_combine, dependencies=[dd(ff).f for ff in self.mforces]) # collection of pots and virs from individual ff objects dself.pots = depend_array(name="pots", value=np.zeros(self.nbeads, float), func=self.pot_combine, dependencies=[dd(ff).pots for ff in self.mforces]) # must take care of the virials! dself.virs = depend_array(name="virs", value=np.zeros((self.nbeads, 3, 3), float), func=self.vir_combine, dependencies=[dd(ff).virs for ff in self.mforces]) dself.extras = depend_value(name="extras", value=np.zeros(self.nbeads, float), func=self.extra_combine, dependencies=[dd(ff).extras for ff in self.mforces]) # total potential and total virial dself.pot = depend_value(name="pot", func=(lambda: self.pots.sum()), dependencies=[dself.pots]) dself.vir = depend_array(name="vir", func=self.get_vir, value=np.zeros((3, 3)), dependencies=[dself.virs]) # SC forces and potential dself.alpha = depend_value(name="alpha", value=0.0) # The number of MTS levels dself.nmtslevels = depend_value(name="nmtslevels", value=0, func=self.get_nmtslevels) # This will be piped from normalmodes dself.omegan2 = depend_value(name="omegan2", value=0) # The Suzuki-Chin difference potential dself.potssc = depend_array(name="potssc", value=np.zeros(self.nbeads, float), dependencies=[dd(self.beads).m, dself.f, dself.pots, dself.alpha, dself.omegan2], func=self.get_potssc) dself.potsc = depend_value(name="potsc", dependencies=[dself.potssc], func=(lambda: self.potssc.sum())) # The coefficients of the physical and the |f|^2 terms dself.coeffsc_part_1 = depend_array(name="coeffsc_part_1", value=np.zeros((self.nbeads, 1), float), func=self.get_coeffsc_part_1) dself.coeffsc_part_2 = depend_array(name="coeffsc_part_2", value=np.zeros((self.nbeads, 1), float), dependencies=[dself.alpha, dself.omegan2], func=self.get_coeffsc_part_2) # A list that contains the high order component of the force and the virial dself.fvir_4th_order = depend_value(name="fvir_4th_order", value=[None, None], dependencies=[dd(self.beads).m, dself.f, dself.pots], func=self.fvir_4th_order_combine) # The high order component of the Suzuki-Chin force. dself.f_4th_order = depend_array(name="f_4th_order", value=np.zeros((self.nbeads, 3 * self.natoms), float), dependencies=[dself.fvir_4th_order], func=(lambda: self.fvir_4th_order[0])) dself.fsc_part_1 = depend_array(name="fsc_part_1", value=np.zeros((self.nbeads, 3 * self.natoms), float), dependencies=[dself.coeffsc_part_1, dself.f], func=self.get_fsc_part_1) dself.fsc_part_2 = depend_array(name="fsc_part_2", value=np.zeros((self.nbeads, 3 * self.natoms), float), dependencies=[dself.coeffsc_part_2, dself.f_4th_order], func=self.get_fsc_part_2) dself. fsc = depend_array(name="fsc", value=np.zeros((self.nbeads, 3 * self.natoms), float), dependencies=[dself.fsc_part_1, dself.fsc_part_2], func=self.get_fsc) # The high order component of the Suzuki-Chin virial. dself.virs_4th_order = depend_array(name="vir_4th_order", value=np.zeros((self.nbeads, 3, 3), float), dependencies=[dself.fvir_4th_order], func=(lambda: self.fvir_4th_order[1])) dself.virssc_part_1 = depend_array(name="virssc_part_1", value=np.zeros((self.nbeads, 3, 3), float), dependencies=[dself.coeffsc_part_1, dself.virs], func=self.get_virssc_part_1) dself.virssc_part_2 = depend_array(name="virssc_part_2", value=np.zeros((self.nbeads, 3, 3), float), dependencies=[dself.coeffsc_part_2, dself.virs_4th_order], func=self.get_virssc_part_2) dself.virssc = depend_array(name="virssc", value=np.zeros((self.nbeads, 3, 3), float), dependencies=[dself.virssc_part_1, dself.virssc_part_2], func=self.get_virssc) dself.virsc = depend_value(name="potsc", dependencies=[dself.potssc], func=(lambda: np.sum(self.virssc, axis=0))) # Add dependencies from the force weights, that are applied here when the total # force is assembled from its components for fc in self.mforces: dself.f.add_dependency(dd(fc).weight) dself.pots.add_dependency(dd(fc).weight) dself.virs.add_dependency(dd(fc).weight)
def main(prefix, temp): temp = unit_to_internal("energy", "kelvin", float(temp)) ipos = [] for filename in sorted(glob.glob(prefix + ".pos*")): ipos.append(open(filename, "r")) ifor = [] for filename in sorted(glob.glob(prefix + ".for*")): ifor.append(open(filename, "r")) ivacfim = open(prefix + ".imvacf", "w") nbeads = len(ipos) if (nbeads != len(ifor)): raise ValueError( "Mismatch between number of output files for forces and positions") natoms = 0 ifr = 0 while True: try: for i in range(nbeads): ret = read_file("xyz", ipos[i]) pos = ret["atoms"] ret = read_file("xyz", ifor[i]) force = ret["atoms"] if natoms == 0: natoms = pos.natoms beads = Beads(natoms, nbeads) forces = Beads(natoms, nbeads) beads[i].q = pos.q beads[i].m = pos.m forces[i].q = force.q except EOFError: # finished reading files break if (ifr == 0): cim = np.zeros((natoms, nbeads + 1), float) q = dstrip(beads.q) f = dstrip(forces.q) m = dstrip(beads.m) qc = dstrip(beads.qc) for j in range(nbeads + 1): for i in range(natoms): dummy = [(q[(j + k) % nbeads, 3 * i:3 * (i + 1)] - qc[3 * i:3 * (i + 1)]) * (-f[k, 3 * i:3 * (i + 1)]) for k in range(nbeads)] cim[i, j] = cim[i, j] + np.sum(dummy) / (nbeads * m[i]) cim[i, j] += 3. * Constants.kb * temp / m[i] ifr += 1 print 'Frame: ', ifr cim[:, :] = cim[:, :] / ifr fullcim = np.zeros(len(cim)) for j in range(nbeads + 1): fullcim[j] = np.sum([i for i in cim[:, j]]) ivacfim.write( "# Imaginary time autocorrelation, averaged through the whole simulation -- beta*hbar is %f \n" % (Constants.hbar / (Constants.kb * temp))) for islice in range(nbeads + 1): ivacfim.write("%f %12.5e \n" % (float(islice) / float(nbeads), fullcim[islice]))
def main(prefix, temp): T = float(temp) fns_pos = sorted(glob.glob(prefix + ".pos*")) fns_for = sorted(glob.glob(prefix + ".for*")) fn_out_kin = prefix + ".kin.xyz" fn_out_kod = prefix + ".kod.xyz" # check that we found the same number of positions and forces files nbeads = len(fns_pos) if nbeads != len(fns_for): print fns_pos print fns_for raise ValueError( "Mismatch between number of input files for forces and positions.") # print some information print 'temperature = {:f} K'.format(T) print print 'number of beads = {:d}'.format(nbeads) print print 'positions and forces file names:' for fn_pos, fn_for in zip(fns_pos, fns_for): print '{:s} {:s}'.format(fn_pos, fn_for) print print 'output file names:' print fn_out_kin print fn_out_kod print temp = unit_to_internal("energy", "kelvin", T) # open input and output files ipos = [open(fn, "r") for fn in fns_pos] ifor = [open(fn, "r") for fn in fns_for] ikin = open(fn_out_kin, "w") ikod = open(fn_out_kod, "w") natoms = 0 ifr = 0 while True: # print progress if ifr % 100 == 0: print '\rProcessing frame {:d}'.format(ifr), sys.stdout.flush() # load one frame try: for i in range(nbeads): ret = read_file("xyz", ipos[i]) pos = ret["atoms"] ret = read_file("xyz", ifor[i]) force = ret["atoms"] if natoms == 0: natoms = pos.natoms beads = Beads(natoms, nbeads) forces = Beads(natoms, nbeads) kcv = np.zeros((natoms, 6), float) beads[i].q = pos.q forces[i].q = force.q except EOFError: # finished reading files break # calculate kinetic energies q = dstrip(beads.q) f = dstrip(forces.q) qc = dstrip(beads.qc) kcv[:] = 0 for j in range(nbeads): for i in range(natoms): kcv[i, 0] += (q[j, i * 3 + 0] - qc[i * 3 + 0]) * f[j, i * 3 + 0] kcv[i, 1] += (q[j, i * 3 + 1] - qc[i * 3 + 1]) * f[j, i * 3 + 1] kcv[i, 2] += (q[j, i * 3 + 2] - qc[i * 3 + 2]) * f[j, i * 3 + 2] kcv[i, 3] += ( q[j, i * 3 + 0] - qc[i * 3 + 0]) * f[j, i * 3 + 1] + ( q[j, i * 3 + 1] - qc[i * 3 + 1]) * f[j, i * 3 + 0] kcv[i, 4] += ( q[j, i * 3 + 0] - qc[i * 3 + 0]) * f[j, i * 3 + 2] + ( q[j, i * 3 + 2] - qc[i * 3 + 2]) * f[j, i * 3 + 0] kcv[i, 5] += ( q[j, i * 3 + 1] - qc[i * 3 + 1]) * f[j, i * 3 + 2] + ( q[j, i * 3 + 2] - qc[i * 3 + 2]) * f[j, i * 3 + 1] kcv *= -0.5 / nbeads kcv[:, 0:3] += 0.5 * Constants.kb * temp kcv[:, 3:6] *= 0.5 # write output ikin.write( "%d\n# Centroid-virial kinetic energy estimator [a.u.] - diagonal terms: xx yy zz\n" % natoms) ikod.write( "%d\n# Centroid-virial kinetic energy estimator [a.u.] - off-diag terms: xy xz yz\n" % natoms) for i in range(natoms): ikin.write("%8s %12.5e %12.5e %12.5e\n" % (pos.names[i], kcv[i, 0], kcv[i, 1], kcv[i, 2])) ikod.write("%8s %12.5e %12.5e %12.5e\n" % (pos.names[i], kcv[i, 3], kcv[i, 4], kcv[i, 5])) ifr += 1 print '\rProcessed {:d} frames.'.format(ifr) ikin.close() ikod.close()
def bind(self, beads, cell, fcomponents, fflist): """Binds beads, cell and forces to the forcefield. Args: beads: Beads object from which the bead positions are taken. cell: Cell object from which the system box is taken. fcomponents: A list of different objects for each force type. For example, if ring polymer contraction is being used, then there may be separate forces for the long and short range part of the potential. fflist: A list of forcefield objects to use to calculate the potential, forces and virial for each force type. To clarify: fcomponents are the names and parameters of forcefields that are active for a certain system. fflist contains the overall list of force providers, and one typically has just one per force kind. """ self.natoms = beads.natoms self.nbeads = beads.nbeads self.beads = beads self.cell = cell self.bound = True self.nforces = len(fcomponents) self.fcomp = fcomponents self.ff = fflist # fflist should be a dictionary of forcefield objects self.mforces = [] self.mbeads = [] self.mrpc = [] # a "function factory" to generate functions to automatically update #contracted paths def make_rpc(rpc, beads): return lambda: rpc.b1tob2(depstrip(beads.q)) # creates new force objects, possibly acting on contracted path #representations for fc in self.fcomp: # creates an automatically-updated contracted beads object newb = fc.nbeads # if the number of beads for this force component is unspecified, # assume full force evaluation if newb == 0: newb = beads.nbeads newforce = ForceComponent(ffield=fc.ffield, name=fc.name, nbeads=newb, weight=fc.weight, mts_weights=fc.mts_weights) newbeads = Beads(beads.natoms, newb) newrpc = nm_rescale(beads.nbeads, newb) # the beads positions for this force components are obtained # automatically, when needed, as a contraction of the full beads dget(newbeads,"q")._func = make_rpc(newrpc, beads) for b in newbeads: # must update also indirect access to the beads coordinates dget(b,"q")._func = dget(newbeads,"q")._func # makes newbeads.q depend from beads.q dget(beads,"q").add_dependant(dget(newbeads,"q")) #now we create a new forcecomponent which is bound to newbeads! newforce.bind(newbeads, cell, fflist) #adds information we will later need to the appropriate lists. self.mbeads.append(newbeads) self.mforces.append(newforce) self.mrpc.append(newrpc) #now must expose an interface that gives overall forces dset(self,"f", depend_array(name="f",value=np.zeros((self.nbeads,3*self.natoms)), func=self.f_combine, dependencies=[dget(ff, "f") for ff in self.mforces] ) ) # collection of pots and virs from individual ff objects dset(self,"pots", depend_array(name="pots", value=np.zeros(self.nbeads,float), func=self.pot_combine, dependencies=[dget(ff, "pots") for ff in self.mforces]) ) # must take care of the virials! dset(self,"virs", depend_array(name="virs", value=np.zeros((self.nbeads,3,3),float), func=self.vir_combine, dependencies=[dget(ff, "virs") for ff in self.mforces]) ) dset(self,"extras", depend_value(name="extras", value=np.zeros(self.nbeads,float), func=self.extra_combine, dependencies=[dget(ff, "extras") for ff in self.mforces])) # total potential and total virial dset(self,"pot", depend_value(name="pot", func=(lambda: self.pots.sum()), dependencies=[dget(self,"pots")])) dset(self,"vir", depend_array(name="vir", func=self.get_vir, value=np.zeros((3,3)), dependencies=[dget(self,"virs")])) # SC forces and potential dset(self, "alpha", depend_value(name="alpha", value=0.5)) # this will be piped from normalmodes dset(self, "omegan2", depend_value(name="alpha", value=0)) dset(self, "SCCALC", depend_value(name="SCCALC", func=self.sccalc, value = [None,None], dependencies=[dget(self, "f"), dget(self,"pots"), dget(self,"alpha"), dget(self,"omegan2")] ) ) dset(self, "fsc", depend_array(name="fsc",value=np.zeros((self.nbeads,3*self.natoms)), dependencies=[dget(self,"SCCALC")], func=(lambda: self.SCCALC[1] ) ) ) dset(self, "potsc", depend_value(name="potsc", dependencies=[dget(self,"SCCALC") ], func=(lambda: self.SCCALC[0] ) ) )
def bind(self, beads, cell, flist): self.natoms = beads.natoms self.nbeads = beads.nbeads self.nforces = len(flist) # flist should be a list of tuples containing ( "name", forcebeads) self.mforces = [] self.mbeads = [] self.mweights = [] self.mrpc = [] # a "function factory" to generate functions to automatically update #contracted paths def make_rpc(rpc, beads): return lambda: rpc.b1tob2(depstrip(beads.q)) # creates new force objects, possibly acting on contracted path #representations for (ftype, fbeads) in flist: # creates an automatically-updated contracted beads object newb = fbeads.nbeads newforce = fbeads.copy() newweight = fbeads.weight # if the number of beads for this force component is unspecified, #assume full force evaluation if newb == 0: newb = beads.nbeads newforce.nbeads = newb newbeads = Beads(beads.natoms, newb) newrpc = nm_rescale(beads.nbeads, newb) dget(newbeads,"q")._func = make_rpc(newrpc, beads) for b in newbeads: # must update also indirect access to the beads coordinates dget(b,"q")._func = dget(newbeads,"q")._func # makes newbeads.q depend from beads.q dget(beads,"q").add_dependant(dget(newbeads,"q")) #now we create a new forcebeads which is bound to newbeads! newforce.bind(newbeads, cell) #adds information we will later need to the appropriate lists. self.mweights.append(newweight) self.mbeads.append(newbeads) self.mforces.append(newforce) self.mrpc.append(newrpc) #now must expose an interface that gives overall forces dset(self,"f", depend_array(name="f",value=np.zeros((self.nbeads,3*self.natoms)), func=self.f_combine, dependencies=[dget(ff, "f") for ff in self.mforces] ) ) # collection of pots and virs from individual ff objects dset(self,"pots", depend_array(name="pots", value=np.zeros(self.nbeads,float), func=self.pot_combine, dependencies=[dget(ff, "pots") for ff in self.mforces]) ) # must take care of the virials! dset(self,"virs", depend_array(name="virs", value=np.zeros((self.nbeads,3,3),float), func=self.vir_combine, dependencies=[dget(ff, "virs") for ff in self.mforces]) ) dset(self,"extras", depend_value(name="extras", value=np.zeros(self.nbeads,float), func=self.extra_combine, dependencies=[dget(ff, "extras") for ff in self.mforces])) # total potential and total virial dset(self,"pot", depend_value(name="pot", func=(lambda: self.pots.sum()), dependencies=[dget(self,"pots")])) dset(self,"vir", depend_array(name="vir", func=self.get_vir, value=np.zeros((3,3)), dependencies=[dget(self,"virs")]))