Exemple #1
0
        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))
Exemple #2
0
    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."
        )