Exemple #1
0
def banner(text, type=1, width=35, strNotOutfile=False):
    """Function to print *text* to output file in a banner of
    minimum width *width* and minimum three-line height for
    *type* = 1 or one-line height for *type* = 2. If *strNotOutfile*
    is True, function returns string rather than printing it
    to output file.

    """
    lines = text.split('\n')
    max_length = 0
    for line in lines:
        if (len(line) > max_length):
            max_length = len(line)

    max_length = max([width, max_length])

    null = ''
    if type == 1:
        banner = '  //' + null.center(max_length, '>') + '//\n'
        for line in lines:
            banner += '  //' + line.center(max_length) + '//\n'
        banner += '  //' + null.center(max_length, '<') + '//\n'

    if type == 2:
        banner = ''
        for line in lines:
            banner += (' ' + line + ' ').center(max_length, '=')

    if strNotOutfile:
        return banner
    else:
        core.print_out(banner)
    def compute_hessian(self, molecule):
        """
        #magic (if magic was easy)
        """

        optstash = p4util.OptionsState(['PRINT'])
        core.set_global_option('PRINT', 0)

        core.print_out("\n\n   Analytical Dispersion Hessians are not supported by dftd3 or gcp.\n")
        core.print_out("       Computing the Hessian through finite difference of gradients.\n\n")

        # Setup the molecule
        molclone = molecule.clone()
        molclone.reinterpret_coordentry(False)
        molclone.fix_orientation(True)
        molclone.fix_com(True)

        # Record undisplaced symmetry for projection of diplaced point groups
        core.set_parent_symmetry(molecule.schoenflies_symbol())

        gradients = []
        for geom in core.fd_geoms_freq_1(molecule, -1):
            molclone.set_geometry(geom)
            molclone.update_geometry()
            gradients.append(self.compute_gradient(molclone))

        H = core.fd_freq_1(molecule, gradients, -1)
        # H.print_out()
        optstash.restore()
        return H
Exemple #3
0
def compare_vectors(expected, computed, digits, label):
    """Function to compare two vectors. Prints :py:func:`util.success`
    when elements of vector *computed* match elements of vector *expected* to
    number of *digits*. Performs a system exit on failure to match symmetry
    structure, dimension, or element values. Used in input files in the test suite.

    """
    if (expected.nirrep() != computed.nirrep()):
        message = ("\t%s has %d irreps, but %s has %d\n." %
                   (expected.name(), expected.nirrep(), computed.name(), computed.nirrep()))
        raise TestComparisonError(message)
    nirreps = expected.nirrep()
    for irrep in range(nirreps):
        if (expected.dim(irrep) != computed.dim(irrep)):
            message = ("\tThe reference has %d entries in irrep %d, but the computed vector has %d\n." %
                       (expected.dim(irrep), irrep, computed.dim(irrep)))
            raise TestComparisonError(message)
        dim = expected.dim(irrep)
        failed = 0
        for entry in range(dim):
            if (abs(expected.get(irrep, entry) - computed.get(irrep, entry)) > 10**(-digits)):
                failed = 1
                break

        if (failed):
            core.print_out("The computed vector\n")
            computed.print_out()
            core.print_out("The reference vector\n")
            expected.print_out()
            message = ("\t%s: computed value (%s) does not match (%s)." %
                       (label, computed.get(irrep, entry), expected.get(irrep, entry)))
            raise TestComparisonError(message)
    success(label)
    return True
Exemple #4
0
def geometry(geom, name="default"):
    """Function to create a molecule object of name *name* from the
    geometry in string *geom*. Permitted for user use but deprecated
    in driver in favor of explicit molecule-passing. Comments within
    the string are filtered.

    """
    molrec = qcel.molparse.from_string(
        geom, enable_qm=True, missing_enabled_return_qm='minimal', enable_efp=True, missing_enabled_return_efp='none')

    molecule = core.Molecule.from_dict(molrec['qm'])
    molecule.set_name(name)

    if 'efp' in molrec:
        try:
            import pylibefp
        except ImportError as e:  # py36 ModuleNotFoundError
            raise ImportError("""Install pylibefp to use EFP functionality. `conda install pylibefp -c psi4` Or build with `-DENABLE_libefp=ON`""") from e
        #print('Using pylibefp: {} (version {})'.format(pylibefp.__file__, pylibefp.__version__))
        efpobj = pylibefp.from_dict(molrec['efp'])
        # pylibefp.core.efp rides along on molecule
        molecule.EFP = efpobj

    # Attempt to go ahead and construct the molecule
    try:
        molecule.update_geometry()
    except:
        core.print_out("Molecule: geometry: Molecule is not complete, please use 'update_geometry'\n"
                       "                    once all variables are set.\n")

    activate(molecule)

    return molecule
Exemple #5
0
def _diag_print_info(solver_name, info, verbose=1):
    """Print a message to the output file at each iteration"""
    if verbose < 1:
        # no printing
        return
    elif verbose == 1:
        # print iter  maxde max|R| conv/restart
        flags = []
        if info['collapse']:
            flags.append("Restart")
        if info['done']:
            flags.append("Converged")

        core.print_out("  {name} iter {ni:3d}:   {m_de:-11.5e} {m_r:12.5e} {flgs}\n".format(
            name=solver_name,
            ni=info['count'],
            m_de=np.max(info['delta_val']),
            m_r=np.max(info['res_norm']),
            flgs="/".join(flags)))
    else:
        # print iter / ssdim folowed by de/|R| for each root
        core.print_out("  {name} iter {ni:3d}: {nv:4d} guess vectors\n".format(
            name=solver_name, ni=info['count'], nv=info['nvec']))
        for i, (e, de, rn) in enumerate(zip(info['val'], info['delta_val'], info['res_norm'])):
            core.print_out("     {nr:2d}: {s:} {e:-11.5f} {de:-11.5e} {rn:12.5e}\n".format(
                nr=i + 1, s=" " * (len(solver_name) - 8), e=e, de=de, rn=rn))
        if info['done']:
            core.print_out("  Solver Converged! all roots\n\n")
        elif info['collapse']:
            core.print_out("  Subspace limits exceeded restarting\n\n")
Exemple #6
0
 def __init__(self, circs):
     if circs[5] == '':
         msg = """{0}: Method '{1}' with {2} '{3}' and REFERENCE '{4}' not available{5}""".format(*circs)
     else:
         msg = """{0}: Method '{1}' with {2} '{3}' and REFERENCE '{4}' not directable to QC_MODULE '{5}'""".format(*circs)
     PsiException.__init__(self, msg)
     self.message = msg
     core.print_out('\nPsiException: %s\n\n' % (msg))
def pybuild_basis(mol,
                  key=None,
                  target=None,
                  fitrole='ORBITAL',
                  other=None,
                  puream=-1,
                  return_atomlist=False,
                  quiet=False):
    if key == 'ORBITAL':
        key = 'BASIS'

    def _resolve_target(key, target):
        """Figure out exactly what basis set was intended by (key, target)
        """
        horde = qcdb.libmintsbasisset.basishorde
        if not target:
            if not key:
                key = 'BASIS'
            target = core.get_global_option(key)

        if target in horde:
            return horde[target]
        return target

    # Figure out what exactly was meant by 'target'.
    resolved_target = _resolve_target(key, target)

    # resolved_target needs to be either a string or function for pyconstuct.
    # if a string, they search for a gbs file with that name.
    # if a function, it needs to apply a basis to each atom.

    bs, basisdict = qcdb.BasisSet.pyconstruct(mol.to_dict(),
                                              key, resolved_target, fitrole, other,
                                              return_dict=True,
                                              return_atomlist=return_atomlist)

    if return_atomlist:
        atom_basis_list = []
        for atbs in basisdict:
            atommol = core.Molecule.from_dict(atbs['molecule'])
            lmbs = core.BasisSet.construct_from_pydict(atommol, atbs, puream)
            atom_basis_list.append(lmbs)
        return atom_basis_list
    if ((sys.version_info < (3, 0) and isinstance(resolved_target, basestring))
            or (sys.version_info >= (3, 0) and isinstance(resolved_target, str))):
        basisdict['name'] = basisdict['name'].split('/')[-1].replace('.gbs', '')
    if callable(resolved_target):
        basisdict['name'] = resolved_target.__name__.replace('basisspec_psi4_yo__', '').upper()

    if not quiet:
        core.print_out(basisdict['message'])
        if 'ECP' in basisdict['message']:
            core.print_out('    !!!  WARNING: ECP capability is in beta. Please check occupations closely.  !!!\n\n')

    if basisdict['key'] is None:
        basisdict['key'] = 'BASIS'
    psibasis = core.BasisSet.construct_from_pydict(mol, basisdict, puream)
    return psibasis
Exemple #8
0
 def __init__(self, option):
     mods_str = ", ".join([m for m in PastureRequiredError.pasture_required_modules[option]])
     msg = PastureRequiredError.msg_tmpl.format(opt=option, modlist=mods_str)
     PsiException.__init__(self, msg)
     module_cmake_args = " ".join(
         ["-DENABLE_{}=ON".format(module) for module in PastureRequiredError.pasture_required_modules[option]])
     msg += PastureRequiredError.install_instructions.format(module_args=module_cmake_args)
     self.message = '\nPsiException: {}\n\n'.format(msg)
     core.print_out(self.message)
Exemple #9
0
def success(label):
    """Function to print a '*label*...PASSED' line to screen.
    Used by :py:func:`util.compare_values` family when functions pass.

    """
    msg = '\t{0:.<66}PASSED'.format(label)
    print(msg)
    sys.stdout.flush()
    core.print_out(msg + '\n')
Exemple #10
0
def extract_sowreap_from_output(sowout, quantity, sownum, linkage, allvital=False, label='electronic energy'):
    """Function to examine file *sowout* from a sow/reap distributed job
    for formatted line with electronic energy information about index
    *sownum* to be used for construction of *quantity* computations as
    directed by master input file with *linkage* kwarg. When file *sowout*
    is missing or incomplete files, function will either return zero
    (*allvital* is ``False``) or terminate (*allvital* is ``True``) since
    some sow/reap procedures can produce meaningful results (database)
    from an incomplete set of sown files, while others cannot (gradient,
    hessian).

    """
    warnings.warn(
        "Using `psi4.driver.p4util.extract_sowreap_from_output` is deprecated, and in 1.4 it will stop working\n",
        category=FutureWarning,
        stacklevel=2)

    E = 0.0

    try:
        freagent = open('%s.out' % (sowout), 'r')
    except IOError:
        if allvital:
            raise ValidationError('Aborting upon output file \'%s.out\' not found.\n' % (sowout))
        else:
            ValidationError('Aborting upon output file \'%s.out\' not found.\n' % (sowout))
            return 0.0
    else:
        while True:
            line = freagent.readline()
            if not line:
                if E == 0.0:
                    if allvital:
                        raise ValidationError(
                            'Aborting upon output file \'%s.out\' has no %s RESULT line.\n' % (sowout, quantity))
                    else:
                        ValidationError(
                            'Aborting upon output file \'%s.out\' has no %s RESULT line.\n' % (sowout, quantity))
                break
            s = line.strip().split(None, 10)
            if (len(s) != 0) and (s[0:3] == [quantity, 'RESULT:', 'computation']):
                if int(s[3]) != linkage:
                    raise ValidationError(
                        'Output file \'%s.out\' has linkage %s incompatible with master.in linkage %s.' %
                        (sowout, str(s[3]), str(linkage)))
                if s[6] != str(sownum + 1):
                    raise ValidationError(
                        'Output file \'%s.out\' has nominal affiliation %s incompatible with item %s.' %
                        (sowout, s[6], str(sownum + 1)))
                if label == 'electronic energy' and s[8:10] == ['electronic', 'energy']:
                    E = float(s[10])
                    core.print_out('%s RESULT: electronic energy = %20.12f\n' % (quantity, E))
                if label == 'electronic gradient' and s[8:10] == ['electronic', 'gradient']:
                    E = ast.literal_eval(s[-1])
                    core.print_out('%s RESULT: electronic gradient = %r\n' % (quantity, E))
        freagent.close()
    return E
Exemple #11
0
 def append_geoms(indices, steps):
     """Given a list of indices and a list of steps to displace each, append the corresponding geometry to the list."""
     new_geom = ref_geom.clone().np
     # Next, to make this salc/magnitude composite.
     index_steps = zip(indices, steps)
     label = _displace_cart(mol, new_geom, data["salc_list"], index_steps, data["disp_size"])
     if data["print_lvl"] > 2:
         core.print_out("\nDisplacement '{}'\n{}\n".format(label, np.array_str(new_geom, **array_format)))
     findifrec["displacements"][label] = {"geometry": new_geom.ravel().tolist()}
Exemple #12
0
def _print_output(complete_dict, output):
    core.print_out('\n   ==> Response Properties <==\n')

    for i, prop in enumerate(complete_dict):
        if not 'User' in prop['name']:
            core.print_out('\n    => {} <=\n\n'.format(prop['name']))
            directions = prop['printout_labels']
            var_name = prop['name'].upper().replace("IES", "Y")
            _print_matrix(directions, output[i], var_name)
Exemple #13
0
def prepare_sapt_molecule(sapt_dimer, sapt_basis):
    """
    Prepares a dimer molecule for a SAPT computations. Returns the dimer, monomerA, and monomerB.
    """

    # Shifting to C1 so we need to copy the active molecule
    sapt_dimer = sapt_dimer.clone()
    if sapt_dimer.schoenflies_symbol() != 'c1':
        core.print_out('  SAPT does not make use of molecular symmetry, further calculations in C1 point group.\n')
        sapt_dimer.reset_point_group('c1')
        sapt_dimer.fix_orientation(True)
        sapt_dimer.fix_com(True)
        sapt_dimer.update_geometry()
    else:
        sapt_dimer.update_geometry()  # make sure since mol from wfn, kwarg, or P::e
        sapt_dimer.fix_orientation(True)
        sapt_dimer.fix_com(True)

    nfrag = sapt_dimer.nfragments()

    if nfrag == 3:
        # Midbond case
        if sapt_basis == 'monomer':
            raise ValidationError("SAPT basis cannot both be monomer centered and have midbond functions.")

        midbond = sapt_dimer.extract_subsets(3)
        ztotal = 0
        for n in range(midbond.natom()):
            ztotal += midbond.Z(n)

        if ztotal > 0:
            raise ValidationError("SAPT third monomr must be a midbond function (all ghosts).")

        ghosts = ([2, 3], [1, 3])
    elif nfrag == 2:
        # Classical dimer case
        ghosts = (2, 1)
    else:
        raise ValidationError('SAPT requires active molecule to have 2 fragments, not %s.' % (nfrag))

    if sapt_basis == 'dimer':
        monomerA = sapt_dimer.extract_subsets(1, ghosts[0])
        monomerA.set_name('monomerA')
        monomerB = sapt_dimer.extract_subsets(2, ghosts[1])
        monomerB.set_name('monomerB')
    elif sapt_basis == 'monomer':
        monomerA = sapt_dimer.extract_subsets(1)
        monomerA.set_name('monomerA')
        monomerB = sapt_dimer.extract_subsets(2)
        monomerB.set_name('monomerB')
    else:
        raise ValidationError("SAPT basis %s not recognized" % sapt_basis)

    return (sapt_dimer, monomerA, monomerB)
Exemple #14
0
def check_disk_df(name, optstash):

    optstash.add_option(['SCF_TYPE'])

    # Alter default algorithm
    if not core.has_global_option_changed('SCF_TYPE'):
        core.set_global_option('SCF_TYPE', 'DISK_DF')
        core.print_out("""    Method '%s' requires SCF_TYPE = DISK_DF, setting.\n""" % name)
    elif core.get_global_option('SCF_TYPE') == "DF":
        core.set_global_option('SCF_TYPE', 'DISK_DF')
        core.print_out("""    Method '%s' requires SCF_TYPE = DISK_DF, setting.\n""" % name)
    else:
        if core.get_global_option('SCF_TYPE') != "DISK_DF":
            raise ValidationError("  %s requires SCF_TYPE = DISK_DF, please use SCF_TYPE = DF to automatically choose the correct DFJK implementation." % name)
Exemple #15
0
def _print_array(name, arr, verbose):
    """print an subspace quantity (numpy array) to the output file

    Parameters
    ----------
    name : str
        The name to print above the array
    arr : :py:class:`np.ndarray`
        The array to print
    verbose : int
        The amount of information to print. Only prints for verbose > 2
    """
    if verbose > 2:
        core.print_out("\n\n{}:\n{}\n".format(name, str(arr)))
Exemple #16
0
def df_mp2_fisapt_dispersion(wfn, primary, auxiliary, cache, do_print=True):

    if do_print:
        core.print_out("\n  ==> E20 Dispersion (MP2) <== \n\n")

    # Build object
    df_matrix_keys = ["Cocc_A", "Cvir_A", "Cocc_B", "Cvir_B"]
    df_mfisapt_keys = ["Caocc0A", "Cvir0A", "Caocc0B", "Cvir0B"]
    matrix_cache = {fkey: cache[ckey] for ckey, fkey in zip(df_matrix_keys, df_mfisapt_keys)}

    other_keys = ["S", "D_A", "P_A", "V_A", "J_A", "K_A", "D_B", "P_B", "V_B", "J_B", "K_B", "K_O"]
    for key in other_keys:
        matrix_cache[key] = cache[key]

    # matrix_cache["K_O"] = matrix_cache["K_O"].transpose()

    df_vector_keys = ["eps_occ_A", "eps_vir_A", "eps_occ_B", "eps_vir_B"]
    df_vfisapt_keys = ["eps_aocc0A", "eps_vir0A", "eps_aocc0B", "eps_vir0B"]
    vector_cache = {fkey: cache[ckey] for ckey, fkey in zip(df_vector_keys, df_vfisapt_keys)}

    wfn.set_basisset("DF_BASIS_SAPT", auxiliary)
    fisapt = core.FISAPT(wfn)

    # Compute!
    fisapt.disp(matrix_cache, vector_cache, False)
    scalars = fisapt.scalars()

    core.print_out("\n")
    core.print_out(print_sapt_var("Disp20 (MP2)", scalars["Disp20"], short=True) + "\n")
    core.print_out(print_sapt_var("Exch-Disp20,u", scalars["Exch-Disp20"], short=True) + "\n")

    ret = {}
    ret["Exch-Disp20,u"] = scalars["Exch-Disp20"]
    ret["Disp20,u"] = scalars["Disp20"]
    return ret
Exemple #17
0
def df_mp2_sapt_dispersion(dimer_wfn, wfn_A, wfn_B, primary_basis, aux_basis, cache, do_print=True):

    if do_print:
        core.print_out("\n  ==> E20 Dispersion (MP2) <== \n\n")

    optstash = p4util.OptionsState(['SAPT', 'SAPT0_E10'], ['SAPT', 'SAPT0_E20IND'], ['SAPT', 'SAPT0_E20DISP'],
                                   ['SAPT', 'SAPT_QUIET'])

    core.set_local_option("SAPT", "SAPT0_E10", False)
    core.set_local_option("SAPT", "SAPT0_E20IND", False)
    core.set_local_option("SAPT", "SAPT0_E20DISP", True)
    core.set_local_option("SAPT", "SAPT_QUIET", True)

    if core.get_option('SCF', 'REFERENCE') == 'RHF':
        core.IO.change_file_namespace(psif.PSIF_SAPT_MONOMERA, 'monomerA', 'dimer')
        core.IO.change_file_namespace(psif.PSIF_SAPT_MONOMERB, 'monomerB', 'dimer')

    core.IO.set_default_namespace('dimer')

    dimer_wfn.set_basisset("DF_BASIS_SAPT", aux_basis)
    dimer_wfn.set_basisset("DF_BASIS_ELST", aux_basis)
    e_sapt = core.sapt(dimer_wfn, wfn_A, wfn_B)

    optstash.restore()

    svars = dimer_wfn.variables()

    core.print_out("\n")
    core.print_out(print_sapt_var("Disp20 (MP2)", svars["E DISP20"], short=True) + "\n")
    core.print_out(print_sapt_var("Exch-Disp20,u", svars["E EXCH-DISP20"], short=True) + "\n")

    ret = {}
    ret["Exch-Disp20,u"] = svars["E EXCH-DISP20"]
    ret["Disp20,u"] = svars["E DISP20"]
    return ret
Exemple #18
0
def scf_initialize(self):
    """Specialized initialization, compute integrals and does everything to prepare for iterations"""

    self.iteration_ = 0
    efp_enabled = hasattr(self.molecule(), 'EFP')

    if core.get_option('SCF', "PRINT") > 0:
        core.print_out("  ==> Pre-Iterations <==\n\n")
        self.print_preiterations()

    if efp_enabled:
        # EFP: Set QM system, options, and callback. Display efp geom in [A]
        efpobj = self.molecule().EFP
        core.print_out(efpobj.banner())
        core.print_out(efpobj.geometry_summary(units_to_bohr=constants.bohr2angstroms))

        efpptc, efpcoords, efpopts = get_qm_atoms_opts(self.molecule())
        efpobj.set_point_charges(efpptc, efpcoords)
        efpobj.set_opts(efpopts, label='psi', append='psi')

        efpobj.set_electron_density_field_fn(field_fn)

    if self.attempt_number_ == 1:
        mints = core.MintsHelper(self.basisset())
        if core.get_global_option('RELATIVISTIC') in ['X2C', 'DKH']:
            mints.set_rel_basisset(self.get_basisset('BASIS_RELATIVISTIC'))

        mints.one_electron_integrals()
        self.integrals()

        core.timer_on("HF: Form core H")
        self.form_H()
        core.timer_off("HF: Form core H")

        if efp_enabled:
            # EFP: Add in permanent moment contribution and cache
            core.timer_on("HF: Form Vefp")
            verbose = core.get_option('SCF', "PRINT")
            Vefp = modify_Fock_permanent(self.molecule(), mints, verbose=verbose-1)
            Vefp = core.Matrix.from_array(Vefp)
            self.H().add(Vefp)
            Horig = self.H().clone()
            self.Horig = Horig
            core.print_out("  QM/EFP: iterating Total Energy including QM/EFP Induction\n")
            core.timer_off("HF: Form Vefp")

        core.timer_on("HF: Form S/X")
        self.form_Shalf()
        core.timer_off("HF: Form S/X")

        core.timer_on("HF: Guess")
        self.guess()
        core.timer_off("HF: Guess")

    else:
        # We're reading the orbitals from the previous set of iterations.
        self.form_D()
        self.set_energies("Total Energy", self.compute_initial_E())
