Exemplo n.º 1
0
def compute_charges(charge_method, charge_type, molecule):
    """
    Compute charges for nbody fragments
    """
    from psi4.driver.driver import energy
    from psi4.driver.p4util.util import oeprop

    charges = {}
    molecule = molecule.clone()
    for i in range(1, molecule.nfragments() + 1):
        molecule.set_name('charges%i' %i)
        e, wfn = energy(charge_method, molecule=molecule.extract_subsets([i]), return_wfn=True)
        oeprop(wfn, charge_type)
        charges[i] = wfn.atomic_point_charges().np

    return charges
Exemplo n.º 2
0
def compute_charges(charge_method, charge_type, molecule):
    """
    Compute charges for nbody fragments
    """
    from psi4.driver.driver import energy
    from psi4.driver.p4util.util import oeprop

    charges = {}
    molecule = molecule.clone()
    for i in range(1, molecule.nfragments() + 1):
        molecule.set_name('charges%i' % i)
        e, wfn = energy(charge_method, molecule=molecule.extract_subsets([i]), return_wfn=True)
        oeprop(wfn, charge_type)
        charges[i] = wfn.atomic_point_charges().np

    return charges
Exemplo n.º 3
0
Arquivo: frac.py Projeto: yxie326/psi4
def ip_fitting(name,
               omega_l=0.05,
               omega_r=2.5,
               omega_convergence=1.0e-3,
               maxiter=20,
               **kwargs):
    """Optimize DFT omega parameter for molecular system.

    Parameters
    ----------
    name : string or function
        DFT functional string name or function defining functional
        whose omega is to be optimized.
    omega_l : float, optional
        Minimum omega to be considered during fitting.
    omega_r : float, optional
        Maximum omega to be considered during fitting.
    molecule : :ref:`molecule <op_py_molecule>`, optional
        Target molecule (neutral) for which omega is to be tuned, if not last defined.
    omega_convergence : float, optional
        Threshold below which to consider omega converged. (formerly omega_tolerance)
    maxiter : int, optional
        Maximum number of iterations towards omega convergence.

    Returns
    -------
    float
        Optimal omega parameter.

    """
    optstash = p4util.OptionsState(['SCF', 'REFERENCE'], ['SCF', 'GUESS'],
                                   ['SCF', 'DF_INTS_IO'], ['SCF', 'DFT_OMEGA'],
                                   ['DOCC'], ['SOCC'])

    kwargs = p4util.kwargs_lower(kwargs)

    # By default, do not read previous 180 orbitals file
    read = False
    read180 = ''
    if 'read' in kwargs:
        read = True
        read180 = kwargs['read']

    if core.get_option('SCF', 'REFERENCE') != 'UKS':
        core.print_out(
            """  Requested procedure `ip_fitting` runs further calculations with UKS reference.\n"""
        )
        core.set_local_option('SCF', 'REFERENCE', 'UKS')

    # Make sure the molecule the user provided is the active one, and neutral
    molecule = kwargs.pop('molecule', core.get_active_molecule())
    molecule.update_geometry()

    if molecule.molecular_charge() != 0:
        raise ValidationError(
            """IP Fitting requires neutral molecule to start.""")
    if molecule.schoenflies_symbol() != 'c1':
        core.print_out(
            """  Requested procedure `ip_fitting` does not make use of molecular symmetry: """
            """further calculations in C1 point group.\n""")
    molecule = molecule.clone()
    molecule.reset_point_group('c1')
    molecule.update_geometry()

    charge0 = molecule.molecular_charge()
    mult0 = molecule.multiplicity()

    # How many electrons are there?
    N = 0
    for A in range(molecule.natom()):
        N += molecule.Z(A)
    N -= charge0
    N = int(N)
    Nb = int((N - mult0 + 1) / 2)
    Na = int(N - Nb)

    # Work in the ot namespace for this procedure
    core.IO.set_default_namespace("ot")

    # Burn in to determine orbital eigenvalues
    if read:
        core.set_local_option("SCF", "GUESS", "READ")
        copy_file_to_scratch(read180, 'psi', 'ot', 180)
    core.set_local_option("SCF", "DF_INTS_IO", "SAVE")
    E, wfn = driver.energy('scf',
                           dft_functional=name,
                           return_wfn=True,
                           molecule=molecule,
                           banner='IP Fitting SCF: Burn-in',
                           **kwargs)
    core.set_local_option("SCF", "DF_INTS_IO", "LOAD")

    if not wfn.functional().is_x_lrc():
        raise ValidationError(
            """Not sensible to optimize omega for non-long-range-correction functional."""
        )

    # Determine H**O, to determine mult1
    eps_a = wfn.epsilon_a()
    eps_b = wfn.epsilon_b()
    if Na == Nb:
        H**O = -Nb
    elif Nb == 0:
        H**O = Na
    else:
        E_a = eps_a.np[int(Na - 1)]
        E_b = eps_b.np[int(Nb - 1)]
        if E_a >= E_b:
            H**O = Na
        else:
            H**O = -Nb

    Na1 = Na
    Nb1 = Nb
    if H**O > 0:
        Na1 -= 1
    else:
        Nb1 -= 1

    charge1 = charge0 + 1
    mult1 = Na1 - Nb1 + 1

    omegas = []
    E0s = []
    E1s = []
    kIPs = []
    IPs = []
    types = []

    # Right endpoint
    core.set_local_option('SCF', 'DFT_OMEGA', omega_r)

    # Neutral
    if read:
        core.set_local_option("SCF", "GUESS", "READ")
        p4util.copy_file_to_scratch(read180, 'psi', 'ot', 180)

    molecule.set_molecular_charge(charge0)
    molecule.set_multiplicity(mult0)
    E0r, wfn = driver.energy('scf',
                             dft_functional=name,
                             return_wfn=True,
                             molecule=molecule,
                             banner='IP Fitting SCF: Neutral, Right Endpoint',
                             **kwargs)
    eps_a = wfn.epsilon_a()
    eps_b = wfn.epsilon_b()
    if Nb == 0:
        E_HOMO = eps_a.np[int(Na - 1)]
    else:
        E_a = eps_a.np[int(Na - 1)]
        E_b = eps_b.np[int(Nb - 1)]
        E_HOMO = max(E_a, E_b)
    E_HOMOr = E_HOMO
    core.IO.change_file_namespace(180, "ot", "neutral")

    # Cation
    if read:
        core.set_local_option("SCF", "GUESS", "READ")
        p4util.copy_file_to_scratch(read180, 'psi', 'ot', 180)

    molecule.set_molecular_charge(charge1)
    molecule.set_multiplicity(mult1)
    E1r = driver.energy('scf',
                        dft_functional=name,
                        molecule=molecule,
                        banner='IP Fitting SCF: Cation, Right Endpoint',
                        **kwargs)
    core.IO.change_file_namespace(180, "ot", "cation")

    IPr = E1r - E0r
    kIPr = -E_HOMOr
    delta_r = IPr - kIPr

    if IPr > kIPr:
        raise ValidationError(
            """\n***IP Fitting Error: Right Omega limit should have kIP > IP: {} !> {}"""
            .format(kIPr, IPr))

    omegas.append(omega_r)
    types.append('Right Limit')
    E0s.append(E0r)
    E1s.append(E1r)
    IPs.append(IPr)
    kIPs.append(kIPr)

    # Use previous orbitals from here out
    core.set_local_option("SCF", "GUESS", "READ")

    # Left endpoint
    core.set_local_option('SCF', 'DFT_OMEGA', omega_l)

    # Neutral
    core.IO.change_file_namespace(180, "neutral", "ot")
    molecule.set_molecular_charge(charge0)
    molecule.set_multiplicity(mult0)
    core.set_global_option("DOCC", [Nb])
    core.set_global_option("SOCC", [Na - Nb])
    E0l, wfn = driver.energy('scf',
                             dft_functional=name,
                             return_wfn=True,
                             molecule=molecule,
                             banner='IP Fitting SCF: Neutral, Left Endpoint',
                             **kwargs)
    eps_a = wfn.epsilon_a()
    eps_b = wfn.epsilon_b()
    if Nb == 0:
        E_HOMO = eps_a.np[int(Na - 1)]
    else:
        E_a = eps_a.np[int(Na - 1)]
        E_b = eps_b.np[int(Nb - 1)]
        E_HOMO = max(E_a, E_b)
    E_HOMOl = E_HOMO
    core.IO.change_file_namespace(180, "ot", "neutral")

    # Cation
    core.IO.change_file_namespace(180, "cation", "ot")
    molecule.set_molecular_charge(charge1)
    molecule.set_multiplicity(mult1)
    core.set_global_option("DOCC", [Nb1])
    core.set_global_option("SOCC", [Na1 - Nb1])
    E1l = driver.energy('scf',
                        dft_functional=name,
                        molecule=molecule,
                        banner='IP Fitting SCF: Cation, Left Endpoint',
                        **kwargs)
    core.IO.change_file_namespace(180, "ot", "cation")

    IPl = E1l - E0l
    kIPl = -E_HOMOl
    delta_l = IPl - kIPl

    if IPl < kIPl:
        raise ValidationError(
            """\n***IP Fitting Error: Left Omega limit should have kIP < IP: {} !< {}"""
            .format(kIPl, IPl))

    omegas.append(omega_l)
    types.append('Left Limit')
    E0s.append(E0l)
    E1s.append(E1l)
    IPs.append(IPl)
    kIPs.append(kIPl)

    converged = False
    repeat_l = 0
    repeat_r = 0
    for step in range(maxiter):

        # Regula Falsi (modified)
        if repeat_l > 1:
            delta_l /= 2.0
        if repeat_r > 1:
            delta_r /= 2.0
        omega = -(omega_r - omega_l) / (delta_r - delta_l) * delta_l + omega_l
        core.set_local_option('SCF', 'DFT_OMEGA', omega)

        # Neutral
        core.IO.change_file_namespace(180, "neutral", "ot")
        molecule.set_molecular_charge(charge0)
        molecule.set_multiplicity(mult0)
        core.set_global_option("DOCC", [Nb])
        core.set_global_option("SOCC", [Na - Nb])
        E0, wfn = driver.energy(
            'scf',
            dft_functional=name,
            return_wfn=True,
            molecule=molecule,
            banner='IP Fitting SCF: Neutral, Omega = {:11.3E}'.format(omega),
            **kwargs)
        eps_a = wfn.epsilon_a()
        eps_b = wfn.epsilon_b()
        if Nb == 0:
            E_HOMO = eps_a.np[int(Na - 1)]
        else:
            E_a = eps_a.np[int(Na - 1)]
            E_b = eps_b.np[int(Nb - 1)]
            E_HOMO = max(E_a, E_b)
        core.IO.change_file_namespace(180, "ot", "neutral")

        # Cation
        core.IO.change_file_namespace(180, "cation", "ot")
        molecule.set_molecular_charge(charge1)
        molecule.set_multiplicity(mult1)
        core.set_global_option("DOCC", [Nb1])
        core.set_global_option("SOCC", [Na1 - Nb1])
        E1 = driver.energy(
            'scf',
            dft_functional=name,
            molecule=molecule,
            banner='IP Fitting SCF: Cation, Omega = {:11.3E}'.format(omega),
            **kwargs)
        core.IO.change_file_namespace(180, "ot", "cation")

        IP = E1 - E0
        kIP = -E_HOMO
        delta = IP - kIP

        if kIP > IP:
            omega_r = omega
            E0r = E0
            E1r = E1
            IPr = IP
            kIPr = kIP
            delta_r = delta
            repeat_r = 0
            repeat_l += 1
        else:
            omega_l = omega
            E0l = E0
            E1l = E1
            IPl = IP
            kIPl = kIP
            delta_l = delta
            repeat_l = 0
            repeat_r += 1

        omegas.append(omega)
        types.append('Regula-Falsi')
        E0s.append(E0)
        E1s.append(E1)
        IPs.append(IP)
        kIPs.append(kIP)

        # Termination
        if abs(omega_l - omega_r) < omega_convergence:
            converged = True
            break

    core.IO.set_default_namespace("")
    core.print_out("""\n    ==> IP Fitting Results <==\n\n""")

    core.print_out("""     => Occupation Determination <= \n\n""")
    core.print_out("""              %6s %6s %6s %6s %6s %6s\n""" %
                   ('N', 'Na', 'Nb', 'Charge', 'Mult', 'H**O'))
    core.print_out("""     Neutral: %6d %6d %6d %6d %6d %6d\n""" %
                   (N, Na, Nb, charge0, mult0, H**O))
    core.print_out("""     Cation:  %6d %6d %6d %6d %6d\n\n""" %
                   (N - 1, Na1, Nb1, charge1, mult1))

    core.print_out("""     => Regula Falsi Iterations <=\n\n""")
    core.print_out("""    %3s %11s %14s %14s %14s %s\n""" %
                   ('N', 'Omega', 'IP', 'kIP', 'Delta', 'Type'))
    for k in range(len(omegas)):
        core.print_out(
            """    %3d %11.3E %14.6E %14.6E %14.6E %s\n""" %
            (k + 1, omegas[k], IPs[k], kIPs[k], IPs[k] - kIPs[k], types[k]))

    optstash.restore()
    if converged:
        core.print_out("""\n    IP Fitting Converged\n""")
        core.print_out("""    Final omega = %14.6E\n""" %
                       ((omega_l + omega_r) / 2))
        core.print_out(
            """\n    "M,I. does the dying. Fleet just does the flying."\n""")
        core.print_out("""            -Starship Troopers\n""")

    else:
        raise ConvergenceError("""IP Fitting """, step + 1)

    return ((omega_l + omega_r) / 2)
