Пример #1
0
        def save_step():
            """function is called after each minimization"""
            scan_coord = self.IC.coordinate_value(xi, IJKL)

            print("current value of scan coordinate : %s" % scan_coord)

            if i == 0:
                mode = "w"
            else:
                mode = "a"
            # save relaxed geometry of step i
            XYZ.write_xyz(self.xyz_scan, [atomlist],
                          title="charge=%s energy=%s" %
                          (self.geom_kwds.get("charge", 0), self.enI),
                          mode=mode)

            # save table with energies along scan
            fh = open(self.dat_scan, mode)
            if i == 0:
                # write header
                print("# Relaxed scan along %s defined by atoms %s" %
                      (coord_type[typ], [I + 1 for I in IJKL]),
                      file=fh)
                print("# state of interest: %d" % self.state, file=fh)
                print("# ", file=fh)
                print("#  Scan coordinate     Energies ", file=fh)
                print("#    %s              Hartree " % units[typ], file=fh)

            print("  %8.5f     " % scan_coord, end=' ', file=fh)
            for en in self.energies:
                print("   %e " % en, end=' ', file=fh)
            print("", file=fh)
            fh.close()
Пример #2
0
def eclipsed_oligomers():
    # build eclipsed oligomers
    for n in [2, 3, 4, 5, 6, 7, 8]:
        distances = 2.5 / AtomicData.bohr_to_angs * np.ones(n)
        angles = np.zeros(n)
        Fn = build_polyfluoerene(distances, angles)
        XYZ.write_xyz("F%d_eclipsed.xyz" % n, [Fn])
Пример #3
0
def capped_uff_nanotube(cnt,NcapN=0, NcapS=0, optimize_uff=1, out_xyz="/tmp/cnt.xyz"):
    """
    build capped nanotube and optimize it with UFF
    """
    nC,nT = cnt.NrCapAtoms()
    print "Expected number of Thomson points nT = %s" % nT
    print "If the caps have holes or very close atoms, you should try increasing"
    print "or reducing the number of Thomson points (by changing the options NcapN or NcapS)"
    if NcapN == 0:
        NcapN = nT
    if NcapS == 0:
        NcapS = nT

    """
    Different number of Thomson points are tested to find
    a pair (NcapN,NcapS) 
    """
    dcap = []
    dnmin=0
    dnmax=1
    ntrial=5
    for dnN in range(dnmin, dnmax):
        for dnS in range(dnmin, dnmax):
            # try for 5 times
            for n in range(0, ntrial):
                dcap.append( (dnN,dnS) )
    dcap = sorted(dcap, key=lambda (a,b): abs(a)+abs(b))

    for (dnN,dnS) in dcap:
        print "north cap: %s points, south cap: %s points" % (NcapN+dnN,NcapS+dnS)
        atomlist_carbons = capped_nanotube(cnt,NcapN+dnN,NcapS+dnS)
        if optimize_uff == 1:
            print "CNT will be optimized further with the Universal Force Field of G09"
            tmp_dir="/tmp"
            com_file = join(tmp_dir, "cnt_uff_opt.com")
            chk_file = join(tmp_dir, "cnt_uff_opt.chk")
            fchk_file = chk_file.replace(".chk", ".fchk")
            Gaussian.write_input(com_file, atomlist_carbons, \
                route="# UFF Opt", \
                title="Optimize (%s,%s)-Nanotube with UFF" % (cnt.n1,cnt.n2), chk=chk_file,mem=1000)
            try:
                Gaussian.run(com_file)
                # format checkpoint file
                Gaussian.formchk(chk_file, fchk_file)
                Data = Checkpoint.parseCheckpointFile(fchk_file)
                pos = Data["_Current_cartesian_coordinates"]
                atomlist_uff = XYZ.vector2atomlist(pos, atomlist_carbons)
                atomlist_carbons = atomlist_uff
            except Gaussian.GaussianError:
                print "UFF-optimization failed!"
                continue
        if check_connectivity(atomlist_carbons) == True:
            # no holes, correct connectivity
            break
        XYZ.write_xyz("/tmp/trials.xyz", [atomlist_carbons], mode="a")
    else:
        print ""

    XYZ.write_xyz(expandvars(expanduser(out_xyz)), [atomlist_carbons])
    print "Geometry of capped CNT written to %s" % out_xyz
def flakes_to_xyz(grown_flakes, out_xyz, cc1=2.56, substitutions=[]):
    generations = grown_flakes.keys()
    generations.sort()

    lat, unitcell, meso, beta = zn_porphene_lattice(
        cc1=cc1, substitutions=substitutions)
    a1, a2, a3 = lat.getLatticeVectors("real")

    if out_xyz[-4:] == ".xyz":
        try:
            os.remove(opts.out_xyz)
        except OSError as e:
            print e
    for gen in generations:
        print "Generation %s (%s flakes)" % (gen, len(grown_flakes[gen]))
        print "========================="
        for fl in grown_flakes[gen]:
            print "weight = %s" % fl.weight
            print fl
            flake_atomlist = fl.build_xyz(a1, a2, a3, unitcell, meso, beta)
            # reorder atomlist so that all hydrogens are placed at the end of the file
            flake_atomlist = XYZ.hydrogens_to_end(flake_atomlist)
            XYZ.write_xyz(expandvars(expanduser(out_xyz)), [flake_atomlist],
                          title="weight=%d" % fl.weight,
                          mode="a")
