Пример #1
0
def prepare_sapt_molecule(sapt_dimer: core.Molecule, sapt_basis: str) -> Tuple[core.Molecule, core.Molecule, core.Molecule]:
    """
    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)
Пример #2
0
    def compute_hessian(self,
                        molecule: core.Molecule,
                        wfn: core.Wavefunction = None) -> core.Matrix:
        """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
            System for which to compute empirical dispersion correction.
        wfn
            Location to set QCVariables

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

        """
        optstash = p4util.OptionsState(['PRINT'], ['PARENT_SYMMETRY'])
        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_global_option("PARENT_SYMMETRY",
                               molecule.schoenflies_symbol())

        findif_meta_dict = driver_findif.hessian_from_gradients_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.assemble_hessian_from_gradients(findif_meta_dict, -1)
        if wfn is not None:
            wfn.set_variable('DISPERSION CORRECTION HESSIAN', H)
        optstash.restore()
        return core.Matrix.from_array(H)