Exemplo n.º 4
0
Arquivo: frac.py Projeto: yxie326/psi4
def frac_traverse(name, **kwargs):
    """Scan electron occupancy from +1 electron to -1.

    Parameters
    ----------
    name : string or function
        DFT functional string name or function defining functional
        whose omega is to be optimized.
    molecule : :ref:`molecule <op_py_molecule>`, optional
        Target molecule (neutral) for which omega is to be tuned, if not last defined.
    cation_mult : int, optional
        Multiplicity of cation, if not neutral multiplicity + 1.
    anion_mult : int, optional
        Multiplicity of anion, if not neutral multiplicity + 1.
    frac_start : int, optional
        Iteration at which to start frac procedure when not reading previous
        guess. Defaults to 25.
    HOMO_occs : list, optional
        Occupations to step through for cation, by default `[1 - 0.1 * x for x in range(11)]`.
    LUMO_occs : list, optional
        Occupations to step through for anion, by default `[1 - 0.1 * x for x in range(11)]`.
    H**O : int, optional
        Index of H**O.
    LUMO : int, optional
        Index of LUMO.
    frac_diis : bool, optional
        Do use DIIS for non-1.0-occupied points?
    neutral_guess : bool, optional
        Do use neutral orbitals as guess for the anion?
    hf_guess: bool, optional
        Do use UHF guess before UKS?
    continuous_guess : bool, optional
        Do carry along guess rather than reguessing at each occupation?
    filename : str, optional
        Result filename, if not name of molecule.

    Returns
    -------
    dict
        Dictionary associating SCF energies with occupations.

    """
    optstash = p4util.OptionsState(
        ['SCF', 'GUESS'],
        ['SCF', 'DF_INTS_IO'],
        ['SCF', 'REFERENCE'],
        ["SCF", "FRAC_START"],
        ["SCF", "FRAC_RENORMALIZE"],
        #["SCF", "FRAC_LOAD"],
        ["SCF", "FRAC_OCC"],
        ["SCF", "FRAC_VAL"],
        ["SCF", "FRAC_DIIS"])
    kwargs = p4util.kwargs_lower(kwargs)

    # Make sure the molecule the user provided is the active one, and neutral
    molecule = kwargs.pop('molecule', core.get_active_molecule())
    molecule.update_geometry()

    if molecule.molecular_charge() != 0:
        raise ValidationError(
            """frac_traverse requires neutral molecule to start.""")
    if molecule.schoenflies_symbol() != 'c1':
        core.print_out(
            """  Requested procedure `frac_traverse` does not make use of molecular symmetry: """
            """further calculations in C1 point group.\n""")
    molecule = molecule.clone()
    molecule.reset_point_group('c1')
    molecule.update_geometry()

    charge0 = molecule.molecular_charge()
    mult0 = molecule.multiplicity()

    chargep = charge0 + 1
    chargem = charge0 - 1

    multp = kwargs.get('cation_mult', mult0 + 1)
    multm = kwargs.get('anion_mult', mult0 + 1)

    # By default, we start the frac procedure on the 25th iteration
    # when not reading a previous guess
    frac_start = kwargs.get('frac_start', 25)

    # By default, we occupy by tenths of electrons
    HOMO_occs = kwargs.get(
        'HOMO_occs', [1.0, 0.9, 0.8, 0.7, 0.6, 0.5, 0.4, 0.3, 0.2, 0.1, 0.0])
    LUMO_occs = kwargs.get(
        'LUMO_occs', [1.0, 0.9, 0.8, 0.7, 0.6, 0.5, 0.4, 0.3, 0.2, 0.1, 0.0])

    # By default, H**O and LUMO are both in alpha
    Z = 0
    for A in range(molecule.natom()):
        Z += molecule.Z(A)
    Z -= charge0
    H**O = kwargs.get('H**O', (Z / 2 + 1 if (Z % 2) else Z / 2))
    LUMO = kwargs.get('LUMO', H**O + 1)

    # By default, DIIS in FRAC (1.0 occupation is always DIIS'd)
    frac_diis = kwargs.get('frac_diis', True)

    # By default, use the neutral orbitals as a guess for the anion
    neutral_guess = kwargs.get('neutral_guess', True)

    # By default, burn-in with UHF first, if UKS
    hf_guess = False
    if core.get_local_option('SCF', 'REFERENCE') == 'UKS':
        hf_guess = kwargs.get('hf_guess', True)

    # By default, re-guess at each N
    continuous_guess = kwargs.get('continuous_guess', False)

    # By default, drop the files to the molecule's name
    root = kwargs.get('filename', molecule.name())
    traverse_filename = root + '.traverse.dat'
    # => Traverse <= #
    occs = []
    energies = []
    potentials = []
    convs = []

    # => Run the neutral for its orbitals, if requested <= #

    core.set_local_option("SCF", "DF_INTS_IO", "SAVE")

    old_guess = core.get_local_option("SCF", "GUESS")
    if (neutral_guess):
        if (hf_guess):
            core.set_local_option("SCF", "REFERENCE", "UHF")
        driver.energy('scf', dft_functional=name, molecule=molecule, **kwargs)
        core.set_local_option("SCF", "GUESS", "READ")
        core.set_local_option("SCF", "DF_INTS_IO", "LOAD")

    # => Run the anion first <= #

    molecule.set_molecular_charge(chargem)
    molecule.set_multiplicity(multm)

    # => Burn the anion in with hf, if requested <= #
    if hf_guess:
        core.set_local_option("SCF", "REFERENCE", "UHF")
        driver.energy('scf', dft_functional=name, molecule=molecule, **kwargs)
        core.set_local_option("SCF", "REFERENCE", "UKS")
        core.set_local_option("SCF", "GUESS", "READ")
        core.set_local_option("SCF", "DF_INTS_IO", "SAVE")

    core.set_local_option("SCF", "FRAC_START", frac_start)
    core.set_local_option("SCF", "FRAC_RENORMALIZE", True)
    # NYI core.set_local_option("SCF", "FRAC_LOAD", False)

    for occ in LUMO_occs:

        core.set_local_option("SCF", "FRAC_OCC", [LUMO])
        core.set_local_option("SCF", "FRAC_VAL", [occ])

        E, wfn = driver.energy('scf',
                               dft_functional=name,
                               return_wfn=True,
                               molecule=molecule,
                               **kwargs)
        C = 1
        if E == 0.0:
            E = core.variable('SCF ITERATION ENERGY')
            C = 0

        if LUMO > 0:
            eps = wfn.epsilon_a()
            potentials.append(eps.get(int(LUMO) - 1))
        else:
            eps = wfn.epsilon_b()
            potentials.append(eps.get(-int(LUMO) - 1))

        occs.append(occ)
        energies.append(E)
        convs.append(C)

        core.set_local_option("SCF", "FRAC_START", 2)
        #core.set_local_option("SCF", "FRAC_LOAD", True)
        core.set_local_option("SCF", "GUESS", "READ")
        core.set_local_option("SCF", "FRAC_DIIS", frac_diis)
        core.set_local_option("SCF", "DF_INTS_IO", "LOAD")

    # => Run the neutral next <= #

    molecule.set_molecular_charge(charge0)
    molecule.set_multiplicity(mult0)

    # Burn the neutral in with hf, if requested <= #

    if not continuous_guess:
        core.set_local_option("SCF", "GUESS", old_guess)
        if hf_guess:
            core.set_local_option("SCF", "FRAC_START", 0)
            core.set_local_option("SCF", "REFERENCE", "UHF")
            driver.energy('scf',
                          dft_functional=name,
                          molecule=molecule,
                          **kwargs)
            core.set_local_option("SCF", "REFERENCE", "UKS")
            core.set_local_option("SCF", "GUESS", "READ")
        # NYI core.set_local_option("SCF", "FRAC_LOAD", False)

    core.set_local_option("SCF", "FRAC_START", frac_start)
    core.set_local_option("SCF", "FRAC_RENORMALIZE", True)

    for occ in HOMO_occs:

        core.set_local_option("SCF", "FRAC_OCC", [H**O])
        core.set_local_option("SCF", "FRAC_VAL", [occ])

        E, wfn = driver.energy('scf',
                               dft_functional=name,
                               return_wfn=True,
                               molecule=molecule,
                               **kwargs)
        C = 1
        if E == 0.0:
            E = core.variable('SCF ITERATION ENERGY')
            C = 0

        if LUMO > 0:
            eps = wfn.epsilon_a()
            potentials.append(eps.get(int(H**O) - 1))
        else:
            eps = wfn.epsilon_b()
            potentials.append(eps.get(-int(H**O) - 1))

        occs.append(occ - 1.0)
        energies.append(E)
        convs.append(C)

        core.set_local_option("SCF", "FRAC_START", 2)
        # NYI core.set_local_option("SCF", "FRAC_LOAD", True)
        core.set_local_option("SCF", "GUESS", "READ")
        core.set_local_option("SCF", "FRAC_DIIS", frac_diis)
        core.set_local_option("SCF", "DF_INTS_IO", "LOAD")

    # => Print the results out <= #
    E = {}
    core.print_out(
        """\n    ==> Fractional Occupation Traverse Results <==\n\n""")
    core.print_out("""    %-11s %-24s %-24s %11s\n""" %
                   ('N', 'Energy', 'H**O Energy', 'Converged'))
    for k in range(len(occs)):
        core.print_out("""    %11.3E %24.16E %24.16E %11d\n""" %
                       (occs[k], energies[k], potentials[k], convs[k]))
        E[occs[k]] = energies[k]

    core.print_out("""
    You trying to be a hero Watkins?
    Just trying to kill some bugs sir!
            -Starship Troopers""")

    # Drop the files out
    with open(traverse_filename, 'w') as fh:
        fh.write("""    %-11s %-24s %-24s %11s\n""" %
                 ('N', 'Energy', 'H**O Energy', 'Converged'))
        for k in range(len(occs)):
            fh.write("""    %11.3E %24.16E %24.16E %11d\n""" %
                     (occs[k], energies[k], potentials[k], convs[k]))

    optstash.restore()
    return E