Пример #5
0
def run_gaussian(atomlist, directory="."):
    """
    run Gaussian input script in `neb.gjf` and read energy and gradient
    from checkpoing file `grad.fchk`.

    Parameters
    ----------
    atomlist:  list of tuples with atomic numbers and cartesian positions (Zat,[x,y,z])
               for each atom
    directory: directory where the calculation should be performed

    Returns
    -------
    en    :  total energies of ground state (in Hartree)
    grad  :  gradient of total energy (in a.u.)
    """
    # create directory if it does not exist already
    os.system("mkdir -p %s" % directory)
    os.system("cp neb.gjf %s/neb.gjf" % directory)
    # update geometry
    XYZ.write_xyz("%s/geometry.xyz" % directory, [atomlist])
    # remove number of atoms and comment
    os.system("cd %s; tail -n +3 geometry.xyz > geom" % directory)
    # calculate electronic structure
    ret = os.system(r"cd %s; g09 < neb.gjf > neb.out" % directory)
    ret &= os.system(r"cd %s; formchk grad.chk >> neb.out" % directory)
    assert ret == 0, "Return status = %s, error in Gaussian calculation, see %s/neb.out!" % (
        ret, directory)
    # read checkpoint files
    data = Checkpoint.parseCheckpointFile("%s/grad.fchk" % directory)

    en = data["_Total_Energy"]
    grad = data["_Cartesian_Gradient"]

    return en, grad
Пример #6
0
def alternately_rotated_oligomers():
    # neighbouring fluorenes are rotated by +-10.5 degrees
    for n in [2, 3, 4, 5, 6, 7, 8]:
        distances = 2.5 / AtomicData.bohr_to_angs * np.ones(n)
        # alternate fluorenes with + or - 10.5 degrees
        angles = 21.0 / 2.0 * np.pi / 180.0 * pow(-1, np.arange(n))
        Fn = build_polyfluoerene(distances, angles)
        XYZ.write_xyz("F%d_rotated.xyz" % n, [Fn])
Пример #7
0
def scan_angle_F2():
    n = 2
    distances = 2.5 / AtomicData.bohr_to_angs * np.ones(n)
    scan_geometries = []
    for a in np.linspace(0.0, np.pi, 80.0):
        print(a * 180.0 / np.pi)
        angles = [a / 2.0, -a / 2.0]
        F2 = build_polyfluoerene(distances, angles)
        scan_geometries.append(F2)
    XYZ.write_xyz("F2_angle_scan.xyz", scan_geometries)
Пример #8
0
 def plot(self, images=[], energies=[], istep=0):
     geometries = [XYZ.vector2atomlist(im, self.atomlist) for im in images]
     xyz_out = "neb_%s_%d.xyz" % (self.name, istep)
     XYZ.write_xyz(xyz_out, geometries)
     print("wrote path for iteration %d to %s" % (istep, xyz_out))
     if energies != []:
         # first column: index of image
         # second column: energy of image
         data = np.vstack((np.arange(0, len(images)), energies)).transpose()
         np.savetxt("path_energies_%s_%d.dat" % (self.name, istep), data)
Пример #9
0
    def addCap(self):
        #
        x_cap = initial_distribution_cap(
            self.Ncap)  # positions of Thomson points on the cap
        # for points in the cap x[i,:] = (theta_i, phi_i)
        # and for points in the tube x[i,:] = (z_i, phi_i)
        s_cap = ["C" for i in range(0, self.Ncap)]  # segment of carbo-nanotube
        # to which the Thomson point belongs, 'C' for cap and 'T' for tube
        o_cap = np.ones(self.Ncap, dtype=int)
        # o[i] == 1, position of i-th Thomson point is optimized
        # o[i] == 0, position is held constant
        #
        x_tube, o_tube, s_tube = thomson_tube(self.cnt.chiral_vector,
                                              self.cnt.tube_vector,
                                              self.cnt.a1, self.cnt.a2)

        # These unit vectors define the orientation of the
        # coordinate system
        ex = np.array([1, 0, 0])
        ey = np.array([0, 1, 0])
        ez = np.array([0, 0, 1])
        self.axes = [ex, ey, ez]
        self.Z0 = 0.0

        # combine Thomson point of cap with those of the tube
        self.x = np.vstack((x_cap, x_tube))
        self.s = np.array(s_cap + s_tube)
        self.o = np.hstack((o_cap, o_tube))

        self.N = len(self.x)

        if self.north_south == "N":
            pass
        elif self.north_south == "S":
            self.x = reflect_tube_xy(self.x, self.s, self.cnt.L)

        atomlist = self.thomson2atomlist()
        XYZ.write_xyz("/tmp/thomson_opt.xyz", [atomlist], mode="w")

        active, inactive = active_layers(self.x, self.s, self.cnt.a1,
                                         self.cnt.a2)

        def savexyz():
            atomlist = self.thomson2atomlist()
            XYZ.write_xyz("/tmp/thomson_opt.xyz", [atomlist], mode="a")

        self.x[active, :], self.s[active], self.o[
            active], self.en, self.grad = optimize_thomson(self.x[active, :],
                                                           self.s[active],
                                                           self.o[active],
                                                           R=self.cnt.R,
                                                           callback=savexyz)
        return (self.en, self.grad)
