Пример #1
0
    def _init_pbc(self, cell, mf, twist):
        from pyscf.pbc import scf
        from pyqmc.supercell import get_supercell_kpts

        # Make sure supercell has attributes S and original_cell
        for attribute in ["original_cell", "S", "scale"]:
            if not hasattr(cell, attribute):
                print('Warning: supercell is missing attribute "%s"' % attribute)
                print("setting original_cell=supercell and S=np.eye(3)")
                cell.original_cell = cell
                cell.S = np.eye(3)
                cell.scale = 1
        self.supercell = cell
        self._cell = cell.original_cell

        # Define kpts
        if twist is None:
            twist = np.zeros(3)
        else:
            twist = np.dot(np.linalg.inv(cell.a), np.mod(twist, 1.0)) * 2 * np.pi
        self.kinds = get_kinds(self._cell, mf, get_supercell_kpts(cell) + twist)
        self._kpts = mf.kpts[self.kinds]
        assert len(self.kinds) == len(self._kpts), (self._kpts, mf.kpts)
        self.nk = len(self._kpts)

        # Define parameters
        self.param_split = {}
        for s, lookup in enumerate(self._coefflookup):
            mclist = []
            for kind in self.kinds:
                if len(mf.mo_coeff[0][0].shape) == 2:
                    mca = mf.mo_coeff[s][kind][:, np.asarray(mf.mo_occ[s][kind] > 0.9)]
                else:
                    minocc = (0.9, 1.1)[s]
                    mca = mf.mo_coeff[kind][:, np.asarray(mf.mo_occ[kind] > minocc)]
                mca = np.real_if_close(mca, tol=self.real_tol)
                mclist.append(mca / np.sqrt(self.nk))
            self.param_split[lookup] = np.cumsum([m.shape[1] for m in mclist])
            self.parameters[lookup] = np.concatenate(mclist, axis=-1)

        self.iscomplex = bool(sum(map(np.iscomplexobj, self.parameters.values())))
        self.iscomplex = self.iscomplex or np.linalg.norm(self._kpts) > 1e-12

        # Define nelec
        if len(mf.mo_coeff[0][0].shape) == 2:
            # Then indices are (spin, kpt, basis, mo)
            self._nelec = [int(np.sum([o[k] for k in self.kinds])) for o in mf.mo_occ]
        elif len(mf.mo_coeff[0][0].shape) == 1:
            # Then indices are (kpt, basis, mo)
            self._nelec = [
                int(np.sum([mf.mo_occ[k] > t for k in self.kinds])) for t in (0.9, 1.1)
            ]
        else:
            print("Warning: PySCFSlater not expecting scf object of type", type(mf))
            scale = self.supercell.scale
            self._nelec = [int(np.round(n * scale)) for n in self._cell.nelec]
        self._nelec = tuple(self._nelec)

        self.evaluate_orbitals = self._evaluate_orbitals_pbc
        self.evaluate_mos = self._evaluate_mos_pbc
Пример #2
0
    def from_mean_field(self, cell, mf, twist=None):
        """
        mf is expected to be a KUHF, KRHF, or equivalent DFT objects.
        Selects occupied orbitals from a given twist
        If cell is a supercell, will automatically choose the folded k-points that correspond to that twist.
        """

        cell = (cell if hasattr(cell, "original_cell") else get_supercell(
            cell, np.asarray([[1, 0, 0], [0, 1, 0], [0, 0, 1]])))

        if twist is None:
            twist = np.zeros(3)
        else:
            twist = np.dot(np.linalg.inv(cell.a), np.mod(twist,
                                                         1.0)) * 2 * np.pi
        kinds = list(
            set(get_k_indices(cell, mf,
                              get_supercell_kpts(cell) + twist)))
        if len(kinds) != cell.scale:
            raise ValueError(
                "Did not find the right number of k-points for this supercell")

        detcoeff = np.array([1.0])
        det_map = np.array([[0], [0]])

        if len(mf.mo_coeff[0][0].shape) == 2:
            occup_k = [[[list(np.argwhere(mf.mo_occ[spin][k] > 0.5)[:, 0])]
                        for k in kinds] for spin in [0, 1]]
        elif len(mf.mo_coeff[0][0].shape) == 1:
            occup_k = [[[list(np.argwhere(mf.mo_occ[k] > 1.5 - spin)[:, 0])]
                        for k in kinds] for spin in [0, 1]]

        occup = [[], []]
        for spin in [0, 1]:
            count = 0
            for occ_k in occup_k[spin]:
                occup[spin] += [o + count for o in occ_k[0]]
                count += len(occ_k[0])

        kpts = mf.kpts[kinds]
        if len(mf.mo_coeff[0][0].shape) == 2:
            mo_coeff = [[
                mf.mo_coeff[spin][k][:, occup_k[spin][kinds.index(k)][0]]
                for k in kinds
            ] for spin in [0, 1]]
        elif len(mf.mo_coeff[0][0].shape) == 1:
            mo_coeff = [[
                mf.mo_coeff[k][:, occup_k[spin][kinds.index(k)][0]]
                for k in kinds
            ] for spin in [0, 1]]
        else:
            raise ValueError("Did not expect an scf object of type", type(mf))
        for s in [0, 1]:
            occup[s] = [occup[s]]
        return (
            detcoeff,
            occup,
            det_map,
            PBCOrbitalEvaluatorKpoints(cell, mo_coeff, kpts),
        )