Exemplo n.º 5
0
Arquivo: frac.py Projeto: yxie326/psi4
def frac_nuke(name, **kwargs):
    """Pull all the electrons out, one at a time"""
    optstash = p4util.OptionsState(
        ['SCF', 'GUESS'],
        ['SCF', 'DF_INTS_IO'],
        ["SCF", "FRAC_START"],
        ["SCF", "FRAC_RENORMALIZE"],
        # NYI ["SCF", "FRAC_LOAD"],
        ["SCF", "FRAC_OCC"],
        ["SCF", "FRAC_VAL"],
        ["SCF", "FRAC_DIIS"])

    kwargs = p4util.kwargs_lower(kwargs)

    # Make sure the molecule the user provided is the active one, and neutral
    molecule = kwargs.pop('molecule', core.get_active_molecule())
    molecule.update_geometry()

    if molecule.molecular_charge() != 0:
        raise ValidationError(
            """frac_nuke requires neutral molecule to start.""")
    if molecule.schoenflies_symbol() != 'c1':
        core.print_out(
            """  Requested procedure `frac_nuke` does not make use of molecular symmetry: """
            """further calculations in C1 point group.\n""")
    molecule = molecule.clone()
    molecule.reset_point_group('c1')
    molecule.update_geometry()

    charge0 = molecule.molecular_charge()
    mult0 = molecule.multiplicity()

    # By default, we start the frac procedure on the 25th iteration
    # when not reading a previous guess
    frac_start = kwargs.get('frac_start', 25)

    # By default, we occupy by tenths of electrons
    foccs = kwargs.get('foccs',
                       [1.0, 0.9, 0.8, 0.7, 0.6, 0.5, 0.4, 0.3, 0.2, 0.1, 0.0])

    # By default, H**O and LUMO are both in alpha
    N = 0
    for A in range(molecule.natom()):
        N += molecule.Z(A)
    N -= charge0
    N = int(N)
    Nb = int((N - mult0 + 1) / 2)
    Na = int(N - Nb)

    charge = charge0
    mult = mult0

    # By default, nuke all the electrons
    Nmin = 0
    if 'nmax' in kwargs:
        Nmin = N - int(kwargs['nmax'])

    # By default, DIIS in FRAC (1.0 occupation is always DIIS'd)
    frac_diis = kwargs.get('frac_diis', True)

    # By default, drop the files to the molecule's name
    root = kwargs.get('filename', molecule.name())
    traverse_filename = root + '.traverse.dat'
    stats_filename = root + '.stats.dat'

    # => Traverse <= #
    core.set_local_option("SCF", "DF_INTS_IO", "SAVE")

    Ns = []
    energies = []
    potentials = []
    convs = []
    stats = []

    # Run one SCF to burn things in
    E, wfn = driver.energy('scf',
                           dft_functional=name,
                           return_wfn=True,
                           molecule=molecule,
                           **kwargs)

    # Determine H**O
    eps_a = wfn.epsilon_a()
    eps_b = wfn.epsilon_b()
    eps_a.print_out()
    if Na == Nb:
        H**O = -Nb
    elif Nb == 0:
        H**O = Na
    else:
        E_a = eps_a.get(int(Na - 1))
        E_b = eps_b.get(int(Nb - 1))
        if E_a >= E_b:
            H**O = Na
        else:
            H**O = -Nb

    stats.append("""    %6d %6d %6d %6d %6d %6d\n""" %
                 (N, Na, Nb, charge, mult, H**O))

    if H**O > 0:
        Na -= 1
    else:
        Nb -= 1
    charge += 1
    mult = Na - Nb + 1

    core.set_local_option("SCF", "DF_INTS_IO", "LOAD")
    core.set_local_option("SCF", "FRAC_START", frac_start)
    core.set_local_option("SCF", "FRAC_RENORMALIZE", True)

    # Nuke 'em Rico!
    for Nintegral in range(N, Nmin, -1):

        # Nuke the current H**O
        for occ in foccs:

            core.set_local_option("SCF", "FRAC_OCC", [H**O])
            core.set_local_option("SCF", "FRAC_VAL", [occ])

            E, wfn = driver.energy('scf',
                                   dft_functional=name,
                                   return_wfn=True,
                                   molecule=molecule,
                                   **kwargs)
            C = 1
            if E == 0.0:
                E = core.variable('SCF ITERATION ENERGY')
                C = 0

            if H**O > 0:
                eps = wfn.epsilon_a()
                potentials.append(eps.np[H**O - 1])
            else:
                eps = wfn.epsilon_b()
                potentials.append(eps.np[-H**O - 1])

            Ns.append(Nintegral + occ - 1.0)
            energies.append(E)
            convs.append(C)

            core.set_local_option("SCF", "FRAC_START", 2)
            # NYI core.set_local_option("SCF", "FRAC_LOAD", True)
            core.set_local_option("SCF", "FRAC_DIIS", frac_diis)
            core.set_local_option("SCF", "GUESS", "READ")

        # Set the next charge/mult
        molecule.set_molecular_charge(charge)
        molecule.set_multiplicity(mult)

        # Determine H**O
        print('DGAS: What ref should this point to?')
        #ref = core.legacy_wavefunction()
        eps_a = wfn.epsilon_a()
        eps_b = wfn.epsilon_b()
        if Na == Nb:
            H**O = -Nb
        elif Nb == 0:
            H**O = Na
        else:
            E_a = eps_a.np[int(Na - 1)]
            E_b = eps_b.np[int(Nb - 1)]
            if E_a >= E_b:
                H**O = Na
            else:
                H**O = -Nb

        stats.append("""    %6d %6d %6d %6d %6d %6d\n""" %
                     (Nintegral - 1, Na, Nb, charge, mult, H**O))

        if H**O > 0:
            Na -= 1
        else:
            Nb -= 1
        charge += 1
        mult = Na - Nb + 1

    core.set_local_option("SCF", "DF_INTS_IO", "NONE")

    # => Print the results out <= #
    E = {}
    core.print_out("""\n    ==> Fractional Occupation Nuke Results <==\n\n""")
    core.print_out("""    %-11s %-24s %-24s %11s\n""" %
                   ('N', 'Energy', 'H**O Energy', 'Converged'))
    for k in range(len(Ns)):
        core.print_out("""    %11.3E %24.16E %24.16E %11d\n""" %
                       (Ns[k], energies[k], potentials[k], convs[k]))
        E[Ns[k]] = energies[k]

    core.print_out('\n')
    core.print_out("""    %6s %6s %6s %6s %6s %6s\n""" %
                   ('N', 'Na', 'Nb', 'Charge', 'Mult', 'H**O'))
    for line in stats:
        core.print_out(line)

    core.print_out(
        '\n    "You shoot a nuke down a bug hole, you got a lot of dead bugs"\n'
    )
    core.print_out('            -Starship Troopers\n')

    # Drop the files out
    with open(traverse_filename, 'w') as fh:
        fh.write("""    %-11s %-24s %-24s %11s\n""" %
                 ('N', 'Energy', 'H**O Energy', 'Converged'))
        for k in range(len(Ns)):
            fh.write("""    %11.3E %24.16E %24.16E %11d\n""" %
                     (Ns[k], energies[k], potentials[k], convs[k]))

    with open(stats_filename, 'w') as fh:
        fh.write("""    %6s %6s %6s %6s %6s %6s\n""" %
                 ('N', 'Na', 'Nb', 'Charge', 'Mult', 'H**O'))
        for line in stats:
            fh.write(line)

    optstash.restore()
    return E