Exemple #19
0
def _process_hessian_symmetry_block(H_block, B_block, massweighter, irrep, print_lvl):
    """Perform post-construction processing for a symmetry block of the Hessian.
       Statements need to be printed, and the Hessian must be made orthogonal.

    Parameters
    ---------
    H_block : ndarray
        A block of the Hessian for an irrep, in mass-weighted salcs.
        Dimensions # cdsalcs by # cdsalcs.
    B_block : ndarray
        A block of the B matrix for an irrep, which transforms CdSalcs to Cartesians.
        Dimensions # cdsalcs by # cartesians.
    massweighter : ndarray
        The mass associated with each atomic coordinate.
        Dimension # cartesians. Due to x, y, z, values appear in groups of three.
    irrep : str
        A string identifying the irrep H_block and B_block are of.
    print_lvl : int
        The level of printing information requested by the user.

    Returns
    -------
    H_block : ndarray
        H_block, but made into an orthogonal array.
    """

    # Symmetrize our Hessian block.
    # The symmetric structure is lost due to errors in the computation
    H_block = (H_block + H_block.T) / 2.0

    if print_lvl >= 3:
        core.print_out("\n    Force Constants for irrep {} in mass-weighted, ".format(irrep))
        core.print_out("symmetry-adapted cartesian coordinates.\n")
        core.print_out("\n{}\n".format(np.array_str(H_block, **array_format)))

    evals, evects = np.linalg.eigh(H_block)
    # Get our eigenvalues and eigenvectors in descending order.
    idx = evals.argsort()[::-1]
    evals = evals[idx]
    evects = evects[:, idx]

    normal_irr = np.dot((B_block * massweighter).T, evects)

    if print_lvl >= 2:
        core.print_out("\n    Normal coordinates (non-mass-weighted) for irrep {}:\n".format(irrep))
        core.print_out("\n{}\n".format(np.array_str(normal_irr, **array_format)))

    return H_block
Exemple #20
0
def _print_matrix(descriptors, content, title):
    length = len(descriptors)

    matrix_header = '         ' + ' {:^10}' * length + '\n'
    core.print_out(matrix_header.format(*descriptors))
    core.print_out('    -----' + ' ----------' * length + '\n')

    for i, desc in enumerate(descriptors):
        core.print_out('    {:^5}'.format(desc))
        for j in range(length):
            core.print_out(' {:>10.5f}'.format(content[i, j]))

            # Set the name
            var_name = title + " " + descriptors[i] + descriptors[j]
            core.set_variable(var_name, content[i, j])
        core.print_out('\n')
Exemple #21
0
def _psi4_true_raise_handler(passfail, label, message, return_message=False, quiet=False):
    """Handle comparison result by printing to screen, printing to Psi output file, raising TestComparisonError, and (incidently) returning."""

    width = 66
    if passfail:
        if not quiet:
            core.print_out(f'    {label:.<{width}}PASSED\n')
            print(f'    {label:.<{width}}PASSED')
            sys.stdout.flush()
    else:
        core.print_out(f'    {label:.<{width}}FAILED')
        print(f'    {label:.<{width}}FAILED')
        sys.stdout.flush()
        raise TestComparisonError(message)

    return passfail
    def print_out(self):
        """Format dispersion parameters of `self` for output file."""

        text = []
        text.append("   => %s: Empirical Dispersion <=" % (self.fctldash.upper() if self.fctldash.upper() else 'Custom'))
        text.append('')
        text.append(self.description)
        text.append(self.dashlevel_citation.rstrip())
        if self.dashparams_citation:
            text.append("    Parametrisation from:{}".format(self.dashparams_citation.rstrip()))
        text.append('')
        for op in self.ordered_params:
            text.append("    %6s = %14.6f" % (op, self.dashparams[op]))
        text.append('\n')

        core.print_out('\n'.join(text))
Exemple #23
0
def pybuild_basis(mol, key=None, target=None, fitrole='ORBITAL', other=None, puream=-1, return_atomlist=False, quiet=False):
    horde = qcdb.libmintsbasisset.basishorde

    if key == 'ORBITAL':
        key = 'BASIS'

    if horde and key:
        tmp = horde.get(core.get_global_option(key), None)
        if tmp:
            target = tmp
        elif target:
            pass
        elif tmp is None:
            target = None
    elif target:
        pass
    elif key is None:
        target = core.get_global_option("BASIS")
        key = 'BASIS'
    else:
        target = core.get_global_option(key)

    basisdict = qcdb.BasisSet.pyconstruct(mol.create_psi4_string_from_molecule(),
                                          key, target, fitrole, other, return_atomlist=return_atomlist)
    if return_atomlist:
        atom_basis_list = []
        for atbs in basisdict:
            atommol = core.Molecule.create_molecule_from_string(atbs['molecule'])
            lmbs = core.BasisSet.construct_from_pydict(atommol, atbs, puream)
            atom_basis_list.append(lmbs)
            #lmbs.print_detail_out()
        return atom_basis_list

    if not quiet:
        core.print_out(basisdict['message'])

    psibasis = core.BasisSet.construct_from_pydict(mol, basisdict, puream)
    ecpbasis = None
    if 'ecp_shell_map' in basisdict:
        ecpbasis = core.BasisSet.construct_ecp_from_pydict(mol, basisdict, puream)

    if key == 'BASIS':
        # For orbitals basis sets, we need to return ECP also
        return psibasis, ecpbasis
    else:
        # There is no ECP basis for auxilliary basis sets
        return psibasis
Exemple #24
0
    def set_cholesky_from(mtd_type):
        type_val = core.get_global_option(mtd_type)
        if type_val == 'CD':
            core.set_local_option('GPU_DFCC', 'DF_BASIS_CC', 'CHOLESKY')
            # Alter default algorithm
            if not core.has_global_option_changed('SCF_TYPE'):
                optstash.add_option(['SCF_TYPE'])
                core.set_global_option('SCF_TYPE', 'CD')
                core.print_out("""    SCF Algorithm Type (re)set to CD.\n""")

        elif type_val in ['DF', 'DISK_DF']:
            if core.get_option('GPU_DFCC', 'DF_BASIS_CC') == 'CHOLESKY':
                core.set_local_option('GPU_DFCC', 'DF_BASIS_CC', '')

            proc_util.check_disk_df(name.upper(), optstash)
        else:
            raise ValidationError("""Invalid type '%s' for DFCC""" % type_val)
Exemple #25
0
def scf_compute_energy(self):
    """Base class Wavefunction requires this function. Here it is
    simply a wrapper around initialize(), iterations(), finalize_energy(). It
    returns the SCF energy computed by finalize_energy().

    """
    if core.get_option('SCF', 'DF_SCF_GUESS') and (core.get_global_option('SCF_TYPE') == 'DIRECT'):
        # speed up DIRECT algorithm (recomputes full (non-DF) integrals
        #   each iter) by first converging via fast DF iterations, then
        #   fully converging in fewer slow DIRECT iterations. aka Andy trick 2.0
        core.print_out("  Starting with a DF guess...\n\n")
        with p4util.OptionsStateCM(['SCF_TYPE']):
            core.set_global_option('SCF_TYPE', 'DF')
            self.initialize()
            try:
                self.iterations()
            except SCFConvergenceError:
                self.finalize()
                raise SCFConvergenceError("""SCF DF preiterations""", self.iteration_, self, 0, 0)
        core.print_out("\n  DF guess converged.\n\n")

        # reset the DIIS & JK objects in prep for DIRECT
        if self.initialized_diis_manager_:
            self.diis_manager().reset_subspace()
        self.initialize_jk(self.memory_jk_)
    else:
        self.initialize()

    try:
        self.iterations()
    except SCFConvergenceError as e:
        if core.get_option("SCF", "FAIL_ON_MAXITER"):
            core.print_out("  Failed to converge.\n")
            # energy = 0.0
            # A P::e fn to either throw or protest upon nonconvergence
            # die_if_not_converged()
            raise e
        else:
            core.print_out("  Energy did not converge, but proceeding anyway.\n\n")
    else:
        core.print_out("  Energy converged.\n\n")

    scf_energy = self.finalize_energy()
    return scf_energy
Exemple #26
0
def _diag_print_converged(solver_name, stats, vals, verbose=1, **kwargs):
    """Print a message to the output file when the solver is converged."""
    if verbose < 1:
        # no printing
        return
    if verbose >= 1:
        # print values summary + number of iterations + # of "big" product evals
        core.print_out(" {} converged in {} iterations\n".format(solver_name, stats[-1]['count']))
        core.print_out("  Root #    eigenvalue\n")
        for (i, vi) in enumerate(vals):
            core.print_out("  {:^6}    {:20.12f}\n".format(i + 1, vi))
        max_nvec = max(istat['nvec'] for istat in stats)
        core.print_out("  Computed a total of {} Large products\n\n".format(stats[-1]['product_count']))
Exemple #27
0
def _print_nbody_energy(energy_body_dict, header):
        core.print_out("""\n   ==> N-Body: %s  energies <==\n\n""" % header)
        core.print_out("""   n-Body     Total Energy [Eh]       I.E. [kcal/mol]      Delta [kcal/mol]\n""")
        previous_e = energy_body_dict[1]
        nbody_range = list(energy_body_dict)
        nbody_range.sort()
        for n in nbody_range:
            delta_e = (energy_body_dict[n] - previous_e)
            delta_e_kcal = delta_e * constants.hartree2kcalmol
            int_e_kcal = (energy_body_dict[n] - energy_body_dict[1]) * constants.hartree2kcalmol
            core.print_out("""     %4s  %20.12f  %20.12f  %20.12f\n""" %
                                        (n, energy_body_dict[n], int_e_kcal, delta_e_kcal))
            previous_e = energy_body_dict[n]
        core.print_out("\n")
Exemple #28
0
def _print_header(complete_dict, n_user):
    core.print_out('\n\n         ---------------------------------------------------------\n'
                   '         {:^57}\n'.format('CPSCF Linear Response Solver') +
                   '         {:^57}\n'.format('by Marvin Lechner and Daniel Smith') +
                   '         ---------------------------------------------------------\n')

    core.print_out('\n   ==> Requested Responses <==\n\n')

    for prop in complete_dict:
        if 'User' not in prop['name']:
            core.print_out('    {}\n'.format(prop['name']))

    if n_user != 0:
        core.print_out('    {} user-supplied vector(s)\n'.format(n_user))
Exemple #29
0
def auto_fragments(**kwargs):
    r"""Detects fragments in unfragmented molecule using BFS algorithm.
    Currently only used for the WebMO implementation of SAPT.

    Parameters
    ----------
    molecule : :ref:`molecule <op_py_molecule>`, optional
        The target molecule, if not the last molecule defined.
    seed_atoms : list, optional
        List of lists of atoms (0-indexed) belonging to independent fragments.
        Useful to prompt algorithm or to define intramolecular fragments through
        border atoms. Example: `[[1, 0], [2]]`

    Returns
    -------
    :py:class:`~psi4.core.Molecule` |w--w| fragmented molecule in
    Cartesian, fixed-geom (no variable values), no dummy-atom format.

    Examples
    --------
    >>> # [1] prepare unfragmented (and non-adjacent-atom) HHFF into (HF)_2 molecule ready for SAPT
    >>> molecule mol {\nH 0.0 0.0 0.0\nH 2.0 0.0 0.0\nF 0.0 1.0 0.0\nF 2.0 1.0 0.0\n}
    >>> print mol.nfragments()  # 1
    >>> fragmol = auto_fragments()
    >>> print fragmol.nfragments()  # 2

    """
    # Make sure the molecule the user provided is the active one
    molecule = kwargs.pop('molecule', core.get_active_molecule())
    seeds = kwargs.pop('seed_atoms', None)
    molecule.update_geometry()
    molname = molecule.name()

    frag, bmol = molecule.BFS(seed_atoms=seeds, return_molecule=True)

    bmol.set_name(molname)
    bmol.print_cluster()
    core.print_out("""  Exiting auto_fragments\n""")

    return bmol
    def compute_hessian(self, molecule):
        """Compute dispersion Hessian based on engine, dispersion level, and parameters in `self`.
        Uses finite difference, as no dispersion engine has analytic second derivatives.

        Parameters
        ----------
        molecule : psi4.core.Molecule
            System for which to compute empirical dispersion correction.

        Returns
        -------
        psi4.core.Matrix
            (3*nat, 3*nat) dispersion Hessian [Eh/a0/a0].

        """
        optstash = p4util.OptionsState(['PRINT'])
        core.set_global_option('PRINT', 0)

        core.print_out("\n\n   Analytical Dispersion Hessians are not supported by dftd3 or gcp.\n")
        core.print_out("       Computing the Hessian through finite difference of gradients.\n\n")

        # Setup the molecule
        molclone = molecule.clone()
        molclone.reinterpret_coordentry(False)
        molclone.fix_orientation(True)
        molclone.fix_com(True)

        # Record undisplaced symmetry for projection of diplaced point groups
        core.set_parent_symmetry(molecule.schoenflies_symbol())

        findif_meta_dict = driver_findif.hessian_from_gradient_geometries(molclone, -1)
        for displacement in findif_meta_dict["displacements"].values():
            geom_array = np.reshape(displacement["geometry"], (-1, 3))
            molclone.set_geometry(core.Matrix.from_array(geom_array))
            molclone.update_geometry()
            displacement["gradient"] = self.compute_gradient(molclone).np.ravel().tolist()

        H = driver_findif.compute_hessian_from_gradients(findif_meta_dict, -1)
        optstash.restore()
        return core.Matrix.from_array(H)
Exemple #31
0
def mcscf_solver(ref_wfn):

    # Build CIWavefunction
    core.prepare_options_for_module("DETCI")
    ciwfn = core.CIWavefunction(ref_wfn)
    ciwfn.set_module("detci")

    # Hush a lot of CI output
    ciwfn.set_print(0)

    # Begin with a normal two-step
    step_type = 'Initial CI'
    total_step = core.Matrix("Total step", ciwfn.get_dimension('OA'),
                             ciwfn.get_dimension('AV'))
    start_orbs = ciwfn.get_orbitals("ROT").clone()
    ciwfn.set_orbitals("ROT", start_orbs)

    # Grab da options
    mcscf_orb_grad_conv = core.get_option("DETCI", "MCSCF_R_CONVERGENCE")
    mcscf_e_conv = core.get_option("DETCI", "MCSCF_E_CONVERGENCE")
    mcscf_max_macroiteration = core.get_option("DETCI", "MCSCF_MAXITER")
    mcscf_type = core.get_option("DETCI", "MCSCF_TYPE")
    mcscf_d_file = core.get_option("DETCI", "CI_FILE_START") + 3
    mcscf_nroots = core.get_option("DETCI", "NUM_ROOTS")
    mcscf_wavefunction_type = core.get_option("DETCI", "WFN")
    mcscf_ndet = ciwfn.ndet()
    mcscf_nuclear_energy = ciwfn.molecule().nuclear_repulsion_energy()
    mcscf_steplimit = core.get_option("DETCI", "MCSCF_MAX_ROT")
    mcscf_rotate = core.get_option("DETCI", "MCSCF_ROTATE")

    # DIIS info
    mcscf_diis_start = core.get_option("DETCI", "MCSCF_DIIS_START")
    mcscf_diis_freq = core.get_option("DETCI", "MCSCF_DIIS_FREQ")
    mcscf_diis_error_type = core.get_option("DETCI", "MCSCF_DIIS_ERROR_TYPE")
    mcscf_diis_max_vecs = core.get_option("DETCI", "MCSCF_DIIS_MAX_VECS")

    # One-step info
    mcscf_target_conv_type = core.get_option("DETCI", "MCSCF_ALGORITHM")
    mcscf_so_start_grad = core.get_option("DETCI", "MCSCF_SO_START_GRAD")
    mcscf_so_start_e = core.get_option("DETCI", "MCSCF_SO_START_E")
    mcscf_current_step_type = 'Initial CI'

    # Start with SCF energy and other params
    scf_energy = ciwfn.variable("HF TOTAL ENERGY")
    eold = scf_energy
    norb_iter = 1
    converged = False
    ah_step = False
    qc_step = False
    approx_integrals_only = True

    # Fake info to start with the initial diagonalization
    ediff = 1.e-4
    orb_grad_rms = 1.e-3

    # Grab needed objects
    diis_obj = solvers.DIIS(mcscf_diis_max_vecs)
    mcscf_obj = ciwfn.mcscf_object()

    # Execute the rotate command
    for rot in mcscf_rotate:
        if len(rot) != 4:
            raise p4util.PsiException(
                "Each element of the MCSCF rotate command requires 4 arguements (irrep, orb1, orb2, theta)."
            )

        irrep, orb1, orb2, theta = rot
        if irrep > ciwfn.Ca().nirrep():
            raise p4util.PsiException(
                "MCSCF_ROTATE: Expression %s irrep number is larger than the number of irreps"
                % (str(rot)))

        if max(orb1, orb2) > ciwfn.Ca().coldim()[irrep]:
            raise p4util.PsiException(
                "MCSCF_ROTATE: Expression %s orbital number exceeds number of orbitals in irrep"
                % (str(rot)))

        theta = np.deg2rad(theta)

        x = ciwfn.Ca().nph[irrep][:, orb1].copy()
        y = ciwfn.Ca().nph[irrep][:, orb2].copy()

        xp = np.cos(theta) * x - np.sin(theta) * y
        yp = np.sin(theta) * x + np.cos(theta) * y

        ciwfn.Ca().nph[irrep][:, orb1] = xp
        ciwfn.Ca().nph[irrep][:, orb2] = yp

    # Limited RAS functionality
    if core.get_local_option(
            "DETCI", "WFN") == "RASSCF" and mcscf_target_conv_type != "TS":
        core.print_out(
            "\n  Warning! Only the TS algorithm for RASSCF wavefunction is currently supported.\n"
        )
        core.print_out("             Switching to the TS algorithm.\n\n")
        mcscf_target_conv_type = "TS"

    # Print out headers
    if mcscf_type == "CONV":
        mtype = "   @MCSCF"
        core.print_out("\n   ==> Starting MCSCF iterations <==\n\n")
        core.print_out(
            "        Iter         Total Energy       Delta E   Orb RMS    CI RMS  NCI NORB\n"
        )
    elif mcscf_type == "DF":
        mtype = "   @DF-MCSCF"
        core.print_out("\n   ==> Starting DF-MCSCF iterations <==\n\n")
        core.print_out(
            "           Iter         Total Energy       Delta E   Orb RMS    CI RMS  NCI NORB\n"
        )
    else:
        mtype = "   @AO-MCSCF"
        core.print_out("\n   ==> Starting AO-MCSCF iterations <==\n\n")
        core.print_out(
            "           Iter         Total Energy       Delta E   Orb RMS    CI RMS  NCI NORB\n"
        )

    # Iterate !
    for mcscf_iter in range(1, mcscf_max_macroiteration + 1):

        # Transform integrals, diagonalize H
        ciwfn.transform_mcscf_integrals(approx_integrals_only)
        nci_iter = ciwfn.diag_h(abs(ediff) * 1.e-2, orb_grad_rms * 1.e-3)

        # After the first diag we need to switch to READ
        ciwfn.set_ci_guess("DFILE")

        ciwfn.form_opdm()
        ciwfn.form_tpdm()
        ci_grad_rms = ciwfn.variable("DETCI AVG DVEC NORM")

        # Update MCSCF object
        Cocc = ciwfn.get_orbitals("DOCC")
        Cact = ciwfn.get_orbitals("ACT")
        Cvir = ciwfn.get_orbitals("VIR")
        opdm = ciwfn.get_opdm(-1, -1, "SUM", False)
        tpdm = ciwfn.get_tpdm("SUM", True)
        mcscf_obj.update(Cocc, Cact, Cvir, opdm, tpdm)

        current_energy = ciwfn.variable("MCSCF TOTAL ENERGY")

        ciwfn.reset_ci_H0block()

        orb_grad_rms = mcscf_obj.gradient_rms()
        ediff = current_energy - eold

        # Print iterations
        print_iteration(mtype, mcscf_iter, current_energy, ediff, orb_grad_rms,
                        ci_grad_rms, nci_iter, norb_iter,
                        mcscf_current_step_type)
        eold = current_energy

        if mcscf_current_step_type == 'Initial CI':
            mcscf_current_step_type = 'TS'

        # Check convergence
        if (orb_grad_rms < mcscf_orb_grad_conv) and (abs(ediff) < abs(mcscf_e_conv)) and\
            (mcscf_iter > 3) and not qc_step:

            core.print_out("\n       %s has converged!\n\n" % mtype)
            converged = True
            break

        # Which orbital convergence are we doing?
        if ah_step:
            converged, norb_iter, step = ah_iteration(mcscf_obj,
                                                      print_micro=False)
            norb_iter += 1

            if converged:
                mcscf_current_step_type = 'AH'
            else:
                core.print_out(
                    "      !Warning. Augmented Hessian did not converge. Taking an approx step.\n"
                )
                step = mcscf_obj.approx_solve()
                mcscf_current_step_type = 'TS, AH failure'

        else:
            step = mcscf_obj.approx_solve()
            step_type = 'TS'

        maxstep = step.absmax()
        if maxstep > mcscf_steplimit:
            core.print_out(
                '      Warning! Maxstep = %4.2f, scaling to %4.2f\n' %
                (maxstep, mcscf_steplimit))
            step.scale(mcscf_steplimit / maxstep)

        xstep = total_step.clone()
        total_step.add(step)

        # Do or add DIIS
        if (mcscf_iter >= mcscf_diis_start) and ("TS"
                                                 in mcscf_current_step_type):

            # Figure out DIIS error vector
            if mcscf_diis_error_type == "GRAD":
                error = core.triplet(ciwfn.get_orbitals("OA"),
                                     mcscf_obj.gradient(),
                                     ciwfn.get_orbitals("AV"), False, False,
                                     True)
            else:
                error = step

            diis_obj.add(total_step, error)

            if not (mcscf_iter % mcscf_diis_freq):
                total_step = diis_obj.extrapolate()
                mcscf_current_step_type = 'TS, DIIS'

        # Build the rotation by continuous updates
        if mcscf_iter == 1:
            totalU = mcscf_obj.form_rotation_matrix(total_step)
        else:
            xstep.axpy(-1.0, total_step)
            xstep.scale(-1.0)
            Ustep = mcscf_obj.form_rotation_matrix(xstep)
            totalU = core.doublet(totalU, Ustep, False, False)

        # Build the rotation directly (not recommended)
        # orbs_mat = mcscf_obj.Ck(start_orbs, total_step)

        # Finally rotate and set orbitals
        orbs_mat = core.doublet(start_orbs, totalU, False, False)
        ciwfn.set_orbitals("ROT", orbs_mat)

        # Figure out what the next step should be
        if (orb_grad_rms < mcscf_so_start_grad) and (abs(ediff) < abs(mcscf_so_start_e)) and\
                (mcscf_iter >= 2):

            if mcscf_target_conv_type == 'AH':
                approx_integrals_only = False
                ah_step = True
            elif mcscf_target_conv_type == 'OS':
                approx_integrals_only = False
                mcscf_current_step_type = 'OS, Prep'
                break
            else:
                continue
        #raise p4util.PsiException("")

    # If we converged do not do onestep
    if converged or (mcscf_target_conv_type != 'OS'):
        one_step_iters = []

    # If we are not converged load in Dvec and build iters array
    else:
        one_step_iters = range(mcscf_iter + 1, mcscf_max_macroiteration + 1)
        dvec = ciwfn.D_vector()
        dvec.init_io_files(True)
        dvec.read(0, 0)
        dvec.symnormalize(1.0, 0)

        ci_grad = ciwfn.new_civector(1, mcscf_d_file + 1, True, True)
        ci_grad.set_nvec(1)
        ci_grad.init_io_files(True)

    # Loop for onestep
    for mcscf_iter in one_step_iters:

        # Transform integrals and update the MCSCF object
        ciwfn.transform_mcscf_integrals(ciwfn.H(), False)
        ciwfn.form_opdm()
        ciwfn.form_tpdm()

        # Update MCSCF object
        Cocc = ciwfn.get_orbitals("DOCC")
        Cact = ciwfn.get_orbitals("ACT")
        Cvir = ciwfn.get_orbitals("VIR")
        opdm = ciwfn.get_opdm(-1, -1, "SUM", False)
        tpdm = ciwfn.get_tpdm("SUM", True)
        mcscf_obj.update(Cocc, Cact, Cvir, opdm, tpdm)

        orb_grad_rms = mcscf_obj.gradient_rms()

        # Warning! Does not work for SA-MCSCF
        current_energy = mcscf_obj.current_total_energy()
        current_energy += mcscf_nuclear_energy

        ciwfn.set_variable("CI ROOT %d TOTAL ENERGY" % 1, current_energy)
        ciwfn.set_variable("CURRENT ENERGY", current_energy)
        ciwfn.set_energy(current_energy)

        docc_energy = mcscf_obj.current_docc_energy()
        ci_energy = mcscf_obj.current_ci_energy()

        # Compute CI gradient
        ciwfn.sigma(dvec, ci_grad, 0, 0)
        ci_grad.scale(2.0, 0)
        ci_grad.axpy(-2.0 * ci_energy, dvec, 0, 0)

        ci_grad_rms = ci_grad.norm(0)
        orb_grad_rms = mcscf_obj.gradient().rms()

        ediff = current_energy - eold

        print_iteration(mtype, mcscf_iter, current_energy, ediff, orb_grad_rms,
                        ci_grad_rms, nci_iter, norb_iter,
                        mcscf_current_step_type)
        mcscf_current_step_type = 'OS'

        eold = current_energy

        if (orb_grad_rms < mcscf_orb_grad_conv) and (abs(ediff) <
                                                     abs(mcscf_e_conv)):

            core.print_out("\n       %s has converged!\n\n" % mtype)
            converged = True
            break

        # Take a step
        converged, norb_iter, nci_iter, step = qc_iteration(
            dvec, ci_grad, ciwfn, mcscf_obj)

        # Rotate integrals to new frame
        total_step.add(step)
        orbs_mat = mcscf_obj.Ck(ciwfn.get_orbitals("ROT"), step)
        ciwfn.set_orbitals("ROT", orbs_mat)

    core.print_out(mtype + " Final Energy: %20.15f\n" % current_energy)

    # Die if we did not converge
    if (not converged):
        if core.get_global_option("DIE_IF_NOT_CONVERGED"):
            raise p4util.PsiException("MCSCF: Iterations did not converge!")
        else:
            core.print_out("\nWarning! MCSCF iterations did not converge!\n\n")

    # Print out CI vector information
    if mcscf_target_conv_type == 'OS':
        dvec.close_io_files()
        ci_grad.close_io_files()

    # For orbital invariant methods we transform the orbitals to the natural or
    # semicanonical basis. Frozen doubly occupied and virtual orbitals are not
    # modified.
    if core.get_option("DETCI", "WFN") == "CASSCF":
        # Do we diagonalize the opdm?
        if core.get_option("DETCI", "NAT_ORBS"):
            ciwfn.ci_nat_orbs()
        else:
            ciwfn.semicanonical_orbs()

        # Retransform intragrals and update CI coeffs., OPDM, and TPDM
        ciwfn.transform_mcscf_integrals(approx_integrals_only)
        ciwfn.set_print(1)
        ciwfn.set_ci_guess("H0_BLOCK")
        nci_iter = ciwfn.diag_h(mcscf_e_conv, mcscf_e_conv**0.5)

        ciwfn.form_opdm()
        ciwfn.form_tpdm()

    proc_util.print_ci_results(ciwfn,
                               "MCSCF",
                               scf_energy,
                               current_energy,
                               print_opdm_no=True)

    # Set final energy
    ciwfn.set_variable("CURRENT ENERGY", ciwfn.variable("MCSCF TOTAL ENERGY"))
    ciwfn.set_energy(ciwfn.variable("MCSCF TOTAL ENERGY"))

    # What do we need to cleanup?
    if core.get_option("DETCI", "MCSCF_CI_CLEANUP"):
        ciwfn.cleanup_ci()
    if core.get_option("DETCI", "MCSCF_DPD_CLEANUP"):
        ciwfn.cleanup_dpd()

    del diis_obj
    del mcscf_obj
    return ciwfn
