Example #1
0
def get_active_space(xyzfile, optionfile):
    """calculates the active space for a given molecule and excited state
    (see http://www.dftbaby.chemie.uni-wuerzburg.de/DFTBaby/mdwiki.html#!WIKI/main_page.md, Active Space)
    
    not implemented in CAST because no use for ground state calculations
    for ground state calculations the active space can be set as small as desired"""

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

    try:
        options = read_options(optionfile)  # read options
        atomlist = XYZ.read_xyz(xyzfile)[0]  # read structure

        init_options = extract_options(options, TD_INIT_OPTIONLIST)
        td_options = extract_options(options, TD_OPTIONLIST)
        kwds = XYZ.extract_keywords_xyz(xyzfile)

        tddftb = LR_TDDFTB(atomlist, **init_options)  # create object
        tddftb.setGeometry(atomlist, charge=kwds.get("charge", 0.0))
        tddftb.getEnergies(**td_options)  # calculate energies
        occ, virt = tddftb.determineActiveSpace()
        return str((occ, virt))
    except:
        print sys.exc_info()
        return "error"
Example #2
0
def calc_gradients(xyzfile, optionfile):
    """calculates DFTB energies and gradients for a molecule in the xyz_file
    with the options given in the optionfile"""

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

    try:
        options = read_options(optionfile)  # read options
        atomlist = XYZ.read_xyz(xyzfile)[0]  # read structure

        init_options = extract_options(options, TD_INIT_OPTIONLIST)
        td_options = extract_options(options, TD_OPTIONLIST)
        grad_options = extract_options(options, GRAD_OPTIONS)
        kwds = XYZ.extract_keywords_xyz(xyzfile)

        tddftb = LR_TDDFTB(atomlist, **init_options)  # create object
        tddftb.setGeometry(atomlist, charge=kwds.get("charge", 0.0))
        tddftb.getEnergies(**td_options)  # calculate energies

        grad = Gradients(tddftb)  # calculate gradients
        grad.getGradients(**grad_options)

        energies = list(tddftb.dftb2.getEnergies())  # get partial energies

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

        return str(energies)

    except:
        print sys.exc_info()
        return "error"
Example #3
0
def calc_energies(xyzfile, optionfile):
    """calculates DFTB energies for a molecule in the xyz_file
    with the options given in the optionfile"""

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

    try:
        options = read_options(optionfile)  # read options
        atomlist = XYZ.read_xyz(xyzfile)[0]  # read structure
        kwds = XYZ.extract_keywords_xyz(xyzfile)

        dftb2 = DFTB2(atomlist, **options)  # create dftb object
        dftb2.setGeometry(atomlist, charge=kwds.get("charge", 0.0))

        scf_options = extract_options(options,
                                      SCF_OPTIONLIST)  # calculate energy
        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"
Example #4
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)
        exit(-1)

    geom_file = args[0]
    energy_file = args[1]
    force_file = args[2]

    print("Compute forces with DFTB")
    print("========================")
    print("")
    fh_en = open(energy_file, "w")
    print("# ELECTRONIC ENERGY / HARTREE", file=fh_en)

    # first geometry
    atomlist = XYZ.read_xyz(geom_file)[0]
    # read charge from title line in .xyz file
    kwds = XYZ.extract_keywords_xyz(geom_file)
    charge = kwds.get("charge", opts.charge)

    pes = PotentialEnergySurfaces(atomlist, charge=charge)
    # dftbaby needs one excited states calculation to set all variables
    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
Example #6
0
    import sys
    import os
    if len(sys.argv) < 3:
        print "Usage: %s .xyz-file .ff-file" % (os.path.basename(sys.argv[0]))
        print "  assigns atom types automatically for geometry in .xyz-file."
        print ""
        print "  This script simply adds a 5th column with the atom type"
        print "  and writes the result to the .ff-file ."
        print " "
        print "  WARNING: The type assignment and the force field implementation itself probably have lots of bugs!"
        exit(-1)
    # laod xyz-file
    xyz_file = sys.argv[1]
    atomlist = XYZ.read_xyz(xyz_file)[0]
    # find total charge
    kwds = XYZ.extract_keywords_xyz(xyz_file)
    charge = kwds.get("charge", 0.0)

    nat = len(atomlist)
    # determine bond orders
    print "connectivity matrix"
    ConMat = XYZ.connectivity_matrix(atomlist, search_neighbours=200)
    print "bond order assignment"
    bondsTuples, bond_orders, lone_pairs, formal_charges = BondOrders.assign_bond_orders(
        atomlist, ConMat, charge=charge)
    # list of bond orders
    bond_orders_atomwise = [[] for i in range(0, nat)]
    # names of atoms connected to each
    bonded_atomnames = [[] for i in range(0, nat)]
    for i, (atI, atJ) in enumerate(bondsTuples):
        BO = bond_orders[i]