Пример #10
0
 def f(x):
     thomson_cap = XYZ.vector2atomlist(x, thomson_cap_ref)
     #        thomson_cap = enforce_constaints(thomson_cap)
     print "thomson_cap"
     print thomson_cap
     thomson_pts = thomson_tube + thomson_cap
     XYZ.write_xyz("/tmp/thomson_minimization.xyz", [thomson_cap], mode="a")
     en = potential_energy(thomson_pts)
     # gradient of potential energy
     grad = XYZ.atomlist2vector(gradient_energy(thomson_pts))
     print "en = %s" % en
     return en  #, grad
Пример #11
0
 def save_xyz(x, mode="a"):
     global step
     if step % opts.save_every != 0:
         step += 1
         return
     step += 1
     atomlist_opt = XYZ.vector2atomlist(x, atomlist)
     atomlist_opt, dummy = enlarged_unitcell(atomlist_opt,
                                             lattice_vectors,
                                             nmax=opts.nr_unit_cells)
     XYZ.write_xyz(xyz_opt, [atomlist_opt], \
                   mode=mode)
Пример #12
0
def build_dimer(output_dir):
    cluster_template = XYZ.read_xyz("water_dimer.xyz")[0]
    names = ["S0->D0", "S0->D1", "S0->D2", "S0->D3", "S0->D4", "S0->D5"]
    ionization_energies = [11.55, 11.86, 13.43, 13.98, 17.71, 18.03]
    orbitals_list = [["1b1", "1b1"], ["1b1", "1b1"], ["3a1", "3a1"], ["3a1", "3a1"], ["1b2", "1b2"], ["1b2", "1b2"]]
    phases_list   = [[ -1  ,   -1 ], [ +1,    -1  ], [ +1  ,  +1  ], [ -1  ,  +1  ], [  0,     +1 ], [  +1 ,  0   ]]
                
    dyson_orbs = []
    for name,IE,orbitals,phases in zip(names, ionization_energies,orbitals_list,phases_list):
        cluster, orb = build_water_cluster(cluster_template, orbitals, phases)
        dyson_orbs.append(orb)

    # save geometry of cluster
    XYZ.write_xyz(join(output_dir, "water_cluster_2.xyz"), [cluster])
    # and dyson orbitals
    dyson_orbs = np.array(dyson_orbs).transpose()
    save_dyson_orbitals(join(output_dir, "water_cluster_2.dyson"), names, ionization_energies, dyson_orbs)
Пример #13
0
def build_monomer(output_dir):
    cluster_template = XYZ.read_xyz("water_monomer.xyz")[0]
    names = ["1b1", "3a1", "1b2", "2a1"]
    ionization_energies = [12.5, 14.8, 18.5, 32.6]
    orbitals_list = [["1b1"], ["3a1"], ["1b2"], ["2a1"]] 
    phases_list   = [[ +1  ], [ +1  ], [ +1  ], [ +1  ]]
                
    dyson_orbs = []
    for name,IE,orbitals,phases in zip(names, ionization_energies,orbitals_list,phases_list):
        cluster, orb = build_water_cluster(cluster_template, orbitals, phases)
        dyson_orbs.append(orb)

    # save geometry of cluster
    XYZ.write_xyz(join(output_dir, "water_cluster_1.xyz"), [cluster])
    # and dyson orbitals
    dyson_orbs = np.array(dyson_orbs).transpose()
    save_dyson_orbitals(join(output_dir, "water_cluster_1.dyson"), names, ionization_energies, dyson_orbs)
Пример #14
0
def dupliverts(xyz_file, frag_links_file, out_xyz_file):
    """
    
    """
    fragments = load_fragments(frag_links_file)
    fragnames = fragments.keys()
    # copy keywords like charge, etc.
    kwds = XYZ.extract_keywords_xyz(xyz_file)
    title = reduce(lambda a, b: a + " " + b,
                   ["%s=%s " % (k, v) for (k, v) in kwds.iteritems()], "")
    #
    for i, fraglist in enumerate(read_xyz_rotation_it(xyz_file)):
        if i == 0:
            mode = 'w'
        else:
            mode = 'a'
        XYZ.write_xyz(out_xyz_file,
                      [substitute_fragments(fraglist, fragnames, fragments)],
                      title=title,
                      mode=mode)
Пример #15
0
 def generate_scaled_geometries(self,
                                scale_min=0.1,
                                scale_max=1.9,
                                Nscale=100):
     """
     Parameters:
     ===========
     scale_min: scale factor for smallest structure
     scale_max: scale factor for largest structure
     Nscale: number of points in the interval [scale_min, scale_max]
     """
     geometry = XYZ.read_xyz(self.xyz_in_file)[0]
     scaled_geoms = []
     for s in linspace(scale_min, scale_max, Nscale):
         scaled_atomlist = []
         for (Zi, (xi, yi, zi)) in geometry:
             scaled_atomlist.append((Zi, (xi * s, yi * s, zi * s)))
         scaled_geoms.append(scaled_atomlist)
     XYZ.write_xyz(self.xyz_scaled_file,
                   scaled_geoms,
                   title="scaled geometries")
Пример #16
0
    cut_atomlist = []
    for i,(Zi,posi) in enumerate(atomlist):
        if i in removed:
            pass
        else:
            cut_atomlist.append( (Zi, posi) )
    return cut_atomlist