Пример #3
0
    def from_mean_field(self,
                        cell,
                        mf,
                        twist=None,
                        determinants=None,
                        tol=None):
        """
        mf is expected to be a KUHF, KRHF, or equivalent DFT objects.
        Selects occupied orbitals from a given twist
        If cell is a supercell, will automatically choose the folded k-points that correspond to that twist.

        """

        cell = (cell
                if hasattr(cell, "original_cell") else supercell.get_supercell(
                    cell, np.asarray([[1, 0, 0], [0, 1, 0], [0, 0, 1]])))
        if twist is None:
            twist = np.zeros(3)
        else:
            twist = np.dot(np.linalg.inv(cell.a), np.mod(twist,
                                                         1.0)) * 2 * np.pi
        kinds = list(
            set(
                get_k_indices(cell, mf,
                              supercell.get_supercell_kpts(cell) + twist)))
        if len(kinds) != cell.scale:
            raise ValueError(
                f"Found {len(kinds)} k-points but should have found {cell.scale}."
            )
        kpts = mf.kpts[kinds]

        if determinants is None:
            determinants = [
                (1.0,
                 pyqmc.determinant_tools.create_pbc_determinant(cell, mf, []))
            ]

        mo_coeff, determinants_flat = select_orbitals_kpoints(
            determinants, mf, kinds)
        detcoeff, occup, det_map = pyqmc.determinant_tools.create_packed_objects(
            determinants_flat, format="list", tol=tol)
        # Check
        for s, (occ_s, nelec_s) in enumerate(zip(occup, cell.nelec)):
            for determinant in occ_s:
                if len(determinant) != nelec_s:
                    raise RuntimeError(
                        f"The number of electrons of spin {s} should be {nelec_s}, but found {len(determinant)} orbital[s]. You may have used a large smearing value.. Please pass your own determinants list. "
                    )

        return (
            detcoeff,
            occup,
            det_map,
            PBCOrbitalEvaluatorKpoints(cell, mo_coeff, kpts),
        )
Пример #4
0
def test_pbc(li_cubic_ccecp):
    from pyqmc import supercell
    import scipy

    mol, mf = li_cubic_ccecp

    # S = np.ones((3, 3)) - np.eye(3)
    S = np.identity(3)
    mol = supercell.get_supercell(mol, S)
    kpts = supercell.get_supercell_kpts(mol)[:2]
    kdiffs = mf.kpts[np.newaxis] - kpts[:, np.newaxis]
    kinds = np.nonzero(np.linalg.norm(kdiffs, axis=-1) < 1e-12)[1]

    # Lowdin orthogonalized AO basis.
    # lowdin = lo.orth_ao(mol, "lowdin")
    loiao = lo.iao.iao(mol.original_cell, mf.mo_coeff, kpts=kpts)
    occs = [mf.mo_occ[k] for k in kinds]
    coefs = [mf.mo_coeff[k] for k in kinds]
    ovlp = mf.get_ovlp()[kinds]
    lowdin = [lo.vec_lowdin(l, o) for l, o in zip(loiao, ovlp)]
    lreps = [np.linalg.multi_dot([l.T, o, c]) for l, o, c in zip(lowdin, ovlp, coefs)]

    # make AO to localized orbital coefficients.
    mfobdm = [np.einsum("ij,j,kj->ik", l.conj(), o, l) for l, o in zip(lreps, occs)]

    ### Test OBDM calculation.
    nconf = 500
    nsteps = 100
    warmup = 6
    wf = Slater(mol, mf)
    configs = initial_guess(mol, nconf)
    obdm_dict = dict(mol=mol, orb_coeff=lowdin, kpts=kpts, nsweeps=4, warmup=10)
    obdm = OBDMAccumulator(**obdm_dict)

    df, coords = vmc(
        wf,
        configs,
        nsteps=nsteps,
        accumulators={"obdm": obdm},  # , "obdm_up": obdm_up, "obdm_down": obdm_down},
        verbose=True,
    )

    obdm_est = {}
    for k in ["obdm"]:  # , "obdm_up", "obdm_down"]:
        avg_norm = np.mean(df[k + "norm"][warmup:], axis=0)
        avg_obdm = np.mean(df[k + "value"][warmup:], axis=0)
        obdm_est[k] = normalize_obdm(avg_obdm, avg_norm)

    mfobdm = scipy.linalg.block_diag(*mfobdm)

    mae = np.mean(np.abs(obdm_est["obdm"] - mfobdm))
    assert mae < 0.05, f"mae {mae}"
