Example #1
0
def run_v2rdm_casscf(name, **kwargs):
    r"""Function encoding sequence of PSI module and plugin calls so that
    v2rdm_casscf can be called via :py:func:`~driver.energy`. For post-scf plugins.

    >>> energy('v2rdm_casscf')

    """

    lowername = name.lower()
    kwargs = p4util.kwargs_lower(kwargs)

    optstash = p4util.OptionsState(
        ['SCF', 'DF_INTS_IO'])

    psi4.set_local_option('SCF', 'DF_INTS_IO', 'SAVE')

    # Your plugin's psi4 run sequence goes here
    scf_wfn = scf_helper(name, **kwargs)

    # if restarting from a checkpoint file, this file
    # needs to be in scratch with the correct name
    filename = psi4.get_option("V2RDM_CASSCF","RESTART_FROM_CHECKPOINT_FILE")

    # todo PSIF_V2RDM_CHECKPOINT should be definied in psifiles.h
    if ( filename != "" ):
        molname = psi4.wavefunction().molecule().name()
        p4util.copy_file_to_scratch(filename,'psi',molname,269,False)

    returnvalue = psi4.plugin('v2rdm_casscf.so',scf_wfn)

    #psi4.set_variable('CURRENT ENERGY', returnvalue)

    return psi4.get_variable('CURRENT ENERGY')
Example #2
0
def run_v2rdm_casscf(name, **kwargs):
    r"""Function encoding sequence of PSI module and plugin calls so that
    v2rdm_casscf can be called via :py:func:`~driver.energy`. For post-scf plugins.

    >>> energy('v2rdm_casscf')

    """

    lowername = name.lower()
    kwargs = p4util.kwargs_lower(kwargs)

    optstash = p4util.OptionsState(['SCF', 'DF_INTS_IO'])

    psi4.set_local_option('SCF', 'DF_INTS_IO', 'SAVE')

    # Your plugin's psi4 run sequence goes here
    scf_wfn = scf_helper(name, **kwargs)

    # if restarting from a checkpoint file, this file
    # needs to be in scratch with the correct name
    filename = psi4.get_option("V2RDM_CASSCF", "RESTART_FROM_CHECKPOINT_FILE")

    # todo PSIF_V2RDM_CHECKPOINT should be definied in psifiles.h
    if (filename != ""):
        molname = psi4.wavefunction().molecule().name()
        p4util.copy_file_to_scratch(filename, 'psi', molname, 269, False)

    returnvalue = psi4.plugin('v2rdm_casscf.so', scf_wfn)

    #psi4.set_variable('CURRENT ENERGY', returnvalue)

    return psi4.get_variable('CURRENT ENERGY')
Example #3
0
def run_v2rdm_casscf(name, **kwargs):
    r"""Function encoding sequence of PSI module and plugin calls so that
    v2rdm_casscf can be called via :py:func:`~driver.energy`. For post-scf plugins.

    >>> energy('v2rdm_casscf')

    """

    lowername = name.lower()
    kwargs = p4util.kwargs_lower(kwargs)

    optstash = p4util.OptionsState(
        ['SCF', 'DF_INTS_IO'])

    psi4.set_local_option('SCF', 'DF_INTS_IO', 'SAVE')

    # Your plugin's psi4 run sequence goes here
    ref_wfn = kwargs.get('ref_wfn', None)
    if ref_wfn is None:
        ref_wfn = driver.scf_helper(name, **kwargs)

    # if restarting from a checkpoint file, this file
    # needs to be in scratch with the correct name
    filename = psi4.get_option("V2RDM_CASSCF","RESTART_FROM_CHECKPOINT_FILE")

    # todo PSIF_V2RDM_CHECKPOINT should be definied in psifiles.h
    if ( filename != "" ):
        molname = ref_wfn.molecule().name()
        p4util.copy_file_to_scratch(filename,'psi',molname,269,False)

    # Ensure IWL files have been written when not using DF/CD
    scf_type = psi4.get_option('SCF', 'SCF_TYPE')
    if ( scf_type == 'PK' or scf_type == 'DIRECT' ):
        proc_util.check_iwl_file_from_scf_type(psi4.get_option('SCF', 'SCF_TYPE'), ref_wfn)

    returnvalue = psi4.plugin('v2rdm_casscf.so', ref_wfn)

    #psi4.set_variable('CURRENT ENERGY', returnvalue)

    #return psi4.get_variable('CURRENT ENERGY')
    return returnvalue
