def readCoordVel(self, dynamics_in): # read initial conditions (coordinates and velocities) and assign atom symbols and masses atomlist_coords, atomlist_vels = XYZ.read_initial_conditions(dynamics_in, units="bohr") self.nat = len(atomlist_coords) self.coordinates = np.zeros((self.nat, 3)) self.velocities = np.zeros((self.nat, 3)) self.masses = np.zeros(self.nat) self.symbols = [] for i,(Zi,posi) in enumerate(atomlist_coords): atname = AtomicData.atom_names[Zi-1] self.symbols.append(atname) self.masses[i] = AtomicData.atom_masses[atname] self.coordinates[i,:] = posi self.velocities[i,:] = atomlist_vels[i][1] self.totalmass=float(sum(self.masses))
parser = OptionParser(usage) parser.add_option( "--convert", dest="convert", help= "Type of conversion: 'b2a' - from bohr to Angstrom, 'a2b' - from Angstrom to bohr [default: %default]", default="b2a") (opts, args) = parser.parse_args() if len(args) < 2: print usage exit(-1) xyz_in = args[0] xyz_out = args[1] if xyz_in[-2:] == "in": # initial conditions file ###.in coords, vels = XYZ.read_initial_conditions(xyz_in, units="") structures = [coords] else: structures = XYZ.read_xyz(xyz_in, units="") unit_fac, units = unit_conversion[opts.convert] for i, atomlist_in in enumerate(structures): vec_in = XYZ.atomlist2vector(atomlist_in) vec_out = unit_fac * vec_in atomlist_out = XYZ.vector2atomlist(vec_out, atomlist_in) if i == 0: mode = "w" else: mode = "a" XYZ.write_xyz(xyz_out, [atomlist_out], units="", mode=mode)
def __init__(self, charge=0, initial_state='0', nstates=0, nstep=1000, nuclear_step=0.1, dyn_mode="E", temp=300.0, timecoupling=1.0, scalar_coupling_threshold=0.01, switch_to_groundstate=1, artificial_energy_conservation=0, time_series=None, output_step=1, fragment_excitation=None): """ Parameters ========== Molecular Dynamics.charge: total charge of the molecule, the cation or anion has to be a closed shell species for TD-DFTB to work properly. Molecular Dynamics.nstates: number of excited states. Only the lowest states are calculated with TD-DFTB. For dynamics in the ground state `nstates` should be set to 0 to avoid the expensive calculation of excitation energies and non-adiabatic couplings. Molecular Dynamics.initial_state: initial electronic state of the trajectory, 0 for ground state. 'brightest' selects the state with the largest oscillator strength as the initial state. 'fragment' creates a superposition of adiabatic states corresponding to a localized excitation on a single fragment or between fragments (see option 'fragment_excitation'). Molecular Dynamics.nstep: number of nuclear time steps. Molecular Dynamics.nuclear_step: length of nuclear time step for integration of Newton's equations (in fs). Molecular Dynamics.dyn_mode: 'T' for constant temperature, 'E' for constant energy. To equilibrate a trajectory on the ground state use 'T', non-adiabatic dynamics on excited states should be run at constant energy. Molecular Dynamics.temp: temperature in Kelvin, only needed if the dynamics is run at constant temperature. The temperature is controlled using a Berendsen thermostat. Molecular Dynamics.timecoupling: Time constant for Berendsen thermostat in fs. The strength of the coupling to the external heat bath is proportional to 1/timecoupling. Molecular Dynamics.scalar_coupling_threshold: Excitation coefficients that are smaller than this threshold are neglected when calculating scalar couplings from the overlap between electronic states at successive time steps. For large molecules this value should be reduced. Molecular Dynamics.switch_to_groundstate: If set to 1, a hop to the ground state is forced if the S0-S1 energy gap drops below 0.1 eV. In TD-DFT(B) conical intersections to the ground state are not described correctly. If a point of point of degeneracy between S0 and S1 is reached, the TD-DFT(B) calculation usually breaks down. If something goes wrong in the excited state calculation, the trajectory continues with the ground state gradients until the excited state calculation starts working again. Molecular Dynamics.artificial_energy_conservation: Energy conservation can be enforced artificially by rescaling the velocities after each time step. This avoids the drift of the total energy observed for long dynamics simulations. This option only takes effect if dyn_mode=="E". Molecular Dynamics.time_series: To better analyze trajectories it is helpful to write out time series of additional quantities along the trajectory. You can specify a list of the desired quantities (so far only --time_series="['particle-hole charges']" is available). Molecular Dynamics.output_step: Output is written to disk only for every N'th time step. Molecular Dynamics.fragment_excitation: The initial state does not have to be an adiabatic state. If initial_state='fragment', this option allows to specify a local excitation on a fragment or a charge-transfer excitation from one fragment to the other as the initial state. To this end the disconnected fragments are identified and the molecular orbitals are localized onto the fragments by the Pipek-Mezey method. The excitation is specified by a tuple of four integers '(ifrag,iorb, afrag,aorb)' with the following meaning, ifrag - index of fragment for occupied orbital (1-based), iorb - occupied orbital counted from the H**O downward (so iorb=0 corresponds to H**O, iorb=1 to H**O-1 etc.), afrag - index of fragment for virtual orbital (1-based), aorb - virtual orbital counted from the LUMO upward (so aorb=0 corresponds to LUMO, aorb=1 to LUMO+1 etc.). For instance, if there are two fragments, the tuple '(1,0,1,0)' constitutes a local H**O(1)->LUMO(1) excitation, while '(1,0,2,0)' constitutes a charge-transfer H**O(1)->LUMO(2) excitation. """ # units checked 06/08/2014 self.fs_to_au = 1.0 / AtomicData.autime2fs # 41.34137333 self.au_to_fs = 1.0 / self.fs_to_au self.ang_to_au = 1.0 / AtomicData.bohr_to_angs #1.0/0.52917721092 self.au_to_ang = AtomicData.bohr_to_angs #0.52917721092 self.kB = AtomicData.kBoltzmann #3.166811382e-6 random.seed() self.charge = charge self.nstep = nstep # number of time steps for dynamics self.tstep = nuclear_step * self.fs_to_au # time step for dynamics self.mode = dyn_mode self.temperature = temp # write information on coefficients and hopping: # 0: only write state.dat, # 1: also |c_i|^2 in coeff_$i.dat, # 2: also hopping probabilities in prob.dat and rejected hops in rej_hop.dat, # 3: also real and imaginary parts of coeffs, 4: coherences instead of real and imaginary parts self.printcoeff = 2 # write nonadiabatic couplings and transition dipole moments if available self.printcoup = 1 self.nstates = nstates + 1 # internally nstates includes the ground state self.writeflag = "xyz" self.scalar_coupling_threshold = scalar_coupling_threshold self.switch_to_groundstate = switch_to_groundstate self.artificial_energy_conservation = artificial_energy_conservation if time_series == None: time_series = [] self.time_series = time_series assert output_step > 0 self.output_step = output_step self.time = 0.0 try: # the initial state is given as an integer index self.state = int(initial_state) except ValueError: assert initial_state in [ "brightest", "fragment" ], "Allowed values for initial_state are integers or 'brightest' or 'fragment'" self.state = initial_state try: ifrag, iorb, afrag, aorb = fragment_excitation self.fragment_excitation = ifrag, iorb, afrag, aorb except (ValueError, TypeError) as e: print "ERROR: expected tuple of integers (ifrag,iorb, afrag,aorb) for option 'fragment_excitation'" print " but got '%s'." % fragment_excitation raise e # read initial conditions (coordinates and velocities) and assign atom symbols and masses atomlist_coords, atomlist_vels = XYZ.read_initial_conditions( "dynamics.in", units="bohr") self.nat = len(atomlist_coords) self.coordinates = np.zeros((self.nat, 3)) self.velocities = np.zeros((self.nat, 3)) self.masses = np.zeros(self.nat) self.symbols = [] for i, (Zi, posi) in enumerate(atomlist_coords): atname = AtomicData.atom_names[Zi - 1] self.symbols.append(atname) self.masses[i] = AtomicData.atom_masses[atname] self.coordinates[i, :] = posi self.velocities[i, :] = atomlist_vels[i][1] self.totalmass = float(sum(self.masses)) if (self.state == 0) and (self.nstates == 1): # DFTBaby program needs to compute excited states at least once # to initialize all variable correctly that are needed for the gradient # calculations. In the first step a single excited state is calculate, in # later steps the excited state calculation is skipped if grounddyn==1. self.nstates += 1 self.grounddyn = 1 else: self.grounddyn = 0 if self.mode == "T" or self.mode == "M": self.currtemperature = 200.0 self.timecoupling = timecoupling * self.fs_to_au
plt.xlabel("Temperature / K") plt.ylabel("P(T) dT") plt.plot((bin_edges[1:] + bin_edges[:-1]) / 2.0, hist) plt.show() if __name__ == "__main__": if len(sys.argv) < 2: print "Usage: python %s <pattern for initial conditions, e.g. structure_>" % sys.argv[ 0] sys.exit(-1) infiles = glob.glob(sys.argv[1] + "*.in") ekins = [] for f in infiles: # compute kinetic energy for all initial conditions atomlist, vellist = XYZ.read_initial_conditions(f, units="bohr") masses = np.zeros(len(atomlist)) for i, (Zi, posi) in enumerate(atomlist): masses[i] = AtomicData.atom_masses[AtomicData.atom_names[Zi - 1]] vel = XYZ.atomlist2vector(vellist) ekin = sum(0.5 * masses * (pow(vel[0::3], 2) + pow(vel[1::3], 2) + pow(vel[2::3], 2))) ekins.append(ekin) # convert kinetic energy to temperature # ekin = nvib * kB * T ekins = np.array(ekins) nat = len(atomlist) if nat < 2: raise Exception( "Since vibrational and rotational degrees are removed, a single atom cannot have any meaningful temperature." )