if __name__ == "__main__":
    import sys
    from os.path import expandvars, expanduser

    from DFTB import XYZ

    usage = "python %s <in .xyz> <out .xyz> <radius in bohr>\n" % sys.argv[0]
    usage += "  removes all atoms outside sphere of radius R and all connected atoms\n"

    if len(sys.argv) < 4:
        print(usage)
        exit(-1)

    xyz_in = expandvars(expanduser(sys.argv[1]))
    xyz_out = expandvars(expanduser(sys.argv[2]))
    R = float(sys.argv[3])

    atomlist = XYZ.read_xyz(xyz_in)[0]
    cut_atomlist = cut_sphere(atomlist, R)
    print("Removed %d atoms" % (len(atomlist) - len(cut_atomlist)))
    XYZ.write_xyz(xyz_out, [cut_atomlist])
Пример #17
0
                ps[3 * A:3 * (A + 1), i] *= 0.001
    #
    # STATISTICS
    # kinetic energy
    Ekin = np.zeros(opts.Nsample)
    for i in range(0, opts.Nsample):
        Ekin[i] = np.sum(ps[:, i]**2 / (2 * np.array(masses)))
    # temperature  (3*N-6)/2 k T = Ekin
    f = len(masses) - 6  # degrees of freedom minus rotation and translation
    T = Ekin * 2.0 / (f * AtomicData.kBoltzmann)
    print "Initial Condition Statistics"
    print "============================"
    print "averages are over %d trajectories" % opts.Nsample
    print "kinetic energy = (%2.7f +- %2.7f) Hartree" % (np.mean(Ekin),
                                                         np.std(Ekin))
    print "temperature    = (%2.7f +- %2.7f) Kelvin" % (np.mean(T), np.std(T))
    print ""

    # geometries only
    wigner_xyz = join(opts.outdir, "wigner.xyz")
    geometries = [
        XYZ.vector2atomlist(qs[:, i], atomlist)
        for i in range(0, opts.Nsample)
    ]
    XYZ.write_xyz(wigner_xyz, geometries)
    print "Wigner ensemble written to file %s" % wigner_xyz

    # initial conditions
    HarmonicApproximation.save_initial_conditions(atomlist, qs, ps,
                                                  opts.outdir, "dynamics")
def transform_turbomole_orbitals(tm_dir, dyson_file, method="atomwise", selected_orbitals=None):
    """
    The molecular orbitals from a Turbomole calculation are transformed
    into the basis used by DFTB. Since in DFTB there are much less atomic orbitals
    this transformation is not bijective and does not conserve the normalization and
    orthogonality among the MOs. 

    Parameters:
    ===========
    tm_dir: directory with coord, basis and mos files
    dyson_file: transformed MO coefficients for DFTB are written to this file
    method: Method used to find the coefficients in the minimal basis
      'atomwise': overlaps are only calculated between orbitals on the same atom (very fast).
      'grid': the DFT orbital mo(r) and the minimal DFT atomic orbitals ao_i(r) are calculated 
         on a grid and the coefficients are obtained by minimizing the deviation
             error(c_i) = integral |mo(r) - sum_i c_i ao_i(r)|^2 dr
         in a least square sense (slower, but more accurate).
    selected_orbitals: list of indeces (starting at 1, e.g. '[1,2,3]') of orbitals that should be transformed.
      If not set all orbitals are transformed.
    """
    print "Reading geometry and basis from Turbomole directory %s" % tm_dir
    Data = Turbomole.parseTurbomole(tm_dir + "/coord")
    atomlist = Data["coord"]
    Data = Turbomole.parseTurbomole(tm_dir + "/basis")
    basis_data = Data["basis"]
    bs_gaussian = GaussianBasisSet(atomlist, basis_data)
    # load Turbomole orbitals
    try:
        Data = Turbomole.parseTurbomole(tm_dir + "/mos")
        orbe,orbs_turbomole = Data["scfmo"]
    except IOError:
        print "'mos' file not found! Maybe this is an open-shell calculation. Trying to read file 'alpha'"
        Data = Turbomole.parseTurbomole(tm_dir + "/alpha")
        orbe,orbs_turbomole = Data["uhfmo_alpha"]
    # Which orbitals should be transformed?
    if selected_orbitals == None:
        selected_mos = np.array(range(0, len(orbe)), dtype=int)
    else:
        selected_mos = np.array(eval(selected_orbitals), dtype=int)-1 
    nmo = len(selected_mos)
    # transform them to DFTB basis
    if method == "atomwise":
        T = bs_gaussian.getTransformation_GTO_to_DFTB()
        orbs = np.dot(T, orbs_turbomole[:,selected_mos])
    elif method == "grid":
        # define grid for integration
        (xmin,xmax),(ymin,ymax),(zmin,zmax) = Cube.get_bbox(atomlist, dbuff=7.0)
        dx,dy,dz = xmax-xmin,ymax-ymin,zmax-zmin
        ppb = 5.0 # Points per bohr
        nx,ny,nz = int(dx*ppb),int(dy*ppb),int(dz*ppb)
        x,y,z = np.mgrid[xmin:xmax:nx*1j, ymin:ymax:ny*1j, zmin:zmax:nz*1j]
        grid = (x,y,z)
        dV = dx/float(nx-1) * dy/float(ny-1) * dz/float(nz-1)
        # numerical atomic DFTB orbitals on the grid
        bs_atomic = AtomicBasisSet(atomlist)
        aos = [bf.amp(x,y,z) for bf in bs_atomic.bfs]
        nao = len(aos)
        # overlaps S2_mn = <m|n>
        S2 = np.zeros((nao,nao))
        for m in range(0, nao):
            S2[m,m] = np.sum(aos[m]*aos[m]*dV)
            for n in range(m+1,nao):
                S2[m,n] = np.sum(aos[m]*aos[n]*dV)
                S2[n,m] = S2[m,n]
        # DFT molecular orbitals on the grid
        mos = [Cube.orbital_amplitude(grid, bs_gaussian.bfs, orbs_turbomole[:,i]).real for i in selected_mos]
        # overlaps S1_mi = <m|i>, m is an atomic DFTB orbital, i a molecular DFT orbital
        S1 = np.zeros((nao,nmo))
        for m in range(0, nao):
            for i in range(0, nmo):
                S1[m,i] = np.sum(aos[m]*mos[i]*dV)
        # Linear regression leads to the matrix equation
        #   sum_n S2_mn c_ni = S1_mi
        # which has to be solved for the coefficients c_ni.
        orbs = la.solve(S2, S1)

    else:
        raise ValueError("Method should be 'atomwise' or 'grid' but not '%s'!" % method)
    # normalize orbitals, due to the incomplete transformation they are not necessarily
    # orthogonal
    dftb2 = DFTB2(atomlist)
    dftb2.setGeometry(atomlist)
    S = dftb2.getOverlapMatrix()
    for i in range(0, nmo):
        norm2 = np.dot(orbs[:,i], np.dot(S, orbs[:,i]))
        orbs[:,i] /= np.sqrt(norm2)
    # save orbitals 
    xyz_file = "geometry.xyz"
    XYZ.write_xyz(xyz_file, [atomlist])
    print "Molecular geometry was written to '%s'." % xyz_file
    ionization_energies = -orbe[selected_mos]
    save_dyson_orbitals(dyson_file, ["%d" % (i+1) for i in selected_mos], ionization_energies, orbs, mode="w")
    print "MO coefficients for DFTB were written to '%s'." % dyson_file