Example #7
0
    # chemical equation
    educts_str = " + ".join([
        "%d %s " % (coef, educt)
        for (coef, educt) in zip(coefs_educts, educts)
    ])
    products_str = " + ".join([
        "%d %s " % (-coef, prod)
        for (coef, prod) in zip(coefs_products, products)
    ])
    reaction_str = educts_str + " <---> " + products_str

    # compute reference energy
    en_ref = 0.0
    for coef, mol in zip(coefs_educts + coefs_products, educts + products):
        en = float(
            XYZ.extract_keywords_xyz(os.path.join("REFERENCE",
                                                  mol + ".xyz"))["energy"])
        en_ref -= coef * en

    # compute DFTB energy
    en_dftb = 0.0
    for coef, mol in zip(coefs_educts + coefs_products, educts + products):
        en = float(
            XYZ.extract_keywords_xyz(os.path.join("DFTB",
                                                  mol + ".xyz"))["energy"])
        en_dftb -= coef * en

    # convert from Hartree to kcal/mol
    en_ref *= AtomicData.hartree_to_kcalmol
    en_dftb *= AtomicData.hartree_to_kcalmol

    print("%40.40s         %+15.1f       %+15.1f" %
Example #8
0
def hessian(xyzfile, optionfile):
    """calculates hessian matrix"""

    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 xyz file
        kwds = XYZ.extract_keywords_xyz(xyzfile)  # read keywords (charge)
        options = read_options(optionfile)  # read options
        scf_options = extract_options(options,
                                      SCF_OPTIONLIST)  # get scf-options

        pes = MyPES(atomlist, options, Nst=max(I + 1, 2), **kwds)  # create PES

        atomvec = XYZ.atomlist2vector(atomlist)  # convert atomlist to vector

        # FIND ENERGY MINIMUM
        # f is the objective function that should be minimized
        # it returns (f(x), f'(x))
        def f(x):
            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]
            return enI, gradI

        minoptions = {'gtol': 1.0e-7, 'norm': 2}
        # somehow numerical_hessian does not work without doing this mimimization before
        res = optimize.minimize(f,
                                atomvec,
                                method="CG",
                                jac=True,
                                options=minoptions)

        # COMPUTE HESSIAN AND VIBRATIONAL MODES
        # The hessian is calculated by numerical differentiation of the
        # analytical gradients
        def grad(x):
            if I == 0:
                enI, gradI = pes.getEnergyAndGradient_S0(x)
            else:
                energies, gradI = pes.getEnergiesAndGradient(x, I)
            return gradI

        print "Computing Hessian"  # calculate hessians from gradients
        hess = HarmonicApproximation.numerical_hessian_G(grad, atomvec)

        string = ""  # create string that is to be written into file
        for line in hess:
            for column in line:
                string += str(column) + " "
            string = string[:-1] + "\n"

        with open("hessian.txt",
                  "w") as hessianfile:  # write hessian matrix to file
            hessianfile.write(string)
            # this would look nicer but is not as exact
            #hessianfile.write(annotated_hessian(atomlist, hess))

        # calculate energy for optimized geometry
        dftb2 = DFTB2(atomlist, **options)  # create dftb object
        dftb2.setGeometry(atomlist, 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"
Example #9
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"
Example #10
0
        exit(-1)

    xyz_in = args[0]
    xyz_out = args[1]

    if len(args) < 3:
        print "possible commands: 'scale', 'dislocate'"
        exit(-1)
    cmd = args[2]
    # the remaining command line arguments depend
    cmd_args = map(eval, args[3:])

    atomlist0 = XYZ.read_xyz(xyz_in)[-1]
    PG = PerturbedGeometries(atomlist0)

    kwds = XYZ.extract_keywords_xyz(xyz_in)

    if cmd == "scale":
        if len(cmd_args) < 3:
            print "Arguments for 'scale':"
            print "    smin smax N"
            exit(-1)
        geometries = PG.scale(*cmd_args)
    elif cmd == "dislocate":
        if len(cmd_args) < 4:
            print "Arguments for 'dislocate':"
            print "    atom radius nshells N"
            exit(-1)
        geometries = PG.dislocate(*cmd_args)
    else:
        raise ValueError("Command '%s' not understood" % cmd)