Пример #5
0
    def from_mean_field(self, cell, mf, twist=None, determinants=None):
        """
        mf is expected to be a KUHF, KRHF, or equivalent DFT objects.
        Selects occupied orbitals from a given twist
        If cell is a supercell, will automatically choose the folded k-points that correspond to that twist.

        """

        cell = (
            cell
            if hasattr(cell, "original_cell")
            else supercell.get_supercell(
                cell, np.asarray([[1, 0, 0], [0, 1, 0], [0, 0, 1]])
            )
        )
        if twist is None:
            twist = np.zeros(3)
        else:
            twist = np.dot(np.linalg.inv(cell.a), np.mod(twist, 1.0)) * 2 * np.pi
        kinds = list(
            set(get_k_indices(cell, mf, supercell.get_supercell_kpts(cell) + twist))
        )
        if len(kinds) != cell.scale:
            raise ValueError(
                f"Found {len(kinds)} k-points but should have found {cell.scale}."
            )
        kpts = mf.kpts[kinds]

        if determinants is None:
            determinants = [
                (1.0, pyqmc.determinant_tools.create_pbc_determinant(cell, mf, []))
            ]

        mo_coeff, determinants_flat = select_orbitals_kpoints(determinants, mf, kinds)
        detcoeff, occup, det_map = pyqmc.determinant_tools.create_packed_objects(
            determinants_flat, format="list"
        )

        return (
            detcoeff,
            occup,
            det_map,
            PBCOrbitalEvaluatorKpoints(cell, mo_coeff, kpts),
        )
Пример #6
0
def test_pbc():
    from pyscf.pbc import gto, scf
    from pyqmc import supercell
    import scipy

    lvecs = (np.ones((3, 3)) - 2 * np.eye(3)) * 2.0
    mol = gto.M(
        atom="H 0. 0. -{0}; H 0. 0. {0}".format(0.7),
        basis="sto-3g",
        unit="bohr",
        verbose=0,
        a=lvecs,
    )
    mf = scf.KRHF(mol, kpts=mol.make_kpts((2, 2, 2)))
    mf = mf.run()

    S = np.ones((3, 3)) - np.eye(3)
    mol = supercell.get_supercell(mol, S)
    kpts = supercell.get_supercell_kpts(mol)[:2]
    kdiffs = mf.kpts[np.newaxis] - kpts[:, np.newaxis]
    kinds = np.nonzero(np.linalg.norm(kdiffs, axis=-1) < 1e-12)[1]

    # Lowdin orthogonalized AO basis.
    # lowdin = lo.orth_ao(mol, "lowdin")
    loiao = lo.iao.iao(mol.original_cell, mf.mo_coeff, kpts=kpts)
    occs = [mf.mo_occ[k] for k in kinds]
    coefs = [mf.mo_coeff[k] for k in kinds]
    ovlp = mf.get_ovlp()[kinds]
    lowdin = [lo.vec_lowdin(l, o) for l, o in zip(loiao, ovlp)]
    lreps = [
        np.linalg.multi_dot([l.T, o, c])
        for l, o, c in zip(lowdin, ovlp, coefs)
    ]

    # make AO to localized orbital coefficients.
    mfobdm = [
        np.einsum("ij,j,kj->ik", l.conj(), o, l) for l, o in zip(lreps, occs)
    ]

    ### Test OBDM calculation.
    nconf = 800
    nsteps = 50
    warmup = 6
    wf = PySCFSlater(mol, mf)
    configs = initial_guess(mol, nconf)
    obdm_dict = dict(mol=mol,
                     orb_coeff=lowdin,
                     kpts=kpts,
                     nsweeps=4,
                     warmup=10)
    obdm = OBDMAccumulator(**obdm_dict)
    obdm_up = OBDMAccumulator(**obdm_dict, spin=0)
    obdm_down = OBDMAccumulator(**obdm_dict, spin=1)

    df, coords = vmc(
        wf,
        configs,
        nsteps=nsteps,
        accumulators={
            "obdm": obdm,
            "obdm_up": obdm_up,
            "obdm_down": obdm_down
        },
        verbose=True,
    )

    obdm_est = {}
    for k in ["obdm", "obdm_up", "obdm_down"]:
        avg_norm = np.mean(df[k + "norm"][warmup:], axis=0)
        avg_obdm = np.mean(df[k + "value"][warmup:], axis=0)
        obdm_est[k] = normalize_obdm(avg_obdm, avg_norm)

    print("Average OBDM(orb,orb)", obdm_est["obdm"].round(3))
    mfobdm = scipy.linalg.block_diag(*mfobdm)
    print("mf obdm", mfobdm.round(3))
    max_abs_err = np.max(np.abs(obdm_est["obdm"] - mfobdm))
    assert max_abs_err < 0.05, "max abs err {0}".format(max_abs_err)
    print(obdm_est["obdm_up"].diagonal().round(3))
    print(obdm_est["obdm_down"].diagonal().round(3))
    mae = np.mean(np.abs(obdm_est["obdm_up"] + obdm_est["obdm_down"] - mfobdm))
    maup = np.mean(np.abs(obdm_est["obdm_up"]))
    madn = np.mean(np.abs(obdm_est["obdm_down"]))
    mamf = np.mean(np.abs(mfobdm))
    assert mae < 0.05, "mae {0}\n maup {1}\n madn {2}\n mamf {3}".format(
        mae, maup, madn, mamf)