Exemple #32
0
def print_iteration(mtype, niter, energy, de, orb_rms, ci_rms, nci, norb,
                    stype):
    core.print_out(
        "%s %2d:  % 18.12f   % 1.4e  %1.2e  %1.2e  %3d  %3d  %s\n" %
        (mtype, niter, energy, de, orb_rms, ci_rms, nci, norb, stype))
Exemple #33
0
def fcidump(wfn, fname='INTDUMP', oe_ints=None):
    """Save integrals to file in FCIDUMP format as defined in Comp. Phys. Commun. 54 75 (1989)
    Additional one-electron integrals, including orbital energies, can also be saved.
    This latter format can be used with the HANDE QMC code but is not standard.

    :returns: None

    :raises: ValidationError when SCF wavefunction is not RHF

    :type wfn: :py:class:`~psi4.core.Wavefunction`
    :param wfn: set of molecule, basis, orbitals from which to generate cube files
    :param fname: name of the integrals file, defaults to INTDUMP
    :param oe_ints: list of additional one-electron integrals to save to file.
    So far only EIGENVALUES is a valid option.

    :examples:

    >>> # [1] Save one- and two-electron integrals to standard FCIDUMP format
    >>> E, wfn = energy('scf', return_wfn=True)
    >>> fcidump(wfn)

    >>> # [2] Save orbital energies, one- and two-electron integrals.
    >>> E, wfn = energy('scf', return_wfn=True)
    >>> fcidump(wfn, oe_ints=['EIGENVALUES'])

    """
    # Get some options
    reference = core.get_option('SCF', 'REFERENCE')
    ints_tolerance = core.get_global_option('INTS_TOLERANCE')
    # Some sanity checks
    if reference not in ['RHF', 'UHF']:
        raise ValidationError(
            'FCIDUMP not implemented for {} references\n'.format(reference))
    if oe_ints is None:
        oe_ints = []

    molecule = wfn.molecule()
    docc = wfn.doccpi()
    frzcpi = wfn.frzcpi()
    frzvpi = wfn.frzvpi()
    active_docc = docc - frzcpi
    active_socc = wfn.soccpi()
    active_mopi = wfn.nmopi() - frzcpi - frzvpi

    nbf = active_mopi.sum() if wfn.same_a_b_orbs() else 2 * active_mopi.sum()
    nirrep = wfn.nirrep()
    nelectron = 2 * active_docc.sum() + active_socc.sum()
    irrep_map = _irrep_map(wfn)

    wfn_irrep = 0
    for h, n_socc in enumerate(active_socc):
        if n_socc % 2 == 1:
            wfn_irrep ^= h

    core.print_out('Writing integrals in FCIDUMP format to ' + fname + '\n')
    # Generate FCIDUMP header
    header = '&FCI\n'
    header += 'NORB={:d},\n'.format(nbf)
    header += 'NELEC={:d},\n'.format(nelectron)
    header += 'MS2={:d},\n'.format(wfn.nalpha() - wfn.nbeta())
    header += 'UHF=.{}.,\n'.format(not wfn.same_a_b_orbs()).upper()
    orbsym = ''
    for h in range(active_mopi.n()):
        for n in range(frzcpi[h], frzcpi[h] + active_mopi[h]):
            orbsym += '{:d},'.format(irrep_map[h])
            if not wfn.same_a_b_orbs():
                orbsym += '{:d},'.format(irrep_map[h])
    header += 'ORBSYM={}\n'.format(orbsym)
    header += 'ISYM={:d},\n'.format(irrep_map[wfn_irrep])
    header += '&END\n'
    with open(fname, 'w') as intdump:
        intdump.write(header)

    # Get an IntegralTransform object
    check_iwl_file_from_scf_type(core.get_global_option('SCF_TYPE'), wfn)
    spaces = [core.MOSpace.all()]
    trans_type = core.IntegralTransform.TransformationType.Restricted
    if not wfn.same_a_b_orbs():
        trans_type = core.IntegralTransform.TransformationType.Unrestricted
    ints = core.IntegralTransform(wfn, spaces, trans_type)
    ints.transform_tei(core.MOSpace.all(), core.MOSpace.all(),
                       core.MOSpace.all(), core.MOSpace.all())
    core.print_out('Integral transformation complete!\n')

    DPD_info = {
        'instance_id': ints.get_dpd_id(),
        'alpha_MO': ints.DPD_ID('[A>=A]+'),
        'beta_MO': 0
    }
    if not wfn.same_a_b_orbs():
        DPD_info['beta_MO'] = ints.DPD_ID("[a>=a]+")
    # Write TEI to fname in FCIDUMP format
    core.fcidump_tei_helper(nirrep, wfn.same_a_b_orbs(), DPD_info,
                            ints_tolerance, fname)

    # Read-in OEI and write them to fname in FCIDUMP format
    # Indexing functions to translate from zero-based (C and Python) to
    # one-based (Fortran)
    mo_idx = lambda x: x + 1
    alpha_mo_idx = lambda x: 2 * x + 1
    beta_mo_idx = lambda x: 2 * (x + 1)

    with open(fname, 'a') as intdump:
        core.print_out('Writing frozen core operator in FCIDUMP format to ' +
                       fname + '\n')
        if reference == 'RHF':
            PSIF_MO_FZC = 'MO-basis Frozen-Core Operator'
            moH = core.Matrix(PSIF_MO_FZC, wfn.nmopi(), wfn.nmopi())
            moH.load(core.IO.shared_object(), psif.PSIF_OEI)
            mo_slice = core.Slice(frzcpi, active_mopi)
            MO_FZC = moH.get_block(mo_slice, mo_slice)
            offset = 0
            for h, block in enumerate(MO_FZC.nph):
                il = np.tril_indices(block.shape[0])
                for index, x in np.ndenumerate(block[il]):
                    row = mo_idx(il[0][index] + offset)
                    col = mo_idx(il[1][index] + offset)
                    if (abs(x) > ints_tolerance):
                        intdump.write(
                            '{:29.20E} {:4d} {:4d} {:4d} {:4d}\n'.format(
                                x, row, col, 0, 0))
                offset += block.shape[0]
            # Additional one-electron integrals as requested in oe_ints
            # Orbital energies
            core.print_out('Writing orbital energies in FCIDUMP format to ' +
                           fname + '\n')
            if 'EIGENVALUES' in oe_ints:
                eigs_dump = write_eigenvalues(
                    wfn.epsilon_a().get_block(mo_slice).to_array(), mo_idx)
                intdump.write(eigs_dump)
        else:
            PSIF_MO_A_FZC = 'MO-basis Alpha Frozen-Core Oper'
            moH_A = core.Matrix(PSIF_MO_A_FZC, wfn.nmopi(), wfn.nmopi())
            moH_A.load(core.IO.shared_object(), psif.PSIF_OEI)
            mo_slice = core.Slice(frzcpi, active_mopi)
            MO_FZC_A = moH_A.get_block(mo_slice, mo_slice)
            offset = 0
            for h, block in enumerate(MO_FZC_A.nph):
                il = np.tril_indices(block.shape[0])
                for index, x in np.ndenumerate(block[il]):
                    row = alpha_mo_idx(il[0][index] + offset)
                    col = alpha_mo_idx(il[1][index] + offset)
                    if (abs(x) > ints_tolerance):
                        intdump.write(
                            '{:29.20E} {:4d} {:4d} {:4d} {:4d}\n'.format(
                                x, row, col, 0, 0))
                offset += block.shape[0]
            PSIF_MO_B_FZC = 'MO-basis Beta Frozen-Core Oper'
            moH_B = core.Matrix(PSIF_MO_B_FZC, wfn.nmopi(), wfn.nmopi())
            moH_B.load(core.IO.shared_object(), psif.PSIF_OEI)
            mo_slice = core.Slice(frzcpi, active_mopi)
            MO_FZC_B = moH_B.get_block(mo_slice, mo_slice)
            offset = 0
            for h, block in enumerate(MO_FZC_B.nph):
                il = np.tril_indices(block.shape[0])
                for index, x in np.ndenumerate(block[il]):
                    row = beta_mo_idx(il[0][index] + offset)
                    col = beta_mo_idx(il[1][index] + offset)
                    if (abs(x) > ints_tolerance):
                        intdump.write(
                            '{:29.20E} {:4d} {:4d} {:4d} {:4d}\n'.format(
                                x, row, col, 0, 0))
                offset += block.shape[0]
            # Additional one-electron integrals as requested in oe_ints
            # Orbital energies
            core.print_out('Writing orbital energies in FCIDUMP format to ' +
                           fname + '\n')
            if 'EIGENVALUES' in oe_ints:
                alpha_eigs_dump = write_eigenvalues(
                    wfn.epsilon_a().get_block(mo_slice).to_array(),
                    alpha_mo_idx)
                beta_eigs_dump = write_eigenvalues(
                    wfn.epsilon_b().get_block(mo_slice).to_array(),
                    beta_mo_idx)
                intdump.write(alpha_eigs_dump + beta_eigs_dump)
        # Dipole integrals
        #core.print_out('Writing dipole moment OEI in FCIDUMP format to ' + fname + '\n')
        # Traceless quadrupole integrals
        #core.print_out('Writing traceless quadrupole moment OEI in FCIDUMP format to ' + fname + '\n')
        # Frozen core + nuclear repulsion energy
        core.print_out(
            'Writing frozen core + nuclear repulsion energy in FCIDUMP format to '
            + fname + '\n')
        e_fzc = ints.get_frozen_core_energy()
        e_nuc = molecule.nuclear_repulsion_energy(
            wfn.get_dipole_field_strength())
        intdump.write('{: 29.20E} {:4d} {:4d} {:4d} {:4d}\n'.format(
            e_fzc + e_nuc, 0, 0, 0, 0))
    core.print_out(
        'Done generating {} with integrals in FCIDUMP format.\n'.format(fname))
Exemple #34
0
def scf_iterate(self, e_conv=None, d_conv=None):

    is_dfjk = core.get_global_option('SCF_TYPE').endswith('DF')
    verbose = core.get_option('SCF', "PRINT")
    reference = core.get_option('SCF', "REFERENCE")

    # self.member_data_ signals are non-local, used internally by c-side fns
    self.diis_enabled_ = self.validate_diis()
    self.MOM_excited_ = _validate_MOM()
    self.diis_start_ = core.get_option('SCF', 'DIIS_START')
    damping_enabled = _validate_damping()
    soscf_enabled = _validate_soscf()
    frac_enabled = _validate_frac()
    efp_enabled = hasattr(self.molecule(), 'EFP')

    # does the JK algorithm use severe screening approximations for early SCF iterations?
    early_screening = self.jk().get_early_screening()

    # has early_screening changed from True to False?
    early_screening_disabled = False

    # SCF iterations!
    SCFE_old = 0.0
    Dnorm = 0.0
    while True:
        self.iteration_ += 1

        diis_performed = False
        soscf_performed = False
        self.frac_performed_ = False
        #self.MOM_performed_ = False  # redundant from common_init()

        self.save_density_and_energy()

        if efp_enabled:
            # EFP: Add efp contribution to Fock matrix
            self.H().copy(self.Horig)
            global mints_psi4_yo
            mints_psi4_yo = core.MintsHelper(self.basisset())
            Vefp = modify_Fock_induced(self.molecule().EFP,
                                       mints_psi4_yo,
                                       verbose=verbose - 1)
            Vefp = core.Matrix.from_array(Vefp)
            self.H().add(Vefp)

        SCFE = 0.0
        self.clear_external_potentials()

        # Two-electron contribution to Fock matrix from self.jk()
        core.timer_on("HF: Form G")
        self.form_G()
        core.timer_off("HF: Form G")

        # Check if special J/K construction algorithms were used
        incfock_performed = hasattr(
            self.jk(), "do_incfock_iter") and self.jk().do_incfock_iter()
        linK_performed = hasattr(self.jk(), "do_linK") and self.jk().do_linK()

        upcm = 0.0
        if core.get_option('SCF', 'PCM'):
            calc_type = core.PCM.CalcType.Total
            if core.get_option("PCM", "PCM_SCF_TYPE") == "SEPARATE":
                calc_type = core.PCM.CalcType.NucAndEle
            Dt = self.Da().clone()
            Dt.add(self.Db())
            upcm, Vpcm = self.get_PCM().compute_PCM_terms(Dt, calc_type)
            SCFE += upcm
            self.push_back_external_potential(Vpcm)
        self.set_variable("PCM POLARIZATION ENERGY", upcm)  # P::e PCM
        self.set_energies("PCM Polarization", upcm)

        upe = 0.0
        if core.get_option('SCF', 'PE'):
            Dt = self.Da().clone()
            Dt.add(self.Db())
            upe, Vpe = self.pe_state.get_pe_contribution(Dt, elec_only=False)
            SCFE += upe
            self.push_back_external_potential(Vpe)
        self.set_variable("PE ENERGY", upe)  # P::e PE
        self.set_energies("PE Energy", upe)

        core.timer_on("HF: Form F")
        # SAD: since we don't have orbitals yet, we might not be able
        # to form the real Fock matrix. Instead, build an initial one
        if (self.iteration_ == 0) and self.sad_:
            self.form_initial_F()
        else:
            self.form_F()
        core.timer_off("HF: Form F")

        if verbose > 3:
            self.Fa().print_out()
            self.Fb().print_out()

        SCFE += self.compute_E()
        if efp_enabled:
            global efp_Dt_psi4_yo

            # EFP: Add efp contribution to energy
            efp_Dt_psi4_yo = self.Da().clone()
            efp_Dt_psi4_yo.add(self.Db())
            SCFE += self.molecule().EFP.get_wavefunction_dependent_energy()

        self.set_energies("Total Energy", SCFE)
        core.set_variable("SCF ITERATION ENERGY", SCFE)
        Ediff = SCFE - SCFE_old
        SCFE_old = SCFE

        status = []

        # Check if we are doing SOSCF
        if (soscf_enabled and (self.iteration_ >= 3) and
            (Dnorm < core.get_option('SCF', 'SOSCF_START_CONVERGENCE'))):
            Dnorm = self.compute_orbital_gradient(
                False, core.get_option('SCF', 'DIIS_MAX_VECS'))
            diis_performed = False
            if self.functional().needs_xc():
                base_name = "SOKS, nmicro="
            else:
                base_name = "SOSCF, nmicro="

            if not _converged(Ediff, Dnorm, e_conv=e_conv, d_conv=d_conv):
                nmicro = self.soscf_update(
                    core.get_option('SCF', 'SOSCF_CONV'),
                    core.get_option('SCF', 'SOSCF_MIN_ITER'),
                    core.get_option('SCF', 'SOSCF_MAX_ITER'),
                    core.get_option('SCF', 'SOSCF_PRINT'))
                # if zero, the soscf call bounced for some reason
                soscf_performed = (nmicro > 0)

                if soscf_performed:
                    self.find_occupation()
                    status.append(base_name + str(nmicro))
                else:
                    if verbose > 0:
                        core.print_out(
                            "Did not take a SOSCF step, using normal convergence methods\n"
                        )

            else:
                # need to ensure orthogonal orbitals and set epsilon
                status.append(base_name + "conv")
                core.timer_on("HF: Form C")
                self.form_C()
                core.timer_off("HF: Form C")
                soscf_performed = True  # Stops DIIS

        if not soscf_performed:
            # Normal convergence procedures if we do not do SOSCF

            # SAD: form initial orbitals from the initial Fock matrix, and
            # reset the occupations. The reset is necessary because SAD
            # nalpha_ and nbeta_ are not guaranteed physical.
            # From here on, the density matrices are correct.
            if (self.iteration_ == 0) and self.sad_:
                self.form_initial_C()
                self.reset_occupation()
                self.find_occupation()

            else:
                # Run DIIS
                core.timer_on("HF: DIIS")
                diis_performed = False
                add_to_diis_subspace = self.diis_enabled_ and self.iteration_ >= self.diis_start_

                Dnorm = self.compute_orbital_gradient(
                    add_to_diis_subspace,
                    core.get_option('SCF', 'DIIS_MAX_VECS'))

                if add_to_diis_subspace:
                    for engine_used in self.diis(Dnorm):
                        status.append(engine_used)

                core.timer_off("HF: DIIS")

                if verbose > 4 and diis_performed:
                    core.print_out("  After DIIS:\n")
                    self.Fa().print_out()
                    self.Fb().print_out()

                # frac, MOM invoked here from Wfn::HF::find_occupation
                core.timer_on("HF: Form C")
                level_shift = core.get_option("SCF", "LEVEL_SHIFT")
                if level_shift > 0 and Dnorm > core.get_option(
                        'SCF', 'LEVEL_SHIFT_CUTOFF'):
                    status.append("SHIFT")
                    self.form_C(level_shift)
                else:
                    self.form_C()
                core.timer_off("HF: Form C")

                if self.MOM_performed_:
                    status.append("MOM")

                if self.frac_performed_:
                    status.append("FRAC")

                if incfock_performed:
                    status.append("INCFOCK")

                if linK_performed:
                    status.append("LINK")

                # Reset occupations if necessary
                if (self.iteration_ == 0) and self.reset_occ_:
                    self.reset_occupation()
                    self.find_occupation()

        # Form new density matrix
        core.timer_on("HF: Form D")
        self.form_D()
        core.timer_off("HF: Form D")

        self.set_variable("SCF ITERATION ENERGY", SCFE)
        core.set_variable("SCF D NORM", Dnorm)

        # After we've built the new D, damp the update
        if (damping_enabled and self.iteration_ > 1
                and Dnorm > core.get_option('SCF', 'DAMPING_CONVERGENCE')):
            damping_percentage = core.get_option('SCF', "DAMPING_PERCENTAGE")
            self.damping_update(damping_percentage * 0.01)
            status.append("DAMP={}%".format(round(damping_percentage)))

        if core.has_option_changed("SCF", "ORBITALS_WRITE"):
            filename = core.get_option("SCF", "ORBITALS_WRITE")
            self.to_file(filename)

        if verbose > 3:
            self.Ca().print_out()
            self.Cb().print_out()
            self.Da().print_out()
            self.Db().print_out()

        # Print out the iteration
        core.print_out(
            "   @%s%s iter %3s: %20.14f   %12.5e   %-11.5e %s\n" %
            ("DF-" if is_dfjk else "", reference, "SAD" if
             ((self.iteration_ == 0) and self.sad_) else self.iteration_, SCFE,
             Ediff, Dnorm, '/'.join(status)))

        # if a an excited MOM is requested but not started, don't stop yet
        # Note that MOM_performed_ just checks initialization, and our convergence measures used the pre-MOM orbitals
        if self.MOM_excited_ and ((not self.MOM_performed_) or self.iteration_
                                  == core.get_option('SCF', "MOM_START")):
            continue

        # if a fractional occupation is requested but not started, don't stop yet
        if frac_enabled and not self.frac_performed_:
            continue

        # this is the first iteration after early screening was turned off
        if early_screening_disabled:
            break

        # Call any postiteration callbacks
        if not ((self.iteration_ == 0) and self.sad_) and _converged(
                Ediff, Dnorm, e_conv=e_conv, d_conv=d_conv):

            if early_screening:

                # we've reached convergence with early screning enabled; disable it on the JK object
                early_screening = False
                self.jk().set_early_screening(early_screening)

                # make note of the change to early screening; next SCF iteration will be the last
                early_screening_disabled = True

                # clear any cached matrices associated with incremental fock construction
                # the change in the screening spoils the linearity in the density matrix
                if hasattr(self.jk(), 'clear_D_prev'):
                    self.jk().clear_D_prev()

                core.print_out(
                    "  Energy and wave function converged with early screening.\n"
                )
                core.print_out(
                    "  Performing final iteration with tighter screening.\n\n")
            else:
                break

        if self.iteration_ >= core.get_option('SCF', 'MAXITER'):
            raise SCFConvergenceError("""SCF iterations""", self.iteration_,
                                      self, Ediff, Dnorm)