Exemplo n.º 6
0
def run_gaussian_2(name, **kwargs):

    # throw an exception for open-shells
    if (core.get_option('SCF','REFERENCE') != 'RHF' ):
        raise ValidationError("""g2 computations require "reference rhf".""")

    # stash user options:
    optstash = p4util.OptionsState(
        ['FNOCC','COMPUTE_TRIPLES'],
        ['FNOCC','COMPUTE_MP4_TRIPLES'],
        ['FREEZE_CORE'],
        ['MP2_TYPE'],
        ['SCF','SCF_TYPE'])

    # override default scf_type
    core.set_local_option('SCF','SCF_TYPE','PK')

    # optimize geometry at scf level
    core.clean()
    core.set_global_option('BASIS',"6-31G(D)")
    driver.optimize('scf')
    core.clean()

    # scf frequencies for zpe
    # NOTE This line should not be needed, but without it there's a seg fault
    scf_e, ref = driver.frequency('scf', return_wfn=True)

    # thermodynamic properties
    du = core.get_variable('INTERNAL ENERGY CORRECTION')
    dh = core.get_variable('ENTHALPY CORRECTION')
    dg = core.get_variable('GIBBS FREE ENERGY CORRECTION')

    freqs   = ref.frequencies()
    nfreq   = freqs.dim(0)
    freqsum = 0.0
    for i in range(0, nfreq):
        freqsum += freqs.get(i)
    zpe = freqsum / p4const.psi_hartree2wavenumbers * 0.8929 * 0.5
    core.clean()

    # optimize geometry at mp2 (no frozen core) level
    # note: freeze_core isn't an option in MP2
    core.set_global_option('FREEZE_CORE',"FALSE")
    core.set_global_option('MP2_TYPE', 'CONV')
    driver.optimize('mp2')
    core.clean()

    # qcisd(t)
    core.set_local_option('FNOCC','COMPUTE_MP4_TRIPLES',"TRUE")
    core.set_global_option('FREEZE_CORE',"TRUE")
    core.set_global_option('BASIS',"6-311G(D_P)")
    ref = driver.proc.run_fnocc('qcisd(t)', return_wfn=True, **kwargs)

    # HLC: high-level correction based on number of valence electrons
    nirrep = ref.nirrep()
    frzcpi = ref.frzcpi()
    nfzc = 0
    for i in range (0,nirrep):
        nfzc += frzcpi[i]
    nalpha = ref.nalpha() - nfzc
    nbeta  = ref.nbeta() - nfzc
    # hlc of gaussian-2
    hlc = -0.00481 * nalpha -0.00019 * nbeta
    # hlc of gaussian-1
    hlc1 = -0.00614 * nalpha

    eqci_6311gdp = core.get_variable("QCISD(T) TOTAL ENERGY")
    emp4_6311gd  = core.get_variable("MP4 TOTAL ENERGY")
    emp2_6311gd  = core.get_variable("MP2 TOTAL ENERGY")
    core.clean()

    # correction for diffuse functions
    core.set_global_option('BASIS',"6-311+G(D_P)")
    driver.energy('mp4')
    emp4_6311pg_dp = core.get_variable("MP4 TOTAL ENERGY")
    emp2_6311pg_dp = core.get_variable("MP2 TOTAL ENERGY")
    core.clean()

    # correction for polarization functions
    core.set_global_option('BASIS',"6-311G(2DF_P)")
    driver.energy('mp4')
    emp4_6311g2dfp = core.get_variable("MP4 TOTAL ENERGY")
    emp2_6311g2dfp = core.get_variable("MP2 TOTAL ENERGY")
    core.clean()

    # big basis mp2
    core.set_global_option('BASIS',"6-311+G(3DF_2P)")
    #run_fnocc('_mp2',**kwargs)
    driver.energy('mp2')
    emp2_big = core.get_variable("MP2 TOTAL ENERGY")
    core.clean()
    eqci       = eqci_6311gdp
    e_delta_g2 = emp2_big + emp2_6311gd - emp2_6311g2dfp - emp2_6311pg_dp
    e_plus     = emp4_6311pg_dp - emp4_6311gd
    e_2df      = emp4_6311g2dfp - emp4_6311gd

    eg2 = eqci + e_delta_g2 + e_plus + e_2df
    eg2_mp2_0k = eqci + (emp2_big - emp2_6311gd) + hlc + zpe

    core.print_out('\n')
    core.print_out('  ==>  G1/G2 Energy Components  <==\n')
    core.print_out('\n')
    core.print_out('        QCISD(T):            %20.12lf\n' % eqci)
    core.print_out('        E(Delta):            %20.12lf\n' % e_delta_g2)
    core.print_out('        E(2DF):              %20.12lf\n' % e_2df)
    core.print_out('        E(+):                %20.12lf\n' % e_plus)
    core.print_out('        E(G1 HLC):           %20.12lf\n' % hlc1)
    core.print_out('        E(G2 HLC):           %20.12lf\n' % hlc)
    core.print_out('        E(ZPE):              %20.12lf\n' % zpe)
    core.print_out('\n')
    core.print_out('  ==>  0 Kelvin Results  <==\n')
    core.print_out('\n')
    eg2_0k = eg2 + zpe + hlc
    core.print_out('        G1:                  %20.12lf\n' % (eqci + e_plus + e_2df + hlc1 + zpe))
    core.print_out('        G2(MP2):             %20.12lf\n' % eg2_mp2_0k)
    core.print_out('        G2:                  %20.12lf\n' % eg2_0k)

    core.set_variable("G1 TOTAL ENERGY",eqci + e_plus + e_2df + hlc1 + zpe)
    core.set_variable("G2 TOTAL ENERGY",eg2_0k)
    core.set_variable("G2(MP2) TOTAL ENERGY",eg2_mp2_0k)

    core.print_out('\n')
    T = core.get_global_option('T')
    core.print_out('  ==>  %3.0lf Kelvin Results  <==\n'% T)
    core.print_out('\n')

    internal_energy = eg2_mp2_0k + du - zpe / 0.8929
    enthalpy        = eg2_mp2_0k + dh - zpe / 0.8929
    gibbs           = eg2_mp2_0k + dg - zpe / 0.8929

    core.print_out('        G2(MP2) energy:      %20.12lf\n' % internal_energy )
    core.print_out('        G2(MP2) enthalpy:    %20.12lf\n' % enthalpy)
    core.print_out('        G2(MP2) free energy: %20.12lf\n' % gibbs)
    core.print_out('\n')

    core.set_variable("G2(MP2) INTERNAL ENERGY",internal_energy)
    core.set_variable("G2(MP2) ENTHALPY",enthalpy)
    core.set_variable("G2(MP2) FREE ENERGY",gibbs)

    internal_energy = eg2_0k + du - zpe / 0.8929
    enthalpy        = eg2_0k + dh - zpe / 0.8929
    gibbs           = eg2_0k + dg - zpe / 0.8929

    core.print_out('        G2 energy:           %20.12lf\n' % internal_energy )
    core.print_out('        G2 enthalpy:         %20.12lf\n' % enthalpy)
    core.print_out('        G2 free energy:      %20.12lf\n' % gibbs)

    core.set_variable("CURRENT ENERGY",eg2_0k)

    core.set_variable("G2 INTERNAL ENERGY",internal_energy)
    core.set_variable("G2 ENTHALPY",enthalpy)
    core.set_variable("G2 FREE ENERGY",gibbs)

    core.clean()

    optstash.restore()

    # return 0K g2 results
    return eg2_0k