Example #4
0
def ip_fitting(molecule, omega_l, omega_r, **kwargs):
    kwargs = p4util.kwargs_lower(kwargs)

    # By default, zero the omega to 3 digits
    omega_tol = kwargs.get('omega_tolerance', 1.0E-3)

    # By default, do up to twenty iterations
    maxiter = kwargs.get('maxiter', 20)

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

    # The molecule is required, and should be the neutral species
    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
    psi4.IO.set_default_namespace("ot")

    # Burn in to determine orbital eigenvalues
    if read:
        psi4.set_global_option("GUESS", "READ")
        copy_file_to_scratch(read180, 'psi', 'ot', 180)
    old_guess = psi4.get_global_option("GUESS")
    psi4.set_global_option("DF_INTS_IO", "SAVE")
    psi4.print_out("""\n\t==> IP Fitting SCF: Burn-in <==\n""")
    E, wfn = energy('scf', return_wfn=True, molecule=molecule, **kwargs)
    psi4.set_global_option("DF_INTS_IO", "LOAD")

    # 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[int(Na - 1)]
        E_b = eps_b[int(Nb - 1)]
        if E_a >= E_b:
            H**O = Na
        else:
            H**O = -Nb

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

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

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

    # Right endpoint
    psi4.set_global_option('DFT_OMEGA', omega_r)

    # Neutral
    if read:
        psi4.set_global_option("GUESS", "READ")
        p4util.copy_file_to_scratch(read180, 'psi', 'ot', 180)

    molecule.set_molecular_charge(charge0)
    molecule.set_multiplicity(mult0)
    psi4.print_out("""\n\t==> IP Fitting SCF: Neutral, Right Endpoint <==\n""")
    E0r, wfn = energy('scf', return_wfn=True, molecule=molecule, **kwargs)
    eps_a = wfn.epsilon_a()
    eps_b = wfn.epsilon_b()
    E_HOMO = 0.0
    if Nb == 0:
        E_HOMO = eps_a[int(Na - 1)]
    else:
        E_a = eps_a[int(Na - 1)]
        E_b = eps_b[int(Nb - 1)]
        if E_a >= E_b:
            E_HOMO = E_a
        else:
            E_HOMO = E_b
    E_HOMOr = E_HOMO
    psi4.IO.change_file_namespace(180, "ot", "neutral")

    # Cation
    if read:
        psi4.set_global_option("GUESS", "READ")
        p4util.copy_file_to_scratch(read180, 'psi', 'ot', 180)

    molecule.set_molecular_charge(charge1)
    molecule.set_multiplicity(mult1)
    psi4.print_out("""\n\t==> IP Fitting SCF: Cation, Right Endpoint <==\n""")
    E1r = energy('scf', molecule=molecule, **kwargs)
    psi4.IO.change_file_namespace(180, "ot", "cation")

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

    if IPr > kIPr:
        message = (
            """\n***IP Fitting Error: Right Omega limit should have kIP > IP"""
        )
        raise ValidationError(message)

    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
    psi4.set_global_option("GUESS", "READ")

    # Left endpoint
    psi4.set_global_option('DFT_OMEGA', omega_l)

    # Neutral
    psi4.IO.change_file_namespace(180, "neutral", "ot")
    molecule.set_molecular_charge(charge0)
    molecule.set_multiplicity(mult0)
    psi4.print_out("""\n\t==> IP Fitting SCF: Neutral, Left Endpoint <==\n""")
    E0l, wfn = energy('scf', return_wfn=True, molecule=molecule, **kwargs)
    eps_a = wfn.epsilon_a()
    eps_b = wfn.epsilon_b()
    E_HOMO = 0.0
    if Nb == 0:
        E_HOMO = eps_a[int(Na - 1)]
    else:
        E_a = eps_a[int(Na - 1)]
        E_b = eps_b[int(Nb - 1)]
        if E_a >= E_b:
            E_HOMO = E_a
        else:
            E_HOMO = E_b
    E_HOMOl = E_HOMO
    psi4.IO.change_file_namespace(180, "ot", "neutral")

    # Cation
    psi4.IO.change_file_namespace(180, "cation", "ot")
    molecule.set_molecular_charge(charge1)
    molecule.set_multiplicity(mult1)
    psi4.print_out("""\n\t==> IP Fitting SCF: Cation, Left Endpoint <==\n""")
    E1l = energy('scf', molecule=molecule, **kwargs)
    psi4.IO.change_file_namespace(180, "ot", "cation")

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

    if IPl < kIPl:
        message = (
            """\n***IP Fitting Error: Left Omega limit should have kIP < IP""")
        raise ValidationError(message)

    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
    step = 0
    while True:

        step = step + 1

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

        # Neutral
        psi4.IO.change_file_namespace(180, "neutral", "ot")
        molecule.set_molecular_charge(charge0)
        molecule.set_multiplicity(mult0)
        psi4.print_out(
            """\n\t==> IP Fitting SCF: Neutral, Omega = %11.3E <==\n""" %
            omega)
        E0, wfn = energy('scf', return_wfn=True, molecule=molecule, **kwargs)
        eps_a = wfn.epsilon_a()
        eps_b = wfn.epsilon_b()
        E_HOMO = 0.0
        if Nb == 0:
            E_HOMO = eps_a[int(Na - 1)]
        else:
            E_a = eps_a[int(Na - 1)]
            E_b = eps_b[int(Nb - 1)]
            if E_a >= E_b:
                E_HOMO = E_a
            else:
                E_HOMO = E_b
        psi4.IO.change_file_namespace(180, "ot", "neutral")

        # Cation
        psi4.IO.change_file_namespace(180, "cation", "ot")
        molecule.set_molecular_charge(charge1)
        molecule.set_multiplicity(mult1)
        psi4.print_out(
            """\n\t==> IP Fitting SCF: Cation, Omega = %11.3E <==\n""" % omega)
        E1 = energy('scf', molecule=molecule, **kwargs)
        psi4.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 = repeat_l + 1
        else:
            omega_l = omega
            E0l = E0
            E1l = E1
            IPl = IP
            kIPl = kIP
            delta_l = delta
            repeat_l = 0
            repeat_r = 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_tol or step > maxiter):
            converged = True
            break

    # Properly, should clone molecule but since not returned and easy to unblemish,
    molecule.set_molecular_charge(charge0)
    molecule.set_multiplicity(mult0)
    psi4.IO.set_default_namespace("")

    psi4.print_out("""\n\t==> IP Fitting Results <==\n\n""")

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

    psi4.print_out("""\t => Regula Falsi Iterations <=\n\n""")
    psi4.print_out("""\t%3s %11s %14s %14s %14s %s\n""" %
                   ('N', 'Omega', 'IP', 'kIP', 'Delta', 'Type'))
    for k in range(len(omegas)):
        psi4.print_out(
            """\t%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]))
    if converged:
        psi4.print_out("""\n\tIP Fitting Converged\n""")
        psi4.print_out("""\tFinal omega = %14.6E\n""" %
                       ((omega_l + omega_r) / 2))
        psi4.print_out(
            """\n\t"M,I. does the dying. Fleet just does the flying."\n""")
        psi4.print_out("""\t\t\t-Starship Troopers\n""")

    else:
        psi4.print_out("""\n\tIP Fitting did not converge!\n""")

    psi4.set_global_option("DF_INTS_IO", "NONE")
    psi4.set_global_option("GUESS", old_guess)
Example #5
0
def ip_fitting(molecule, omega_l, omega_r, **kwargs):
    kwargs = p4util.kwargs_lower(kwargs)

    # By default, zero the omega to 3 digits
    omega_tol = kwargs.get('omega_tolerance', 1.0E-3)

    # By default, do up to twenty iterations
    maxiter = kwargs.get('maxiter', 20)

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

    # The molecule is required, and should be the neutral species
    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
    psi4.IO.set_default_namespace("ot")

    # Burn in to determine orbital eigenvalues
    if read:
        psi4.set_global_option("GUESS", "READ")
        copy_file_to_scratch(read180, 'psi', 'ot', 180)
    old_guess = psi4.get_global_option("GUESS")
    psi4.set_global_option("DF_INTS_IO", "SAVE")
    psi4.print_out("""\n\t==> IP Fitting SCF: Burn-in <==\n""")
    E, wfn = energy('scf', return_wfn=True, molecule=molecule, **kwargs)
    psi4.set_global_option("DF_INTS_IO", "LOAD")

    # 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[int(Na - 1)]
        E_b = eps_b[int(Nb - 1)]
        if E_a >= E_b:
            H**O = Na
        else:
            H**O = -Nb

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

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

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

    # Right endpoint
    psi4.set_global_option('DFT_OMEGA', omega_r)

    # Neutral
    if read:
        psi4.set_global_option("GUESS", "READ")
        p4util.copy_file_to_scratch(read180, 'psi', 'ot', 180)

    molecule.set_molecular_charge(charge0)
    molecule.set_multiplicity(mult0)
    psi4.print_out("""\n\t==> IP Fitting SCF: Neutral, Right Endpoint <==\n""")
    E0r, wfn = energy('scf', return_wfn=True, molecule=molecule, **kwargs)
    eps_a = wfn.epsilon_a()
    eps_b = wfn.epsilon_b()
    E_HOMO = 0.0;
    if Nb == 0:
        E_HOMO = eps_a[int(Na - 1)]
    else:
        E_a = eps_a[int(Na - 1)]
        E_b = eps_b[int(Nb - 1)]
        if E_a >= E_b:
            E_HOMO = E_a
        else:
            E_HOMO = E_b
    E_HOMOr = E_HOMO
    psi4.IO.change_file_namespace(180, "ot", "neutral")

    # Cation
    if read:
        psi4.set_global_option("GUESS", "READ")
        p4util.copy_file_to_scratch(read180, 'psi', 'ot', 180)

    molecule.set_molecular_charge(charge1)
    molecule.set_multiplicity(mult1)
    psi4.print_out("""\n\t==> IP Fitting SCF: Cation, Right Endpoint <==\n""")
    E1r = energy('scf', molecule=molecule, **kwargs)
    psi4.IO.change_file_namespace(180, "ot", "cation")

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

    if IPr > kIPr:
        message = ("""\n***IP Fitting Error: Right Omega limit should have kIP > IP""")
        raise ValidationError(message)

    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
    psi4.set_global_option("GUESS", "READ")

    # Left endpoint
    psi4.set_global_option('DFT_OMEGA', omega_l)

    # Neutral
    psi4.IO.change_file_namespace(180, "neutral", "ot")
    molecule.set_molecular_charge(charge0)
    molecule.set_multiplicity(mult0)
    psi4.print_out("""\n\t==> IP Fitting SCF: Neutral, Left Endpoint <==\n""")
    E0l, wfn = energy('scf', return_wfn=True, molecule=molecule, **kwargs)
    eps_a = wfn.epsilon_a()
    eps_b = wfn.epsilon_b()
    E_HOMO = 0.0
    if Nb == 0:
        E_HOMO = eps_a[int(Na - 1)]
    else:
        E_a = eps_a[int(Na - 1)]
        E_b = eps_b[int(Nb - 1)]
        if E_a >= E_b:
            E_HOMO = E_a
        else:
            E_HOMO = E_b
    E_HOMOl = E_HOMO
    psi4.IO.change_file_namespace(180, "ot", "neutral")

    # Cation
    psi4.IO.change_file_namespace(180, "cation", "ot")
    molecule.set_molecular_charge(charge1)
    molecule.set_multiplicity(mult1)
    psi4.print_out("""\n\t==> IP Fitting SCF: Cation, Left Endpoint <==\n""")
    E1l = energy('scf', molecule=molecule, **kwargs)
    psi4.IO.change_file_namespace(180, "ot", "cation")

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

    if IPl < kIPl:
        message = ("""\n***IP Fitting Error: Left Omega limit should have kIP < IP""")
        raise ValidationError(message)

    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
    step = 0
    while True:

        step = step + 1

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

        # Neutral
        psi4.IO.change_file_namespace(180, "neutral", "ot")
        molecule.set_molecular_charge(charge0)
        molecule.set_multiplicity(mult0)
        psi4.print_out("""\n\t==> IP Fitting SCF: Neutral, Omega = %11.3E <==\n""" % omega)
        E0, wfn = energy('scf', return_wfn=True, molecule=molecule, **kwargs)
        eps_a = wfn.epsilon_a()
        eps_b = wfn.epsilon_b()
        E_HOMO = 0.0
        if Nb == 0:
            E_HOMO = eps_a[int(Na - 1)]
        else:
            E_a = eps_a[int(Na - 1)]
            E_b = eps_b[int(Nb - 1)]
            if E_a >= E_b:
                E_HOMO = E_a
            else:
                E_HOMO = E_b
        psi4.IO.change_file_namespace(180, "ot", "neutral")

        # Cation
        psi4.IO.change_file_namespace(180, "cation", "ot")
        molecule.set_molecular_charge(charge1)
        molecule.set_multiplicity(mult1)
        psi4.print_out("""\n\t==> IP Fitting SCF: Cation, Omega = %11.3E <==\n""" % omega)
        E1 = energy('scf', molecule=molecule, **kwargs)
        psi4.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 = repeat_l + 1
        else:
            omega_l = omega
            E0l = E0
            E1l = E1
            IPl = IP
            kIPl = kIP
            delta_l = delta
            repeat_l = 0;
            repeat_r = 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_tol or step > maxiter):
            converged = True
            break

    # Properly, should clone molecule but since not returned and easy to unblemish,
    molecule.set_molecular_charge(charge0)
    molecule.set_multiplicity(mult0)
    psi4.IO.set_default_namespace("")

    psi4.print_out("""\n\t==> IP Fitting Results <==\n\n""")

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

    psi4.print_out("""\t => Regula Falsi Iterations <=\n\n""")
    psi4.print_out("""\t%3s %11s %14s %14s %14s %s\n""" % ('N','Omega','IP','kIP','Delta','Type'))
    for k in range(len(omegas)):
        psi4.print_out("""\t%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]))
    if converged:
        psi4.print_out("""\n\tIP Fitting Converged\n""")
        psi4.print_out("""\tFinal omega = %14.6E\n""" % ((omega_l + omega_r) / 2))
        psi4.print_out("""\n\t"M,I. does the dying. Fleet just does the flying."\n""")
        psi4.print_out("""\t\t\t-Starship Troopers\n""")

    else:
        psi4.print_out("""\n\tIP Fitting did not converge!\n""")

    psi4.set_global_option("DF_INTS_IO", "NONE")
    psi4.set_global_option("GUESS", old_guess)