Exemple #35
0
 def callback(output):
     core.print_out(f"{output}\n")
Exemple #36
0
def _pybuild_basis(mol,
                   key=None,
                   target=None,
                   fitrole='ORBITAL',
                   other=None,
                   puream=-1,
                   return_atomlist=False,
                   quiet=False):
    if key == 'ORBITAL':
        key = 'BASIS'

    def _resolve_target(key, target):
        """Figure out exactly what basis set was intended by (key, target)
        """
        horde = qcdb.libmintsbasisset.basishorde
        if not target:
            if not key:
                key = 'BASIS'
            target = core.get_global_option(key)

        if target in horde:
            return horde[target]
        return target

    # Figure out what exactly was meant by 'target'.
    resolved_target = _resolve_target(key, target)

    # resolved_target needs to be either a string or function for pyconstuct.
    # if a string, they search for a gbs file with that name.
    # if a function, it needs to apply a basis to each atom.

    bs, basisdict = qcdb.BasisSet.pyconstruct(mol.to_dict(),
                                              key,
                                              resolved_target,
                                              fitrole,
                                              other,
                                              return_dict=True,
                                              return_atomlist=return_atomlist)

    if return_atomlist:
        atom_basis_list = []
        for atbs in basisdict:
            atommol = core.Molecule.from_dict(atbs['molecule'])
            lmbs = core.BasisSet.construct_from_pydict(atommol, atbs, puream)
            atom_basis_list.append(lmbs)
        return atom_basis_list
    if isinstance(resolved_target, str):
        basisdict['name'] = basisdict['name'].split('/')[-1].replace(
            '.gbs', '')
    if callable(resolved_target):
        basisdict['name'] = resolved_target.__name__.replace(
            'basisspec_psi4_yo__', '').upper()

    if not quiet:
        core.print_out(basisdict['message'])
        if 'ECP' in basisdict['message']:
            core.print_out(
                '    !!!  WARNING: ECP capability is in beta. Please check occupations closely.  !!!\n\n'
            )

    if basisdict['key'] is None:
        basisdict['key'] = 'BASIS'
    psibasis = core.BasisSet.construct_from_pydict(mol, basisdict, puream)
    return psibasis
Exemple #37
0
def run_sapt_dft(name, **kwargs):
    optstash = p4util.OptionsState(['SCF', 'SCF_TYPE'], ['SCF', 'REFERENCE'],
                                   ['SCF', 'DFT_GRAC_SHIFT'],
                                   ['SCF', 'SAVE_JK'])

    core.tstart()
    # Alter default algorithm
    if not core.has_option_changed('SCF', 'SCF_TYPE'):
        core.set_local_option('SCF', 'SCF_TYPE', 'DF')

    core.prepare_options_for_module("SAPT")

    # Get the molecule of interest
    ref_wfn = kwargs.get('ref_wfn', None)
    if ref_wfn is None:
        sapt_dimer = kwargs.pop('molecule', core.get_active_molecule())
    else:
        core.print_out(
            'Warning! SAPT argument "ref_wfn" is only able to use molecule information.'
        )
        sapt_dimer = ref_wfn.molecule()

    sapt_dimer, monomerA, monomerB = proc_util.prepare_sapt_molecule(
        sapt_dimer, "dimer")

    # Grab overall settings
    mon_a_shift = core.get_option("SAPT", "SAPT_DFT_GRAC_SHIFT_A")
    mon_b_shift = core.get_option("SAPT", "SAPT_DFT_GRAC_SHIFT_B")
    do_delta_hf = core.get_option("SAPT", "SAPT_DFT_DO_DHF")
    sapt_dft_functional = core.get_option("SAPT", "SAPT_DFT_FUNCTIONAL")

    # Print out the title and some information
    core.print_out("\n")
    core.print_out(
        "         ---------------------------------------------------------\n")
    core.print_out("         " + "SAPT(DFT) Procedure".center(58) + "\n")
    core.print_out("\n")
    core.print_out("         " + "by Daniel G. A. Smith".center(58) + "\n")
    core.print_out(
        "         ---------------------------------------------------------\n")
    core.print_out("\n")

    core.print_out("  ==> Algorithm <==\n\n")
    core.print_out("   SAPT DFT Functional     %12s\n" %
                   str(sapt_dft_functional))
    core.print_out("   Monomer A GRAC Shift    %12.6f\n" % mon_a_shift)
    core.print_out("   Monomer B GRAC Shift    %12.6f\n" % mon_b_shift)
    core.print_out("   Delta HF                %12s\n" %
                   ("True" if do_delta_hf else "False"))
    core.print_out("   JK Algorithm            %12s\n" %
                   core.get_option("SCF", "SCF_TYPE"))
    core.print_out("\n")
    core.print_out("   Required computations:\n")
    if (do_delta_hf):
        core.print_out("     HF  (Dimer)\n")
        core.print_out("     HF  (Monomer A)\n")
        core.print_out("     HF  (Monomer B)\n")
    core.print_out("     DFT (Monomer A)\n")
    core.print_out("     DFT (Monomer B)\n")
    core.print_out("\n")

    if (sapt_dft_functional != "HF") and ((mon_a_shift == 0.0) or
                                          (mon_b_shift == 0.0)):
        raise ValidationError(
            'SAPT(DFT): must set both "SAPT_DFT_GRAC_SHIFT_A" and "B".')

    if (core.get_option('SCF', 'REFERENCE') != 'RHF'):
        raise ValidationError(
            'SAPT(DFT) currently only supports restricted references.')

    core.IO.set_default_namespace('dimer')
    data = {}

    if (core.get_option('SCF', 'SCF_TYPE') == 'DF'):
        # core.set_global_option('DF_INTS_IO', 'LOAD')
        core.set_global_option('DF_INTS_IO', 'SAVE')

    # # Compute dimer wavefunction
    hf_cache = {}
    hf_wfn_dimer = None
    if do_delta_hf:
        if (core.get_option('SCF', 'SCF_TYPE') == 'DF'):
            core.set_global_option('DF_INTS_IO', 'SAVE')

        hf_data = {}
        hf_wfn_dimer = scf_helper("SCF",
                                  molecule=sapt_dimer,
                                  banner="SAPT(DFT): delta HF Dimer",
                                  **kwargs)
        hf_data["HF DIMER"] = core.get_variable("CURRENT ENERGY")

        if (core.get_option('SCF', 'SCF_TYPE') == 'DF'):
            core.IO.change_file_namespace(97, 'dimer', 'monomerA')
        hf_wfn_A = scf_helper("SCF",
                              molecule=monomerA,
                              banner="SAPT(DFT): delta HF Monomer A",
                              **kwargs)
        hf_data["HF MONOMER A"] = core.get_variable("CURRENT ENERGY")

        core.set_global_option("SAVE_JK", True)
        if (core.get_option('SCF', 'SCF_TYPE') == 'DF'):
            core.IO.change_file_namespace(97, 'monomerA', 'monomerB')
        hf_wfn_B = scf_helper("SCF",
                              molecule=monomerB,
                              banner="SAPT(DFT): delta HF Monomer B",
                              **kwargs)
        hf_data["HF MONOMER B"] = core.get_variable("CURRENT ENERGY")
        core.set_global_option("SAVE_JK", False)

        # Move it back to monomer A
        if (core.get_option('SCF', 'SCF_TYPE') == 'DF'):
            core.IO.change_file_namespace(97, 'monomerB', 'dimer')

        core.print_out("\n")
        core.print_out(
            "         ---------------------------------------------------------\n"
        )
        core.print_out("         " +
                       "SAPT(DFT): delta HF Segement".center(58) + "\n")
        core.print_out("\n")
        core.print_out("         " +
                       "by Daniel G. A. Smith and Rob Parrish".center(58) +
                       "\n")
        core.print_out(
            "         ---------------------------------------------------------\n"
        )
        core.print_out("\n")

        # Build cache and JK
        sapt_jk = hf_wfn_B.jk()

        hf_cache = sapt_jk_terms.build_sapt_jk_cache(hf_wfn_A, hf_wfn_B,
                                                     sapt_jk, True)

        # Electostatics
        elst = sapt_jk_terms.electrostatics(hf_cache, True)
        hf_data.update(elst)

        # Exchange
        exch = sapt_jk_terms.exchange(hf_cache, sapt_jk, True)
        hf_data.update(exch)

        # Induction
        ind = sapt_jk_terms.induction(
            hf_cache,
            sapt_jk,
            True,
            maxiter=core.get_option("SAPT", "MAXITER"),
            conv=core.get_option("SAPT", "D_CONVERGENCE"),
            Sinf=core.get_option("SAPT", "DO_IND_EXCH_SINF"))
        hf_data.update(ind)

        dhf_value = hf_data["HF DIMER"] - hf_data["HF MONOMER A"] - hf_data[
            "HF MONOMER B"]

        core.print_out("\n")
        core.print_out(
            print_sapt_hf_summary(hf_data, "SAPT(HF)", delta_hf=dhf_value))

        data["Delta HF Correction"] = core.get_variable("SAPT(DFT) Delta HF")
        sapt_jk.finalize()

    if hf_wfn_dimer is None:
        dimer_wfn = core.Wavefunction.build(sapt_dimer,
                                            core.get_global_option("BASIS"))
    else:
        dimer_wfn = hf_wfn_dimer

    # Set the primary functional
    core.set_local_option('SCF', 'REFERENCE', 'RKS')

    # Compute Monomer A wavefunction
    if (core.get_option('SCF', 'SCF_TYPE') == 'DF'):
        core.IO.change_file_namespace(97, 'dimer', 'monomerA')

    if mon_a_shift:
        core.set_global_option("DFT_GRAC_SHIFT", mon_a_shift)

    # Save the JK object
    core.IO.set_default_namespace('monomerA')
    wfn_A = scf_helper(sapt_dft_functional,
                       post_scf=False,
                       molecule=monomerA,
                       banner="SAPT(DFT): DFT Monomer A",
                       **kwargs)
    data["DFT MONOMERA"] = core.get_variable("CURRENT ENERGY")

    core.set_global_option("DFT_GRAC_SHIFT", 0.0)

    # Compute Monomer B wavefunction
    if (core.get_option('SCF', 'SCF_TYPE') == 'DF'):
        core.IO.change_file_namespace(97, 'monomerA', 'monomerB')

    if mon_b_shift:
        core.set_global_option("DFT_GRAC_SHIFT", mon_b_shift)

    core.set_global_option("SAVE_JK", True)
    core.IO.set_default_namespace('monomerB')
    wfn_B = scf_helper(sapt_dft_functional,
                       post_scf=False,
                       molecule=monomerB,
                       banner="SAPT(DFT): DFT Monomer B",
                       **kwargs)
    data["DFT MONOMERB"] = core.get_variable("CURRENT ENERGY")

    core.set_global_option("DFT_GRAC_SHIFT", 0.0)

    # Write out header
    scf_alg = core.get_option("SCF", "SCF_TYPE")
    sapt_dft_header(sapt_dft_functional, mon_a_shift, mon_b_shift,
                    bool(do_delta_hf), scf_alg)

    # Call SAPT(DFT)
    sapt_jk = wfn_B.jk()
    sapt_dft(dimer_wfn,
             wfn_A,
             wfn_B,
             sapt_jk=sapt_jk,
             data=data,
             print_header=False)

    # Copy data back into globals
    for k, v in data.items():
        core.set_variable(k, v)

    core.tstop()

    return dimer_wfn
Exemple #38
0
def extract_sowreap_from_output(sowout,
                                quantity,
                                sownum,
                                linkage,
                                allvital=False,
                                label='electronic energy'):
    """Function to examine file *sowout* from a sow/reap distributed job
    for formatted line with electronic energy information about index
    *sownum* to be used for construction of *quantity* computations as
    directed by master input file with *linkage* kwarg. When file *sowout*
    is missing or incomplete files, function will either return zero
    (*allvital* is ``False``) or terminate (*allvital* is ``True``) since
    some sow/reap procedures can produce meaningful results (database)
    from an incomplete set of sown files, while others cannot (gradient,
    hessian).

    """
    warnings.warn(
        "Using `psi4.driver.p4util.extract_sowreap_from_output` is deprecated, and in 1.4 it will stop working\n",
        category=FutureWarning,
        stacklevel=2)

    E = 0.0

    try:
        freagent = open('%s.out' % (sowout), 'r')
    except IOError:
        if allvital:
            raise ValidationError(
                'Aborting upon output file \'%s.out\' not found.\n' % (sowout))
        else:
            return 0.0
    else:
        while True:
            line = freagent.readline()
            if not line:
                if E == 0.0:
                    raise ValidationError(
                        'Aborting upon output file \'%s.out\' has no %s RESULT line.\n'
                        % (sowout, quantity))
                break
            s = line.strip().split(None, 10)
            if (len(s) != 0) and (s[0:3]
                                  == [quantity, 'RESULT:', 'computation']):
                if int(s[3]) != linkage:
                    raise ValidationError(
                        'Output file \'%s.out\' has linkage %s incompatible with master.in linkage %s.'
                        % (sowout, str(s[3]), str(linkage)))
                if s[6] != str(sownum + 1):
                    raise ValidationError(
                        'Output file \'%s.out\' has nominal affiliation %s incompatible with item %s.'
                        % (sowout, s[6], str(sownum + 1)))
                if label == 'electronic energy' and s[8:10] == [
                        'electronic', 'energy'
                ]:
                    E = float(s[10])
                    core.print_out('%s RESULT: electronic energy = %20.12f\n' %
                                   (quantity, E))
                if label == 'electronic gradient' and s[8:10] == [
                        'electronic', 'gradient'
                ]:
                    E = ast.literal_eval(s[-1])
                    core.print_out('%s RESULT: electronic gradient = %r\n' %
                                   (quantity, E))
        freagent.close()
    return E
Exemple #39
0
def ah_iteration(mcscf_obj,
                 tol=1e-3,
                 max_iter=15,
                 lindep=1e-14,
                 print_micro=True):
    """
    Solve the generalized eigenvalue problem:
    | 0,  g.T | | 1/l | =   | 1/l |
    | g,  H/l | | X   | = e | X   |

    Where g is the gradient, H is the orbital Hessian, X is our orbital update step,
    and l is the eigenvalue.

    In some ways this is the subspace reduction of the full MCSCF Hessian where the
    CC part has been solved exactly. When this occurs the OC and CO elements collapse
    to the above and the CC Hessian becomes diagonally dominant.

    We can solve this through Davidson iterations where we condition the edges. It's the
    Pulay equations all over again, just iterative.

    Watch out for lambdas that are zero. Looking for the lambda that is ~1.

    """

    # Unpack information
    orb_grad = mcscf_obj.gradient()
    precon = mcscf_obj.H_approx_diag()
    approx_step = mcscf_obj.approx_solve()
    orb_grad_ssq = orb_grad.sum_of_squares()

    # Gears
    min_lambda = 0.3
    converged = False
    warning_neg = False
    warning_mult = False

    fullG = np.zeros((max_iter + 2, max_iter + 2))
    fullS = np.zeros((max_iter + 2, max_iter + 2))
    fullS[np.diag_indices_from(fullS)] = 1

    guesses = []
    sigma_list = []
    guesses.append(approx_step)
    sigma_list.append(mcscf_obj.compute_Hk(approx_step))

    if print_micro:
        core.print_out(
            "\n                             Eigenvalue          Rel dE          dX \n"
        )

    # Run Davidson look for lambda ~ 1
    old_val = 0
    for microi in range(1, max_iter + 1):

        # Gradient
        fullG[0, microi] = guesses[-1].vector_dot(orb_grad)
        for i in range(microi):
            fullG[i + 1, microi] = guesses[-1].vector_dot(sigma_list[i])
            fullS[i + 1, microi] = guesses[-1].vector_dot(guesses[i])

        fullG[microi] = fullG[:, microi]
        fullS[microi] = fullS[:, microi]

        wlast = old_val

        # Slice out relevant S and G
        S = fullS[:microi + 1, :microi + 1]
        G = fullG[:microi + 1, :microi + 1]

        # Solve Gv = lSv
        v, L = np.linalg.eigh(S)
        mask = v > (np.min(np.abs(v)) * 1.e-10)
        invL = L[:, mask] * (v[mask]**-0.5)

        # Solve in S basis, rotate back
        evals, evecs = np.linalg.eigh(np.dot(invL.T, G).dot(invL))
        vectors = np.dot(invL, evecs)

        # Figure out the right root to follow
        if np.sum(np.abs(vectors[0]) > min_lambda) == 0:
            raise PsiException("Augmented Hessian: Could not find the correct root!\n"\
                               "Try starting AH when the MCSCF wavefunction is more converged.")

        if np.sum(np.abs(vectors[0]) > min_lambda) > 1 and not warning_mult:
            core.print_out(
                "   Warning! Multiple eigenvectors found to follow. Following closest to \lambda = 1.\n"
            )
            warning_mult = True

        idx = (np.abs(1 - np.abs(vectors[0]))).argmin()
        lam = abs(vectors[0, idx])
        subspace_vec = vectors[1:, idx]

        # Negative roots should go away?
        if idx > 0 and evals[idx] < -5.0e-6 and not warning_neg:
            core.print_out(
                '   Warning! AH might follow negative eigenvalues!\n')
            warning_neg = True

        diff_val = evals[idx] - old_val
        old_val = evals[idx]

        new_guess = guesses[0].clone()
        new_guess.zero()
        for num, c in enumerate(subspace_vec / lam):
            new_guess.axpy(c, guesses[num])

        # Build estimated sigma vector
        new_dx = sigma_list[0].clone()
        new_dx.zero()
        for num, c in enumerate(subspace_vec):
            new_dx.axpy(c, sigma_list[num])

        # Consider restraints
        new_dx.axpy(lam, orb_grad)
        new_dx.axpy(old_val * lam, new_guess)

        norm_dx = (new_dx.sum_of_squares() / orb_grad_ssq)**0.5

        if print_micro:
            core.print_out(
                "      AH microiter %2d   % 18.12e   % 6.4e   % 6.4e\n" %
                (microi, evals[idx], diff_val / evals[idx], norm_dx))

        if abs(old_val - wlast) < tol and norm_dx < (tol**0.5):
            converged = True
            break

        # Apply preconditioner
        tmp = precon.clone()
        val = tmp.clone()
        val.set(evals[idx])
        tmp.subtract(val)
        new_dx.apply_denominator(tmp)

        guesses.append(new_dx)
        sigma_list.append(mcscf_obj.compute_Hk(new_dx))

    if print_micro and converged:
        core.print_out("\n")
        #    core.print_out("      AH converged!       \n\n")

    #if not converged:
    #    core.print_out("      !Warning. Augmented Hessian did not converge.\n")

    new_guess.scale(-1.0)

    return converged, microi, new_guess
Exemple #40
0
def run_qcschema(input_data, clean=True):

    outfile = os.path.join(core.IOManager.shared_object().get_default_path(),
                           str(uuid.uuid4()) + ".qcschema_tmpout")
    core.set_output_file(outfile, False)
    print_header()

    start_time = datetime.datetime.now()

    try:
        input_model = qcng.util.model_wrapper(input_data,
                                              qcel.models.AtomicInput)

        # Echo the infile on the outfile
        core.print_out("\n  ==> Input QCSchema <==\n")
        core.print_out(
            "\n--------------------------------------------------------------------------\n"
        )
        core.print_out(pp.pformat(json.loads(input_model.json())))
        core.print_out(
            "\n--------------------------------------------------------------------------\n"
        )

        keep_wfn = input_model.protocols.wavefunction != 'none'

        # qcschema should be copied
        ret_data = run_json_qcschema(input_model.dict(),
                                     clean,
                                     False,
                                     keep_wfn=keep_wfn)
        ret_data["provenance"] = {
            "creator": "Psi4",
            "version": __version__,
            "routine": "psi4.schema_runner.run_qcschema"
        }

        exit_printing(start_time=start_time, success=True)

        ret = qcel.models.AtomicResult(**ret_data,
                                       stdout=_read_output(outfile))

    except Exception as exc:

        if not isinstance(input_data, dict):
            input_data = input_data.dict()

        input_data = input_data.copy()
        input_data["stdout"] = _read_output(outfile)
        ret = qcel.models.FailedOperation(
            input_data=input_data,
            success=False,
            error={
                'error_type':
                type(exc).__name__,
                'error_message':
                ''.join(traceback.format_exception(*sys.exc_info())),
            })

    atexit.register(_quiet_remove, outfile)

    return ret
Exemple #41
0
def run_sf_sapt(name, **kwargs):
    optstash = p4util.OptionsState(['SCF_TYPE'],
                                   ['SCF', 'REFERENCE'],
                                   ['SCF', 'DFT_GRAC_SHIFT'],
                                   ['SCF', 'SAVE_JK'])

    core.tstart()

    # Alter default algorithm
    if not core.has_global_option_changed('SCF_TYPE'):
        core.set_global_option('SCF_TYPE', 'DF')

    core.prepare_options_for_module("SAPT")

    # Get the molecule of interest
    ref_wfn = kwargs.get('ref_wfn', None)
    if ref_wfn is None:
        sapt_dimer = kwargs.pop('molecule', core.get_active_molecule())
    else:
        core.print_out('Warning! SAPT argument "ref_wfn" is only able to use molecule information.')
        sapt_dimer = ref_wfn.molecule()

    sapt_dimer, monomerA, monomerB = proc_util.prepare_sapt_molecule(sapt_dimer, "dimer")

    # Print out the title and some information
    core.print_out("\n")
    core.print_out("         ---------------------------------------------------------\n")
    core.print_out("         " + "Spin-Flip SAPT Procedure".center(58) + "\n")
    core.print_out("\n")
    core.print_out("         " + "by Daniel G. A. Smith and Konrad Patkowski".center(58) + "\n")
    core.print_out("         ---------------------------------------------------------\n")
    core.print_out("\n")

    core.print_out("  ==> Algorithm <==\n\n")
    core.print_out("   JK Algorithm            %12s\n" % core.get_option("SCF", "SCF_TYPE"))
    core.print_out("\n")
    core.print_out("   Required computations:\n")
    core.print_out("     HF  (Monomer A)\n")
    core.print_out("     HF  (Monomer B)\n")
    core.print_out("\n")

    if (core.get_option('SCF', 'REFERENCE') != 'ROHF'):
        raise ValidationError('Spin-Flip SAPT currently only supports restricted open-shell references.')

    # Run the two monomer computations
    core.IO.set_default_namespace('dimer')
    data = {}

    if (core.get_global_option('SCF_TYPE') == 'DF'):
        core.set_global_option('DF_INTS_IO', 'SAVE')

    # Compute dimer wavefunction
    wfn_A = scf_helper("SCF", molecule=monomerA, banner="SF-SAPT: HF Monomer A", **kwargs)

    core.set_global_option("SAVE_JK", True)
    wfn_B = scf_helper("SCF", molecule=monomerB, banner="SF-SAPT: HF Monomer B", **kwargs)
    sapt_jk = wfn_B.jk()
    core.set_global_option("SAVE_JK", False)
    core.print_out("\n")
    core.print_out("         ---------------------------------------------------------\n")
    core.print_out("         " + "Spin-Flip SAPT Exchange and Electrostatics".center(58) + "\n")
    core.print_out("\n")
    core.print_out("         " + "by Daniel G. A. Smith and Konrad Patkowski".center(58) + "\n")
    core.print_out("         ---------------------------------------------------------\n")
    core.print_out("\n")

    sf_data = sapt_sf_terms.compute_sapt_sf(sapt_dimer, sapt_jk, wfn_A, wfn_B)

    # Print the results
    core.print_out("   Spin-Flip SAPT Results\n")
    core.print_out("  " + "-" * 103 + "\n")

    for key, value in sf_data.items():
        value = sf_data[key]
        print_vals = (key, value * 1000, value * constants.hartree2kcalmol, value * constants.hartree2kJmol)
        string = "    %-26s % 15.8f [mEh] % 15.8f [kcal/mol] % 15.8f [kJ/mol]\n" % print_vals
        core.print_out(string)
    core.print_out("  " + "-" * 103 + "\n\n")

    dimer_wfn = core.Wavefunction.build(sapt_dimer, wfn_A.basisset())

    # Set variables
    psivar_tanslator = {
        "Elst10": "SAPT ELST ENERGY",
        "Exch10(S^2) [diagonal]": "SAPT EXCH10(S^2),DIAGONAL ENERGY",
        "Exch10(S^2) [off-diagonal]": "SAPT EXCH10(S^2),OFF-DIAGONAL ENERGY",
        "Exch10(S^2) [highspin]": "SAPT EXCH10(S^2),HIGHSPIN ENERGY",
    }

    for k, v in sf_data.items():
        psi_k = psivar_tanslator[k]
        
        dimer_wfn.set_variable(psi_k, v)
        core.set_variable(psi_k, v)

    # Copy over highspin
    core.set_variable("SAPT EXCH ENERGY", sf_data["Exch10(S^2) [highspin]"])

    core.tstop()

    return dimer_wfn