Exemplo n.º 7
0
def run_gaussian_2(name, **kwargs):

    # throw an exception for open-shells
    if (core.get_option('SCF', 'REFERENCE') != 'RHF'):
        raise ValidationError("""g2 computations require "reference rhf".""")

    # stash user options:
    optstash = p4util.OptionsState(['FNOCC', 'COMPUTE_TRIPLES'],
                                   ['FNOCC', 'COMPUTE_MP4_TRIPLES'], ['BASIS'],
                                   ['FREEZE_CORE'], ['MP2_TYPE'], ['SCF_TYPE'])

    # override default scf_type
    core.set_global_option('SCF_TYPE', 'PK')

    # optimize geometry at scf level
    core.clean()
    core.set_global_option('BASIS', "6-31G(D)")
    driver.optimize('scf')
    core.clean()

    # scf frequencies for zpe
    # NOTE This line should not be needed, but without it there's a seg fault
    scf_e, ref = driver.frequency('scf', return_wfn=True)

    # thermodynamic properties
    du = core.variable('THERMAL ENERGY CORRECTION')
    dh = core.variable('ENTHALPY CORRECTION')
    dg = core.variable('GIBBS FREE ENERGY CORRECTION')

    freqs = ref.frequencies()
    nfreq = freqs.dim(0)
    freqsum = 0.0
    for i in range(0, nfreq):
        freqsum += freqs.get(i)
    zpe = freqsum / constants.hartree2wavenumbers * 0.8929 * 0.5
    core.clean()

    # optimize geometry at mp2 (no frozen core) level
    # note: freeze_core isn't an option in MP2
    core.set_global_option('FREEZE_CORE', "FALSE")
    core.set_global_option('MP2_TYPE', 'CONV')
    driver.optimize('mp2')
    core.clean()

    # qcisd(t)
    core.set_local_option('FNOCC', 'COMPUTE_MP4_TRIPLES', "TRUE")
    core.set_global_option('FREEZE_CORE', "TRUE")
    core.set_global_option('BASIS', "6-311G(D_P)")
    ref = driver.proc.run_fnocc('qcisd(t)', return_wfn=True, **kwargs)

    # HLC: high-level correction based on number of valence electrons
    nirrep = ref.nirrep()
    frzcpi = ref.frzcpi()
    nfzc = 0
    for i in range(0, nirrep):
        nfzc += frzcpi[i]
    nalpha = ref.nalpha() - nfzc
    nbeta = ref.nbeta() - nfzc
    # hlc of gaussian-2
    hlc = -0.00481 * nalpha - 0.00019 * nbeta
    # hlc of gaussian-1
    hlc1 = -0.00614 * nalpha

    eqci_6311gdp = core.variable("QCISD(T) TOTAL ENERGY")
    emp4_6311gd = core.variable("MP4 TOTAL ENERGY")
    emp2_6311gd = core.variable("MP2 TOTAL ENERGY")
    core.clean()

    # correction for diffuse functions
    core.set_global_option('BASIS', "6-311+G(D_P)")
    driver.energy('mp4')
    emp4_6311pg_dp = core.variable("MP4 TOTAL ENERGY")
    emp2_6311pg_dp = core.variable("MP2 TOTAL ENERGY")
    core.clean()

    # correction for polarization functions
    core.set_global_option('BASIS', "6-311G(2DF_P)")
    driver.energy('mp4')
    emp4_6311g2dfp = core.variable("MP4 TOTAL ENERGY")
    emp2_6311g2dfp = core.variable("MP2 TOTAL ENERGY")
    core.clean()

    # big basis mp2
    core.set_global_option('BASIS', "6-311+G(3DF_2P)")
    #run_fnocc('_mp2',**kwargs)
    driver.energy('mp2')
    emp2_big = core.variable("MP2 TOTAL ENERGY")
    core.clean()
    eqci = eqci_6311gdp
    e_delta_g2 = emp2_big + emp2_6311gd - emp2_6311g2dfp - emp2_6311pg_dp
    e_plus = emp4_6311pg_dp - emp4_6311gd
    e_2df = emp4_6311g2dfp - emp4_6311gd

    eg2 = eqci + e_delta_g2 + e_plus + e_2df
    eg2_mp2_0k = eqci + (emp2_big - emp2_6311gd) + hlc + zpe

    core.print_out('\n')
    core.print_out('  ==>  G1/G2 Energy Components  <==\n')
    core.print_out('\n')
    core.print_out('        QCISD(T):            %20.12lf\n' % eqci)
    core.print_out('        E(Delta):            %20.12lf\n' % e_delta_g2)
    core.print_out('        E(2DF):              %20.12lf\n' % e_2df)
    core.print_out('        E(+):                %20.12lf\n' % e_plus)
    core.print_out('        E(G1 HLC):           %20.12lf\n' % hlc1)
    core.print_out('        E(G2 HLC):           %20.12lf\n' % hlc)
    core.print_out('        E(ZPE):              %20.12lf\n' % zpe)
    core.print_out('\n')
    core.print_out('  ==>  0 Kelvin Results  <==\n')
    core.print_out('\n')
    eg2_0k = eg2 + zpe + hlc
    core.print_out('        G1:                  %20.12lf\n' %
                   (eqci + e_plus + e_2df + hlc1 + zpe))
    core.print_out('        G2(MP2):             %20.12lf\n' % eg2_mp2_0k)
    core.print_out('        G2:                  %20.12lf\n' % eg2_0k)

    core.set_variable("G1 TOTAL ENERGY", eqci + e_plus + e_2df + hlc1 + zpe)
    core.set_variable("G2 TOTAL ENERGY", eg2_0k)
    core.set_variable("G2(MP2) TOTAL ENERGY", eg2_mp2_0k)

    core.print_out('\n')
    T = core.get_global_option('T')
    core.print_out('  ==>  %3.0lf Kelvin Results  <==\n' % T)
    core.print_out('\n')

    internal_energy = eg2_mp2_0k + du - zpe / 0.8929
    enthalpy = eg2_mp2_0k + dh - zpe / 0.8929
    gibbs = eg2_mp2_0k + dg - zpe / 0.8929

    core.print_out('        G2(MP2) energy:      %20.12lf\n' % internal_energy)
    core.print_out('        G2(MP2) enthalpy:    %20.12lf\n' % enthalpy)
    core.print_out('        G2(MP2) free energy: %20.12lf\n' % gibbs)
    core.print_out('\n')

    core.set_variable("G2(MP2) INTERNAL ENERGY", internal_energy)
    core.set_variable("G2(MP2) ENTHALPY", enthalpy)
    core.set_variable("G2(MP2) FREE ENERGY", gibbs)

    internal_energy = eg2_0k + du - zpe / 0.8929
    enthalpy = eg2_0k + dh - zpe / 0.8929
    gibbs = eg2_0k + dg - zpe / 0.8929

    core.print_out('        G2 energy:           %20.12lf\n' % internal_energy)
    core.print_out('        G2 enthalpy:         %20.12lf\n' % enthalpy)
    core.print_out('        G2 free energy:      %20.12lf\n' % gibbs)

    core.set_variable("CURRENT ENERGY", eg2_0k)

    core.set_variable("G2 INTERNAL ENERGY", internal_energy)
    core.set_variable("G2 ENTHALPY", enthalpy)
    core.set_variable("G2 FREE ENERGY", gibbs)

    core.clean()

    optstash.restore()

    # return 0K g2 results
    return eg2_0k