Пример #19
0
        coord_name = "DIHEDRAL(%d-%d-%d-%d)" % (I, J, K, L)
    else:
        raise ValueError("Format of scan '%s' not understood!" % scan)

    # shift indices to programmer's style (starting at 0)
    IJKL = map(lambda I: I - 1, IJKL)

    IC = InternalValenceCoords(atomlist0, freeze=freeze, verbose=opts.verbose)

    # cartesian coordinates along the scan
    scan_geometries = [atomlist0]
    # value of internal coordinate IJKL along the scan
    val0 = IC.coordinate_value(x0, IJKL)
    scan_coords = [val0]

    x1 = x0
    for i in range(0, nsteps):
        # cartesian coordinates at displaced geometry
        x1 = IC.internal_step(x1, IJKL, incr)
        # new value of internal coordinate, should be approximately
        #  val0 + incr
        val1 = IC.coordinate_value(x1, IJKL)

        atomlist1 = XYZ.vector2atomlist(x1, atomlist0)
        scan_geometries.append(atomlist1)
        scan_coords.append(val1)
        print "step %d  %s = %10.6f" % (i + 1, coord_name, val1)

    XYZ.write_xyz(xyz_out, scan_geometries, mode="w")
    print "displaced geometries were saved to '%s'" % xyz_out
Пример #20
0
"""
split an xyz file that contains many structures into separate files
"""
from DFTB import XYZ

if __name__ == "__main__":
    import sys
    import optparse
    usage = "Usage: python %s <xyz file with many structures> <output prefix>\n" % sys.argv[
        0]
    usage += "  splits the input file into output prefix_####.xyz"

    parser = optparse.OptionParser(usage)
    parser.add_option(
        "--step",
        dest="step",
        help="Only every N-th geometry is extracted [default: %default]",
        type=int,
        default=1)
    (opts, args) = parser.parse_args()

    if len(args) < 2:
        print(usage)
        exit(-1)
    xyz_file = sys.argv[1]
    prefix = sys.argv[2]
    structures = XYZ.read_xyz(xyz_file)
    for i, atomlist in enumerate(structures):
        if (i + 1) % opts.step == 0 or i == 0:
            XYZ.write_xyz(prefix + "%.4d.xyz" % (i + 1), [atomlist])
        tmp_com = tmp_dir + "gaussian.com"
        tmp_out = tmp_dir + "gaussian.log"
        tmp_chk = tmp_dir + "gaussian.chk"
        if i == 0:
            guess=""
        else:
            # read starting MOs from checkpoint file
            guess="Guess=Read"
        Gaussian.write_input(tmp_com, atomlist, \
                        route="# %s/%s %s Force Integral=(Grid=Ultrafine) Geom=NoCrowd" % (options.method, options.basis_set, guess), \
                        chk_file=tmp_chk, \
                        title="Gradients for fitting repulsive potential", \
                        charge=options.charge, multiplicity=options.multiplicity)
        # compute forces with gaussian
        os.system("g09 < %s > %s" % (tmp_com, tmp_out))

        en_tot = Gaussian.read_total_energy(tmp_out)
        print("Structure %d   enTot= %s Hartree" % (i, en_tot))
        forces_dic = Gaussian.read_forces(tmp_out)
        forces = []
        for center in list(forces_dic.keys()):
            forces.append(forces_dic[center])
        print("%2.7f" % en_tot, file=fh_en)
        XYZ.write_xyz(force_file, [forces],
                      title="forces with %s/%s, total_energy=%2.7f" % (options.method, options.basis_set, en_tot),
                      units="hartree/bohr",
                      mode=mode)
        mode = 'a'

    fh_en.close()