Exemple #42
0
def scf_print_preiterations(self, small=False):
    # small version does not print Nalpha,Nbeta,Ndocc,Nsocc, e.g. for SAD guess where they are not
    # available
    ct = self.molecule().point_group().char_table()

    if not small:
        core.print_out(
            "   -------------------------------------------------------\n")
        core.print_out(
            "    Irrep   Nso     Nmo     Nalpha   Nbeta   Ndocc  Nsocc\n")
        core.print_out(
            "   -------------------------------------------------------\n")

        for h in range(self.nirrep()):
            core.print_out(
                f"     {ct.gamma(h).symbol():<3s}   {self.nsopi()[h]:6d}  {self.nmopi()[h]:6d}  {self.nalphapi()[h]:6d}  {self.nbetapi()[h]:6d}  {self.doccpi()[h]:6d}  {self.soccpi()[h]:6d}\n"
            )

        core.print_out(
            "   -------------------------------------------------------\n")
        core.print_out(
            f"    Total  {self.nso():6d}  {self.nmo():6d}  {self.nalpha():6d}  {self.nbeta():6d}  {self.nbeta():6d}  {self.nalpha() - self.nbeta():6d}\n"
        )
        core.print_out(
            "   -------------------------------------------------------\n\n")
    else:
        core.print_out("   -------------------------\n")
        core.print_out("    Irrep   Nso     Nmo    \n")
        core.print_out("   -------------------------\n")

        for h in range(self.nirrep()):
            core.print_out(
                f"     {ct.gamma(h).symbol():<3s}   {self.nsopi()[h]:6d}  {self.nmopi()[h]:6d} \n"
            )

        core.print_out("   -------------------------\n")
        core.print_out(f"    Total  {self.nso():6d}  {self.nmo():6d}\n")
        core.print_out("   -------------------------\n\n")
Exemple #43
0
def sapt_dft_header(sapt_dft_functional="unknown",
                    mon_a_shift=None,
                    mon_b_shift=None,
                    do_delta_hf="N/A",
                    jk_alg="N/A"):
    # Print out the title and some information
    core.print_out("\n")
    core.print_out(
        "         ---------------------------------------------------------\n")
    core.print_out("         " +
                   "SAPT(DFT): Intermolecular Interaction Segment".center(58) +
                   "\n")
    core.print_out("\n")
    core.print_out("         " +
                   "by Daniel G. A. Smith and Rob Parrish".center(58) + "\n")
    core.print_out(
        "         ---------------------------------------------------------\n")
    core.print_out("\n")

    core.print_out("  ==> Algorithm <==\n\n")
    core.print_out("   SAPT DFT Functional     %12s\n" %
                   str(sapt_dft_functional))
    if mon_a_shift:
        core.print_out("   Monomer A GRAC Shift    %12.6f\n" % mon_a_shift)
    if mon_b_shift:
        core.print_out("   Monomer B GRAC Shift    %12.6f\n" % mon_b_shift)
    core.print_out("   Delta HF                %12s\n" % do_delta_hf)
    core.print_out("   JK Algorithm            %12s\n" % jk_alg)
Exemple #44
0
def test_ccl_functional(functional, ccl_functional):

    check = True

    if (not os.path.exists('data_pt_%s.html' % (ccl_functional))):
        os.system('wget ftp://ftp.dl.ac.uk/qcg/dft_library/data_pt_%s.html' %
                  ccl_functional)
    fh = open('data_pt_%s.html' % (ccl_functional))
    lines = fh.readlines()
    fh.close()

    points = []
    point = {}

    rho_line = re.compile(
        r'^\s*rhoa=\s*(-?\d+\.\d+E[+-]\d+)\s*rhob=\s*(-?\d+\.\d+E[+-]\d+)\s*sigmaaa=\s*(-?\d+\.\d+E[+-]\d+)\s*sigmaab=\s*(-?\d+\.\d+E[+-]\d+)\s*sigmabb=\s*(-?\d+\.\d+E[+-]\d+)\s*'
    )
    val_line = re.compile(r'^\s*(\w*)\s*=\s*(-?\d+\.\d+E[+-]\d+)')

    aliases = {
        'zk': 'v',
        'vrhoa': 'v_rho_a',
        'vrhob': 'v_rho_b',
        'vsigmaaa': 'v_gamma_aa',
        'vsigmaab': 'v_gamma_ab',
        'vsigmabb': 'v_gamma_bb',
        'v2rhoa2': 'v_rho_a_rho_a',
        'v2rhoab': 'v_rho_a_rho_b',
        'v2rhob2': 'v_rho_b_rho_b',
        'v2rhoasigmaaa': 'v_rho_a_gamma_aa',
        'v2rhoasigmaab': 'v_rho_a_gamma_ab',
        'v2rhoasigmabb': 'v_rho_a_gamma_bb',
        'v2rhobsigmaaa': 'v_rho_b_gamma_aa',
        'v2rhobsigmaab': 'v_rho_b_gamma_ab',
        'v2rhobsigmabb': 'v_rho_b_gamma_bb',
        'v2sigmaaa2': 'v_gamma_aa_gamma_aa',
        'v2sigmaaaab': 'v_gamma_aa_gamma_ab',
        'v2sigmaaabb': 'v_gamma_aa_gamma_bb',
        'v2sigmaab2': 'v_gamma_ab_gamma_ab',
        'v2sigmaabbb': 'v_gamma_ab_gamma_bb',
        'v2sigmabb2': 'v_gamma_bb_gamma_bb',
    }

    for line in lines:

        mobj = re.match(rho_line, line)
        if (mobj):

            if len(point):
                points.append(point)
                point = {}

            point['rho_a'] = float(mobj.group(1))
            point['rho_b'] = float(mobj.group(2))
            point['gamma_aa'] = float(mobj.group(3))
            point['gamma_ab'] = float(mobj.group(4))
            point['gamma_bb'] = float(mobj.group(5))

            continue

        mobj = re.match(val_line, line)
        if (mobj):
            point[aliases[mobj.group(1)]] = float(mobj.group(2))

    points.append(point)

    N = len(points)
    rho_a = core.Vector(N)
    rho_b = core.Vector(N)
    gamma_aa = core.Vector(N)
    gamma_ab = core.Vector(N)
    gamma_bb = core.Vector(N)
    tau_a = core.Vector(N)
    tau_b = core.Vector(N)

    index = 0
    for point in points:
        rho_a[index] = point['rho_a']
        rho_b[index] = point['rho_b']
        gamma_aa[index] = point['gamma_aa']
        gamma_ab[index] = point['gamma_ab']
        gamma_bb[index] = point['gamma_bb']
        index = index + 1

    super = build_superfunctional(functional, N, 1)
    super.test_functional(rho_a, rho_b, gamma_aa, gamma_ab, gamma_bb, tau_a,
                          tau_b)

    v = super.value('V')
    v_rho_a = super.value('V_RHO_A')
    v_rho_b = super.value('V_RHO_B')
    v_gamma_aa = super.value('V_GAMMA_AA')
    v_gamma_ab = super.value('V_GAMMA_AB')
    v_gamma_bb = super.value('V_GAMMA_BB')

    if not v_gamma_aa:
        v_gamma_aa = tau_a
        v_gamma_ab = tau_a
        v_gamma_bb = tau_a

    tasks = [
        'v', 'v_rho_a', 'v_rho_b', 'v_gamma_aa', 'v_gamma_ab', 'v_gamma_bb'
    ]
    mapping = {
        'v': v,
        'v_rho_a': v_rho_a,
        'v_rho_b': v_rho_b,
        'v_gamma_aa': v_gamma_aa,
        'v_gamma_ab': v_gamma_ab,
        'v_gamma_bb': v_gamma_bb,
    }

    super.print_detail(3)
    index = 0
    for point in points:
        core.print_out(
            'rho_a= %11.3E, rho_b= %11.3E, gamma_aa= %11.3E, gamma_ab= %11.3E, gamma_bb= %11.3E\n'
            % (rho_a[index], rho_b[index], gamma_aa[index], gamma_ab[index],
               gamma_bb[index]))

        for task in tasks:
            v_ref = point[task]
            v_obs = mapping[task][index]
            delta = v_obs - v_ref
            if (v_ref == 0.0):
                epsilon = 0.0
            else:
                epsilon = abs(delta / v_ref)
            if (epsilon < 1.0E-11):
                passed = 'PASSED'
            else:
                passed = 'FAILED'
                check = False

            core.print_out('\t%-15s %24.16E %24.16E %24.16E %24.16E %6s\n' %
                           (task, v_ref, v_obs, delta, epsilon, passed))

        index = index + 1

    core.print_out('\n')
    return check
Exemple #45
0
def sapt_dft(dimer_wfn,
             wfn_A,
             wfn_B,
             sapt_jk=None,
             sapt_jk_B=None,
             data=None,
             print_header=True,
             cleanup_jk=True):
    """
    The primary SAPT(DFT) algorithm to compute the interaction energy once the wavefunctions have been built.

    Example
    -------

    dimer = psi4.geometry('''
      Ne
      --
      Ar 1 6.5
      units bohr
    ''')

    psi4.set_options({"BASIS": "aug-cc-pVDZ"})

    # Prepare the fragments
    sapt_dimer, monomerA, monomerB = psi4.proc_util.prepare_sapt_molecule(sapt_dimer, "dimer")

    # Run the first monomer
    set DFT_GRAC_SHIFT 0.203293
    wfnA, energyA = psi4.energy("PBE0", monomer=monomerA, return_wfn=True)

    # Run the second monomer
    set DFT_GRAC_SHIFT 0.138264
    wfnB, energyB = psi4.energy("PBE0", monomer=monomerB, return_wfn=True)

    # Build the dimer wavefunction
    wfnD = psi4.core.Wavefunction.build(sapt_dimer)

    # Compute SAPT(DFT) from the provided wavefunctions
    data = psi4.procrouting.sapt.sapt_dft(wfnD, wfnA, wfnB)
    """

    # Handle the input options
    if print_header:
        sapt_dft_header()

    if sapt_jk is None:

        core.print_out("\n   => Building SAPT JK object <= \n\n")
        sapt_jk = core.JK.build(dimer_wfn.basisset())
        sapt_jk.set_do_J(True)
        sapt_jk.set_do_K(True)
        if wfn_A.functional().is_x_lrc():
            sapt_jk.set_do_wK(True)
            sapt_jk.set_omega(wfn_A.functional().x_omega())
        sapt_jk.initialize()
        sapt_jk.print_header()

        if wfn_B.functional().is_x_lrc() and (wfn_A.functional().x_omega() !=
                                              wfn_B.functional().x_omega()):
            core.print_out("   => Monomer B: Building SAPT JK object <= \n\n")
            core.print_out(
                "      Reason: MonomerA Omega != MonomerB Omega\n\n")
            sapt_jk_B = core.JK.build(dimer_wfn.basisset())
            sapt_jk_B.set_do_J(True)
            sapt_jk_B.set_do_K(True)
            sapt_jk_B.set_do_wK(True)
            sapt_jk_B.set_omega(wfn_B.functional().x_omega())
            sapt_jk_B.initialize()
            sapt_jk_B.print_header()
    else:
        sapt_jk.set_do_K(True)

    if data is None:
        data = {}

    cache = sapt_jk_terms.build_sapt_jk_cache(wfn_A, wfn_B, sapt_jk, True)

    # Electostatics
    elst = sapt_jk_terms.electrostatics(cache, True)
    data.update(elst)

    # Exchange
    exch = sapt_jk_terms.exchange(cache, sapt_jk, True)
    data.update(exch)

    # Induction
    ind = sapt_jk_terms.induction(cache,
                                  sapt_jk,
                                  True,
                                  sapt_jk_B=sapt_jk_B,
                                  maxiter=core.get_option("SAPT", "MAXITER"),
                                  conv=core.get_option("SAPT",
                                                       "D_CONVERGENCE"),
                                  Sinf=core.get_option("SAPT",
                                                       "DO_IND_EXCH_SINF"))
    data.update(ind)

    # Blow away JK object before doing MP2 for memory considerations
    if cleanup_jk:
        sapt_jk.finalize()

    # Dispersion
    primary_basis = wfn_A.basisset()
    core.print_out("\n")
    aux_basis = core.BasisSet.build(dimer_wfn.molecule(), "DF_BASIS_MP2",
                                    core.get_option("DFMP2", "DF_BASIS_MP2"),
                                    "RIFIT", core.get_global_option('BASIS'))
    fdds_disp = sapt_mp2_terms.df_fdds_dispersion(primary_basis, aux_basis,
                                                  cache)
    data.update(fdds_disp)

    if core.get_option("SAPT", "SAPT_DFT_MP2_DISP_ALG") == "FISAPT":
        mp2_disp = sapt_mp2_terms.df_mp2_fisapt_dispersion(wfn_A,
                                                           primary_basis,
                                                           aux_basis,
                                                           cache,
                                                           do_print=True)
    else:
        mp2_disp = sapt_mp2_terms.df_mp2_sapt_dispersion(dimer_wfn,
                                                         wfn_A,
                                                         wfn_B,
                                                         primary_basis,
                                                         aux_basis,
                                                         cache,
                                                         do_print=True)
    data.update(mp2_disp)

    # Print out final data
    core.print_out("\n")
    core.print_out(print_sapt_dft_summary(data, "SAPT(DFT)"))

    return data
Exemple #46
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
Exemple #47
0
def scf_xtpl_helgaker_2(functionname: str,
                        zLO: int,
                        valueLO: Extrapolatable,
                        zHI: int,
                        valueHI: Extrapolatable,
                        verbose: int = 1,
                        alpha: Optional[float] = None) -> Extrapolatable:
    r"""Extrapolation scheme using exponential form for reference energies with two adjacent
    zeta-level bases. Used by :py:func:`~psi4.cbs`.

    Parameters
    ----------
    functionname
        Name of the CBS component (e.g., 'HF') used in summary printing.
    zLO
        Zeta number of the smaller basis set in 2-point extrapolation.
    valueLO
        Energy, gradient, or Hessian value at the smaller basis set in 2-point
        extrapolation.
    zHI
        Zeta number of the larger basis set in 2-point extrapolation.
        Must be `zLO + 1`.
    valueHI
        Energy, gradient, or Hessian value at the larger basis set in 2-point
        extrapolation.
    verbose
        Controls volume of printing.
    alpha
        Fitted 2-point parameter. Overrides the default :math:`\alpha = 1.63`

    Returns
    -------
    float or ndarray
        Eponymous function applied to input zetas and values; type from `valueLO`.

    Notes
    -----
    The extrapolation is calculated according to [1]_:
    :math:`E_{total}^X = E_{total}^{\infty} + \beta e^{-\alpha X}, \alpha = 1.63`

    References
    ----------

    .. [1] Halkier, Helgaker, Jorgensen, Klopper, & Olsen, Chem. Phys. Lett. 302 (1999) 437-446,
       DOI: 10.1016/S0009-2614(99)00179-7

    Examples
    --------
    >>> # [1] Hartree-Fock extrapolation
    >>> psi4.energy('cbs', scf_wfn='hf', scf_basis='cc-pV[DT]Z', scf_scheme='scf_xtpl_helgaker_2')

    """

    if type(valueLO) != type(valueHI):
        raise ValidationError(
            f"scf_xtpl_helgaker_2: Inputs must be of the same datatype! ({type(valueLO)}, {type(valueHI)})"
        )

    if alpha is None:
        alpha = 1.63

    beta_division = 1 / (math.exp(-1 * alpha * zLO) *
                         (math.exp(-1 * alpha) - 1))
    beta_mult = math.exp(-1 * alpha * zHI)

    if isinstance(valueLO, float):
        beta = (valueHI - valueLO) * beta_division
        value = valueHI - beta * beta_mult

        if verbose:
            # Output string with extrapolation parameters
            cbsscheme = ''
            cbsscheme += """\n   ==> Helgaker 2-point exponential SCF extrapolation for method: %s <==\n\n""" % (
                functionname.upper())
            cbsscheme += """   LO-zeta (%s) Energy:               % 16.12f\n""" % (
                str(zLO), valueLO)
            cbsscheme += """   HI-zeta (%s) Energy:               % 16.12f\n""" % (
                str(zHI), valueHI)
            cbsscheme += """   Alpha (exponent) Value:           % 16.12f\n""" % (
                alpha)
            cbsscheme += """   Beta (coefficient) Value:         % 16.12f\n\n""" % (
                beta)

            name_str = "%s/(%s,%s)" % (functionname.upper(),
                                       _zeta_val2sym[zLO].upper(),
                                       _zeta_val2sym[zHI].upper())
            cbsscheme += """   @Extrapolated """
            cbsscheme += name_str + ':'
            cbsscheme += " " * (18 - len(name_str))
            cbsscheme += """% 16.12f\n\n""" % value
            core.print_out(cbsscheme)

        return value

    elif isinstance(valueLO, (core.Matrix, core.Vector)):
        valueLO = valueLO.to_array()
        valueHI = valueHI.to_array()

        beta = (valueHI - valueLO) * beta_division
        value = valueHI - beta * beta_mult

        if verbose > 2:
            cbsscheme = f"""\n   ==> Helgaker 2-point exponential SCF extrapolation for method: {functionname.upper()} <==\n"""
            cbsscheme += f"""\n   LO-zeta ({zLO}) Data\n"""
            cbsscheme += nppp(valueLO)
            cbsscheme += f"""\n   HI-zeta ({zHI}) Data\n"""
            cbsscheme += nppp(valueHI)

            cbsscheme += f"""\n   Alpha (exponent) Value:          {alpha:16.8f}"""
            cbsscheme += f"""\n   Beta Data\n"""
            cbsscheme += nppp(beta)
            cbsscheme += f"""\n   Extrapolated Data\n"""
            cbsscheme += nppp(value)
            cbsscheme += "\n"
            core.print_out(cbsscheme)

        value = core.Matrix.from_array(value)
        return value

    else:
        raise ValidationError(
            f"scf_xtpl_helgaker_2: datatype is not recognized '{type(valueLO)}'."
        )