Exemplo n.º 8
0
def ip_fitting(name, omega_l=0.05, omega_r=2.5, omega_convergence=1.0e-3, maxiter=20, **kwargs):
    """Optimize DFT omega parameter for molecular system.

    Parameters
    ----------
    name : string or function
        DFT functional string name or function defining functional
        whose omega is to be optimized.
    omega_l : float, optional
        Minimum omega to be considered during fitting.
    omega_r : float, optional
        Maximum omega to be considered during fitting.
    molecule : :ref:`molecule <op_py_molecule>`, optional
        Target molecule (neutral) for which omega is to be tuned, if not last defined.
    omega_convergence : float, optional
        Threshold below which to consider omega converged. (formerly omega_tolerance)
    maxiter : int, optional
        Maximum number of iterations towards omega convergence.

    Returns
    -------
    float
        Optimal omega parameter.

    """
    optstash = p4util.OptionsState(
        ['SCF', 'REFERENCE'],
        ['SCF', 'GUESS'],
        ['SCF', 'DF_INTS_IO'],
        ['SCF', 'DFT_OMEGA'],
        ['DOCC'],
        ['SOCC'])

    kwargs = p4util.kwargs_lower(kwargs)

    # By default, do not read previous 180 orbitals file
    read = False
    read180 = ''
    if 'read' in kwargs:
        read = True
        read180 = kwargs['read']

    if core.get_option('SCF', 'REFERENCE') != 'UKS':
        core.print_out("""  Requested procedure `ip_fitting` runs further calculations with UKS reference.\n""")
        core.set_local_option('SCF', 'REFERENCE', 'UKS')

    # Make sure the molecule the user provided is the active one, and neutral
    molecule = kwargs.pop('molecule', core.get_active_molecule())
    molecule.update_geometry()

    if molecule.molecular_charge() != 0:
        raise ValidationError("""IP Fitting requires neutral molecule to start.""")
    if molecule.schoenflies_symbol() != 'c1':
        core.print_out("""  Requested procedure `ip_fitting` does not make use of molecular symmetry: """
                       """further calculations in C1 point group.\n""")
    molecule = molecule.clone()
    molecule.reset_point_group('c1')
    molecule.update_geometry()

    charge0 = molecule.molecular_charge()
    mult0 = molecule.multiplicity()

    # How many electrons are there?
    N = 0
    for A in range(molecule.natom()):
        N += molecule.Z(A)
    N -= charge0
    N = int(N)
    Nb = int((N - mult0 + 1) / 2)
    Na = int(N - Nb)

    # Work in the ot namespace for this procedure
    core.IO.set_default_namespace("ot")

    # Burn in to determine orbital eigenvalues
    if read:
        core.set_local_option("SCF", "GUESS", "READ")
        copy_file_to_scratch(read180, 'psi', 'ot', 180)
    core.set_local_option("SCF", "DF_INTS_IO", "SAVE")
    E, wfn = driver.energy('scf', dft_functional=name, return_wfn=True, molecule=molecule,
                           banner='IP Fitting SCF: Burn-in', **kwargs)
    core.set_local_option("SCF", "DF_INTS_IO", "LOAD")

    if not wfn.functional().is_x_lrc():
        raise ValidationError("""Not sensible to optimize omega for non-long-range-correction functional.""")

    # Determine H**O, to determine mult1
    eps_a = wfn.epsilon_a()
    eps_b = wfn.epsilon_b()
    if Na == Nb:
        H**O = -Nb
    elif Nb == 0:
        H**O = Na
    else:
        E_a = eps_a.np[int(Na - 1)]
        E_b = eps_b.np[int(Nb - 1)]
        if E_a >= E_b:
            H**O = Na
        else:
            H**O = -Nb

    Na1 = Na
    Nb1 = Nb
    if H**O > 0:
        Na1 -= 1
    else:
        Nb1 -= 1

    charge1 = charge0 + 1
    mult1 = Na1 - Nb1 + 1

    omegas = []
    E0s = []
    E1s = []
    kIPs = []
    IPs = []
    types = []

    # Right endpoint
    core.set_local_option('SCF', 'DFT_OMEGA', omega_r)

    # Neutral
    if read:
        core.set_local_option("SCF", "GUESS", "READ")
        p4util.copy_file_to_scratch(read180, 'psi', 'ot', 180)

    molecule.set_molecular_charge(charge0)
    molecule.set_multiplicity(mult0)
    E0r, wfn = driver.energy('scf', dft_functional=name, return_wfn=True, molecule=molecule,
                             banner='IP Fitting SCF: Neutral, Right Endpoint', **kwargs)
    eps_a = wfn.epsilon_a()
    eps_b = wfn.epsilon_b()
    if Nb == 0:
        E_HOMO = eps_a.np[int(Na - 1)]
    else:
        E_a = eps_a.np[int(Na - 1)]
        E_b = eps_b.np[int(Nb - 1)]
        E_HOMO = max(E_a, E_b)
    E_HOMOr = E_HOMO
    core.IO.change_file_namespace(180, "ot", "neutral")

    # Cation
    if read:
        core.set_local_option("SCF", "GUESS", "READ")
        p4util.copy_file_to_scratch(read180, 'psi', 'ot', 180)

    molecule.set_molecular_charge(charge1)
    molecule.set_multiplicity(mult1)
    E1r = driver.energy('scf', dft_functional=name, molecule=molecule,
                               banner='IP Fitting SCF: Cation, Right Endpoint', **kwargs)
    core.IO.change_file_namespace(180, "ot", "cation")

    IPr = E1r - E0r
    kIPr = -E_HOMOr
    delta_r = IPr - kIPr

    if IPr > kIPr:
        raise ValidationError("""\n***IP Fitting Error: Right Omega limit should have kIP > IP: {} !> {}""".format(kIPr, IPr))

    omegas.append(omega_r)
    types.append('Right Limit')
    E0s.append(E0r)
    E1s.append(E1r)
    IPs.append(IPr)
    kIPs.append(kIPr)

    # Use previous orbitals from here out
    core.set_local_option("SCF", "GUESS", "READ")

    # Left endpoint
    core.set_local_option('SCF', 'DFT_OMEGA', omega_l)

    # Neutral
    core.IO.change_file_namespace(180, "neutral", "ot")
    molecule.set_molecular_charge(charge0)
    molecule.set_multiplicity(mult0)
    core.set_global_option("DOCC", [Nb])
    core.set_global_option("SOCC", [Na - Nb])
    E0l, wfn = driver.energy('scf', dft_functional=name, return_wfn=True, molecule=molecule,
                             banner='IP Fitting SCF: Neutral, Left Endpoint', **kwargs)
    eps_a = wfn.epsilon_a()
    eps_b = wfn.epsilon_b()
    if Nb == 0:
        E_HOMO = eps_a.np[int(Na - 1)]
    else:
        E_a = eps_a.np[int(Na - 1)]
        E_b = eps_b.np[int(Nb - 1)]
        E_HOMO = max(E_a, E_b)
    E_HOMOl = E_HOMO
    core.IO.change_file_namespace(180, "ot", "neutral")

    # Cation
    core.IO.change_file_namespace(180, "cation", "ot")
    molecule.set_molecular_charge(charge1)
    molecule.set_multiplicity(mult1)
    core.set_global_option("DOCC", [Nb1])
    core.set_global_option("SOCC", [Na1 - Nb1])
    E1l = driver.energy('scf', dft_functional=name, molecule=molecule,
                        banner='IP Fitting SCF: Cation, Left Endpoint', **kwargs)
    core.IO.change_file_namespace(180, "ot", "cation")

    IPl = E1l - E0l
    kIPl = -E_HOMOl
    delta_l = IPl - kIPl

    if IPl < kIPl:
        raise ValidationError("""\n***IP Fitting Error: Left Omega limit should have kIP < IP: {} !< {}""".format(kIPl, IPl))

    omegas.append(omega_l)
    types.append('Left Limit')
    E0s.append(E0l)
    E1s.append(E1l)
    IPs.append(IPl)
    kIPs.append(kIPl)

    converged = False
    repeat_l = 0
    repeat_r = 0
    for step in range(maxiter):

        # Regula Falsi (modified)
        if repeat_l > 1:
            delta_l /= 2.0
        if repeat_r > 1:
            delta_r /= 2.0
        omega = - (omega_r - omega_l) / (delta_r - delta_l) * delta_l + omega_l
        core.set_local_option('SCF', 'DFT_OMEGA', omega)

        # Neutral
        core.IO.change_file_namespace(180, "neutral", "ot")
        molecule.set_molecular_charge(charge0)
        molecule.set_multiplicity(mult0)
        core.set_global_option("DOCC", [Nb])
        core.set_global_option("SOCC", [Na - Nb])
        E0, wfn = driver.energy('scf', dft_functional=name, return_wfn=True, molecule=molecule,
                                banner='IP Fitting SCF: Neutral, Omega = {:11.3E}'.format(omega), **kwargs)
        eps_a = wfn.epsilon_a()
        eps_b = wfn.epsilon_b()
        if Nb == 0:
            E_HOMO = eps_a.np[int(Na - 1)]
        else:
            E_a = eps_a.np[int(Na - 1)]
            E_b = eps_b.np[int(Nb - 1)]
            E_HOMO = max(E_a, E_b)
        core.IO.change_file_namespace(180, "ot", "neutral")

        # Cation
        core.IO.change_file_namespace(180, "cation", "ot")
        molecule.set_molecular_charge(charge1)
        molecule.set_multiplicity(mult1)
        core.set_global_option("DOCC", [Nb1])
        core.set_global_option("SOCC", [Na1 - Nb1])
        E1 = driver.energy('scf', dft_functional=name, molecule=molecule,
                           banner='IP Fitting SCF: Cation, Omega = {:11.3E}'.format(omega), **kwargs)
        core.IO.change_file_namespace(180, "ot", "cation")

        IP = E1 - E0
        kIP = -E_HOMO
        delta = IP - kIP

        if kIP > IP:
            omega_r = omega
            E0r = E0
            E1r = E1
            IPr = IP
            kIPr = kIP
            delta_r = delta
            repeat_r = 0
            repeat_l += 1
        else:
            omega_l = omega
            E0l = E0
            E1l = E1
            IPl = IP
            kIPl = kIP
            delta_l = delta
            repeat_l = 0
            repeat_r += 1

        omegas.append(omega)
        types.append('Regula-Falsi')
        E0s.append(E0)
        E1s.append(E1)
        IPs.append(IP)
        kIPs.append(kIP)

        # Termination
        if abs(omega_l - omega_r) < omega_convergence:
            converged = True
            break

    core.IO.set_default_namespace("")
    core.print_out("""\n    ==> IP Fitting Results <==\n\n""")

    core.print_out("""     => Occupation Determination <= \n\n""")
    core.print_out("""              %6s %6s %6s %6s %6s %6s\n""" % ('N', 'Na', 'Nb', 'Charge', 'Mult', 'H**O'))
    core.print_out("""     Neutral: %6d %6d %6d %6d %6d %6d\n""" % (N, Na, Nb, charge0, mult0, H**O))
    core.print_out("""     Cation:  %6d %6d %6d %6d %6d\n\n""" % (N - 1, Na1, Nb1, charge1, mult1))

    core.print_out("""     => Regula Falsi Iterations <=\n\n""")
    core.print_out("""    %3s %11s %14s %14s %14s %s\n""" % ('N','Omega','IP','kIP','Delta','Type'))
    for k in range(len(omegas)):
        core.print_out("""    %3d %11.3E %14.6E %14.6E %14.6E %s\n""" %
                       (k + 1, omegas[k], IPs[k], kIPs[k], IPs[k] - kIPs[k], types[k]))

    optstash.restore()
    if converged:
        core.print_out("""\n    IP Fitting Converged\n""")
        core.print_out("""    Final omega = %14.6E\n""" % ((omega_l + omega_r) / 2))
        core.print_out("""\n    "M,I. does the dying. Fleet just does the flying."\n""")
        core.print_out("""            -Starship Troopers\n""")

    else:
        raise ConvergenceError("""IP Fitting """, step + 1)

    return ((omega_l + omega_r) / 2)
