From bcd94bf5cc072f9f27d5753c18dcaefbba9cc3a3 Mon Sep 17 00:00:00 2001 From: Basil Ibrahim Date: Wed, 21 Feb 2024 18:27:08 +0000 Subject: [PATCH 1/6] Some changes --- examples/ewf/molecules/62-external-solver.py | 32 +++++++++++++++----- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/examples/ewf/molecules/62-external-solver.py b/examples/ewf/molecules/62-external-solver.py index b7ba22c8..73759d7a 100644 --- a/examples/ewf/molecules/62-external-solver.py +++ b/examples/ewf/molecules/62-external-solver.py @@ -43,13 +43,13 @@ use_sym = True nfrag = 1 # When using symmetry, we have to specify the number of atoms in the fragment in this case. #bath_opts = dict(bathtype="full") # This is a complete bath space (should be exact) -bath_opts = dict(bathtype="dmet") # This is the smallest bath size +bath_opts = dict(bathtype="full") # This is the smallest bath size # bath_opts = dict(bathtype='mp2', threshold=1.e-6) # Run vayesta for comparison with FCI solver -emb = vayesta.ewf.EWF(mf, solver="FCI", bath_options=bath_opts, solver_options=dict(conv_tol=1.e-14) +emb = vayesta.ewf.EWF(mf, solver="FCI", bath_options=bath_opts, solver_options=dict(conv_tol=1.e-14)) # Set up fragments -with emb.iao_fragmentation() as f: +with emb.iaopao_fragmentation() as f: if use_sym: # Add rotational symmetry # Set order of rotation (2: 180 degrees, 3: 120 degrees, 4: 90: degrees,...), @@ -64,7 +64,7 @@ # Run vayesta again, but just dump clusters, rather than solve them emb_dump = vayesta.ewf.EWF(mf, solver="DUMP", bath_options=bath_opts, solver_options=dict(dumpfile="clusters-rhf.h5")) # Set up fragments -with emb_dump.iao_fragmentation() as f: +with emb_dump.iaopao_fragmentation() as f: if use_sym: # Add rotational symmetry # Set order of rotation (2: 180 degrees, 3: 120 degrees, 4: 90: degrees,...), @@ -130,8 +130,24 @@ def __repr__(self): if use_sym: e_corr *= natom // nfrag -print("Full system mean-field energy = %f" % mf.e_tot) -print("Full system CCSD correlation energy = %f" % cc.e_corr) -print("Full system FCI correlation energy: {}".format(ci.e_tot-mf.e_tot)) -print("Vayesta correlation energy = %f" % emb.e_corr) + +def get_vayesta_dmet_energy(emb, part_cumulant=True, approx_cumulant=True): + # Get democratically patitioned energy from vayesta + + e_nuc = emb.mf.mol.energy_nuc() + hcore = emb.get_hcore() + eris = pyscf.ao2mo.kernel(emb.mf.mol, emb.mf.mo_coeff, compact=False).reshape([mol.nao]*4) + dm1 = emb.make_rdm1_demo(ao_basis=False) + dm2 = emb.make_rdm2_demo(ao_basis=False, part_cumulant=part_cumulant, approx_cumulant=approx_cumulant) + #dm1, dm2 = ci.make_rdm12() + return e_nuc + np.sum(hcore*dm1) + np.sum(eris*dm2)/2 + +print("Full system mean-field energy = %f" % mf.e_tot) +print("Full system CCSD correlation energy = %f" % cc.e_tot) +print("Full system FCI correlation energy = %f" %(ci.e_tot)) +print("Vayesta correlation energy = %f" % emb.e_corr) +print("Vayesta partitioned cumulant energy = %f" % emb.get_dmet_energy(part_cumulant=True)) +print("Vayesta partitioned cumulant energy = %f" % get_vayesta_dmet_energy(emb, part_cumulant=True, approx_cumulant=False)) +print("Vayesta partitioned approx cumulant energy = %f" % emb.get_dmet_energy(part_cumulant=False)) +print("Vayesta partitioned approx cumulant energy = %f" % get_vayesta_dmet_energy(emb, part_cumulant=True, approx_cumulant=True)) print("Correlation energy from external FCI solver = %f" % e_corr) From add1c49b29849133c849548ec9240c3e2a9ef203 Mon Sep 17 00:00:00 2001 From: Basil Ibrahim Date: Mon, 26 Feb 2024 14:34:11 +0000 Subject: [PATCH 2/6] Example with different DMET energy methods --- .../63-external-solver-dm-corr-energy.py | 232 ++++++++++++++++++ 1 file changed, 232 insertions(+) create mode 100644 examples/ewf/molecules/63-external-solver-dm-corr-energy.py diff --git a/examples/ewf/molecules/63-external-solver-dm-corr-energy.py b/examples/ewf/molecules/63-external-solver-dm-corr-energy.py new file mode 100644 index 00000000..df0ab511 --- /dev/null +++ b/examples/ewf/molecules/63-external-solver-dm-corr-energy.py @@ -0,0 +1,232 @@ +'''Use the cluster dump functionality (see 20-dump-clusters.py) to dump the clusters, +read them back in, solve them with pyscf's FCI solver, and show that the same result +is achieved as Vayesta's internal functionality. Note that this just computes the +'projected' energy estimator over the clusters, from the C2 amplitudes.''' +import numpy as np +import pyscf +import pyscf.gto +import pyscf.scf +import pyscf.fci +import vayesta +import vayesta.ewf +from vayesta.misc.molecules import ring +from vayesta.core.types import Orbitals, FCI_WaveFunction, CISD_WaveFunction +import h5py + +# Create natom ring of minimal basis hydrogen atoms +natom = 6 +mol = pyscf.gto.Mole() +mol.atom = ring("H", natom, 1.5) +mol.basis = "sto-3g" +mol.output = "pyscf.out" +mol.verbose = 5 +mol.symmetry = True +mol.build() + +# Hartree-Fock +mf = pyscf.scf.RHF(mol) +mf.kernel() +print('Mean-Field (Hartree--Fock) energy = {}'.format(mf.e_tot)) +assert mf.converged + + + +# Vayesta options +use_sym = True +nfrag = 1 # When using symmetry, we have to specify the number of atoms in the fragment in this case. +#bath_opts = dict(bathtype="full") # This is a complete bath space (should be exact) +bath_opts = dict(bathtype="dmet") # This is the smallest bath size +# bath_opts = dict(bathtype='mp2', threshold=1.e-6) + +# Run vayesta for comparison with FCI solver +emb = vayesta.ewf.EWF(mf, solver="FCI", bath_options=bath_opts, solver_options=dict(conv_tol=1.e-14)) +# Set up fragments +with emb.iaopao_fragmentation() as f: + if use_sym: + # Add rotational symmetry + # Set order of rotation (2: 180 degrees, 3: 120 degrees, 4: 90: degrees,...), + # axis along which to rotate and center of rotation (default units for axis and center are Angstroms): + with f.rotational_symmetry(order=natom//nfrag, axis=[0, 0, 1]): + f.add_atomic_fragment(range(nfrag)) + else: + # Add all atoms as separate fragments + f.add_all_atomic_fragments() +emb.kernel() + +# Run vayesta again, but just dump clusters, rather than solve them +emb_dump = vayesta.ewf.EWF(mf, solver="DUMP", bath_options=bath_opts, solver_options=dict(dumpfile="clusters-rhf.h5")) +# Set up fragments +with emb_dump.iaopao_fragmentation() as f: + if use_sym: + # Add rotational symmetry + # Set order of rotation (2: 180 degrees, 3: 120 degrees, 4: 90: degrees,...), + # axis along which to rotate and center of rotation (default units for axis and center are Angstroms): + with f.rotational_symmetry(order=natom//nfrag, axis=[0, 0, 1]): + f.add_atomic_fragment(range(nfrag)) + else: + # Add all atoms as separate fragments + f.add_all_atomic_fragments() +print('Total number of fragments (inc. sym related): {}'.format(len(emb_dump.fragments))) +emb_dump.kernel() + +class Cluster(object): + + def __init__(self, key, cluster): + + self.key = key + self.c_frag = np.array(cluster["c_frag"]) # Fragment orbitals (AO,Frag) + self.c_cluster = np.array(cluster["c_cluster"]) # Cluster orbitals (AO,Cluster) + + self.norb, self.nocc, self.nvir = cluster.attrs["norb"], cluster.attrs["nocc"], cluster.attrs["nvir"] + self.fock = np.array(cluster["fock"]) # Fock matrix (Cluster,Cluster) + self.h1e = np.array(cluster["heff"]) # 1 electron integrals (Cluster,Cluster) + self.h2e = np.array(cluster["eris"]) # 2 electron integrals (Cluster,Cluster,Cluster,Cluster) + + def __repr__(self): + return self.key + +# Load clusters from file +with h5py.File("clusters-rhf.h5", "r") as f: + clusters = [Cluster(key, cluster) for key, cluster in f.items()] +print(clusters) +print("Clusters loaded: %d" % len(clusters)) + +# To complete the info we need the AO overlap matrix (also get the MO coefficients) +mo_coeff, ovlp = mf.mo_coeff, mf.get_ovlp() + + +def split_dm2(nocc, dm1, dm2, ao_repr=False): + dm2_2 = dm2.copy() # Approx cumulant + dm2_1 = np.zeros_like(dm2) # Correlated 1DM contribution + dm2_0 = np.zeros_like(dm2) # Mean-field 1DM contribution + + for i in range(nocc): + dm2_1[i, i, :, :] += dm1 * 2 + dm2_1[:, :, i, i] += dm1 * 2 + dm2_1[:, i, i, :] -= dm1 + dm2_1[i, :, :, i] -= dm1.T + + for i in range(nocc): + for j in range(nocc): + dm2_0[i, i, j, j] += 4 + dm2_0[i, j, j, i] -= 2 + + dm2_2 -= dm2_0 + dm2_1 + return dm2_0, dm2_1, dm2_2 + + +# Full system Hamiltonian (AO basis) +h1e_ao = mf.get_hcore() +h2e_ao = mol.intor("int2e") + +print("\nHartree-Fock\n------------") +dm1_ao_hf = mf.make_rdm1() +dm2_ao_hf = mf.make_rdm2() +e1_hf = np.einsum('pq,pq->', h1e_ao, dm1_ao_hf) +e2_hf = 0.5 * np.einsum('pqrs,pqrs->', h2e_ao, dm2_ao_hf) +print("E = %f" % (e1_hf+e2_hf+mol.energy_nuc())) +print("E1 = %f" % e1_hf) +print("E2 = %f" % e2_hf) +# Full-system FCI for comparison + +print("\nFCI\n------------") +fci = pyscf.fci.FCI(mf) +e_ci, c_ci = fci.kernel() +dm1_mo_fci, dm2_mo_fci = fci.make_rdm12(c_ci, dm1_ao_hf.shape[0], mol.nelec) +dm1_ao_fci = mf.mo_coeff @ dm1_mo_fci @ mf.mo_coeff.T +dm2_ao_fci = np.einsum('pqrs,ip,jq,kr,ls->ijkl', dm2_mo_fci, mf.mo_coeff, mf.mo_coeff, mf.mo_coeff, mf.mo_coeff) +e1_fci = np.einsum('pq,pq->', h1e_ao, dm1_ao_fci) +e2_fci = 0.5 * np.einsum('pqrs,pqrs->', h2e_ao, dm2_ao_fci) +print("E = %f" % (e1_fci+e2_fci+mol.energy_nuc()-mf.e_tot)) +print("E1 = %f" % e1_fci) +print("E2 = %f" % e2_fci) + + +print("\nDemocratic Partitioning\n------------") +# Go through each cluster, and solve it with pyscf's FCI module. Find its energy contribution by passing in the hamiltonian. +# Calculate democratically partitioned energy and 1DM +e1_dpart, e2_dpart = 0, 0 +for ind, cluster in enumerate(clusters): + # Solve, and return energy and FCI wave function + energy, ci_vec = pyscf.fci.direct_spin0.kernel(cluster.h1e, cluster.h2e, cluster.norb, nelec=(cluster.nocc, cluster.nocc), conv_tol=1.e-14) + + orbs = Orbitals(cluster.c_cluster, occ=cluster.nocc) + wf = FCI_WaveFunction(orbs, ci_vec)#.as_cisd(c0=1.0) + dm1_cls, dm2_cls = wf.make_rdm1(), wf.make_rdm2() + nocc = cluster.nocc + + + # Project DMs + proj = cluster.c_frag.T @ ovlp @ cluster.c_cluster + proj = proj.T @ proj + dm1_cls = proj @ dm1_cls + dm1_cls = 0.5 * (dm1_cls + dm1_cls.T) + + # Project 2DM + dm2_cls = np.einsum('Ijkl,iI->ijkl', dm2_cls, proj) + + # Calculate effective 1 body Hamiltonian and subtract cluster contribution to Veff + heff = cluster.c_cluster.T @ (mf.get_hcore() + mf.get_veff()/2) @ cluster.c_cluster + heff -= np.einsum("iipq->pq", cluster.h2e[:nocc, :nocc, :, :]) - np.einsum("iqpi->pq", cluster.h2e[:nocc, :, :, :nocc]) / 2 + + # Calculate energy contributions + e1_dpart+= np.einsum('pq,pq->', heff, dm1_cls) + e2_dpart+= 0.5 * np.einsum('pqrs,pqrs->', cluster.h2e, dm2_cls) + +if use_sym: + e1_dpart *= natom // nfrag + e2_dpart *= natom // nfrag + +print("E = %f" % (e1_dpart+e2_dpart+mol.energy_nuc()-mf.e_tot)) +print("E1 = %f" % e1_dpart) +print("E2 = %f" % e2_dpart) + +print("\nPartitioned FCI\n------------") +e1_pf, e22_pf = 0, 0 +nocc = int(mf.mo_occ.sum()//2) +dm1_mo_fci[np.diag_indices(nocc)] -= 2 # Subtract HF contribtuion +h2e_mo = np.einsum('ijkl,ip,jq,kr,ls->pqrs', h2e_ao, mf.mo_coeff, mf.mo_coeff, mf.mo_coeff, mf.mo_coeff) +dm2_0, dm2_1, dm2_2 = split_dm2(nocc, dm1_mo_fci, dm2_mo_fci) +e22_pf = 0.5 * np.einsum('pqrs,pqrs->', h2e_mo, dm2_2) +fock_mo = mf.mo_coeff.T @ mf.get_fock() @ mf.mo_coeff +e1_pf = np.einsum('pq,pq->', fock_mo, dm1_mo_fci) +print("E = %f" % (e1_pf+e22_pf)) +print("E1 = %f" % e1_pf) +print("E2_2 = %f" % e22_pf) + +print("\nPartitioned Cumulant\n------------") +# Calculate 1DM energy contribution over full system from previously obtained democratically partitioned 1DM + +e22_pc = 0 +dm1_ao_pc = np.zeros_like(dm1_ao_fci) +for ind, cluster in enumerate(clusters): + # Solve, and return energy and FCI wave function + energy, ci_vec = pyscf.fci.direct_spin0.kernel(cluster.h1e, cluster.h2e, cluster.norb, nelec=(cluster.nocc, cluster.nocc), conv_tol=1.e-14) + + orbs = Orbitals(cluster.c_cluster, occ=cluster.nocc) + wf = FCI_WaveFunction(orbs, ci_vec)#.as_cisd(c0=1.0) + dm1_cls, dm2_cls = wf.make_rdm1(), wf.make_rdm2() + nocc = cluster.nocc + + dm1_cls[np.diag_indices(cluster.nocc)] -= 2 # Subtract HF contribtuion + dm2_0, dm2_1, dm2_2 = split_dm2(cluster.nocc, dm1_cls, dm2_cls) # Split into HF, correlated non-cumulant and cumulant contributions + + # Project and rotate to AO basis + proj = cluster.c_frag.T @ ovlp @ cluster.c_cluster + proj = proj.T @ proj + dm1_cls = proj @ dm1_cls + dm1_ao_pc += cluster.c_cluster @ dm1_cls @ cluster.c_cluster.T + + # Project 2DM and contract with 2-electron integrals within cluster + dm2_2 = np.einsum('Ijkl,iI->ijkl', dm2_2, proj) + e22_pc += 0.5 * np.einsum('pqrs,pqrs->', cluster.h2e, dm2_2) + +# Calculate correlated non-cumulant contribution over full system +e1_pc = np.einsum('pq,pq->', mf.get_fock(), dm1_ao_pc) + +if use_sym: + e1_pc *= natom // nfrag + e22_pc *= natom // nfrag +print("E = %f" % (e1_pc+e22_pc)) +print("E1 = %f" % e1_pc) +print("E2_2 = %f" % e22_pc) From 628af8cb6559253d5e210d1db619be36f9fafba0 Mon Sep 17 00:00:00 2001 From: Basil Ibrahim Date: Mon, 26 Feb 2024 15:03:51 +0000 Subject: [PATCH 3/6] Tidy up --- .../63-external-solver-dm-corr-energy.py | 64 +++++++------------ 1 file changed, 22 insertions(+), 42 deletions(-) diff --git a/examples/ewf/molecules/63-external-solver-dm-corr-energy.py b/examples/ewf/molecules/63-external-solver-dm-corr-energy.py index df0ab511..6f14aae9 100644 --- a/examples/ewf/molecules/63-external-solver-dm-corr-energy.py +++ b/examples/ewf/molecules/63-external-solver-dm-corr-energy.py @@ -1,7 +1,7 @@ '''Use the cluster dump functionality (see 20-dump-clusters.py) to dump the clusters, read them back in, solve them with pyscf's FCI solver, and show that the same result -is achieved as Vayesta's internal functionality. Note that this just computes the -'projected' energy estimator over the clusters, from the C2 amplitudes.''' +is achieved as Vayesta's internal functionality. This computes various the energy via +paritioning and a partitioned cumulant.''' import numpy as np import pyscf import pyscf.gto @@ -14,7 +14,7 @@ import h5py # Create natom ring of minimal basis hydrogen atoms -natom = 6 +natom = 10 mol = pyscf.gto.Mole() mol.atom = ring("H", natom, 1.5) mol.basis = "sto-3g" @@ -29,8 +29,6 @@ print('Mean-Field (Hartree--Fock) energy = {}'.format(mf.e_tot)) assert mf.converged - - # Vayesta options use_sym = True nfrag = 1 # When using symmetry, we have to specify the number of atoms in the fragment in this case. @@ -88,13 +86,11 @@ def __repr__(self): # Load clusters from file with h5py.File("clusters-rhf.h5", "r") as f: clusters = [Cluster(key, cluster) for key, cluster in f.items()] -print(clusters) print("Clusters loaded: %d" % len(clusters)) # To complete the info we need the AO overlap matrix (also get the MO coefficients) mo_coeff, ovlp = mf.mo_coeff, mf.get_ovlp() - def split_dm2(nocc, dm1, dm2, ao_repr=False): dm2_2 = dm2.copy() # Approx cumulant dm2_1 = np.zeros_like(dm2) # Correlated 1DM contribution @@ -114,35 +110,20 @@ def split_dm2(nocc, dm1, dm2, ao_repr=False): dm2_2 -= dm2_0 + dm2_1 return dm2_0, dm2_1, dm2_2 - # Full system Hamiltonian (AO basis) h1e_ao = mf.get_hcore() h2e_ao = mol.intor("int2e") -print("\nHartree-Fock\n------------") -dm1_ao_hf = mf.make_rdm1() -dm2_ao_hf = mf.make_rdm2() -e1_hf = np.einsum('pq,pq->', h1e_ao, dm1_ao_hf) -e2_hf = 0.5 * np.einsum('pqrs,pqrs->', h2e_ao, dm2_ao_hf) -print("E = %f" % (e1_hf+e2_hf+mol.energy_nuc())) -print("E1 = %f" % e1_hf) -print("E2 = %f" % e2_hf) # Full-system FCI for comparison - -print("\nFCI\n------------") fci = pyscf.fci.FCI(mf) e_ci, c_ci = fci.kernel() -dm1_mo_fci, dm2_mo_fci = fci.make_rdm12(c_ci, dm1_ao_hf.shape[0], mol.nelec) +dm1_mo_fci, dm2_mo_fci = fci.make_rdm12(c_ci, h1e_ao.shape[0], mol.nelec) dm1_ao_fci = mf.mo_coeff @ dm1_mo_fci @ mf.mo_coeff.T dm2_ao_fci = np.einsum('pqrs,ip,jq,kr,ls->ijkl', dm2_mo_fci, mf.mo_coeff, mf.mo_coeff, mf.mo_coeff, mf.mo_coeff) e1_fci = np.einsum('pq,pq->', h1e_ao, dm1_ao_fci) e2_fci = 0.5 * np.einsum('pqrs,pqrs->', h2e_ao, dm2_ao_fci) -print("E = %f" % (e1_fci+e2_fci+mol.energy_nuc()-mf.e_tot)) -print("E1 = %f" % e1_fci) -print("E2 = %f" % e2_fci) - -print("\nDemocratic Partitioning\n------------") +# Democratic Partitioning # Go through each cluster, and solve it with pyscf's FCI module. Find its energy contribution by passing in the hamiltonian. # Calculate democratically partitioned energy and 1DM e1_dpart, e2_dpart = 0, 0 @@ -150,12 +131,11 @@ def split_dm2(nocc, dm1, dm2, ao_repr=False): # Solve, and return energy and FCI wave function energy, ci_vec = pyscf.fci.direct_spin0.kernel(cluster.h1e, cluster.h2e, cluster.norb, nelec=(cluster.nocc, cluster.nocc), conv_tol=1.e-14) + # Build cluster denisty matrices orbs = Orbitals(cluster.c_cluster, occ=cluster.nocc) wf = FCI_WaveFunction(orbs, ci_vec)#.as_cisd(c0=1.0) dm1_cls, dm2_cls = wf.make_rdm1(), wf.make_rdm2() - nocc = cluster.nocc - # Project DMs proj = cluster.c_frag.T @ ovlp @ cluster.c_cluster proj = proj.T @ proj @@ -166,6 +146,7 @@ def split_dm2(nocc, dm1, dm2, ao_repr=False): dm2_cls = np.einsum('Ijkl,iI->ijkl', dm2_cls, proj) # Calculate effective 1 body Hamiltonian and subtract cluster contribution to Veff + nocc = cluster.nocc heff = cluster.c_cluster.T @ (mf.get_hcore() + mf.get_veff()/2) @ cluster.c_cluster heff -= np.einsum("iipq->pq", cluster.h2e[:nocc, :nocc, :, :]) - np.einsum("iqpi->pq", cluster.h2e[:nocc, :, :, :nocc]) / 2 @@ -177,11 +158,7 @@ def split_dm2(nocc, dm1, dm2, ao_repr=False): e1_dpart *= natom // nfrag e2_dpart *= natom // nfrag -print("E = %f" % (e1_dpart+e2_dpart+mol.energy_nuc()-mf.e_tot)) -print("E1 = %f" % e1_dpart) -print("E2 = %f" % e2_dpart) - -print("\nPartitioned FCI\n------------") +# Partitioned FCI e1_pf, e22_pf = 0, 0 nocc = int(mf.mo_occ.sum()//2) dm1_mo_fci[np.diag_indices(nocc)] -= 2 # Subtract HF contribtuion @@ -190,28 +167,25 @@ def split_dm2(nocc, dm1, dm2, ao_repr=False): e22_pf = 0.5 * np.einsum('pqrs,pqrs->', h2e_mo, dm2_2) fock_mo = mf.mo_coeff.T @ mf.get_fock() @ mf.mo_coeff e1_pf = np.einsum('pq,pq->', fock_mo, dm1_mo_fci) -print("E = %f" % (e1_pf+e22_pf)) -print("E1 = %f" % e1_pf) -print("E2_2 = %f" % e22_pf) -print("\nPartitioned Cumulant\n------------") -# Calculate 1DM energy contribution over full system from previously obtained democratically partitioned 1DM +# Partitioned Cumulant +# Calculate 1DM energy contribution over full system from previously obtained democratically partitioned 1DM e22_pc = 0 dm1_ao_pc = np.zeros_like(dm1_ao_fci) for ind, cluster in enumerate(clusters): # Solve, and return energy and FCI wave function energy, ci_vec = pyscf.fci.direct_spin0.kernel(cluster.h1e, cluster.h2e, cluster.norb, nelec=(cluster.nocc, cluster.nocc), conv_tol=1.e-14) + # Build cluster denisty matrices and split into seperate contributions orbs = Orbitals(cluster.c_cluster, occ=cluster.nocc) - wf = FCI_WaveFunction(orbs, ci_vec)#.as_cisd(c0=1.0) + wf = FCI_WaveFunction(orbs, ci_vec) dm1_cls, dm2_cls = wf.make_rdm1(), wf.make_rdm2() nocc = cluster.nocc - dm1_cls[np.diag_indices(cluster.nocc)] -= 2 # Subtract HF contribtuion dm2_0, dm2_1, dm2_2 = split_dm2(cluster.nocc, dm1_cls, dm2_cls) # Split into HF, correlated non-cumulant and cumulant contributions - # Project and rotate to AO basis + # Project 1DM and rotate to AO basis proj = cluster.c_frag.T @ ovlp @ cluster.c_cluster proj = proj.T @ proj dm1_cls = proj @ dm1_cls @@ -227,6 +201,12 @@ def split_dm2(nocc, dm1, dm2, ao_repr=False): if use_sym: e1_pc *= natom // nfrag e22_pc *= natom // nfrag -print("E = %f" % (e1_pc+e22_pc)) -print("E1 = %f" % e1_pc) -print("E2_2 = %f" % e22_pc) + +print("Correlation Energies\n--------------------") +print("FCI energy from density matrix = %f" % (e1_fci+e2_fci+mol.energy_nuc()-mf.e_tot)) +print("External democratic paritioning = %f" % (e1_dpart+e2_dpart+mol.energy_nuc()-mf.e_tot)) +print("Vayesta democratic paritioning = %f" % (emb.get_dmet_energy(part_cumulant=False)-mf.e_tot)) +print("FCI energy from cumulant = %f" % (e1_pf+e22_pf)) +print("External partitioned cumulant = %f" % (e1_pc+e22_pc)) +print("Vayesta partitioned cumulant = %f" % (emb.get_dmet_energy(part_cumulant=True)-mf.e_tot)) + From 3b826b0d4ab2358211ec32ccb2a53deee33cb9bd Mon Sep 17 00:00:00 2001 From: Basil Ibrahim Date: Mon, 26 Feb 2024 15:07:27 +0000 Subject: [PATCH 4/6] Revert to IAO fragmentation --- examples/ewf/molecules/63-external-solver-dm-corr-energy.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/ewf/molecules/63-external-solver-dm-corr-energy.py b/examples/ewf/molecules/63-external-solver-dm-corr-energy.py index 6f14aae9..da97d662 100644 --- a/examples/ewf/molecules/63-external-solver-dm-corr-energy.py +++ b/examples/ewf/molecules/63-external-solver-dm-corr-energy.py @@ -39,7 +39,7 @@ # Run vayesta for comparison with FCI solver emb = vayesta.ewf.EWF(mf, solver="FCI", bath_options=bath_opts, solver_options=dict(conv_tol=1.e-14)) # Set up fragments -with emb.iaopao_fragmentation() as f: +with emb.iao_fragmentation() as f: if use_sym: # Add rotational symmetry # Set order of rotation (2: 180 degrees, 3: 120 degrees, 4: 90: degrees,...), @@ -54,7 +54,7 @@ # Run vayesta again, but just dump clusters, rather than solve them emb_dump = vayesta.ewf.EWF(mf, solver="DUMP", bath_options=bath_opts, solver_options=dict(dumpfile="clusters-rhf.h5")) # Set up fragments -with emb_dump.iaopao_fragmentation() as f: +with emb_dump.iao_fragmentation() as f: if use_sym: # Add rotational symmetry # Set order of rotation (2: 180 degrees, 3: 120 degrees, 4: 90: degrees,...), From 3b88f969a1ba4adbbe9e26ae78b9d38426c65065 Mon Sep 17 00:00:00 2001 From: Basil Ibrahim Date: Mon, 26 Feb 2024 15:09:55 +0000 Subject: [PATCH 5/6] Tidy example 63 --- examples/ewf/molecules/62-external-solver.py | 32 +++++--------------- 1 file changed, 8 insertions(+), 24 deletions(-) diff --git a/examples/ewf/molecules/62-external-solver.py b/examples/ewf/molecules/62-external-solver.py index 73759d7a..b7ba22c8 100644 --- a/examples/ewf/molecules/62-external-solver.py +++ b/examples/ewf/molecules/62-external-solver.py @@ -43,13 +43,13 @@ use_sym = True nfrag = 1 # When using symmetry, we have to specify the number of atoms in the fragment in this case. #bath_opts = dict(bathtype="full") # This is a complete bath space (should be exact) -bath_opts = dict(bathtype="full") # This is the smallest bath size +bath_opts = dict(bathtype="dmet") # This is the smallest bath size # bath_opts = dict(bathtype='mp2', threshold=1.e-6) # Run vayesta for comparison with FCI solver -emb = vayesta.ewf.EWF(mf, solver="FCI", bath_options=bath_opts, solver_options=dict(conv_tol=1.e-14)) +emb = vayesta.ewf.EWF(mf, solver="FCI", bath_options=bath_opts, solver_options=dict(conv_tol=1.e-14) # Set up fragments -with emb.iaopao_fragmentation() as f: +with emb.iao_fragmentation() as f: if use_sym: # Add rotational symmetry # Set order of rotation (2: 180 degrees, 3: 120 degrees, 4: 90: degrees,...), @@ -64,7 +64,7 @@ # Run vayesta again, but just dump clusters, rather than solve them emb_dump = vayesta.ewf.EWF(mf, solver="DUMP", bath_options=bath_opts, solver_options=dict(dumpfile="clusters-rhf.h5")) # Set up fragments -with emb_dump.iaopao_fragmentation() as f: +with emb_dump.iao_fragmentation() as f: if use_sym: # Add rotational symmetry # Set order of rotation (2: 180 degrees, 3: 120 degrees, 4: 90: degrees,...), @@ -130,24 +130,8 @@ def __repr__(self): if use_sym: e_corr *= natom // nfrag - -def get_vayesta_dmet_energy(emb, part_cumulant=True, approx_cumulant=True): - # Get democratically patitioned energy from vayesta - - e_nuc = emb.mf.mol.energy_nuc() - hcore = emb.get_hcore() - eris = pyscf.ao2mo.kernel(emb.mf.mol, emb.mf.mo_coeff, compact=False).reshape([mol.nao]*4) - dm1 = emb.make_rdm1_demo(ao_basis=False) - dm2 = emb.make_rdm2_demo(ao_basis=False, part_cumulant=part_cumulant, approx_cumulant=approx_cumulant) - #dm1, dm2 = ci.make_rdm12() - return e_nuc + np.sum(hcore*dm1) + np.sum(eris*dm2)/2 - -print("Full system mean-field energy = %f" % mf.e_tot) -print("Full system CCSD correlation energy = %f" % cc.e_tot) -print("Full system FCI correlation energy = %f" %(ci.e_tot)) -print("Vayesta correlation energy = %f" % emb.e_corr) -print("Vayesta partitioned cumulant energy = %f" % emb.get_dmet_energy(part_cumulant=True)) -print("Vayesta partitioned cumulant energy = %f" % get_vayesta_dmet_energy(emb, part_cumulant=True, approx_cumulant=False)) -print("Vayesta partitioned approx cumulant energy = %f" % emb.get_dmet_energy(part_cumulant=False)) -print("Vayesta partitioned approx cumulant energy = %f" % get_vayesta_dmet_energy(emb, part_cumulant=True, approx_cumulant=True)) +print("Full system mean-field energy = %f" % mf.e_tot) +print("Full system CCSD correlation energy = %f" % cc.e_corr) +print("Full system FCI correlation energy: {}".format(ci.e_tot-mf.e_tot)) +print("Vayesta correlation energy = %f" % emb.e_corr) print("Correlation energy from external FCI solver = %f" % e_corr) From 3008d218241a1d30518f43bcc27ac866ddb92ad5 Mon Sep 17 00:00:00 2001 From: Basil Ibrahim Date: Mon, 26 Feb 2024 15:12:08 +0000 Subject: [PATCH 6/6] Rename example --- ...-external-solver.py => 62-external-solver-amplitude-energy.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename examples/ewf/molecules/{62-external-solver.py => 62-external-solver-amplitude-energy.py} (100%) diff --git a/examples/ewf/molecules/62-external-solver.py b/examples/ewf/molecules/62-external-solver-amplitude-energy.py similarity index 100% rename from examples/ewf/molecules/62-external-solver.py rename to examples/ewf/molecules/62-external-solver-amplitude-energy.py