Пример #22
0
    usage += "  To see a list of all available fragments run the program without the list parameter.\n"
    usage += "  Type --help to see all options."
    parser = optparse.OptionParser(usage)
    parser.add_option(
        "--filter_mode",
        dest="filter_mode",
        help=
        "Determines whether the filter should 'keep' or 'delete' the selected fragments [default: %default]",
        default="keep")
    parser.add_option(
        "--out_xyz",
        dest="out_xyz",
        help="Filtered geometry is written to this file [default: %default]",
        default="filtered.xyz")

    (opts, args) = parser.parse_args()
    if len(args) < 1:
        print usage
        exit(-1)
    xyz_in = args[0]
    selected_fragments = args[1:]

    atomlist_full = XYZ.read_xyz(xyz_in)[-1]
    atomlist_filtered = filter_fragments(atomlist_full,
                                         selected_fragments,
                                         filter_mode=opts.filter_mode)

    if len(selected_fragments) > 0:
        XYZ.write_xyz(opts.out_xyz, [atomlist_filtered])
        print "filtered geometry written to %s" % opts.out_xyz
Пример #23
0
    import sys

    atomlist0 = XYZ.read_xyz(sys.argv[1])[-1]
    x0 = XYZ.atomlist2vector(atomlist0)

    IC = InternalValenceCoords(atomlist0, verbose=3)

    test_wilson_bmatrix(IC.force_field, x0)

    # 1) transform cartesian to internal coordinates, x0 ~ q0
    q0 = IC.cartesian2internal(x0)

    # 2) Take a step along the last internal coordinate,
    # this will only work if the coordinate is not coupled
    # to any other.
    dq = np.zeros(len(q0))
    dq[-1] = 0.1
    q = q0 + dq

    # 3) and transform back x ~ q
    x = IC.internal2cartesian(q)

    # veriy that really x corresponds to internal coordinate q
    q_test = IC.cartesian2internal(x)
    err = la.norm(q - q_test)
    #    assert err < 1.0e-10, "|q(x(q)) - q|= %e" % err

    # 4) save initial and displaced geometries
    atomlist = XYZ.vector2atomlist(x, atomlist0)
    XYZ.write_xyz("/tmp/test_internal_coords.xyz", [atomlist0, atomlist])
Пример #24
0
 def save_xyz(x, mode="a"):
     atomlist_opt = XYZ.vector2atomlist(x, atomlist)
     XYZ.write_xyz(xyz_trace, [atomlist_opt],
                   title="charge=%s" % kwds.get("charge", 0),
                   mode=mode)
Пример #25
0
#

import sys
import os.path

from DFTB import XYZ
from DFTB.Formats.Gaussian2py import Gaussian

if len(sys.argv) < 3:
    print("")
    print("Usage: %s  log-file  xyz-file" % os.path.basename(sys.argv[0]))
    print("")
    print("   extract all geometries and SCF energies from Gaussian log-file")
    print("   and write them to an xyz-file.")
    print("")
    exit(-1)

# input file
log_file = sys.argv[1]
# output file
xyz_file = sys.argv[2]

atomlists = Gaussian.read_geometries_it(log_file)
energies = Gaussian.read_scf_energies_it(log_file)

titles = ["ENERGY= %f" % en for en in energies]

XYZ.write_xyz(xyz_file, atomlists, title=titles)

print("geometries written to '%s'" % xyz_file)
Пример #26
0
    # interpolation parameter
    rs = np.linspace(0.0, 1.0, N)

    geometries_interp = []

    if opts.coord_system == "cartesian":
        for r in rs:
            xr = x0 + r * (x1 - x0)
            geometries_interp.append(XYZ.vector2atomlist(xr, atomlist0))
    elif opts.coord_system == "internal":
        # explicit bonds, shift atom indices from 1- to 0-indexing
        explicit_bonds = [(I - 1, J - 1)
                          for (I, J) in eval(opts.explicit_bonds)]

        IC = InternalValenceCoords(atomlist0, explicit_bonds=explicit_bonds)
        # initial and final geometry in internal coordinates
        q1 = IC.cartesian2internal(x1)
        q0 = IC.cartesian2internal(x0)
        for r in rs:
            qr = q0 + r * (q1 - q0)
            xr = IC.internal2cartesian(qr)
            geometries_interp.append(XYZ.vector2atomlist(xr, atomlist0))
    else:
        raise ValueError(
            "Coordinate system '%s' not understood, valid options are 'internal' and 'cartesian'"
            % opts.coord_system)

    XYZ.write_xyz(xyz_interp, geometries_interp)
    print "Interpolated geometries written to %s" % xyz_interp
    x = XYZ.atomlist2vector(atomlist)
    pes.getEnergies(x)

    for i, atomlist in enumerate(XYZ.read_xyz(geom_file)):
        # compute electronic ground state forces with DFTB
        x = XYZ.atomlist2vector(atomlist)
        en = pes.getEnergy_S0(x)
        # total ground state energy including repulsive potential
        en_tot = en[0]
        print("Structure %d   enTot= %s Hartree" % (i, en_tot))
        # electronic energy without repulsive potential
        en_elec = pes.tddftb.dftb2.getEnergies()[2]
        gradVrep, gradE0, gradExc = pes.grads.gradient(I=0)
        # exclude repulsive potential from forces
        grad = gradE0 + gradExc
        forces = XYZ.vector2atomlist(-grad, atomlist)
        if i == 0:
            mode = 'w'
        else:
            mode = 'a'
        print("%2.7f" % en_elec, file=fh_en)

        XYZ.write_xyz(
            force_file, [forces],
            title="forces with DFTB, total_energy=%2.7f  elec_energy=%2.7f" %
            (en_tot, en_elec),
            units="hartree/bohr",
            mode=mode)

    fh_en.close()
