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)