Exemple #48
0
def scf_finalize_energy(self):
    """Performs stability analysis and calls back SCF with new guess
    if needed, Returns the SCF energy. This function should be called
    once orbitals are ready for energy/property computations, usually
    after iterations() is called.

    """

    # post-scf vv10 correlation
    if core.get_option(
            'SCF', "DFT_VV10_POSTSCF") and self.functional().vv10_b() > 0.0:
        self.functional().set_lock(False)
        self.functional().set_do_vv10(True)
        self.functional().set_lock(True)
        core.print_out(
            "  ==> Computing Non-Self-Consistent VV10 Energy Correction <==\n\n"
        )
        SCFE = 0.0
        self.form_V()
        SCFE += self.compute_E()
        self.set_energies("Total Energy", SCFE)

    # Perform wavefunction stability analysis before doing
    # anything on a wavefunction that may not be truly converged.
    if core.get_option('SCF', 'STABILITY_ANALYSIS') != "NONE":

        # Don't bother computing needed integrals if we can't do anything with them.
        if self.functional().needs_xc():
            raise ValidationError(
                "Stability analysis not yet supported for XC functionals.")

        # We need the integral file, make sure it is written and
        # compute it if needed
        if core.get_option('SCF', 'REFERENCE') != "UHF":
            #psio = core.IO.shared_object()
            #psio.open(constants.PSIF_SO_TEI, 1)  # PSIO_OPEN_OLD
            #try:
            #    psio.tocscan(constants.PSIF_SO_TEI, "IWL Buffers")
            #except TypeError:
            #    # "IWL Buffers" actually found but psio_tocentry can't be returned to Py
            #    psio.close(constants.PSIF_SO_TEI, 1)
            #else:
            #    # tocscan returned None
            #    psio.close(constants.PSIF_SO_TEI, 1)

            # logic above foiled by psio_tocentry not returning None<--nullptr in pb11 2.2.1
            #   so forcibly recomputing for now until stability revamp
            core.print_out("    SO Integrals not on disk. Computing...")
            mints = core.MintsHelper(self.basisset())
            #next 2 lines fix a bug that prohibits relativistic stability analysis

            mints.integrals()
            core.print_out("done.\n")

            # Q: Not worth exporting all the layers of psio, right?

        follow = self.stability_analysis()

        while follow and self.attempt_number_ <= core.get_option(
                'SCF', 'MAX_ATTEMPTS'):
            self.attempt_number_ += 1
            core.print_out(
                "    Running SCF again with the rotated orbitals.\n")

            if self.initialized_diis_manager_:
                self.diis_manager_.reset_subspace()
            # reading the rotated orbitals in before starting iterations
            self.form_D()
            self.set_energies("Total Energy", self.compute_initial_E())
            self.iterations()
            follow = self.stability_analysis()

        if follow and self.attempt_number_ > core.get_option(
                'SCF', 'MAX_ATTEMPTS'):
            core.print_out(
                "    There's still a negative eigenvalue. Try modifying FOLLOW_STEP_SCALE\n"
            )
            core.print_out(
                "    or increasing MAX_ATTEMPTS (not available for PK integrals).\n"
            )

    # At this point, we are not doing any more SCF cycles
    #   and we can compute and print final quantities.

    if hasattr(self.molecule(), 'EFP'):
        efpobj = self.molecule().EFP

        efpobj.compute()  # do_gradient=do_gradient)
        efpene = efpobj.get_energy(label='psi')
        efp_wfn_independent_energy = efpene['total'] - efpene['ind']
        self.set_energies("EFP", efpene['total'])

        SCFE = self.get_energies("Total Energy")
        SCFE += efp_wfn_independent_energy
        self.set_energies("Total Energy", SCFE)
        core.print_out(efpobj.energy_summary(scfefp=SCFE, label='psi'))

        self.set_variable("EFP ELST ENERGY", efpene['electrostatic'] +
                          efpene['charge_penetration'] +
                          efpene['electrostatic_point_charges'])  # P::e EFP
        self.set_variable("EFP IND ENERGY", efpene['polarization'])  # P::e EFP
        self.set_variable("EFP DISP ENERGY", efpene['dispersion'])  # P::e EFP
        self.set_variable("EFP EXCH ENERGY",
                          efpene['exchange_repulsion'])  # P::e EFP
        self.set_variable("EFP TOTAL ENERGY", efpene['total'])  # P::e EFP
        self.set_variable("CURRENT ENERGY", efpene['total'])  # P::e EFP

    core.print_out("\n  ==> Post-Iterations <==\n\n")

    if self.V_potential():
        quad = self.V_potential().quadrature_values()
        rho_a = quad['RHO_A'] / 2 if self.same_a_b_dens() else quad['RHO_A']
        rho_b = quad['RHO_B'] / 2 if self.same_a_b_dens() else quad['RHO_B']
        rho_ab = (rho_a + rho_b)
        self.set_variable("GRID ELECTRONS TOTAL", rho_ab)  # P::e SCF
        self.set_variable("GRID ELECTRONS ALPHA", rho_a)  # P::e SCF
        self.set_variable("GRID ELECTRONS BETA", rho_b)  # P::e SCF
        dev_a = rho_a - self.nalpha()
        dev_b = rho_b - self.nbeta()
        core.print_out(f"   Electrons on quadrature grid:\n")
        if self.same_a_b_dens():
            core.print_out(
                f"      Ntotal   = {rho_ab:15.10f} ; deviation = {dev_b+dev_a:.3e} \n\n"
            )
        else:
            core.print_out(
                f"      Nalpha   = {rho_a:15.10f} ; deviation = {dev_a:.3e}\n")
            core.print_out(
                f"      Nbeta    = {rho_b:15.10f} ; deviation = {dev_b:.3e}\n")
            core.print_out(
                f"      Ntotal   = {rho_ab:15.10f} ; deviation = {dev_b+dev_a:.3e} \n\n"
            )
        if ((dev_b + dev_a) > 0.1):
            core.print_out(
                "   WARNING: large deviation in the electron count on grid detected. Check grid size!"
            )
    self.check_phases()
    self.compute_spin_contamination()
    self.frac_renormalize()
    reference = core.get_option("SCF", "REFERENCE")

    energy = self.get_energies("Total Energy")

    #    fail_on_maxiter = core.get_option("SCF", "FAIL_ON_MAXITER")
    #    if converged or not fail_on_maxiter:
    #
    #        if print_lvl > 0:
    #            self.print_orbitals()
    #
    #        if converged:
    #            core.print_out("  Energy converged.\n\n")
    #        else:
    #            core.print_out("  Energy did not converge, but proceeding anyway.\n\n")

    if core.get_option('SCF', 'PRINT') > 0:
        self.print_orbitals()

    is_dfjk = core.get_global_option('SCF_TYPE').endswith('DF')
    core.print_out("  @%s%s Final Energy: %20.14f" %
                   ('DF-' if is_dfjk else '', reference, energy))
    # if (perturb_h_) {
    #     core.print_out(" with %f %f %f perturbation" %
    #                    (dipole_field_strength_[0], dipole_field_strength_[1], dipole_field_strength_[2]))
    # }
    core.print_out("\n\n")
    self.print_energies()

    self.clear_external_potentials()
    if core.get_option('SCF', 'PCM'):
        calc_type = core.PCM.CalcType.Total
        if core.get_option("PCM", "PCM_SCF_TYPE") == "SEPARATE":
            calc_type = core.PCM.CalcType.NucAndEle
        Dt = self.Da().clone()
        Dt.add(self.Db())
        _, Vpcm = self.get_PCM().compute_PCM_terms(Dt, calc_type)
        self.push_back_external_potential(Vpcm)
        # Set callback function for CPSCF
        self.set_external_cpscf_perturbation(
            "PCM", lambda pert_dm: self.get_PCM().compute_V(pert_dm))

    if core.get_option('SCF', 'PE'):
        Dt = self.Da().clone()
        Dt.add(self.Db())
        _, Vpe = self.pe_state.get_pe_contribution(Dt, elec_only=False)
        self.push_back_external_potential(Vpe)
        # Set callback function for CPSCF
        self.set_external_cpscf_perturbation(
            "PE", lambda pert_dm: self.pe_state.get_pe_contribution(
                pert_dm, elec_only=True)[1])

    # Orbitals are always saved, in case an MO guess is requested later
    # save_orbitals()

    # Shove variables into global space
    for k, v in self.variables().items():
        core.set_variable(k, v)

    # TODO re-enable
    self.finalize()
    if self.V_potential():
        self.V_potential().clear_collocation_cache()

    core.print_out("\nComputation Completed\n")
    core.del_variable("SCF D NORM")

    return energy
Exemple #49
0
def build_superfunctional(name, restricted):
    npoints = core.get_option("SCF", "DFT_BLOCK_MAX_POINTS")
    deriv = 1  # Default depth for now

    # We are a XC generating function

    if hasattr(name, '__call__'):
        custom_error = "SCF: Custom functional type must either be a SuperFunctional or a tuple of (SuperFunctional, (base_name, dashparam))."
        sfunc = name("name", npoints, deriv, restricted)

        # Without Dispersion
        if isinstance(sfunc, core.SuperFunctional):
            sup = (sfunc, False)
        # With Dispersion
        elif isinstance(sup[0], core.SuperFunctional):
            sup = sfunc
            # Can we validate dispersion?
        else:
            raise ValidationError(custom_error)

        # Double check that the SuperFunctional is correctly sized (why dont we always do this?)
        sup[0].set_max_points(npoints)
        sup[0].set_deriv(deriv)
        sup[0].allocate()

    # Check for supplied dict_func functionals
    elif isinstance(name, dict):
        sup = dft_builder.build_superfunctional_from_dictionary(
            name, npoints, deriv, restricted)
    # Check for pre-defined dict-based functionals
    elif name.lower() in dft_builder.functionals:
        sup = dft_builder.build_superfunctional_from_dictionary(
            dft_builder.functionals[name.lower()], npoints, deriv, restricted)
    else:
        raise ValidationError("SCF: Functional (%s) not found!" % name)

    if (core.get_global_option('INTEGRAL_PACKAGE')
            == 'ERD') and (sup[0].is_x_lrc() or sup[0].is_c_lrc()):
        raise ValidationError(
            "INTEGRAL_PACKAGE ERD does not play nicely with omega ERI's, so stopping."
        )

    # Lock and unlock the functional
    sup[0].set_lock(False)

    # Set options
    if core.has_option_changed("SCF", "DFT_OMEGA") and sup[0].is_x_lrc():
        omega = core.get_option("SCF", "DFT_OMEGA")
        sup[0].set_x_omega(omega)

        # We also need to loop through all of the exchange functionals
        if sup[0].is_libxc_func():
            # Full libxc funcs are dropped in c_functionals (smooth move!)
            sup[0].c_functionals()[0].set_omega(omega)
        else:
            for x_func in sup[0].x_functionals():
                x_func.set_omega(omega)
    if core.has_option_changed("SCF", "DFT_OMEGA_C") and sup[0].is_c_lrc():
        sup[0].set_c_omega(core.get_option("SCF", "DFT_OMEGA_C"))

    if core.has_option_changed("SCF", "DFT_ALPHA"):
        sup[0].set_x_alpha(core.get_option("SCF", "DFT_ALPHA"))
    if core.has_option_changed("SCF", "DFT_ALPHA_C"):
        sup[0].set_c_alpha(core.get_option("SCF", "DFT_ALPHA_C"))

    # add VV10 correlation to any functional or modify existing
    # custom procedures using name 'scf' without any quadrature grid like HF will fail and are not detected
    if (core.has_option_changed("SCF", "NL_DISPERSION_PARAMETERS")
            and sup[0].vv10_b() > 0.0):
        if (name.lower() == 'hf'):
            raise ValidationError("SCF: HF with -NL not implemented")
        nl_tuple = core.get_option("SCF", "NL_DISPERSION_PARAMETERS")
        sup[0].set_vv10_b(nl_tuple[0])
        if len(nl_tuple) > 1:
            sup[0].set_vv10_c(nl_tuple[1])
        if len(nl_tuple) > 2:
            raise ValidationError(
                "too many entries in NL_DISPERSION_PARAMETERS for DFT-NL")
    elif core.has_option_changed("SCF", "DFT_VV10_B"):
        if (name.lower() == 'hf'):
            raise ValidationError("SCF: HF with -NL not implemented")
        vv10_b = core.get_option("SCF", "DFT_VV10_B")
        sup[0].set_vv10_b(vv10_b)
        if core.has_option_changed("SCF", "DFT_VV10_C"):
            vv10_c = core.get_option("SCF", "DFT_VV10_C")
            sup[0].set_vv10_c(vv10_c)
        if (abs(sup[0].vv10_c() - 0.0) <= 1e-8):
            core.print_out(
                "SCF: VV10_C not specified. Using default (C=0.0093)!")
            sup[0].set_vv10_c(0.0093)

    if (core.has_option_changed("SCF", "NL_DISPERSION_PARAMETERS")
            and core.has_option_changed("SCF", "DFT_VV10_B")):
        raise ValidationError(
            "SCF: Decide between NL_DISPERSION_PARAMETERS and DFT_VV10_B !!")

    # Check SCF_TYPE
    if sup[0].is_x_lrc() and (core.get_global_option("SCF_TYPE")
                              not in ["DIRECT", "DF", "OUT_OF_CORE", "PK"]):
        raise ValidationError(
            "SCF: SCF_TYPE (%s) not supported for range-separated functionals, plese use SCF_TYPE = 'DF' to automatically select the correct JK build."
            % core.get_global_option("SCF_TYPE"))

    if (core.get_global_option('INTEGRAL_PACKAGE')
            == 'ERD') and (sup[0].is_x_lrc()):
        raise ValidationError(
            'INTEGRAL_PACKAGE ERD does not play nicely with LRC DFT functionals, so stopping.'
        )

    sup[0].set_lock(True)

    return sup
Exemple #50
0
def scf_xtpl_truhlar_2(functionname: str,
                       zLO: int,
                       valueLO: Extrapolatable,
                       zHI: int,
                       valueHI: Extrapolatable,
                       verbose: int = 1,
                       alpha: Optional[float] = None) -> Extrapolatable:
    r"""Extrapolation scheme using power form for reference energies with two adjacent
    zeta-level bases. Used by :py:func:`~psi4.cbs`.

    Parameters
    ----------
    functionname
        Name of the CBS component (e.g., 'HF') used in summary printing.
    zLO
        Zeta number of the smaller basis set in 2-point extrapolation.
    valueLO
        Energy, gradient, or Hessian value at the smaller basis set in 2-point
        extrapolation.
    zHI
        Zeta number of the larger basis set in 2-point extrapolation
        Must be `zLO + 1`.
    valueHI
        Energy, gradient, or Hessian value at the larger basis set in 2-point
        extrapolation.
    verbose
        Controls volume of printing.
    alpha
        Overrides the default :math:`\alpha = 3.4`

    Returns
    -------
    float or ndarray
        Eponymous function applied to input zetas and values; type from `valueLO`.

    Notes
    -----
    The extrapolation is calculated according to [2]_:
    :math:`E_{total}^X = E_{total}^{\infty} + \beta X^{-\alpha}, \alpha = 3.4`

    References
    ----------

    .. [2] Truhlar, Chem. Phys. Lett. 294 (1998) 45-48,
       DOI: 10.1016/S0009-2614(98)00866-5

    """

    if type(valueLO) != type(valueHI):
        raise ValidationError(
            f"scf_xtpl_truhlar_2: Inputs must be of the same datatype! ({type(valueLO)}, {type(valueHI)})"
        )

    if alpha is None:
        alpha = 3.40

    beta_division = 1 / (zHI**(-1 * alpha) - zLO**(-1 * alpha))
    beta_mult = zHI**(-1 * alpha)

    if isinstance(valueLO, float):
        beta = (valueHI - valueLO) * beta_division
        value = valueHI - beta * beta_mult

        if verbose:
            # Output string with extrapolation parameters
            cbsscheme = ''
            cbsscheme += """\n   ==> Truhlar 2-point power form SCF extrapolation for method: %s <==\n\n""" % (
                functionname.upper())
            cbsscheme += """   LO-zeta (%s) Energy:               % 16.12f\n""" % (
                str(zLO), valueLO)
            cbsscheme += """   HI-zeta (%s) Energy:               % 16.12f\n""" % (
                str(zHI), valueHI)
            cbsscheme += """   Alpha (exponent) Value:           % 16.12f\n""" % (
                alpha)
            cbsscheme += """   Beta (coefficient) Value:         % 16.12f\n\n""" % (
                beta)

            name_str = "%s/(%s,%s)" % (functionname.upper(),
                                       _zeta_val2sym[zLO].upper(),
                                       _zeta_val2sym[zHI].upper())
            cbsscheme += """   @Extrapolated """
            cbsscheme += name_str + ':'
            cbsscheme += " " * (18 - len(name_str))
            cbsscheme += """% 16.12f\n\n""" % value
            core.print_out(cbsscheme)

        return value

    elif isinstance(valueLO, (core.Matrix, core.Vector)):
        valueLO = valueLO.to_array()
        valueHI = valueHI.to_array()

        beta = (valueHI - valueLO) * beta_division
        value = valueHI - beta * beta_mult

        if verbose > 2:
            cbsscheme = f"""\n   ==> Truhlar 2-point power SCF extrapolation for method: {functionname.upper()} <==\n"""
            cbsscheme += f"""\n   LO-zeta ({zLO}) Data\n"""
            cbsscheme += nppp(valueLO)
            cbsscheme += f"""\n   HI-zeta ({zHI}) Data\n"""
            cbsscheme += nppp(valueHI)

            cbsscheme += f"""\n   Alpha (exponent) Value:          {alpha:16.8f}"""
            cbsscheme += f"""\n   Beta Data\n"""
            cbsscheme += nppp(beta)
            cbsscheme += f"""\n   Extrapolated Data\n"""
            cbsscheme += nppp(value)
            cbsscheme += "\n"
            core.print_out(cbsscheme)

        value = core.Matrix.from_array(value)
        return value

    else:
        raise ValidationError(
            f"scf_xtpl_truhlar_2: datatype is not recognized '{type(valueLO)}'."
        )
Exemple #51
0
def compute_sapt_sf(dimer, jk, wfn_A, wfn_B, do_print=True):
    """
    Computes Elst and Spin-Flip SAPT0 for ROHF wavefunctions
    """

    if do_print:
        core.print_out("\n  ==> Preparing SF-SAPT Data Cache <== \n\n")
        jk.print_header()

    ### Build intermediates

    # Pull out Wavefunction A quantities
    ndocc_A = wfn_A.doccpi().sum()
    nsocc_A = wfn_A.soccpi().sum()

    Cocc_A = np.asarray(wfn_A.Ca_subset("AO", "OCC"))
    Ci = Cocc_A[:, :ndocc_A]
    Ca = Cocc_A[:, ndocc_A:]
    Pi = np.dot(Ci, Ci.T)
    Pa = np.dot(Ca, Ca.T)

    mints = core.MintsHelper(wfn_A.basisset())
    V_A = mints.ao_potential()

    # Pull out Wavefunction B quantities
    ndocc_B = wfn_B.doccpi().sum()
    nsocc_B = wfn_B.soccpi().sum()

    Cocc_B = np.asarray(wfn_B.Ca_subset("AO", "OCC"))
    Cj = Cocc_B[:, :ndocc_B]
    Cb = Cocc_B[:, ndocc_B:]
    Pj = np.dot(Cj, Cj.T)
    Pb = np.dot(Cb, Cb.T)

    mints = core.MintsHelper(wfn_B.basisset())
    V_B = mints.ao_potential()

    # Pull out generic quantities
    S = np.asarray(wfn_A.S())

    intermonomer_nuclear_repulsion = dimer.nuclear_repulsion_energy()
    intermonomer_nuclear_repulsion -= wfn_A.molecule(
    ).nuclear_repulsion_energy()
    intermonomer_nuclear_repulsion -= wfn_B.molecule(
    ).nuclear_repulsion_energy()

    num_el_A = (2 * ndocc_A + nsocc_A)
    num_el_B = (2 * ndocc_B + nsocc_B)

    ### Build JK Terms
    if do_print:
        core.print_out("\n  ==> Computing required JK matrices <== \n\n")

    # Writen so that we can reorganize order to save on DF-JK cost.
    pairs = [("ii", Ci, None, Ci), ("ij", Ci, _chain_dot(Ci.T, S, Cj), Cj),
             ("jj", Cj, None, Cj), ("aa", Ca, None, Ca),
             ("aj", Ca, _chain_dot(Ca.T, S, Cj), Cj),
             ("ib", Ci, _chain_dot(Ci.T, S, Cb), Cb), ("bb", Cb, None, Cb),
             ("ab", Ca, _chain_dot(Ca.T, S, Cb), Cb)]

    # Reorganize
    names = [x[0] for x in pairs]
    Cleft = [x[1] for x in pairs]
    rotations = [x[2] for x in pairs]
    Cright = [x[3] for x in pairs]

    tmp_J, tmp_K = _sf_compute_JK(jk, Cleft, Cright, rotations)

    J = {key: val for key, val in zip(names, tmp_J)}
    K = {key: val for key, val in zip(names, tmp_K)}

    ### Compute Terms
    if do_print:
        core.print_out(
            "\n  ==> Computing Spin-Flip Exchange and Electrostatics <== \n\n")

    w_A = V_A + 2 * J["ii"] + J["aa"]
    w_B = V_B + 2 * J["jj"] + J["bb"]

    h_Aa = V_A + 2 * J["ii"] + J["aa"] - K["ii"] - K["aa"]
    h_Ab = V_A + 2 * J["ii"] + J["aa"] - K["ii"]

    h_Ba = V_B + 2 * J["jj"] + J["bb"] - K["jj"]
    h_Bb = V_B + 2 * J["jj"] + J["bb"] - K["jj"] - K["bb"]

    ### Build electrostatics

    # socc/socc term
    two_el_repulsion = np.vdot(Pa, J["bb"])
    attractive_a = np.vdot(V_A, Pb) * nsocc_A / num_el_A
    attractive_b = np.vdot(V_B, Pa) * nsocc_B / num_el_B
    nuclear_repulsion = intermonomer_nuclear_repulsion * nsocc_A * nsocc_B / (
        num_el_A * num_el_B)
    elst_abab = two_el_repulsion + attractive_a + attractive_b + nuclear_repulsion

    # docc/socc term
    two_el_repulsion = np.vdot(Pi, J["bb"])
    attractive_a = np.vdot(V_A, Pb) * ndocc_A / num_el_A
    attractive_b = np.vdot(V_B, Pi) * nsocc_B / num_el_B
    nuclear_repulsion = intermonomer_nuclear_repulsion * ndocc_A * nsocc_B / (
        num_el_A * num_el_B)
    elst_ibib = 2 * (two_el_repulsion + attractive_a + attractive_b +
                     nuclear_repulsion)

    # socc/docc term
    two_el_repulsion = np.vdot(Pa, J["jj"])
    attractive_a = np.vdot(V_A, Pj) * nsocc_A / num_el_A
    attractive_b = np.vdot(V_B, Pa) * ndocc_B / num_el_B
    nuclear_repulsion = intermonomer_nuclear_repulsion * nsocc_A * ndocc_B / (
        num_el_A * num_el_B)
    elst_jaja = 2 * (two_el_repulsion + attractive_a + attractive_b +
                     nuclear_repulsion)

    # docc/docc term
    two_el_repulsion = np.vdot(Pi, J["jj"])
    attractive_a = np.vdot(V_A, Pj) * ndocc_A / num_el_A
    attractive_b = np.vdot(V_B, Pi) * ndocc_B / num_el_B
    nuclear_repulsion = intermonomer_nuclear_repulsion * ndocc_A * ndocc_B / (
        num_el_A * num_el_B)
    elst_ijij = 4 * (two_el_repulsion + attractive_a + attractive_b +
                     nuclear_repulsion)

    elst = elst_abab + elst_ibib + elst_jaja + elst_ijij
    # print(print_sapt_var("Elst,10", elst))

    ### Start diagonal exchange

    exch_diag = 0.0
    exch_diag -= np.vdot(Pj, 2 * K["ii"] + K["aa"])
    exch_diag -= np.vdot(Pb, K["ii"])
    exch_diag -= np.vdot(_chain_dot(Pi, S, Pj), (h_Aa + h_Ab + h_Ba + h_Bb))
    exch_diag -= np.vdot(_chain_dot(Pa, S, Pj), (h_Aa + h_Ba))
    exch_diag -= np.vdot(_chain_dot(Pi, S, Pb), (h_Ab + h_Bb))

    exch_diag += 2.0 * np.vdot(_chain_dot(Pj, S, Pi, S, Pb), w_A)
    exch_diag += 2.0 * np.vdot(_chain_dot(Pj, S, Pi, S, Pj), w_A)
    exch_diag += np.vdot(_chain_dot(Pb, S, Pi, S, Pb), w_A)
    exch_diag += np.vdot(_chain_dot(Pj, S, Pa, S, Pj), w_A)

    exch_diag += 2.0 * np.vdot(_chain_dot(Pi, S, Pj, S, Pi), w_B)
    exch_diag += 2.0 * np.vdot(_chain_dot(Pi, S, Pj, S, Pa), w_B)
    exch_diag += np.vdot(_chain_dot(Pi, S, Pb, S, Pi), w_B)
    exch_diag += np.vdot(_chain_dot(Pa, S, Pj, S, Pa), w_B)

    exch_diag -= 2.0 * np.vdot(_chain_dot(Pi, S, Pj), K["ij"])
    exch_diag -= 2.0 * np.vdot(_chain_dot(Pa, S, Pj), K["ij"])
    exch_diag -= 2.0 * np.vdot(_chain_dot(Pi, S, Pb), K["ij"])

    exch_diag -= np.vdot(_chain_dot(Pa, S, Pj), K["aj"])
    exch_diag -= np.vdot(_chain_dot(Pi, S, Pb), K["ib"])
    # print(print_sapt_var("Exch10,offdiagonal", exch_diag))

    ### Start off-diagonal exchange

    exch_offdiag = 0.0
    exch_offdiag -= np.vdot(Pb, K["aa"])
    exch_offdiag -= np.vdot(_chain_dot(Pa, S, Pb), (h_Aa + h_Bb))
    exch_offdiag += np.vdot(_chain_dot(Pa, S, Pj), K["bb"])
    exch_offdiag += np.vdot(_chain_dot(Pi, S, Pb), K["aa"])

    exch_offdiag += 2.0 * np.vdot(_chain_dot(Pj, S, Pa, S, Pb), w_A)
    exch_offdiag += np.vdot(_chain_dot(Pb, S, Pa, S, Pb), w_A)

    exch_offdiag += 2.0 * np.vdot(_chain_dot(Pi, S, Pb, S, Pa), w_B)
    exch_offdiag += np.vdot(_chain_dot(Pa, S, Pb, S, Pa), w_B)

    exch_offdiag -= 2.0 * np.vdot(_chain_dot(Pa, S, Pb), K["ij"])
    exch_offdiag -= 2.0 * np.vdot(_chain_dot(Pa, S, Pb), K["ib"])
    exch_offdiag -= 2.0 * np.vdot(_chain_dot(Pa, S, Pj), K["ab"])
    exch_offdiag -= 2.0 * np.vdot(_chain_dot(Pa, S, Pj), K["ib"])

    exch_offdiag -= np.vdot(_chain_dot(Pa, S, Pb), K["ab"])
    # print(print_sapt_var("Exch10,off-diagonal", exch_offdiag))
    # print(print_sapt_var("Exch10(S^2)", exch_offdiag + exch_diag))

    ret_values = OrderedDict({
        "Elst10":
        elst,
        "Exch10(S^2) [diagonal]":
        exch_diag,
        "Exch10(S^2) [off-diagonal]":
        exch_offdiag,
        "Exch10(S^2) [highspin]":
        exch_offdiag + exch_diag,
    })

    return ret_values