Пример #28
0
    def opt(self, max_iter=5000, step_size=1.0, gtol=0.005):
        """
        optimize MECI by following the gradient downhill

        Optional
        --------
        max_iter  :  maximum number of steps
        step_size :  The geometry is updated by making a step
                       x -> x - step_size * grad
        gtol      :  tolerance for the gradient norm
        """
        print("optimize MECI by following the gradient")
        print("  lower state :  %d" % state1)
        print("  upper state :  %d" % state2)
        print("Intermediate geometries are written to 'meci_path.xyz'")
        print("and a table with energies is written to 'meci_energies.dat'")

        # initial geometry
        x = XYZ.atomlist2vector(self.atomlist0)
        # overwrite geometries from previous run
        mode = "w"
        en_fh = open("meci_energies.dat", "w")
        print("# optimization of MECI", file=en_fh)
        print(
            "# STEP     ENERGY(1)/Hartree    ENERGY(2)/Hartree    ENERGY(3)-EPS/Hartree",
            file=en_fh)

        for i in range(0, max_iter):
            e1, e2, grad = self.getGradient(x)
            # energy gap
            en_gap = e2 - e1
            self.adjust_shift(en_gap)

            # save intermediate steps and energies
            atomlist = XYZ.vector2atomlist(x, self.atomlist0)
            XYZ.write_xyz("meci_path.xyz", [atomlist],
                          title="ENERGY= %e  GAP= %e" % (e2, en_gap),
                          mode=mode)
            print(" %4.1d      %+15.10f      %+15.10f      %+15.10f" %
                  (i, e1, e2, e2 - self.epsilon),
                  file=en_fh)
            en_fh.flush()

            # append to trajectory file
            mode = "a"
            #

            gnorm = la.norm(grad)
            print(" %4.1d    e2= %e  e2-e1= %e   |grad|= %e  (tolerance= %e)" %
                  (i, e2, en_gap, gnorm, gtol))
            if gnorm < gtol:
                break

            if self.coord_system == "cartesian":
                # descend along gradient directly in cartesian coordinates
                x -= step_size * grad
            elif self.coord_system == "internal":
                # use internal redundant coordinates
                # 1) transform cartesian to internal coordinates x -> q
                q = self.ic.cartesian2internal(x)
                # 2) transform cartesian gradient to internal coordinates
                # dE/dx -> dE/dq
                grad_intern = self.ic.transform_gradient(x, grad)
                # 3) take step along gradient in internal coordinates
                q = q - step_size * grad_intern
                # 4) deduce new cartesian coordinates from new internal coordinates q
                x = self.ic.internal2cartesian(q)

        else:
            print("exceeded maximum number of steps")

        en_fh.close()