Example #6
0
def ip_fitting(mol, omega_l, omega_r, **kwargs):
    kwargs = p4util.kwargs_lower(kwargs)

    # By default, zero the omega to 3 digits
    omega_tol = 1.0E-3;
    if (kwargs.has_key('omega_tolerance')):
        omega_tol = kwargs['omega_tolerance']

    # By default, do up to twenty iterations
    maxiter = 20;
    if (kwargs.has_key('maxiter')):
        maxiter = kwargs['maxiter']

    # By default, do not read previous 180 orbitals file
    read = False;
    read180 = ''
    if (kwargs.has_key('read')):
        read = True;
        read180 = kwargs['read']

    # The molecule is required, and should be the neutral species
    mol.update_geometry()
    activate(mol)
    charge0 = mol.molecular_charge()
    mult0   = mol.multiplicity()

    # How many electrons are there?
    N = 0;
    for A in range(mol.natom()):
        N += mol.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
    psi4.IO.set_default_namespace("ot")

    # Burn in to determine orbital eigenvalues
    if (read):
        psi4.set_global_option("GUESS", "READ")
        copy_file_to_scratch(read180, 'psi', 'ot', 180)
    old_guess = psi4.get_global_option("GUESS")
    psi4.set_global_option("DF_INTS_IO", "SAVE")
    psi4.print_out('\n\t==> IP Fitting SCF: Burn-in <==\n')
    energy('scf')
    psi4.set_global_option("DF_INTS_IO", "LOAD")

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

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

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

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

    # Right endpoint
    psi4.set_global_option('DFT_OMEGA',omega_r)

    # Neutral
    if (read):
        psi4.set_global_option("GUESS", "READ")
        p4util.copy_file_to_scratch(read180, 'psi', 'ot', 180)

    mol.set_molecular_charge(charge0)
    mol.set_multiplicity(mult0)
    psi4.print_out('\n\t==> IP Fitting SCF: Neutral, Right Endpoint <==\n')
    E0r = energy('scf')
    ref = psi4.wavefunction()
    eps_a = ref.epsilon_a()
    eps_b = ref.epsilon_b()
    E_HOMO = 0.0;
    if (Nb == 0):
        E_HOMO = eps_a[int(Na-1)]
    else:
        E_a = eps_a[int(Na - 1)]
        E_b = eps_b[int(Nb - 1)]
        if (E_a >= E_b):
            E_HOMO = E_a;
        else:
            E_HOMO = E_b;
    E_HOMOr = E_HOMO;
    psi4.IO.change_file_namespace(180,"ot","neutral")

    # Cation
    if (read):
        psi4.set_global_option("GUESS", "READ")
        p4util.copy_file_to_scratch(read180, 'psi', 'ot', 180)

    mol.set_molecular_charge(charge1)
    mol.set_multiplicity(mult1)
    psi4.print_out('\n\t==> IP Fitting SCF: Cation, Right Endpoint <==\n')
    E1r = energy('scf')
    psi4.IO.change_file_namespace(180,"ot","cation")

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

    if (IPr > kIPr):
        psi4.print_out('\n***IP Fitting Error: Right Omega limit should have kIP > IP')
        sys.exit(1)

    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
    psi4.set_global_option("GUESS","READ")

    # Left endpoint
    psi4.set_global_option('DFT_OMEGA',omega_l)

    # Neutral
    psi4.IO.change_file_namespace(180,"neutral","ot")
    mol.set_molecular_charge(charge0)
    mol.set_multiplicity(mult0)
    psi4.print_out('\n\t==> IP Fitting SCF: Neutral, Left Endpoint <==\n')
    E0l = energy('scf')
    ref = psi4.wavefunction()
    eps_a = ref.epsilon_a()
    eps_b = ref.epsilon_b()
    E_HOMO = 0.0;
    if (Nb == 0):
        E_HOMO = eps_a[int(Na-1)]
    else:
        E_a = eps_a[int(Na - 1)]
        E_b = eps_b[int(Nb - 1)]
        if (E_a >= E_b):
            E_HOMO = E_a;
        else:
            E_HOMO = E_b;
    E_HOMOl = E_HOMO;
    psi4.IO.change_file_namespace(180,"ot","neutral")

    # Cation
    psi4.IO.change_file_namespace(180,"cation","ot")
    mol.set_molecular_charge(charge1)
    mol.set_multiplicity(mult1)
    psi4.print_out('\n\t==> IP Fitting SCF: Cation, Left Endpoint <==\n')
    E1l = energy('scf')
    psi4.IO.change_file_namespace(180,"ot","cation")

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

    if (IPl < kIPl):
        psi4.print_out('\n***IP Fitting Error: Left Omega limit should have kIP < IP')
        sys.exit(1)

    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;
    step = 0;
    while True:

        step = step + 1;

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

        # Neutral
        psi4.IO.change_file_namespace(180,"neutral","ot")
        mol.set_molecular_charge(charge0)
        mol.set_multiplicity(mult0)
        psi4.print_out('\n\t==> IP Fitting SCF: Neutral, Omega = %11.3E <==\n' % omega)
        E0 = energy('scf')
        ref = psi4.wavefunction()
        eps_a = ref.epsilon_a()
        eps_b = ref.epsilon_b()
        E_HOMO = 0.0;
        if (Nb == 0):
            E_HOMO = eps_a[int(Na-1)]
        else:
            E_a = eps_a[int(Na - 1)]
            E_b = eps_b[int(Nb - 1)]
            if (E_a >= E_b):
                E_HOMO = E_a;
            else:
                E_HOMO = E_b;
        psi4.IO.change_file_namespace(180,"ot","neutral")

        # Cation
        psi4.IO.change_file_namespace(180,"cation","ot")
        mol.set_molecular_charge(charge1)
        mol.set_multiplicity(mult1)
        psi4.print_out('\n\t==> IP Fitting SCF: Cation, Omega = %11.3E <==\n' % omega)
        E1 = energy('scf')
        psi4.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 = repeat_l + 1;
        else:
            omega_l = omega
            E0l = E0
            E1l = E1
            IPl = IP
            kIPl = kIP
            delta_l = delta
            repeat_l = 0;
            repeat_r = 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_tol or step > maxiter):
            converged = True;
            break

    psi4.IO.set_default_namespace("")

    psi4.print_out('\n\t==> IP Fitting Results <==\n\n')

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

    psi4.print_out('\t => Regula Falsi Iterations <=\n\n')
    psi4.print_out('\t%3s %11s %14s %14s %14s %s\n' % ('N','Omega','IP','kIP','Delta','Type'))
    for k in range(len(omegas)):
        psi4.print_out('\t%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]))
    if (converged):
        psi4.print_out('\n\tIP Fitting Converged\n')
        psi4.print_out('\tFinal omega = %14.6E\n' % ((omega_l + omega_r) / 2))
        psi4.print_out('\n\t"M,I. does the dying. Fleet just does the flying."\n')
        psi4.print_out('\t\t\t-Starship Troopers\n')

    else:
        psi4.print_out('\n\tIP Fitting did not converge!\n')

    psi4.set_global_option("DF_INTS_IO", "NONE")
    psi4.set_global_option("GUESS", old_guess)