Exemplo n.º 9
0
def frac_traverse(name, **kwargs):
    """Scan electron occupancy from +1 electron to -1.

    Parameters
    ----------
    name : string or function
        DFT functional string name or function defining functional
        whose omega is to be optimized.
    molecule : :ref:`molecule <op_py_molecule>`, optional
        Target molecule (neutral) for which omega is to be tuned, if not last defined.
    cation_mult : int, optional
        Multiplicity of cation, if not neutral multiplicity + 1.
    anion_mult : int, optional
        Multiplicity of anion, if not neutral multiplicity + 1.
    frac_start : int, optional
        Iteration at which to start frac procedure when not reading previous
        guess. Defaults to 25.
    HOMO_occs : list, optional
        Occupations to step through for cation, by default `[1 - 0.1 * x for x in range(11)]`.
    LUMO_occs : list, optional
        Occupations to step through for anion, by default `[1 - 0.1 * x for x in range(11)]`.
    H**O : int, optional
        Index of H**O.
    LUMO : int, optional
        Index of LUMO.
    frac_diis : bool, optional
        Do use DIIS for non-1.0-occupied points?
    neutral_guess : bool, optional
        Do use neutral orbitals as guess for the anion?
    hf_guess: bool, optional
        Do use UHF guess before UKS?
    continuous_guess : bool, optional
        Do carry along guess rather than reguessing at each occupation?
    filename : str, optional
        Result filename, if not name of molecule.

    Returns
    -------
    dict
        Dictionary associating SCF energies with occupations.

    """
    optstash = p4util.OptionsState(
        ['SCF', 'GUESS'],
        ['SCF', 'DF_INTS_IO'],
        ['SCF', 'REFERENCE'],
        ["SCF", "FRAC_START"],
        ["SCF", "FRAC_RENORMALIZE"],
        #["SCF", "FRAC_LOAD"],
        ["SCF", "FRAC_OCC"],
        ["SCF", "FRAC_VAL"],
        ["SCF", "FRAC_DIIS"])
    kwargs = p4util.kwargs_lower(kwargs)

    # Make sure the molecule the user provided is the active one, and neutral
    molecule = kwargs.pop('molecule', core.get_active_molecule())
    molecule.update_geometry()

    if molecule.molecular_charge() != 0:
        raise ValidationError("""frac_traverse requires neutral molecule to start.""")
    if molecule.schoenflies_symbol() != 'c1':
        core.print_out("""  Requested procedure `frac_traverse` does not make use of molecular symmetry: """
                       """further calculations in C1 point group.\n""")
    molecule = molecule.clone()
    molecule.reset_point_group('c1')
    molecule.update_geometry()

    charge0 = molecule.molecular_charge()
    mult0 = molecule.multiplicity()

    chargep = charge0 + 1
    chargem = charge0 - 1

    multp = kwargs.get('cation_mult', mult0 + 1)
    multm = kwargs.get('anion_mult', mult0 + 1)

    # By default, we start the frac procedure on the 25th iteration
    # when not reading a previous guess
    frac_start = kwargs.get('frac_start', 25)

    # By default, we occupy by tenths of electrons
    HOMO_occs = kwargs.get('HOMO_occs', [1.0, 0.9, 0.8, 0.7, 0.6, 0.5, 0.4, 0.3, 0.2, 0.1, 0.0])
    LUMO_occs = kwargs.get('LUMO_occs', [1.0, 0.9, 0.8, 0.7, 0.6, 0.5, 0.4, 0.3, 0.2, 0.1, 0.0])

    # By default, H**O and LUMO are both in alpha
    Z = 0
    for A in range(molecule.natom()):
        Z += molecule.Z(A)
    Z -= charge0
    H**O = kwargs.get('H**O', (Z / 2 + 1 if (Z % 2) else Z / 2))
    LUMO = kwargs.get('LUMO', H**O + 1)

    # By default, DIIS in FRAC (1.0 occupation is always DIIS'd)
    frac_diis = kwargs.get('frac_diis', True)

    # By default, use the neutral orbitals as a guess for the anion
    neutral_guess = kwargs.get('neutral_guess', True)

    # By default, burn-in with UHF first, if UKS
    hf_guess = False
    if core.get_local_option('SCF', 'REFERENCE') == 'UKS':
        hf_guess = kwargs.get('hf_guess', True)

    # By default, re-guess at each N
    continuous_guess = kwargs.get('continuous_guess', False)

    # By default, drop the files to the molecule's name
    root = kwargs.get('filename', molecule.name())
    traverse_filename = root + '.traverse.dat'
    # => Traverse <= #
    occs = []
    energies = []
    potentials = []
    convs = []

    # => Run the neutral for its orbitals, if requested <= #

    core.set_local_option("SCF", "DF_INTS_IO", "SAVE")

    old_guess = core.get_local_option("SCF", "GUESS")
    if (neutral_guess):
        if (hf_guess):
            core.set_local_option("SCF", "REFERENCE", "UHF")
        driver.energy('scf', dft_functional=name, molecule=molecule, **kwargs)
        core.set_local_option("SCF", "GUESS", "READ")
        core.set_local_option("SCF", "DF_INTS_IO", "LOAD")

    # => Run the anion first <= #

    molecule.set_molecular_charge(chargem)
    molecule.set_multiplicity(multm)

    # => Burn the anion in with hf, if requested <= #
    if hf_guess:
        core.set_local_option("SCF", "REFERENCE","UHF")
        driver.energy('scf', dft_functional=name, molecule=molecule, **kwargs)
        core.set_local_option("SCF", "REFERENCE", "UKS")
        core.set_local_option("SCF", "GUESS", "READ")
        core.set_local_option("SCF", "DF_INTS_IO", "SAVE")

    core.set_local_option("SCF", "FRAC_START", frac_start)
    core.set_local_option("SCF", "FRAC_RENORMALIZE", True)
    # NYI core.set_local_option("SCF", "FRAC_LOAD", False)

    for occ in LUMO_occs:

        core.set_local_option("SCF", "FRAC_OCC", [LUMO])
        core.set_local_option("SCF", "FRAC_VAL", [occ])

        E, wfn = driver.energy('scf', dft_functional=name, return_wfn=True, molecule=molecule, **kwargs)
        C = 1
        if E == 0.0:
            E = core.variable('SCF ITERATION ENERGY')
            C = 0

        if LUMO > 0:
            eps = wfn.epsilon_a()
            potentials.append(eps.get(int(LUMO) - 1))
        else:
            eps = wfn.epsilon_b()
            potentials.append(eps.get(-int(LUMO) - 1))

        occs.append(occ)
        energies.append(E)
        convs.append(C)

        core.set_local_option("SCF", "FRAC_START", 2)
        #core.set_local_option("SCF", "FRAC_LOAD", True)
        core.set_local_option("SCF", "GUESS", "READ")
        core.set_local_option("SCF", "FRAC_DIIS", frac_diis)
        core.set_local_option("SCF", "DF_INTS_IO", "LOAD")


    # => Run the neutral next <= #

    molecule.set_molecular_charge(charge0)
    molecule.set_multiplicity(mult0)

    # Burn the neutral in with hf, if requested <= #

    if not continuous_guess:
        core.set_local_option("SCF", "GUESS", old_guess)
        if hf_guess:
            core.set_local_option("SCF", "FRAC_START", 0)
            core.set_local_option("SCF", "REFERENCE", "UHF")
            driver.energy('scf', dft_functional=name, molecule=molecule, **kwargs)
            core.set_local_option("SCF", "REFERENCE", "UKS")
            core.set_local_option("SCF", "GUESS", "READ")
        # NYI core.set_local_option("SCF", "FRAC_LOAD", False)

    core.set_local_option("SCF", "FRAC_START", frac_start)
    core.set_local_option("SCF", "FRAC_RENORMALIZE", True)

    for occ in HOMO_occs:

        core.set_local_option("SCF", "FRAC_OCC", [H**O])
        core.set_local_option("SCF", "FRAC_VAL", [occ])

        E, wfn = driver.energy('scf', dft_functional=name, return_wfn=True, molecule=molecule, **kwargs)
        C = 1
        if E == 0.0:
            E = core.variable('SCF ITERATION ENERGY')
            C = 0

        if LUMO > 0:
            eps = wfn.epsilon_a()
            potentials.append(eps.get(int(H**O) - 1))
        else:
            eps = wfn.epsilon_b()
            potentials.append(eps.get(-int(H**O) - 1))

        occs.append(occ - 1.0)
        energies.append(E)
        convs.append(C)

        core.set_local_option("SCF", "FRAC_START", 2)
        # NYI core.set_local_option("SCF", "FRAC_LOAD", True)
        core.set_local_option("SCF", "GUESS", "READ")
        core.set_local_option("SCF", "FRAC_DIIS", frac_diis)
        core.set_local_option("SCF", "DF_INTS_IO", "LOAD")

    # => Print the results out <= #
    E = {}
    core.print_out("""\n    ==> Fractional Occupation Traverse Results <==\n\n""")
    core.print_out("""    %-11s %-24s %-24s %11s\n""" % ('N', 'Energy', 'H**O Energy', 'Converged'))
    for k in range(len(occs)):
        core.print_out("""    %11.3E %24.16E %24.16E %11d\n""" % (occs[k], energies[k], potentials[k], convs[k]))
        E[occs[k]] = energies[k]

    core.print_out("""
    You trying to be a hero Watkins?
    Just trying to kill some bugs sir!
            -Starship Troopers""")

    # Drop the files out
    with open(traverse_filename, 'w') as fh:
        fh.write("""    %-11s %-24s %-24s %11s\n""" % ('N', 'Energy', 'H**O Energy', 'Converged'))
        for k in range(len(occs)):
            fh.write("""    %11.3E %24.16E %24.16E %11d\n""" % (occs[k], energies[k], potentials[k], convs[k]))

    optstash.restore()
    return E