Пример #29
0
    def __init__(self, atomlist, hubbard_U):
        """
        
        Parameters:
        ===========
        bfs: list of numeric basis functions
        bfs_aux: list of auxiliary basis functions
        """
        self.atomlist = atomlist
        self.bfs = AtomicBasisSet(atomlist).bfs
        self.bfs_aux = AuxiliaryBasisSet(atomlist, hubbard_U).bfs
        # create a list of points that should have the symmetry
        # of the molecule on which the true density should agree
        # with the model density
        Xs,Ys,Zs = [], [], []
        # atomic centers
        for Zi,posi in atomlist:
            x,y,z = posi
            Xs.append(x)
            Ys.append(y)
            Zs.append(z)
        # points between atoms
        for i,(Zi,posi) in enumerate(atomlist):
            for j,(Zj,posj) in enumerate(atomlist):
                if i == j:
                    continue
                Rij = np.array(posj)-np.array(posi)
                x,y,z = np.array(posi) + 0.33*Rij
                Xs.append(x)
                Ys.append(y)
                Zs.append(z)
                x,y,z = np.array(posi) - 0.33*Rij
                Xs.append(x)
                Ys.append(y)
                Zs.append(z)


        # points perpendicular to plane between 3 atoms
        for i,(Zi,posi) in enumerate(atomlist):
            for j,(Zj,posj) in enumerate(atomlist):
                if i == j:
                    continue
                for k,(Zk,posk) in enumerate(atomlist):
                    if i == k:
                        continue
                    if i == j:
                        continue
                    Rij = np.array(posj) - np.array(posi)
                    Rik = np.array(posk) - np.array(posi)
                    x,y,z = np.array(posi) + 0.25*np.cross(Rij, Rik)
                    Xs.append(x)
                    Ys.append(y)
                    Zs.append(z)

        Xs,Ys,Zs = np.mgrid[-6.0:6.0:30j,-6.0:6.0:30j,-6.0:6.0:30j]
        Xs = Xs.ravel()
        Ys = Ys.ravel()
        Zs = Zs.ravel()
        grid = np.array(Xs), np.array(Ys), np.array(Zs)

        # number of fit parameters
        self.Nfit = len(self.bfs_aux)
        assert self.Nfit % 4 == 0
        # number of basis functions
        self.Nbfs = len(self.bfs)
        # number of sample points
        self.Npts = len(Xs)
        assert self.Npts > self.Nfit
        # save grid to xyz file
        gridlist = atomlist[:]
        for i in range(0, self.Npts):
            gridlist.append( (1, (Xs[i], Ys[i], Zs[i])) )
        XYZ.write_xyz("/tmp/fitgrid.xyz", [gridlist])
        # evaluate all basis functions on the grid
        self.bf_grid = np.zeros((self.Npts, self.Nbfs))
        for m,bfm in enumerate(self.bfs):
            self.bf_grid[:,m] = bfm.amp(*grid)        
        # evaluate fit functions on the grid
        self.bf_aux_grid = np.zeros((self.Npts, self.Nfit))
        for m,bfm_aux in enumerate(self.bfs_aux):
            self.bf_aux_grid[:,m] = bfm_aux.amp(*grid)

        #
        M = self.bf_aux_grid
        self.M = M
         # constrained   C.x - Q = 0
        Id4 = np.eye(4)
        C = np.hstack([Id4 for i in range(0, self.Nfit/4)])
        Ct = C.transpose()
        #
        Mt = M.transpose()
        MtM = np.dot(Mt, M)
        MtMinv = la.inv(MtM)
        #
        self.A1 = np.dot(C,np.dot(MtMinv, Mt))
        self.A2 = np.dot(C,np.dot(MtMinv, Ct))
        self.A3 = np.dot(MtMinv, Ct)
        self.A4 = np.dot(MtMinv,Mt)
Пример #30
0
def opt(xyzfile, optionfile):
    """performs an optimization"""

    outputfile = open("output_dftb.txt", "a")  # redirect output to file
    sys.stdout = outputfile

    try:
        I = 0  # index of electronic state (ground state)

        atomlist = XYZ.read_xyz(xyzfile)[0]  # read atomlist
        kwds = XYZ.extract_keywords_xyz(
            xyzfile)  # read keywords from xyz-file (charge)
        options = read_options(optionfile)  # read options
        scf_options = extract_options(options,
                                      SCF_OPTIONLIST)  # get scf-options

        # optimization (taken from optimize.py)
        pes = MyPES(atomlist, options, Nst=max(I + 1, 2), **kwds)

        x0 = XYZ.atomlist2vector(atomlist)  #convert geometry to a vector

        def f(x):
            save_xyz(x)  # also save geometries from line searches

            if I == 0 and type(pes.tddftb.XmY) != type(None):
                # only ground state is needed. However, at the start
                # a single TD-DFT calculation is performed to initialize
                # all variables (e.g. X-Y), so that the program does not
                # complain about non-existing variables.
                enI, gradI = pes.getEnergyAndGradient_S0(x)
            else:
                energies, gradI = pes.getEnergiesAndGradient(x, I)
                enI = energies[I]
            print "E = %2.7f" % (enI)
            return enI, gradI

        xyz_trace = xyzfile.replace(".xyz", "_trace.xyz")

        # This is a callback function that is executed by numpy for each optimization step.
        # It appends the current geometry to an xyz-file.
        def save_xyz(x, mode="a"):
            atomlist_opt = XYZ.vector2atomlist(x, atomlist)
            XYZ.write_xyz(xyz_trace, [atomlist_opt],
                          title="charge=%s" % kwds.get("charge", 0),
                          mode=mode)

        save_xyz(x0, mode="w")  # write original geometry

        Nat = len(atomlist)
        min_options = {'gtol': 1.0e-7, 'norm': 2}
        # The "BFGS" method is probably better than "CG", but the line search in BFGS is expensive.
        res = optimize.minimize(f,
                                x0,
                                method="CG",
                                jac=True,
                                callback=save_xyz,
                                options=min_options)
        # res = optimize.minimize(f, x0, method="BFGS", jac=True, callback=save_xyz, options=options)
        xopt = res.x
        save_xyz(xopt)

        print "Intermediate geometries written into file {}".format(xyz_trace)

        # write optimized geometry into file
        atomlist_opt = XYZ.vector2atomlist(xopt, atomlist)
        xyz_opt = xyzfile.replace(".xyz", "_opt.xyz")
        XYZ.write_xyz(xyz_opt, [atomlist_opt],
                      title="charge=%s" % kwds.get("charge", 0),
                      mode="w")

        # calculate energy for optimized geometry
        dftb2 = DFTB2(atomlist_opt, **options)  # create dftb object
        dftb2.setGeometry(atomlist_opt, charge=kwds.get("charge", 0.0))

        dftb2.getEnergy(**scf_options)
        energies = list(dftb2.getEnergies())  # get partial energies

        if dftb2.long_range_correction == 1:  # add long range correction to partial energies
            energies.append(dftb2.E_HF_x)

        return str(energies)

    except:
        print sys.exc_info()
        return "error"