Exemple #52
0
def df_fdds_dispersion(primary, auxiliary, cache, is_hybrid, x_alpha, leg_points=10, leg_lambda=0.3, do_print=True):

    rho_thresh = core.get_option("SAPT", "SAPT_FDDS_V2_RHO_CUTOFF")
    if do_print:
        core.print_out("\n  ==> E20 Dispersion (CHF FDDS) <== \n\n")
        core.print_out("   Legendre Points:  % 10d\n" % leg_points)
        core.print_out("   Lambda Shift:     % 10.3f\n" % leg_lambda)
        core.print_out("   Fxc Kernal:       % 10s\n" % "ALDA")
        core.print_out("   (P|Fxc|Q) Thresh: % 8.3e\n" % rho_thresh)

    # Build object
    df_matrix_keys = ["Cocc_A", "Cvir_A", "Cocc_B", "Cvir_B"]
    fdds_matrix_cache = {key: cache[key] for key in df_matrix_keys}

    df_vector_keys = ["eps_occ_A", "eps_vir_A", "eps_occ_B", "eps_vir_B"]
    fdds_vector_cache = {key: cache[key] for key in df_vector_keys}

    fdds_obj = core.FDDS_Dispersion(primary, auxiliary, fdds_matrix_cache, fdds_vector_cache, is_hybrid)

    # Aux Densities
    D = fdds_obj.project_densities([cache["D_A"], cache["D_B"]])

    # Temps
    half_Saux = fdds_obj.aux_overlap().clone()
    half_Saux.power(-0.5, 1.e-12)

    halfp_Saux = fdds_obj.aux_overlap().clone()
    halfp_Saux.power(0.5, 1.e-12)

    # Builds potentials
    W_A = fdds_obj.metric().clone()
    W_A.axpy(1.0, _compute_fxc(D[0], half_Saux, halfp_Saux, x_alpha, rho_thresh=rho_thresh))
    W_A = W_A.to_array()

    W_B = fdds_obj.metric().clone()
    W_B.axpy(1.0, _compute_fxc(D[1], half_Saux, halfp_Saux, x_alpha, rho_thresh=rho_thresh))
    W_B = W_B.to_array()

    # Nuke the densities
    del D

    metric = fdds_obj.metric().clone().to_array()
    metric_inv = fdds_obj.metric_inv().clone().to_array()

    # Integrate
    core.print_out("\n   => Time Integration <= \n\n")

    val_pack = ("Omega", "Weight", "Disp20,u", "Disp20", "time [s]")
    core.print_out("% 12s % 12s % 14s % 14s % 10s\n" % val_pack)
    start_time = time.time()

    total_uc = 0
    total_c = 0

    # Read R
    if is_hybrid:
        R_A = fdds_obj.R_A().to_array()
        R_B = fdds_obj.R_B().to_array()
        Rtinv_A = np.linalg.pinv(R_A, rcond=1.e-13).transpose()
        Rtinv_B = np.linalg.pinv(R_B, rcond=1.e-13).transpose()

    for point, weight in zip(*np.polynomial.legendre.leggauss(leg_points)):

        omega = leg_lambda * (1.0 - point) / (1.0 + point)
        lambda_scale = ((2.0 * leg_lambda) / (point + 1.0)**2)

        # Monomer A
        if is_hybrid:
            aux_dict = fdds_obj.form_aux_matrices("A", omega)
            aux_dict = {k: v.to_array() for k, v in aux_dict.items()}
            X_A_uc = aux_dict["amp"].copy()
            X_A = X_A_uc - x_alpha * aux_dict["K2L"]

            # K matrices
            K_A = -x_alpha * aux_dict["K1LD"] - x_alpha * aux_dict["K2LD"] + x_alpha * x_alpha * aux_dict["K21L"]
            KRS_A = K_A.dot(Rtinv_A).dot(metric)
        else:
            X_A = fdds_obj.form_unc_amplitude("A", omega)
            X_A.scale(-1.0)
            X_A = X_A.to_array()
            X_A_uc = X_A.copy()

        # Coupled A
        XSW_A = X_A.dot(metric_inv).dot(W_A)
        if is_hybrid:
            XSW_A += 0.25 * KRS_A

        amplitude = np.linalg.pinv(metric - XSW_A, rcond=1.e-13)
        X_A_coupled = X_A + XSW_A.dot(amplitude).dot(X_A)

        del X_A, XSW_A, amplitude
        if is_hybrid:
            del K_A, KRS_A, aux_dict

        # Monomer B
        if is_hybrid:
            aux_dict = fdds_obj.form_aux_matrices("B", omega)
            aux_dict = {k: v.to_array() for k, v in aux_dict.items()}
            X_B_uc = aux_dict["amp"].copy()
            X_B = X_B_uc - x_alpha * aux_dict["K2L"]

            # K matrices
            K_B = -x_alpha * aux_dict["K1LD"] - x_alpha * aux_dict["K2LD"] + x_alpha * x_alpha * aux_dict["K21L"]
            KRS_B = K_B.dot(Rtinv_B).dot(metric)
        else:
            X_B = fdds_obj.form_unc_amplitude("B", omega)
            X_B.scale(-1.0)
            X_B = X_B.to_array()
            X_B_uc = X_B.copy()

        # Coupled B
        XSW_B = X_B.dot(metric_inv).dot(W_B)
        if is_hybrid:
            XSW_B += 0.25 * KRS_B

        amplitude = np.linalg.pinv(metric - XSW_B, rcond=1.e-13)
        X_B_coupled = X_B + XSW_B.dot(amplitude).dot(X_B)

        del X_B, XSW_B, amplitude
        if is_hybrid:
            del K_B, KRS_B, aux_dict

        # Make sure the results are symmetrized
        X_A_uc = _symmetrize(X_A_uc)
        X_B_uc = _symmetrize(X_B_uc)
        X_A_coupled = _symmetrize(X_A_coupled)
        X_B_coupled = _symmetrize(X_B_coupled)

        # Combine
        tmp_uc = metric_inv.dot(X_A_uc).dot(metric_inv)
        value_uc = np.dot(tmp_uc.flatten(), X_B_uc.flatten())
        del tmp_uc

        tmp_c = metric_inv.dot(X_A_coupled).dot(metric_inv)
        value_c = np.dot(tmp_c.flatten(), X_B_coupled.flatten())

        # Tally
        total_uc += value_uc * weight * lambda_scale
        total_c += value_c * weight * lambda_scale

        if do_print:
            tmp_disp_unc = value_uc * weight * lambda_scale
            tmp_disp = value_c * weight * lambda_scale
            fdds_time = time.time() - start_time

            val_pack = (omega, weight, tmp_disp_unc, tmp_disp, fdds_time)
            core.print_out("% 12.3e % 12.3e % 14.3e % 14.3e %10d\n" % val_pack)

    Disp20_uc = -1.0 / (2.0 * np.pi) * total_uc
    Disp20_c = -1.0 / (2.0 * np.pi) * total_c

    core.print_out("\n")
    core.print_out(print_sapt_var("Disp20,u", Disp20_uc, short=True) + "\n")
    core.print_out(print_sapt_var("Disp20", Disp20_c, short=True) + "\n")

    return {"Disp20,FDDS (unc)": Disp20_uc, "Disp20": Disp20_c}
Exemple #53
0
def scf_xtpl_karton_2(functionname: str,
                      zLO: int,
                      valueLO: Extrapolatable,
                      zHI: int,
                      valueHI: Extrapolatable,
                      verbose: int = 1,
                      alpha: Optional[float] = None) -> Extrapolatable:
    r"""Extrapolation scheme using root-power form for reference energies with two adjacent
    zeta-level bases. Used by :py:func:`~psi4.cbs`.

    Parameters
    ----------
    functionname
        Name of the CBS component (e.g., 'HF') used in summary printing.
    zLO
        Zeta number of the smaller basis set in 2-point extrapolation.
    valueLO
        Energy, gradient, or Hessian value at the smaller basis set in 2-point
        extrapolation.
    zHI
        Zeta number of the larger basis set in 2-point extrapolation
        Must be `zLO + 1`.
    valueHI
        Energy, gradient, or Hessian value at the larger basis set in 2-point
        extrapolation.
    verbose
        Controls volume of printing.
    alpha
        Overrides the default :math:`\alpha = 6.3`

    Returns
    -------
    float or ndarray
        Eponymous function applied to input zetas and values; type from `valueLO`.

    Notes
    -----
    The extrapolation is calculated according to [3]_:
    :math:`E_{total}^X = E_{total}^{\infty} + \beta e^{-\alpha\sqrt{X}}, \alpha = 6.3`

    References
    ----------

    .. [3] Karton, Martin, Theor. Chem. Acc. 115 (2006) 330-333,
       DOI: 10.1007/s00214-005-0028-6

    """

    if type(valueLO) != type(valueHI):
        raise ValidationError(
            f"scf_xtpl_karton_2: Inputs must be of the same datatype! ({type(valueLO)}, {type(valueHI)})"
        )

    if alpha is None:
        alpha = 6.30

    # prior to April 2022, this wrong expression was used
    # beta_division = 1 / (math.exp(-1 * alpha) * (math.exp(math.sqrt(zHI)) - math.exp(math.sqrt(zLO))))
    beta_division = 1 / (math.exp(-1 * alpha * math.sqrt(zHI)) -
                         math.exp(-1 * alpha * math.sqrt(zLO)))
    beta_mult = math.exp(-1 * alpha * math.sqrt(zHI))

    if isinstance(valueLO, float):
        beta = (valueHI - valueLO) * beta_division
        value = valueHI - beta * beta_mult

        if verbose:
            # Output string with extrapolation parameters
            cbsscheme = ''
            cbsscheme += """\n   ==> Karton 2-point power form SCF extrapolation for method: %s <==\n\n""" % (
                functionname.upper())
            cbsscheme += """   LO-zeta (%s) Energy:               % 16.12f\n""" % (
                str(zLO), valueLO)
            cbsscheme += """   HI-zeta (%s) Energy:               % 16.12f\n""" % (
                str(zHI), valueHI)
            cbsscheme += """   Alpha (exponent) Value:           % 16.12f\n""" % (
                alpha)
            cbsscheme += """   Beta (coefficient) Value:         % 16.12f\n\n""" % (
                beta)

            name_str = "%s/(%s,%s)" % (functionname.upper(),
                                       _zeta_val2sym[zLO].upper(),
                                       _zeta_val2sym[zHI].upper())
            cbsscheme += """   @Extrapolated """
            cbsscheme += name_str + ':'
            cbsscheme += " " * (18 - len(name_str))
            cbsscheme += """% 16.12f\n\n""" % value
            core.print_out(cbsscheme)

        return value

    elif isinstance(valueLO, (core.Matrix, core.Vector)):
        valueLO = valueLO.to_array()
        valueHI = valueHI.to_array()

        beta = (valueHI - valueLO) * beta_division
        value = valueHI - beta * beta_mult

        if verbose > 2:
            cbsscheme = f"""\n   ==> Karton 2-point power SCF extrapolation for method: {functionname.upper()} <==\n"""
            cbsscheme += f"""\n   LO-zeta ({zLO}) Data\n"""
            cbsscheme += nppp(valueLO)
            cbsscheme += f"""\n   HI-zeta ({zHI}) Data\n"""
            cbsscheme += nppp(valueHI)

            cbsscheme += f"""\n   Alpha (exponent) Value:          {alpha:16.8f}"""
            cbsscheme += f"""\n   Beta Data\n"""
            cbsscheme += nppp(beta)
            cbsscheme += f"""\n   Extrapolated Data\n"""
            cbsscheme += nppp(value)
            cbsscheme += "\n"
            core.print_out(cbsscheme)

        value = core.Matrix.from_array(value)
        return value

    else:
        raise ValidationError(
            f"scf_xtpl_Karton_2: datatype is not recognized '{type(valueLO)}'."
        )
Exemple #54
0
def scf_initialize(self):
    """Specialized initialization, compute integrals and does everything to prepare for iterations"""

    # Figure out memory distributions

    # Get memory in terms of doubles
    total_memory = (core.get_memory() /
                    8) * core.get_global_option("SCF_MEM_SAFETY_FACTOR")

    # Figure out how large the DFT collocation matrices are
    vbase = self.V_potential()
    if vbase:
        collocation_size = vbase.grid().collocation_size()
        if vbase.functional().ansatz() == 1:
            collocation_size *= 4  # First derivs
        elif vbase.functional().ansatz() == 2:
            collocation_size *= 10  # Second derivs
    else:
        collocation_size = 0

    # Change allocation for collocation matrices based on DFT type
    jk = _build_jk(self, total_memory)
    jk_size = jk.memory_estimate()

    # Give remaining to collocation
    if total_memory > jk_size:
        collocation_memory = total_memory - jk_size
    # Give up to 10% to collocation
    elif (total_memory * 0.1) > collocation_size:
        collocation_memory = collocation_size
    else:
        collocation_memory = total_memory * 0.1

    if collocation_memory > collocation_size:
        collocation_memory = collocation_size

    # Set constants
    self.iteration_ = 0
    self.memory_jk_ = int(total_memory - collocation_memory)
    self.memory_collocation_ = int(collocation_memory)

    if self.get_print():
        core.print_out("  ==> Integral Setup <==\n\n")

    # Initialize EFP
    efp_enabled = hasattr(self.molecule(), 'EFP')
    if efp_enabled:
        # EFP: Set QM system, options, and callback. Display efp geom in [A]
        efpobj = self.molecule().EFP
        core.print_out(efpobj.banner())
        core.print_out(
            efpobj.geometry_summary(units_to_bohr=constants.bohr2angstroms))

        efpptc, efpcoords, efpopts = get_qm_atoms_opts(self.molecule())
        efpobj.set_point_charges(efpptc, efpcoords)
        efpobj.set_opts(efpopts, label='psi', append='psi')

        efpobj.set_electron_density_field_fn(efp_field_fn)

    # Initialize all integrals and perform the first guess
    if self.attempt_number_ == 1:
        mints = core.MintsHelper(self.basisset())

        self.initialize_jk(self.memory_jk_, jk=jk)
        if self.V_potential():
            self.V_potential().build_collocation_cache(
                self.memory_collocation_)
        core.timer_on("HF: Form core H")
        self.form_H()
        core.timer_off("HF: Form core H")

        if efp_enabled:
            # EFP: Add in permanent moment contribution and cache
            core.timer_on("HF: Form Vefp")
            verbose = core.get_option('SCF', "PRINT")
            Vefp = modify_Fock_permanent(self.molecule(),
                                         mints,
                                         verbose=verbose - 1)
            Vefp = core.Matrix.from_array(Vefp)
            self.H().add(Vefp)
            Horig = self.H().clone()
            self.Horig = Horig
            core.print_out(
                "  QM/EFP: iterating Total Energy including QM/EFP Induction\n"
            )
            core.timer_off("HF: Form Vefp")

        core.timer_on("HF: Form S/X")
        self.form_Shalf()
        core.timer_off("HF: Form S/X")

        core.print_out("\n  ==> Pre-Iterations <==\n\n")

        core.timer_on("HF: Guess")
        self.guess()
        core.timer_off("HF: Guess")
        # Print out initial docc/socc/etc data
        if self.get_print():
            lack_occupancy = core.get_local_option('SCF', 'GUESS') in ['SAD']
            if core.get_global_option('GUESS') in ['SAD']:
                lack_occupancy = core.get_local_option('SCF',
                                                       'GUESS') in ['AUTO']
                self.print_preiterations(small=lack_occupancy)
            else:
                self.print_preiterations(small=lack_occupancy)

    else:
        # We're reading the orbitals from the previous set of iterations.
        self.form_D()
        self.set_energies("Total Energy", self.compute_initial_E())

    # turn off VV10 for iterations
    if core.get_option(
            'SCF', "DFT_VV10_POSTSCF") and self.functional().vv10_b() > 0.0:
        core.print_out("  VV10: post-SCF option active \n \n")
        self.functional().set_lock(False)
        self.functional().set_do_vv10(False)
        self.functional().set_lock(True)

    # Print iteration header
    is_dfjk = core.get_global_option('SCF_TYPE').endswith('DF')
    diis_rms = core.get_option('SCF', 'DIIS_RMS_ERROR')
    core.print_out("  ==> Iterations <==\n\n")
    core.print_out(
        "%s                        Total Energy        Delta E     %s |[F,P]|\n\n"
        % ("   " if is_dfjk else "", "RMS" if diis_rms else "MAX"))
Exemple #55
0
def scf_xtpl_helgaker_3(functionname: str,
                        zLO: int,
                        valueLO: Extrapolatable,
                        zMD: int,
                        valueMD: Extrapolatable,
                        zHI: int,
                        valueHI: Extrapolatable,
                        verbose: int = 1,
                        alpha: Optional[float] = None) -> Extrapolatable:
    r"""Extrapolation scheme for reference energies with three adjacent zeta-level bases.
    Used by :py:func:`~psi4.cbs`.

    Parameters
    ----------
    functionname
        Name of the CBS component (e.g., 'HF') used in summary printing.
    zLO
        Zeta number of the smaller basis set in 3-point extrapolation.
    valueLO
        Energy, gradient, or Hessian value at the smaller basis set in 3-point
        extrapolation.
    zMD
        Zeta number of the medium basis set in 3-point extrapolation.
        Must be `zLO + 1`.
    valueMD
        Energy, gradient, or Hessian value at the medium basis set in 3-point
        extrapolation.
    zHI
        Zeta number of the larger basis set in 3-point extrapolation.
        Must be `zLO + 2`.
    valueHI
        Energy, gradient, or Hessian value at the larger basis set in 3-point
        extrapolation.
    verbose
        Controls volume of printing.
    alpha
        Not used.

    Returns
    -------
    float or ndarray
        Eponymous function applied to input zetas and values; type from `valueLO`.

    Notes
    -----
    The extrapolation is calculated according to [4]_:
    :math:`E_{total}^X = E_{total}^{\infty} + \beta e^{-\alpha X}, \alpha = 3.0`

    References
    ----------

    .. [4] Halkier, Helgaker, Jorgensen, Klopper, & Olsen, Chem. Phys. Lett. 302 (1999) 437-446,
       DOI: 10.1016/S0009-2614(99)00179-7

    Examples
    --------
    >>> # [1] Hartree-Fock extrapolation
    >>> psi4.energy('cbs', scf_wfn='hf', scf_basis='cc-pV[DTQ]Z', scf_scheme='scf_xtpl_helgaker_3')

    """

    if (type(valueLO) != type(valueMD)) or (type(valueMD) != type(valueHI)):
        raise ValidationError(
            f"scf_xtpl_helgaker_3: Inputs must be of the same datatype! ({type(valueLO)}, {type(valueMD)}, {type(valueHI)})"
        )

    if isinstance(valueLO, float):

        ratio = (valueHI - valueMD) / (valueMD - valueLO)
        alpha = -1 * math.log(ratio)
        beta = (valueHI - valueMD) / (math.exp(-1 * alpha * zMD) * (ratio - 1))
        value = valueHI - beta * math.exp(-1 * alpha * zHI)

        if verbose:
            # Output string with extrapolation parameters
            cbsscheme = ''
            cbsscheme += """\n   ==> Helgaker 3-point SCF extrapolation for method: %s <==\n\n""" % (
                functionname.upper())
            cbsscheme += """   LO-zeta (%s) Energy:               % 16.12f\n""" % (
                str(zLO), valueLO)
            cbsscheme += """   MD-zeta (%s) Energy:               % 16.12f\n""" % (
                str(zMD), valueMD)
            cbsscheme += """   HI-zeta (%s) Energy:               % 16.12f\n""" % (
                str(zHI), valueHI)
            cbsscheme += """   Alpha (exponent) Value:           % 16.12f\n""" % (
                alpha)
            cbsscheme += """   Beta (coefficient) Value:         % 16.12f\n\n""" % (
                beta)

            name_str = "%s/(%s,%s,%s)" % (
                functionname.upper(), _zeta_val2sym[zLO].upper(),
                _zeta_val2sym[zMD].upper(), _zeta_val2sym[zHI].upper())
            cbsscheme += """   @Extrapolated """
            cbsscheme += name_str + ':'
            cbsscheme += " " * (18 - len(name_str))
            cbsscheme += """% 16.12f\n\n""" % value
            core.print_out(cbsscheme)

        return value

    elif isinstance(valueLO, (core.Matrix, core.Vector)):
        valueLO = np.array(valueLO)
        valueMD = np.array(valueMD)
        valueHI = np.array(valueHI)

        nonzero_mask = np.abs(valueHI) > 1.e-14
        top = (valueHI - valueMD)[nonzero_mask]
        bot = (valueMD - valueLO)[nonzero_mask]

        ratio = top / bot
        alpha = -1 * np.log(np.abs(ratio))
        beta = top / (np.exp(-1 * alpha * zMD) * (ratio - 1))
        np_value = valueHI.copy()
        np_value[nonzero_mask] -= beta * np.exp(-1 * alpha * zHI)
        np_value[~nonzero_mask] = 0.0

        if verbose > 2:
            cbsscheme = f"""\n   ==> Helgaker 3-point power SCF extrapolation for method: {functionname.upper()} <==\n"""
            cbsscheme += f"""\n   LO-zeta ({zLO}) Data\n"""
            cbsscheme += nppp(valueLO)
            cbsscheme += f"""\n   MD-zeta ({zMD}) Data\n"""
            cbsscheme += nppp(valueMD)
            cbsscheme += f"""\n   HI-zeta ({zHI}) Data\n"""
            cbsscheme += nppp(valueHI)

            cbsscheme += f"""\n   Alpha Data\n"""
            cbsscheme += nppp(alpha)
            cbsscheme += f"""\n   Beta Data\n"""
            cbsscheme += nppp(beta)
            cbsscheme += f"""\n   Extrapolated Data\n"""
            cbsscheme += nppp(np_value)
            cbsscheme += "\n"
            core.print_out(cbsscheme)

        ## Build and set from numpy routines
        #value = core.Matrix(*valueHI.shape)
        #value_view = np.asarray(value)
        #value_view[:] = np_value
        #return value

        np_value = core.Matrix.from_array(np_value)
        return np_value

    else:
        raise ValidationError(
            f"scf_xtpl_helgaker_3: datatype is not recognized '{type(valueLO)}'."
        )
