def base_test(self, system, method, kind): hf = cache.hfdata[system] refdata = cache.reference_data[system] ref = refdata[method][kind] n_ref = len(ref["eigenvectors_singles"]) refstate = adcc.ReferenceState(hf) groundstate = adcc.LazyMp(refstate) mtms = [ compute_modified_transition_moments( groundstate, refstate.operators.electric_dipole[i], "adc2") for i in range(3) ] for i in range(n_ref): ref_s = ref["eigenvectors_singles"][i] ref_d = ref["eigenvectors_doubles"][i] mtm_np_s = [mtms[i]['s'].to_ndarray() for i in range(3)] mtm_np_d = [mtms[i]['d'].to_ndarray() for i in range(3)] # computing the scalar product of the eigenvector # and the modified transition moments yields # the transition dipole moment (doi.org/10.1063/1.1752875) res_tdm = -1.0 * np.array([ np.sum(ref_s * mtm_s) + np.sum(ref_d * mtm_d) for mtm_s, mtm_d in zip(mtm_np_s, mtm_np_d) ]) ref_tdm = ref["transition_dipole_moments"][i] # Test norm and actual values res_tdm_norm = np.sum(res_tdm * res_tdm) ref_tdm_norm = np.sum(ref_tdm * ref_tdm) assert res_tdm_norm == approx(ref_tdm_norm, abs=1e-8) np.testing.assert_allclose(res_tdm, ref_tdm, atol=1e-8)
def operator_import_from_ao_test(scfres, ao_dict, operator="electric_dipole"): refstate = adcc.ReferenceState(scfres) occa = refstate.orbital_coefficients_alpha("o1b").to_ndarray() occb = refstate.orbital_coefficients_beta("o1b").to_ndarray() virta = refstate.orbital_coefficients_alpha("v1b").to_ndarray() virtb = refstate.orbital_coefficients_beta("v1b").to_ndarray() dip_imported = getattr(refstate.operators, operator) for i, ao_component in enumerate(ao_dict): dip_oo = np.einsum('ib,ba,ja->ij', occa, ao_component, occa) dip_oo += np.einsum('ib,ba,ja->ij', occb, ao_component, occb) dip_ov = np.einsum('ib,ba,ja->ij', occa, ao_component, virta) dip_ov += np.einsum('ib,ba,ja->ij', occb, ao_component, virtb) dip_vv = np.einsum('ib,ba,ja->ij', virta, ao_component, virta) dip_vv += np.einsum('ib,ba,ja->ij', virtb, ao_component, virtb) dip_mock = {"o1o1": dip_oo, "o1v1": dip_ov, "v1v1": dip_vv} dip_imported_comp = dip_imported[i] if not dip_imported_comp.is_symmetric: dip_vo = np.einsum('ib,ba,ja->ij', virta, ao_component, occa) dip_vo += np.einsum('ib,ba,ja->ij', virtb, ao_component, occb) dip_mock["v1o1"] = dip_vo for b in dip_imported_comp.blocks: np.testing.assert_allclose(dip_mock[b], dip_imported_comp[b].to_ndarray(), atol=refstate.conv_tol)
def dump_matrix(basis, method): key = basis.replace("*", "s").replace("-", "").lower() fn = "water_" + key + "_" + method + ".hdf5" if os.path.isfile(fn): with h5py.File(fn, "r") as fp: return np.asarray(fp["adc_matrix"]) mol = gto.M(atom="""O 0 0 0 H 0 0 1.795239827225189 H 1.693194615993441 0 -0.599043184453037""", basis=basis, unit="Bohr") scfres = scf.RHF(mol) scfres.conv_tol = 1e-13 scfres.kernel() mat = adcc.AdcMatrix(method, adcc.ReferenceState(scfres)) key = basis.replace("*", "s").replace("-", "").lower() mat = mat.to_dense_matrix() fn = "water_" + key + "_" + method + ".hdf5" if not os.path.isfile(fn): with h5py.File(fn, "w") as fp: fp.create_dataset("adc_matrix", data=mat, compression="gzip") with h5py.File(fn, "r") as fp: return np.asarray(fp["adc_matrix"])
def refstate(self): def cache_eri(refstate): refstate.import_all() return refstate return { k: cache_eri(adcc.ReferenceState(self.hfdata[k])) for k in self.testcases }
def template_test_h2o_sto3g(self, method): scfres = self._run_scf_h2o_sto3g() if "cvs" in method: refstate = adcc.ReferenceState(scfres, core_orbitals=1) n_states = 2 else: refstate = adcc.ReferenceState(scfres) n_states = 3 state_singlets = adcc.run_adc(refstate, method=method, n_singlets=n_states, conv_tol=self.conv_tol) assert np.all(_residual_norms(state_singlets) < self.conv_tol) state_triplets = adcc.run_adc(refstate, method=method, n_triplets=n_states, conv_tol=self.conv_tol) assert np.all(_residual_norms(state_triplets) < self.conv_tol) assert_allclose(state_singlets.excitation_energy, _singlets[method], atol=self.conv_tol * 10) assert_allclose(state_triplets.excitation_energy, _triplets[method], atol=self.conv_tol * 10)
def dump_imported(key, dump_cvs=True): dumpfile = "{}_hfimport.hdf5".format(key) if os.path.isfile(dumpfile): return # Done already print("Caching data for {} ...".format(key)) data = cache.hfdata[key] dictionary = {} # TODO once hfdata is an HDF5 file # refcases = ast.literal_eval(data["reference_cases"][()]) refcases = ast.literal_eval(data["reference_cases"]) for name, args in refcases.items(): print("Working on {} {} ...".format(key, name)) refstate = adcc.ReferenceState(data, **args) for k, v in build_dict(refstate).items(): dictionary[name + "/" + k] = v print("Writing data for {} ...".format(key)) hdf5io.save(dumpfile, dictionary)
def setup(self, basis, reference, block): import adcc # Run SCF in pyscf mol = gto.M( atom='O 0 0 0;' 'H 0 0 1.795239827225189;' 'H 1.693194615993441 0 -0.599043184453037', basis=basis, unit="Bohr", # Disable commandline argument parsing in pyscf parse_arg=False, dump_input=False, ) scfres = getattr(scf, reference)(mol) scfres.conv_tol = 1e-8 scfres.kernel() self.scfres = scfres self.refstate = adcc.ReferenceState(self.scfres)
def operator_import_test(scfres, ao_dict): refstate = adcc.ReferenceState(scfres) occa = refstate.orbital_coefficients_alpha("o1b").to_ndarray() occb = refstate.orbital_coefficients_beta("o1b").to_ndarray() virta = refstate.orbital_coefficients_alpha("v1b").to_ndarray() virtb = refstate.orbital_coefficients_beta("v1b").to_ndarray() for i, ao_component in enumerate(ao_dict): dip_oo = np.einsum('ib,ba,ja->ij', occa, ao_component, occa) dip_oo += np.einsum('ib,ba,ja->ij', occb, ao_component, occb) dip_ov = np.einsum('ib,ba,ja->ij', occa, ao_component, virta) dip_ov += np.einsum('ib,ba,ja->ij', occb, ao_component, virtb) dip_vv = np.einsum('ib,ba,ja->ij', virta, ao_component, virta) dip_vv += np.einsum('ib,ba,ja->ij', virtb, ao_component, virtb) dip_mock = {"o1o1": dip_oo, "o1v1": dip_ov, "v1v1": dip_vv} dip_imported = refstate.operators.electric_dipole[i] for b in dip_imported.blocks: assert_allclose_signfix(dip_mock[b], dip_imported[b].to_ndarray(), atol=refstate.conv_tol)
def template_hf_properties_h2o(self, basis): results = {} for b in backends: results[b] = adcc.ReferenceState(cached_backend_hf( b, "h2o", basis)) compare_hf_properties(results, 5e-9)
def base_test(self, n_alpha, n_beta, n_bas, n_orbs_alpha, restricted, check_symmetry=False, core_orbitals=[], frozen_core=[], frozen_virtual=[]): if not isinstance(restricted, bool): restricted = (restricted == "restricted") data = HfCounterData(n_alpha, n_beta, n_bas, n_orbs_alpha, restricted) refstate = adcc.ReferenceState(data, core_orbitals, frozen_core, frozen_virtual, symmetry_check_on_import=check_symmetry, import_all_below_n_orbs=None) # Setup spaces and refstate axis subspaces = ["o1", "v1"] ref_axis = {"b": np.arange(1, n_bas + 1)} done_a = [] # Orbitals which are done (occ or virt) done_b = [] na_rest = n_alpha # Remaining alpha and beta orbitals to distribute nb_rest = n_beta def add_subspace(orbitals, sid): # Add a new subspace subspaces.append(sid) orbs_a = np.array(orbitals[0]) + 1 orbs_b = np.array(orbitals[1]) + 1 + n_orbs_alpha if restricted: orbs_b -= n_orbs_alpha ref_axis[sid] = ((orbs_a, orbs_b)) done_a.extend(orbs_a) done_b.extend(orbs_b) if core_orbitals: add_subspace(core_orbitals, "o2") na_rest -= len(core_orbitals[0]) nb_rest -= len(core_orbitals[1]) if frozen_core: add_subspace(frozen_core, "o3") na_rest -= len(frozen_core[0]) nb_rest -= len(frozen_core[1]) if frozen_virtual: add_subspace(frozen_virtual, "v2") notdone_a = np.array([ o for o in data.get_fa_range() if not np.any(np.abs(done_a - o) < 1e-12) ]) notdone_b = np.array([ o for o in data.get_fb_range() if not np.any(np.abs(done_b - o) < 1e-12) ]) ref_axis["o1"] = ((notdone_a[:na_rest], notdone_b[:nb_rest])) ref_axis["v1"] = ((notdone_a[na_rest:], notdone_b[nb_rest:])) # General properties assert refstate.restricted == restricted assert refstate.spin_multiplicity == (1 if restricted else 0) assert refstate.has_core_occupied_space == ("o2" in subspaces) assert refstate.irreducible_representation == "A" assert refstate.n_orbs == n_orbs_alpha + n_orbs_alpha assert refstate.n_orbs_alpha == n_orbs_alpha assert refstate.n_orbs_beta == n_orbs_alpha assert refstate.n_alpha == n_alpha assert refstate.n_beta == n_beta assert refstate.conv_tol == 1e-10 assert refstate.energy_scf == -1. # Orben for ss in subspaces: assert_array_equal( refstate.orbital_energies(ss).to_ndarray(), np.hstack(ref_axis[ss])) # Orbcoeff for ss in subspaces: coeff_a = ref_axis[ss][0][:, None] * data.mul(1) \ + data.get_b_range()[None, :] coeff_b = ref_axis[ss][1][:, None] * data.mul(1) \ + data.get_b_range()[None, :] nfa, nb = coeff_a.shape nfb, nb = coeff_b.shape coeff_full = np.zeros((nfa + nfb, 2 * nb)) coeff_full[:nfa, :nb] = coeff_a coeff_full[nfa:, nb:] = coeff_b assert_array_equal( refstate.orbital_coefficients(ss + "b").to_ndarray(), coeff_full) # Fock for ss1 in subspaces: for ss2 in subspaces: assert_array_equal( refstate.fock(ss1 + ss2).to_ndarray(), data.fold_fock(ref_axis[ss1], ref_axis[ss2]))
self.omegamat = adcc.ones_like(self.diagonal()) * omega def __matmul__(self, other): return super().__matmul__(other) - self.omegamat * other # Run SCF in pyscf mol = gto.M(atom=""" Ne """, basis='aug-cc-pvdz', unit="Bohr") scfres = scf.RHF(mol) scfres.conv_tol = 1e-12 scfres.conv_tol_grad = 1e-9 scfres.kernel() refstate = adcc.ReferenceState(scfres) matrix = ShiftedMat("adc3", refstate, omega=0.0) rhs = modified_transition_moments("adc2", matrix.ground_state, refstate.operators.electric_dipole[0]) preconditioner = JacobiPreconditioner(matrix) freq = 0.0 preconditioner.update_shifts(freq) explicit_symmetrisation = IndexSymmetrisation(matrix) x0 = preconditioner.apply(rhs) res = conjugate_gradient(matrix, rhs=rhs, x0=x0, callback=default_print, Pinv=preconditioner,
def relax_cvs(scfres, method, state, ctol=5e-5): singles_block_only = False if adcc.AdcMethod(method).level > 1 and "d" not in state.matrix.blocks: singles_block_only = True # Singles block only method refstate = adcc.ReferenceState(scfres) origmatrix = adcc.AdcBlockView(adcc.AdcMatrix(method, refstate), "s") else: refstate = adcc.ReferenceState(scfres) origmatrix = adcc.AdcMatrix(method, refstate) matrix = AdcMatrixShifted(origmatrix) explicit_symmetrisation = IndexSpinSymmetrisation( matrix, enforce_spin_kind=state.kind) assert state.kind == "singlet" fullvec = [ guess_zero(matrix, spin_block_symmetrisation="symmetric") for i in range(len(state.excitation_vectors)) ] for i in range(len(state.excitation_vectors)): project_amplitude(state.excitation_vectors[i], fullvec[i]) preconditioner = JacobiPreconditioner(matrix) relaxed_vec = [] relaxed_ene = [] residual_norms = [] for i in range(len(state.excitation_vectors)): print("=================") print(" State {}".format(i)) print("=================") vec = fullvec[i].copy( ) # Not sure this copy is needed, do it for safety origvec = vec ene = state.excitation_energies[i] eneold = ene histories = [] residual = 100000 xold = vec preconditioner.update_shifts(ene - 1e-2) matrix.update_omega(ene - 1e-3) print("--> Starting energy {}: {}".format(i, ene)) for it in range(100): eps = 1e-3 # numerical fuzzing to improve conditioning if residual > eps / 10 and it > 0: matrix.update_omega(ene - eps) preconditioner.update_shifts(ene - eps) res = conjugate_gradient( matrix, rhs=xold, x0=xold, callback=default_print, Pinv=preconditioner, conv_tol=ctol / 10, max_iter=400, ) x = res.solution x = explicit_symmetrisation.symmetrise([x], [origvec])[0] x /= np.sqrt(x @ x) ene = x @ matrix.matmul_orig(x) enediff = ene - eneold overlap = np.sqrt(np.abs(origvec @ x)) resres = matrix.matmul_orig(x) - ene * x residual = np.sqrt(resres @ resres) print("--> Energy {}: {} (enediff: {})" "".format(it, ene, enediff)) print("--> Overlap {}: {}".format(it, overlap)) print("--> Residual {}: {}".format(it, residual)) if np.abs(overlap - 1) > 0.2: if not histories: if i == 0: print( " !!! Low overlap detected and got no history" "... trying again") xold = origvec else: raise RuntimeError("Low overlap and got no history.") # Pick the energy of the historic result with the best overlap # (smallest aberration from 1) ene = sorted(histories, key=lambda x: x[1])[0][0] + eps print( " !!! Low overlap detected! Changing shift to {:.6g} " "and trying again !!!".format(ene)) xold = origvec elif residual < ctol: print("--> converged") break else: xold = x eneold = ene histories.append((ene, np.abs(overlap - 1))) residual_norms.append(np.sqrt(resres @ resres)) relaxed_vec.append(x) relaxed_ene.append(ene) class CvsRelaxationState: pass res = CvsRelaxationState() res.matrix = origmatrix res.kind = "singlet" res.eigenvectors = relaxed_vec res.eigenvalues = np.array(relaxed_ene) property_method = None if singles_block_only: # To not get crashes on property calculation (missing doubles part) property_method = "adc1" sstate = adcc.ExcitedStates(res, method=method, property_method=property_method) sstate.residual_norms = np.array(residual_norms) return sstate
#!/usr/bin/env python3 ## vi: tabstop=4 shiftwidth=4 softtabstop=4 expandtab import adcc from import_data import import_data from adcc.caching_policy import GatherStatisticsPolicy # Gather precomputed data data = import_data() # Initialise the caching policy: statistics_policy = GatherStatisticsPolicy() mp = adcc.LazyMp(adcc.ReferenceState(data), statistics_policy) # Run an adc2 calculation: singlets = adcc.adc2x(mp, n_singlets=5, conv_tol=1e-8) triplets = adcc.adc2x(mp, n_triplets=5, conv_tol=1e-8) print(singlets.describe()) print(triplets.describe()) print("Tensor cache statistics:") print(statistics_policy.call_count)
def eri_asymm_construction_test(scfres, core_orbitals=0): hfdata = adcc.backends.import_scf_results(scfres) refstate = adcc.ReferenceState(hfdata, core_orbitals=core_orbitals) subspaces = refstate.mospaces.subspaces ss_pairs = [] for i in range(len(subspaces)): for j in range(i, len(subspaces)): ss1, ss2 = subspaces[i], subspaces[j] ss_pairs.append(ss1 + ss2) # build the full ERI tensor eri_chem = np.empty( (hfdata.n_orbs, hfdata.n_orbs, hfdata.n_orbs, hfdata.n_orbs)) sfull = slice(hfdata.n_orbs) hfdata.fill_eri_ffff((sfull, sfull, sfull, sfull), eri_chem) eri_phys = eri_chem.transpose(0, 2, 1, 3) # full anti-symmetrized ERI tensor eri_asymm = eri_phys - eri_phys.transpose(1, 0, 2, 3) n_orbs = hfdata.n_orbs n_alpha = hfdata.n_alpha n_beta = hfdata.n_beta n_orbs_alpha = hfdata.n_orbs_alpha aro1 = slice(core_orbitals, n_alpha, 1) bro1 = slice(n_orbs_alpha + core_orbitals, n_orbs_alpha + n_beta, 1) aro2 = slice(0, core_orbitals, 1) bro2 = slice(n_orbs_alpha, n_orbs_alpha + core_orbitals, 1) arv = slice(n_alpha, n_orbs_alpha, 1) brv = slice(n_orbs_alpha + n_beta, n_orbs, 1) lookuptable = { "o1": { "a": aro1, "b": bro1, }, "o2": { "a": aro2, "b": bro2, }, "v1": { "a": arv, "b": brv, } } n_elec = n_alpha + n_beta n_virt_a = n_orbs_alpha - n_alpha lookuptable_prelim = { "o1": { "a": slice(0, n_alpha - core_orbitals, 1), "b": slice(n_alpha - core_orbitals, n_elec, 1) }, "o2": { "a": slice(0, core_orbitals, 1), "b": slice(core_orbitals, 2 * core_orbitals, 1) }, "v1": { "a": slice(0, n_virt_a, 1), "b": slice(n_virt_a, n_orbs - n_elec, 1) } } # loop over all spaces and compare imported # tensor to full tensor for i in range(len(ss_pairs)): for j in range(i, len(ss_pairs)): p1, p2 = ss_pairs[i], ss_pairs[j] s = p1 + p2 n = 2 s_clean = [s[i:i + n] for i in range(0, len(s), n)] imported_asymm = refstate.eri(s).to_ndarray() for allowed_spin in eri_phys_asymm_spin_allowed_prefactors: sl = [lookuptable[x] for x in s_clean] sl = [ sl[x][y] for x, y in enumerate(list(allowed_spin.transposition)) ] sl2 = [lookuptable_prelim[x] for x in s_clean] sl2 = [ sl2[x][y] for x, y in enumerate(list(allowed_spin.transposition)) ] sl = tuple(sl) sl2 = tuple(sl2) np.testing.assert_almost_equal( eri_asymm[sl], imported_asymm[sl2], err_msg="""ERIs wrong in space {} """ """and spin block {}""".format(s, allowed_spin))
def compare_refstate_with_reference(data, reference, spec, scfres=None, compare_orbcoeff=True, compare_eri="value"): # Extract convergence tolerance setting for comparison threshold if scfres is None: import_data = data atol = data["conv_tol"] else: import_data = scfres if hasattr(scfres, "conv_tol"): atol = scfres.conv_tol else: atol = data["conv_tol"] # TODO once hfdata is an HDF5 file # refcases = ast.literal_eval(data["reference_cases"][()]) refcases = ast.literal_eval(data["reference_cases"]) refstate = adcc.ReferenceState(import_data, **refcases[spec]) subspaces = { "gen": ["o1", "v1"], "cvs": ["o1", "o2", "v1"], "fc": ["o1", "o3", "v1"], "fv": ["o1", "v1", "v2"], "fc-fv": ["o1", "o3", "v1", "v2"], "fv-cvs": ["o1", "o2", "v1", "v2"] }[spec] assert subspaces == [e.decode() for e in reference["subspaces"]] # General properties assert refstate.restricted == data["restricted"] assert refstate.spin_multiplicity == (1 if data["restricted"] else 0) assert refstate.has_core_occupied_space == ("o2" in subspaces) assert refstate.irreducible_representation == "A" assert refstate.n_orbs == 2 * data["n_orbs_alpha"] assert refstate.n_orbs_alpha == data["n_orbs_alpha"] assert refstate.n_orbs_beta == data["n_orbs_alpha"] assert refstate.n_alpha == sum(data["occupation_f"][:refstate.n_orbs_alpha]) assert refstate.n_beta == sum(data["occupation_f"][refstate.n_orbs_alpha:]) assert refstate.conv_tol == atol # because atol is set to be the SCF conv_tol assert_allclose(refstate.energy_scf, data["energy_scf"], atol=atol) assert refstate.mospaces.subspaces == subspaces multipoles = data['multipoles'] assert_allclose(refstate.nuclear_total_charge, multipoles["nuclear_0"], atol=atol) assert_allclose(refstate.nuclear_dipole, multipoles["nuclear_1"], atol=atol) if "electric_dipole" in refstate.operators.available and \ "elec_1" in multipoles: refstate2 = adcc.ReferenceState(data) assert_allclose(refstate.dipole_moment, refstate2.dipole_moment, atol=atol) for ss in subspaces: assert_allclose(refstate.orbital_energies(ss).to_ndarray(), reference["orbital_energies"][ss], atol=atol) if compare_orbcoeff: for ss in subspaces: orbcoeff = refstate.orbital_coefficients(ss + "b").to_ndarray() orbcoeff_ref = reference["orbital_coefficients"][ss + "b"] assert_allclose(orbcoeff, orbcoeff_ref, atol=atol) for ss in reference["fock"].keys(): assert_allclose(refstate.fock(ss).to_ndarray(), reference["fock"][ss], atol=atol) if compare_eri == "abs": for ss in reference["eri"].keys(): assert_almost_equal(np.abs(refstate.eri(ss).to_ndarray()), np.abs(reference["eri"][ss])) elif compare_eri == "value": for ss in reference["eri"].keys(): assert_allclose(refstate.eri(ss).to_ndarray(), reference["eri"][ss], atol=atol)