Exemplo n.º 10
0
def frac_nuke(name, **kwargs):
    """Pull all the electrons out, one at a time"""
    optstash = p4util.OptionsState(
        ['SCF', 'GUESS'],
        ['SCF', 'DF_INTS_IO'],
        ["SCF", "FRAC_START"],
        ["SCF", "FRAC_RENORMALIZE"],
        # NYI ["SCF", "FRAC_LOAD"],
        ["SCF", "FRAC_OCC"],
        ["SCF", "FRAC_VAL"],
        ["SCF", "FRAC_DIIS"])

    kwargs = p4util.kwargs_lower(kwargs)

    # Make sure the molecule the user provided is the active one, and neutral
    molecule = kwargs.pop('molecule', core.get_active_molecule())
    molecule.update_geometry()

    if molecule.molecular_charge() != 0:
        raise ValidationError("""frac_nuke requires neutral molecule to start.""")
    if molecule.schoenflies_symbol() != 'c1':
        core.print_out("""  Requested procedure `frac_nuke` does not make use of molecular symmetry: """
                       """further calculations in C1 point group.\n""")
    molecule = molecule.clone()
    molecule.reset_point_group('c1')
    molecule.update_geometry()

    charge0 = molecule.molecular_charge()
    mult0 = molecule.multiplicity()

    # By default, we start the frac procedure on the 25th iteration
    # when not reading a previous guess
    frac_start = kwargs.get('frac_start', 25)

    # By default, we occupy by tenths of electrons
    foccs = kwargs.get('foccs', [1.0, 0.9, 0.8, 0.7, 0.6, 0.5, 0.4, 0.3, 0.2, 0.1, 0.0])

    # By default, H**O and LUMO are both in alpha
    N = 0
    for A in range(molecule.natom()):
        N += molecule.Z(A)
    N -= charge0
    N = int(N)
    Nb = int((N - mult0 + 1) / 2)
    Na = int(N - Nb)

    charge = charge0
    mult = mult0

    # By default, nuke all the electrons
    Nmin = 0
    if 'nmax' in kwargs:
        Nmin = N - int(kwargs['nmax'])

    # By default, DIIS in FRAC (1.0 occupation is always DIIS'd)
    frac_diis = kwargs.get('frac_diis', True)

    # By default, drop the files to the molecule's name
    root = kwargs.get('filename', molecule.name())
    traverse_filename = root + '.traverse.dat'
    stats_filename = root + '.stats.dat'

    # => Traverse <= #
    core.set_local_option("SCF", "DF_INTS_IO", "SAVE")

    Ns = []
    energies = []
    potentials = []
    convs = []
    stats = []

    # Run one SCF to burn things in
    E, wfn = driver.energy('scf', dft_functional=name, return_wfn=True, molecule=molecule, **kwargs)

    # Determine H**O
    eps_a = wfn.epsilon_a()
    eps_b = wfn.epsilon_b()
    eps_a.print_out()
    if Na == Nb:
        H**O = -Nb
    elif Nb == 0:
        H**O = Na
    else:
        E_a = eps_a.get(int(Na - 1))
        E_b = eps_b.get(int(Nb - 1))
        if E_a >= E_b:
            H**O = Na
        else:
            H**O = -Nb

    stats.append("""    %6d %6d %6d %6d %6d %6d\n""" % (N, Na, Nb, charge, mult, H**O))

    if H**O > 0:
        Na -= 1
    else:
        Nb -= 1
    charge += 1
    mult = Na - Nb + 1

    core.set_local_option("SCF", "DF_INTS_IO", "LOAD")
    core.set_local_option("SCF", "FRAC_START", frac_start)
    core.set_local_option("SCF", "FRAC_RENORMALIZE", True)

    # Nuke 'em Rico!
    for Nintegral in range(N, Nmin, -1):

        # Nuke the current H**O
        for occ in foccs:

            core.set_local_option("SCF", "FRAC_OCC", [H**O])
            core.set_local_option("SCF", "FRAC_VAL", [occ])

            E, wfn = driver.energy('scf', dft_functional=name, return_wfn=True, molecule=molecule, **kwargs)
            C = 1
            if E == 0.0:
                E = core.variable('SCF ITERATION ENERGY')
                C = 0

            if H**O > 0:
                eps = wfn.epsilon_a()
                potentials.append(eps.np[H**O - 1])
            else:
                eps = wfn.epsilon_b()
                potentials.append(eps.np[-H**O - 1])

            Ns.append(Nintegral + occ - 1.0)
            energies.append(E)
            convs.append(C)

            core.set_local_option("SCF", "FRAC_START", 2)
            # NYI core.set_local_option("SCF", "FRAC_LOAD", True)
            core.set_local_option("SCF", "FRAC_DIIS", frac_diis)
            core.set_local_option("SCF", "GUESS", "READ")

        # Set the next charge/mult
        molecule.set_molecular_charge(charge)
        molecule.set_multiplicity(mult)

        # Determine H**O
        print('DGAS: What ref should this point to?')
        #ref = core.legacy_wavefunction()
        eps_a = wfn.epsilon_a()
        eps_b = wfn.epsilon_b()
        if Na == Nb:
            H**O = -Nb
        elif Nb == 0:
            H**O = Na
        else:
            E_a = eps_a.np[int(Na - 1)]
            E_b = eps_b.np[int(Nb - 1)]
            if E_a >= E_b:
                H**O = Na
            else:
                H**O = -Nb

        stats.append("""    %6d %6d %6d %6d %6d %6d\n""" % (Nintegral-1, Na, Nb, charge, mult, H**O))

        if H**O > 0:
            Na -= 1
        else:
            Nb -= 1
        charge += 1
        mult = Na - Nb + 1

    core.set_local_option("SCF", "DF_INTS_IO", "NONE")

    # => Print the results out <= #
    E = {}
    core.print_out("""\n    ==> Fractional Occupation Nuke Results <==\n\n""")
    core.print_out("""    %-11s %-24s %-24s %11s\n""" % ('N', 'Energy', 'H**O Energy', 'Converged'))
    for k in range(len(Ns)):
        core.print_out("""    %11.3E %24.16E %24.16E %11d\n""" % (Ns[k], energies[k], potentials[k], convs[k]))
        E[Ns[k]] = energies[k]

    core.print_out('\n')
    core.print_out("""    %6s %6s %6s %6s %6s %6s\n""" % ('N', 'Na', 'Nb', 'Charge', 'Mult', 'H**O'))
    for line in stats:
        core.print_out(line)

    core.print_out('\n    "You shoot a nuke down a bug hole, you got a lot of dead bugs"\n')
    core.print_out('            -Starship Troopers\n')

    # Drop the files out
    with open(traverse_filename, 'w') as fh:
        fh.write("""    %-11s %-24s %-24s %11s\n""" % ('N', 'Energy', 'H**O Energy', 'Converged'))
        for k in range(len(Ns)):
            fh.write("""    %11.3E %24.16E %24.16E %11d\n""" % (Ns[k], energies[k], potentials[k], convs[k]))

    with open(stats_filename, 'w') as fh:
        fh.write("""    %6s %6s %6s %6s %6s %6s\n""" % ('N', 'Na', 'Nb', 'Charge', 'Mult', 'H**O'))
        for line in stats:
            fh.write(line)

    optstash.restore()
    return E
Exemplo n.º 11
0
def run_psi4(para: dict):
    try:
        if (not para.__contains__("multiplicity")):
            para["multiplicity"] = 1

        if (not para.__contains__("charge")):
            para["charge"] = 0

        if (not para.__contains__("basis")):
            para["basis"] = 0

        if (not para.__contains__("EQ_TOLERANCE")):
            para["EQ_TOLERANCE"] = 1e-8

        str_mol = para["mol"]
        str_mol = str_mol + "\n symmetry c1"

        mol = geometry(str_mol, "mol")

        core.IO.set_default_namespace("mol")
        mol.set_multiplicity(para["multiplicity"])
        mol.set_molecular_charge(para["charge"])

        core.set_global_option("BASIS", para["basis"])

        core.set_global_option("SCF_TYPE", "pk")

        core.set_global_option("SOSCF", "false")

        core.set_global_option("FREEZE_CORE", "false")

        core.set_global_option("DF_SCF_GUESS", "false")

        core.set_global_option("OPDM", "true")

        core.set_global_option("TPDM", "true")

        core.set_global_option("MAXITER", 1e6)

        core.set_global_option("NUM_AMPS_PRINT", 1e6)

        core.set_global_option("R_CONVERGENCE", 1e-6)

        core.set_global_option("D_CONVERGENCE", 1e-6)

        core.set_global_option("E_CONVERGENCE", 1e-6)

        core.set_global_option("DAMPING_PERCENTAGE", 0)

        if mol.multiplicity == 1:
            core.set_global_option("REFERENCE", "rhf")
            core.set_global_option("GUESS", "sad")
        else:
            core.set_global_option("REFERENCE", "rohf")
            core.set_global_option("GUESS", "gwh")
        hf_energy, hf_wavefunction = energy('scf', return_wfn=True)
    except Exception as exception:
        return (-1, traceback.format_exc())
    else:
        nuclear_repulsion = mol.nuclear_repulsion_energy()
        canonical_orbitals = numpy.asarray(hf_wavefunction.Ca())

        mints = core.MintsHelper(hf_wavefunction.basisset())
        fermion_str = get_molecular_hamiltonian(mints, canonical_orbitals,
                                                nuclear_repulsion,
                                                para["EQ_TOLERANCE"])
        return (0, fermion_str)