Exemple #56
0
def corl_xtpl_helgaker_2(functionname: str,
                         zLO: int,
                         valueLO: Extrapolatable,
                         zHI: int,
                         valueHI: Extrapolatable,
                         verbose: int = 1,
                         alpha: Optional[float] = None) -> Extrapolatable:
    r"""Extrapolation scheme for correlation energies with two adjacent zeta-level bases.
    Used by :py:func:`~psi4.cbs`.

    Parameters
    ----------
    functionname
        Name of the CBS component (e.g., 'MP2') used in summary printing.
    zLO
        Zeta number of the smaller basis set in 2-point extrapolation.
    valueLO
        Energy, gradient, or Hessian value at the smaller basis set in 2-point
        extrapolation.
    zHI
        Zeta number of the larger basis set in 2-point extrapolation.
        Must be `zLO + 1`.
    valueHI
        Energy, gradient, or Hessian value at the larger basis set in 2-point
        extrapolation.
    verbose
        Controls volume of printing.
    alpha
        Overrides the default :math:`\alpha = 3.0`

    Returns
    -------
    float or numpy.ndarray
        Eponymous function applied to input zetas and values; type from `valueLO`.

    Notes
    -----
    The extrapolation is calculated according to [5]_:
    :math:`E_{corl}^X = E_{corl}^{\infty} + \beta X^{-alpha}`

    References
    ----------

    .. [5] Halkier, Helgaker, Jorgensen, Klopper, Koch, Olsen, & Wilson,
       Chem. Phys. Lett. 286 (1998) 243-252,
       DOI: 10.1016/S0009-2614(99)00179-7

    Examples
    --------
    >>> # [1] CISD extrapolation
    >>> energy('cbs', corl_wfn='cisd', corl_basis='cc-pV[DT]Z', corl_scheme='corl_xtpl_helgaker_2')

    """
    if type(valueLO) != type(valueHI):
        raise ValidationError(
            f"corl_xtpl_helgaker_2: Inputs must be of the same datatype! ({type(valueLO)}, {type(valueHI)})"
        )

    if alpha is None:
        alpha = 3.0

    if isinstance(valueLO, float):
        value = (valueHI * zHI**alpha - valueLO * zLO**alpha) / (zHI**alpha -
                                                                 zLO**alpha)
        beta = (valueHI - valueLO) / (zHI**(-alpha) - zLO**(-alpha))

        final = value
        if verbose:
            # Output string with extrapolation parameters
            cbsscheme = f"""\n\n   ==> Helgaker 2-point correlated extrapolation for method: {functionname.upper()} <==\n\n"""
            cbsscheme += """   LO-zeta (%s) Energy:               % 16.12f\n""" % (
                str(zLO), valueLO)
            cbsscheme += """   HI-zeta (%s) Energy:               % 16.12f\n""" % (
                str(zHI), valueHI)
            cbsscheme += """   Alpha (exponent) Value:           % 16.12f\n""" % alpha
            cbsscheme += f"""   Beta (coefficient) Value:         {beta: 16.12f}\n\n"""
            cbsscheme += """   Extrapolated Energy:              % 16.12f\n\n""" % value
            # Note that in energy-only days, this used to print SCF and Correlation, not Total, Energy

            name_str = "%s/(%s,%s)" % (functionname.upper(),
                                       _zeta_val2sym[zLO].upper(),
                                       _zeta_val2sym[zHI].upper())
            cbsscheme += """   @Extrapolated """
            cbsscheme += name_str + ':'
            cbsscheme += " " * (19 - len(name_str))
            cbsscheme += """% 16.12f\n\n""" % final
            core.print_out(cbsscheme)

        return final

    elif isinstance(valueLO, (core.Matrix, core.Vector)):
        valueLO = np.array(valueLO)
        valueHI = np.array(valueHI)

        value = (valueHI * zHI**alpha - valueLO * zLO**alpha) / (zHI**alpha -
                                                                 zLO**alpha)
        beta = (valueHI - valueLO) / (zHI**(-alpha) - zLO**(-alpha))

        if verbose > 2:
            cbsscheme = f"""\n   ==> Helgaker 2-point correlated extrapolation for method: {functionname.upper()} <==\n"""
            cbsscheme += f"""\n   LO-zeta ({zLO}) Data\n"""
            cbsscheme += nppp(valueLO)
            cbsscheme += f"""\n   HI-zeta ({zHI}) Data\n"""
            cbsscheme += nppp(valueHI)

            cbsscheme += f"""\n   Alpha (exponent) Value:          {alpha:16.8f}"""
            cbsscheme += f"""\n   Beta Data\n"""
            cbsscheme += nppp(beta)
            cbsscheme += f"""\n   Extrapolated Data\n"""
            cbsscheme += nppp(value)
            cbsscheme += "\n"
            core.print_out(cbsscheme)

        value = core.Matrix.from_array(value)
        return value

    else:
        raise ValidationError(
            f"corl_xtpl_helgaker_2: datatype is not recognized '{type(valueLO)}'."
        )
Exemple #57
0
def print_ci_results(ciwfn, rname, scf_e, ci_e, print_opdm_no=False):
    """
    Printing for all CI Wavefunctions
    """

    # Print out energetics
    core.print_out("\n   ==> Energetics <==\n\n")
    core.print_out("    SCF energy =         %20.15f\n" % scf_e)
    if "CI" in rname:
        core.print_out("    Total CI energy =    %20.15f\n" % ci_e)
    elif "MP" in rname:
        core.print_out("    Total MP energy =    %20.15f\n" % ci_e)
    elif "ZAPT" in rname:
        core.print_out("    Total ZAPT energy =  %20.15f\n" % ci_e)
    else:
        core.print_out("    Total MCSCF energy = %20.15f\n" % ci_e)

    # Nothing to be done for ZAPT or MP
    if ("MP" in rname) or ("ZAPT" in rname):
        core.print_out("\n")
        return

    # Initial info
    ci_nroots = core.get_option("DETCI", "NUM_ROOTS")
    irrep_labels = ciwfn.molecule().irrep_labels()

    # Grab the D-vector
    dvec = ciwfn.D_vector()
    dvec.init_io_files(True)

    for root in range(ci_nroots):
        core.print_out("\n   ==> %s root %d information <==\n\n" %
                       (rname, root))

        # Print total energy
        root_e = ciwfn.variable("CI ROOT %d TOTAL ENERGY" % (root))
        core.print_out("    %s Root %d energy =  %20.15f\n" %
                       (rname, root, root_e))

        # Print natural occupations
        if print_opdm_no:
            core.print_out("\n   Active Space Natural occupation numbers:\n\n")

            occs_list = []
            r_opdm = ciwfn.get_opdm(root, root, "SUM", False)
            for h in range(len(r_opdm.nph)):
                if 0 in r_opdm.nph[h].shape:
                    continue
                nocc, rot = np.linalg.eigh(r_opdm.nph[h])
                for e in nocc:
                    occs_list.append((e, irrep_labels[h]))

            occs_list.sort(key=lambda x: -x[0])

            cnt = 0
            for value, label in occs_list:
                value, label = occs_list[cnt]
                core.print_out("      %4s  % 8.6f" % (label, value))
                cnt += 1
                if (cnt % 3) == 0:
                    core.print_out("\n")

            if (cnt % 3):
                core.print_out("\n")

        # Print CIVector information
        ciwfn.print_vector(dvec, root)

    # True to keep the file
    dvec.close_io_files(True)
Exemple #58
0
def anharmonicity(rvals: List,
                  energies: List,
                  plot_fit: str = '',
                  mol=None) -> Dict:
    """Generates spectroscopic constants for a diatomic molecules.
       Fits a diatomic potential energy curve using a weighted least squares approach
       (c.f. https://doi.org/10.1063/1.4862157, particularly eqn. 7), locates the minimum
       energy point, and then applies second order vibrational perturbation theory to obtain spectroscopic
       constants.  Any number of points greater than 4 may be provided, and they should bracket the minimum.
       The data need not be evenly spaced, and can be provided in any order.  The data are weighted such that
       those closest to the minimum have highest impact.

       A dictionary with the following keys, which correspond to spectroscopic constants, is returned:

       :param rvals: The bond lengths (in Angstrom) for which energies are
           provided, of length at least 5 and equal to the length of the energies array

       :param energies: The energies (Eh) computed at the bond lengths in the rvals list

       :param plot_fit: A string describing where to save a plot of the harmonic and anharmonic fits, the
           inputted data points, re, r0 and the first few energy levels, if matplotlib
           is available.  Set to 'screen' to generate an interactive plot on the screen instead. If a filename is
           provided, the image type is determined by the extension; see matplotlib for supported file types.

       :returns: (*dict*) Keys: "re", "r0", "we", "wexe", "nu", "ZPVE(harmonic)", "ZPVE(anharmonic)", "Be", "B0", "ae", "De"
                 corresponding to the spectroscopic constants in cm-1
    """

    angstrom_to_bohr = 1.0 / constants.bohr2angstroms
    angstrom_to_meter = 10e-10

    # Make sure the input is valid
    if len(rvals) != len(energies):
        raise ValidationError(
            "The number of energies must match the number of distances")
    npoints = len(rvals)
    if npoints < 5:
        raise ValidationError(
            "At least 5 data points must be provided to compute anharmonicity")
    core.print_out("\n\nPerforming a fit to %d data points\n" % npoints)

    # Sort radii and values first from lowest to highest radius
    indices = np.argsort(rvals)
    rvals = np.array(rvals)[indices]
    energies = np.array(energies)[indices]

    # Make sure the molecule the user provided is the active one
    molecule = mol or core.get_active_molecule()
    molecule.update_geometry()
    natoms = molecule.natom()
    if natoms != 2:
        raise Exception(
            "The current molecule must be a diatomic for this code to work!")
    m1 = molecule.mass(0)
    m2 = molecule.mass(1)

    # Find rval of the minimum of energies, check number of points left and right
    min_index = np.argmin(energies)
    if min_index < 3:
        core.print_out(
            "\nWarning: fewer than 3 points provided with a r < r(min(E))!\n")
    if min_index >= len(energies) - 3:
        core.print_out(
            "\nWarning: fewer than 3 points provided with a r > r(min(E))!\n")

    # Optimize the geometry, refitting the surface around each new geometry
    core.print_out("\nOptimizing geometry based on current surface:\n\n")
    re = rvals[min_index]
    maxit = 30
    thres = 1.0e-9
    for i in range(maxit):
        derivs = least_squares_fit_polynomial(rvals,
                                              energies,
                                              localization_point=re)
        e, g, H = derivs[0:3]
        core.print_out("       E = %20.14f, x = %14.7f, grad = %20.14f\n" %
                       (e, re, g))
        if abs(g) < thres:
            break
        re -= g / H
        if i == maxit - 1:
            raise ConvergenceError("diatomic geometry optimization", maxit)
    core.print_out(" Final E = %20.14f, x = %14.7f, grad = %20.14f\n" %
                   (e, re, g))
    if re < min(rvals):
        raise Exception(
            "Minimum energy point is outside range of points provided.  Use a lower range of r values."
        )
    if re > max(rvals):
        raise Exception(
            "Minimum energy point is outside range of points provided.  Use a higher range of r values."
        )

    # Convert to convenient units, and compute spectroscopic constants
    d0, d1, d2, d3, d4 = derivs * constants.hartree2aJ
    core.print_out("\nEquilibrium Energy %20.14f Hartrees\n" % e)
    core.print_out("Gradient           %20.14f\n" % g)
    core.print_out("Quadratic Force Constant %14.7f MDYNE/A\n" % d2)
    core.print_out("Cubic Force Constant     %14.7f MDYNE/A**2\n" % d3)
    core.print_out("Quartic Force Constant   %14.7f MDYNE/A**3\n" % d4)

    hbar = constants.h / (2.0 * np.pi)
    mu = ((m1 * m2) / (m1 + m2)) * constants.amu2kg
    we = 5.3088375e-11 * np.sqrt(d2 / mu)
    wexe = (1.2415491e-6) * (we / d2)**2 * ((5.0 * d3 * d3) / (3.0 * d2) - d4)

    # Rotational constant: Be
    I = ((m1 * m2) /
         (m1 + m2)) * constants.amu2kg * (re * angstrom_to_meter)**2
    B = constants.h / (8.0 * np.pi**2 * constants.c * I)

    # alpha_e and quartic centrifugal distortion constant
    ae = -(6.0 * B**2 / we) * ((1.05052209e-3 * we * d3) /
                               (np.sqrt(B * d2**3)) + 1.0)
    de = 4.0 * B**3 / we**2

    # B0 and r0 (plus re check using Be)
    B0 = B - ae / 2.0
    r0 = np.sqrt(constants.h / (8.0 * np.pi**2 * mu * constants.c * B0))
    recheck = np.sqrt(constants.h / (8.0 * np.pi**2 * mu * constants.c * B))
    r0 /= angstrom_to_meter
    recheck /= angstrom_to_meter

    # Fundamental frequency nu
    nu = we - 2.0 * wexe
    zpve_nu = 0.5 * we - 0.25 * wexe
    zpve_we = 0.5 * we

    # Generate pretty pictures, if requested
    if (plot_fit):
        try:
            import matplotlib.pyplot as plt
        except ImportError:
            msg = "\n\tPlot not generated; matplotlib is not installed on this machine.\n\n"
            print(msg)
            core.print_out(msg)

        # Correct the derivatives for the missing factorial prefactors
        dvals = np.zeros(5)
        dvals[0:5] = derivs[0:5]
        dvals[2] /= 2
        dvals[3] /= 6
        dvals[4] /= 24

        # Default plot range, before considering energy levels
        minE = np.min(energies)
        maxE = np.max(energies)
        minR = np.min(rvals)
        maxR = np.max(rvals)

        # Plot vibrational energy levels
        we_au = we / constants.hartree2wavenumbers
        wexe_au = wexe / constants.hartree2wavenumbers
        coefs2 = [dvals[2], dvals[1], dvals[0]]
        coefs4 = [dvals[4], dvals[3], dvals[2], dvals[1], dvals[0]]
        for n in range(3):
            Eharm = we_au * (n + 0.5)
            Evpt2 = Eharm - wexe_au * (n + 0.5)**2
            coefs2[-1] = -Eharm
            coefs4[-1] = -Evpt2
            roots2 = np.roots(coefs2)
            roots4 = np.roots(coefs4)
            xvals2 = roots2 + re
            xvals4 = np.choose(np.where(np.isreal(roots4)),
                               roots4)[0].real + re
            Eharm += dvals[0]
            Evpt2 += dvals[0]
            plt.plot(xvals2, [Eharm, Eharm], 'b', linewidth=1)
            plt.plot(xvals4, [Evpt2, Evpt2], 'g', linewidth=1)
            maxE = Eharm
            maxR = np.max([xvals2, xvals4])
            minR = np.min([xvals2, xvals4])

        # Find ranges for the plot
        dE = maxE - minE
        minE -= 0.2 * dE
        maxE += 0.4 * dE
        dR = maxR - minR
        minR -= 0.2 * dR
        maxR += 0.2 * dR

        # Generate the fitted PES
        xpts = np.linspace(minR, maxR, 1000)
        xrel = xpts - re
        xpows = xrel[:, None]**range(5)
        fit2 = np.einsum('xd,d', xpows[:, 0:3], dvals[0:3])
        fit4 = np.einsum('xd,d', xpows, dvals)

        # Make / display the plot
        plt.plot(xpts,
                 fit2,
                 'b',
                 linewidth=2.5,
                 label='Harmonic (quadratic) fit')
        plt.plot(xpts,
                 fit4,
                 'g',
                 linewidth=2.5,
                 label='Anharmonic (quartic) fit')
        plt.plot([re, re], [minE, maxE], 'b--', linewidth=0.5)
        plt.plot([r0, r0], [minE, maxE], 'g--', linewidth=0.5)
        plt.scatter(rvals,
                    energies,
                    c='Black',
                    linewidth=3,
                    label='Input Data')
        plt.legend()

        plt.xlabel('Bond length (Angstroms)')
        plt.ylabel('Energy (Eh)')
        plt.xlim(minR, maxR)
        plt.ylim(minE, maxE)
        if plot_fit == 'screen':
            plt.show()
        else:
            plt.savefig(plot_fit)
            core.print_out("\n\tPES fit saved to %s.\n\n" % plot_fit)

    core.print_out("\nre       = %10.6f A  check: %10.6f\n" % (re, recheck))
    core.print_out("r0       = %10.6f A\n" % r0)
    core.print_out("E at re  = %17.10f Eh\n" % e)
    core.print_out("we       = %10.4f cm-1\n" % we)
    core.print_out("wexe     = %10.4f cm-1\n" % wexe)
    core.print_out("nu       = %10.4f cm-1\n" % nu)
    core.print_out("ZPVE(we) = %10.4f cm-1\n" % zpve_we)
    core.print_out("ZPVE(nu) = %10.4f cm-1\n" % zpve_nu)
    core.print_out("Be       = %10.4f cm-1\n" % B)
    core.print_out("B0       = %10.4f cm-1\n" % B0)
    core.print_out("ae       = %10.4f cm-1\n" % ae)
    core.print_out("De       = %10.7f cm-1\n" % de)
    results = {
        "re": re,
        "r0": r0,
        "we": we,
        "wexe": wexe,
        "nu": nu,
        "E(re)": e,
        "ZPVE(harmonic)": zpve_we,
        "ZPVE(anharmonic)": zpve_nu,
        "Be": B,
        "B0": B0,
        "ae": ae,
        "De": de
    }
    return results
Exemple #59
0
def scf_print_energies(self):
    enuc = self.get_energies('Nuclear')
    e1 = self.get_energies('One-Electron')
    e2 = self.get_energies('Two-Electron')
    exc = self.get_energies('XC')
    ed = self.get_energies('-D')
    self.del_variable('-D Energy')
    evv10 = self.get_energies('VV10')
    eefp = self.get_energies('EFP')
    epcm = self.get_energies('PCM Polarization')
    epe = self.get_energies('PE Energy')

    hf_energy = enuc + e1 + e2
    dft_energy = hf_energy + exc + ed + evv10
    total_energy = dft_energy + eefp + epcm + epe

    core.print_out("   => Energetics <=\n\n")
    core.print_out(
        "    Nuclear Repulsion Energy =        {:24.16f}\n".format(enuc))
    core.print_out(
        "    One-Electron Energy =             {:24.16f}\n".format(e1))
    core.print_out(
        "    Two-Electron Energy =             {:24.16f}\n".format(e2))
    if self.functional().needs_xc():
        core.print_out(
            "    DFT Exchange-Correlation Energy = {:24.16f}\n".format(exc))
        core.print_out(
            "    Empirical Dispersion Energy =     {:24.16f}\n".format(ed))
        core.print_out(
            "    VV10 Nonlocal Energy =            {:24.16f}\n".format(evv10))
    if core.get_option('SCF', 'PCM'):
        core.print_out(
            "    PCM Polarization Energy =         {:24.16f}\n".format(epcm))
    if core.get_option('SCF', 'PE'):
        core.print_out(
            "    PE Energy =                       {:24.16f}\n".format(epe))
    if hasattr(self.molecule(), 'EFP'):
        core.print_out(
            "    EFP Energy =                      {:24.16f}\n".format(eefp))
    core.print_out("    Total Energy =                    {:24.16f}\n".format(
        total_energy))

    if core.get_option('SCF', 'PE'):
        core.print_out(self.pe_state.cppe_state.summary_string)

    self.set_variable("NUCLEAR REPULSION ENERGY", enuc)  # P::e SCF
    self.set_variable("ONE-ELECTRON ENERGY", e1)  # P::e SCF
    self.set_variable("TWO-ELECTRON ENERGY", e2)  # P::e SCF
    if self.functional().needs_xc():
        self.set_variable("DFT XC ENERGY", exc)  # P::e SCF
        self.set_variable("DFT VV10 ENERGY", evv10)  # P::e SCF
        self.set_variable("DFT FUNCTIONAL TOTAL ENERGY",
                          hf_energy + exc + evv10)  # P::e SCF
        #self.set_variable(self.functional().name() + ' FUNCTIONAL TOTAL ENERGY', hf_energy + exc + evv10)
        self.set_variable("DFT TOTAL ENERGY",
                          dft_energy)  # overwritten later for DH  # P::e SCF
    else:
        self.set_variable("HF TOTAL ENERGY", hf_energy)  # P::e SCF
    if hasattr(self, "_disp_functor"):
        self.set_variable("DISPERSION CORRECTION ENERGY", ed)  # P::e SCF
    #if abs(ed) > 1.0e-14:
    #    for pv, pvv in self.variables().items():
    #        if abs(pvv - ed) < 1.0e-14:
    #            if pv.endswith('DISPERSION CORRECTION ENERGY') and pv.startswith(self.functional().name()):
    #                fctl_plus_disp_name = pv.split()[0]
    #                self.set_variable(fctl_plus_disp_name + ' TOTAL ENERGY', dft_energy)  # overwritten later for DH
    #else:
    #    self.set_variable(self.functional().name() + ' TOTAL ENERGY', dft_energy)  # overwritten later for DH

    self.set_variable("SCF ITERATIONS", self.iteration_)  # P::e SCF
Exemple #60
0
def prepare_sapt_molecule(sapt_dimer, sapt_basis):
    """
    Prepares a dimer molecule for a SAPT computations. Returns the dimer, monomerA, and monomerB.
    """

    # Shifting to C1 so we need to copy the active molecule
    sapt_dimer = sapt_dimer.clone()
    if sapt_dimer.schoenflies_symbol() != 'c1':
        core.print_out(
            '  SAPT does not make use of molecular symmetry, further calculations in C1 point group.\n'
        )
        sapt_dimer.reset_point_group('c1')
        sapt_dimer.fix_orientation(True)
        sapt_dimer.fix_com(True)
        sapt_dimer.update_geometry()
    else:
        sapt_dimer.update_geometry(
        )  # make sure since mol from wfn, kwarg, or P::e
        sapt_dimer.fix_orientation(True)
        sapt_dimer.fix_com(True)

    nfrag = sapt_dimer.nfragments()

    if nfrag == 3:
        # Midbond case
        if sapt_basis == 'monomer':
            raise ValidationError(
                "SAPT basis cannot both be monomer centered and have midbond functions."
            )

        midbond = sapt_dimer.extract_subsets(3)
        ztotal = 0
        for n in range(midbond.natom()):
            ztotal += midbond.Z(n)

        if ztotal > 0:
            raise ValidationError(
                "SAPT third monomer must be a midbond function (all ghosts).")

        ghosts = ([2, 3], [1, 3])
    elif nfrag == 2:
        # Classical dimer case
        ghosts = (2, 1)
    else:
        raise ValidationError(
            'SAPT requires active molecule to have 2 fragments, not %s.' %
            (nfrag))

    if sapt_basis == 'dimer':
        monomerA = sapt_dimer.extract_subsets(1, ghosts[0])
        monomerA.set_name('monomerA')
        monomerB = sapt_dimer.extract_subsets(2, ghosts[1])
        monomerB.set_name('monomerB')
    elif sapt_basis == 'monomer':
        monomerA = sapt_dimer.extract_subsets(1)
        monomerA.set_name('monomerA')
        monomerB = sapt_dimer.extract_subsets(2)
        monomerB.set_name('monomerB')
    else:
        raise ValidationError("SAPT basis %s not recognized" % sapt_basis)

    return (sapt_dimer, monomerA, monomerB)