Пример #7
0
    def __init__(self,
                 supercell,
                 mf,
                 tol=-1,
                 detwt=(1, ),
                 occup=None,
                 map_dets=None,
                 twist=None):
        """
        detwt: list of determinant weights
        occup: list (spin, det, dict{kind: occupation list})
        map_dets: list (spin, ndet) to identify which determinant of each spin to use (e.g. may use the same up-determinant in multiple products)
        """
        for attribute in ["original_cell", "S"]:
            if not hasattr(supercell, attribute):
                print('Warning: supercell is missing attribute "%s"' %
                      attribute)
                print("setting original_cell=supercell and S=np.eye(3)")
                supercell.original_cell = supercell
                supercell.S = np.eye(3)

        assert occup is not None
        assert len(map_dets[0]) == len(detwt) and len(
            map_dets[1]) == len(detwt)
        self.parameters = {"det_coeff": np.array(detwt)}

        self.tol = tol
        self.real_tol = 1e4
        self._mol = supercell.original_cell
        self._nelec = tuple(
            int(sum(len(v) for v in o[0].values())) for o in occup)

        self.supercell = supercell
        if twist is None:
            twist = np.zeros(3)
        else:
            twist = np.dot(np.linalg.inv(supercell.a), np.mod(twist,
                                                              1.0)) * 2 * np.pi
        self.kinds = get_kinds(self._mol, mf,
                               get_supercell_kpts(supercell) + twist)
        self._kpts = mf.kpts[self.kinds]
        assert len(self.kinds) == len(self._kpts), (self._kpts, mf.kpts)
        self.nk = len(self._kpts)
        print("nk", self.nk, self.kinds)

        maxorb = [{
            k: np.amax([np.amax(list(d[k]) + [-1]) for d in o]) + 1
            for k in self.kinds
        } for o in occup]

        self.param_split = {}
        self._coefflookup = ("mo_coeff_alpha", "mo_coeff_beta")
        for s, lookup in enumerate(self._coefflookup):
            mclist = []
            for kind in self.kinds:
                if len(mf.mo_coeff[0][0].shape) == 2:
                    mca = mf.mo_coeff[s][kind][:, :maxorb[s][kind]]
                else:
                    mca = mf.mo_coeff[kind][:, :maxorb[s][kind]]
                mca = np.real_if_close(mca, tol=self.real_tol)
                mclist.append(mca / np.sqrt(self.nk))
            self.param_split[lookup] = np.cumsum([m.shape[1] for m in mclist])
            self.parameters[lookup] = np.concatenate(mclist, axis=-1)

        # _det_occup: Spin, [(Ndet_up_unique, nup), (Ndet_dn_unique, ndn)]
        self._det_occup = [
            np.zeros((len(o), n), dtype=int)
            for o, n in zip(occup, self._nelec)
        ]
        for s, o in enumerate(occup):
            orb_inds = np.cumsum([0] + [maxorb[s][k] for k in self.kinds[:-1]])
            for d, det in enumerate(o):
                self._det_occup[s][d] = np.concatenate([
                    np.array(det[k]) + ind
                    for k, ind in zip(self.kinds, orb_inds)
                ])
        self._det_map = np.asarray(map_dets)  # Spin, N_det
        print("det_coeff", self.parameters["det_coeff"])
        print("_det_occup\n", self._det_occup)
        print("_det_map\n", self._det_map)

        self.iscomplex = bool(
            sum(map(np.iscomplexobj, self.parameters.values())))
        self.iscomplex = self.iscomplex or np.linalg.norm(self._kpts) > 1e-12
        self.dtype = complex if self.iscomplex else float
        if self.iscomplex:
            self.get_phase = slater.get_complex_phase
            self.get_wrapphase = slater.get_wrapphase_complex
        else:
            self.get_phase = np.sign
            self.get_wrapphase = slater.get_wrapphase_real