def template_pe_formaldehyde(self, basis, method, backend): basename = f"formaldehyde_{basis}_pe_{method}" qc_result = qchem_data[basename] pe_options = {"potfile": pe_potentials["fa_6w"]} scfres = cached_backend_hf(backend, "formaldehyde", basis, pe_options=pe_options) state = adcc.run_adc(scfres, method=method, n_singlets=5, conv_tol=1e-10) assert_allclose(qc_result["excitation_energy"], state.excitation_energy_uncorrected, atol=1e-5) assert_allclose(+qc_result["excitation_energy"] + qc_result["pe_ptss_correction"] + qc_result["pe_ptlr_correction"], state.excitation_energy, atol=1e-5) assert_allclose(qc_result["pe_ptss_correction"], state.pe_ptss_correction, atol=1e-5) assert_allclose(qc_result["pe_ptlr_correction"], state.pe_ptlr_correction, atol=1e-5)
def template_pcm_ptlr_formaldehyde(self, basis, method, backend): if method != "adc1": pytest.skip("Data only available for adc1.") c = config[backend] basename = f"formaldehyde_{basis}_pcm_{method}" result = c["data"][basename] run_hf = c["run_hf"] scfres = run_hf(static_data.xyz["formaldehyde"], basis, charge=0, multiplicity=1, conv_tol=1e-12, conv_tol_grad=1e-11, max_iter=150, pcm_options=c["pcm_options"]) assert_allclose(scfres.energy_scf, result["energy_scf"], atol=1e-8) state = adcc.run_adc(scfres, method=method, n_singlets=5, conv_tol=1e-7, environment="ptlr") # compare ptLR result to LR data assert_allclose(state.excitation_energy, result["lr_excitation_energy"], atol=5e-3) # Consistency check with values obtained with ADCc assert_allclose(state.excitation_energy, result["ptlr_adcc_excitation_energy"], atol=1e-6) if backend == "psi4": # remove cavity files from PSI4 PCM calculations remove_cavity_psi4()
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 template_pcm_linear_response_formaldehyde(self, basis, method, backend): if method != "adc1": pytest.skip("Reference only exists for adc1.") c = config[backend] basename = f"formaldehyde_{basis}_pcm_{method}" result = c["data"][basename] run_hf = c["run_hf"] scfres = run_hf(static_data.xyz["formaldehyde"], basis, charge=0, multiplicity=1, conv_tol=1e-12, conv_tol_grad=1e-11, max_iter=150, pcm_options=c["pcm_options"]) assert_allclose(scfres.energy_scf, result["energy_scf"], atol=1e-8) matrix = adcc.AdcMatrix(method, scfres) solvent = AdcExtraTerm(matrix, {'ph_ph': block_ph_ph_0_pcm}) matrix += solvent assert len(matrix.extra_terms) state = adcc.run_adc(matrix, n_singlets=5, conv_tol=1e-7, environment=False) assert_allclose( state.excitation_energy_uncorrected, result["lr_excitation_energy"], atol=1e-5 ) state_cis = adcc.ExcitedStates(state, property_method="adc0") assert_allclose( state_cis.oscillator_strength, result["lr_osc_strength"], atol=1e-3 ) # invalid combination with pytest.raises(InputError): adcc.run_adc(scfres, method=method, n_singlets=5, environment={"linear_response": True, "ptlr": True}) # no environment specified with pytest.raises(InputError): adcc.run_adc(scfres, method=method, n_singlets=5) # automatically add coupling term state = adcc.run_adc(scfres, method=method, n_singlets=5, conv_tol=1e-7, environment="linear_response") assert_allclose( state.excitation_energy_uncorrected, result["lr_excitation_energy"], atol=1e-5 ) if backend == "psi4": # remove cavity files from PSI4 PCM calculations remove_cavity_psi4()
def template_pe_linear_response_formaldehyde(self, basis, method, backend): if method != "adc2": pytest.skip("Reference only exists for adc2.") basename = f"formaldehyde_{basis}_pe_{method}" tm_result = tmole_data[basename] pe_options = {"potfile": pe_potentials["fa_6w"]} scfres = cached_backend_hf(backend, "formaldehyde", basis, pe_options=pe_options) assert_allclose(scfres.energy_scf, tm_result["energy_scf"], atol=1e-8) matrix = adcc.AdcMatrix(method, scfres) solvent = AdcExtraTerm(matrix, {'ph_ph': block_ph_ph_0_pe}) # manually add the coupling term matrix += solvent assert len(matrix.extra_terms) assert_allclose(matrix.ground_state.energy(2), tm_result["energy_mp2"], atol=1e-8) state = adcc.run_adc(matrix, n_singlets=5, conv_tol=1e-7, environment=False) assert_allclose(state.excitation_energy_uncorrected, tm_result["excitation_energy"], atol=1e-6) # invalid combination with pytest.raises(InputError): adcc.run_adc(scfres, method=method, n_singlets=5, environment={ "linear_response": True, "ptlr": True }) # no scheme specified with pytest.raises(InputError): adcc.run_adc(scfres, method=method, n_singlets=5) # automatically add coupling term state = adcc.run_adc(scfres, method=method, n_singlets=5, conv_tol=1e-7, environment="linear_response") assert_allclose(state.excitation_energy_uncorrected, tm_result["excitation_energy"], atol=1e-6)
class TestAdcMatrixDenseExport(unittest.TestCase): def base_test(self, case, method, conv_tol=1e-8, **kwargs): kwargs.setdefault("n_states", 10) n_states = kwargs["n_states"] if "cvs" in method: refstate = cache.refstate_cvs[case] else: refstate = cache.refstate[case] matrix = adcc.AdcMatrix(method, refstate) state = adcc.run_adc(matrix, method=method, conv_tol=conv_tol, **kwargs) dense = matrix.to_dense_matrix() assert_allclose(dense, dense.T, rtol=1e-10, atol=1e-12) n_decimals = 10 spectrum = np.linalg.eigvalsh(dense) rounded = np.unique(np.round(spectrum, n_decimals))[:n_states] assert_allclose(state.excitation_energies, rounded, atol=10 * conv_tol)
def run_adcc_ptlr(wfn): return adcc.run_adc(wfn, method="adc1", n_singlets=5, conv_tol=1e-7, environment="ptlr")
def dump_reference_adcc(data, method, dumpfile, mp_tree="mp", adc_tree="adc", n_states_full=None, n_guess_singles=None, **kwargs): if isinstance(dumpfile, h5py.File): out = dumpfile elif isinstance(dumpfile, str): out = h5py.File(dumpfile, "w") else: raise TypeError( "Unknown type for out, only HDF5 file and str supported.") # TODO: spin-flip, etc. states = [] if "n_states" in kwargs: state = adcc.run_adc(data, method=method, **kwargs) states.append(state) else: n_singlets = kwargs.pop("n_singlets", 0) n_triplets = kwargs.pop("n_triplets", 0) if n_singlets: state = adcc.run_adc(data, method=method, n_singlets=n_singlets, n_guesses=n_guess_singles, **kwargs) states.append(state) if n_triplets: state = adcc.run_adc(data, method=method, n_triplets=n_triplets, n_guesses=n_guess_singles, **kwargs) states.append(state) if not len(states): raise ValueError("No excited states obtained.") # # MP # mp = out.create_group(mp_tree) # obtain ground state ground_state = states[0].ground_state mp["mp2/energy"] = ground_state.energy_correction(2) if "cvs" not in method: # TODO: MP3 energy correction missing in adcc for cvs mp["mp3/energy"] = ground_state.energy_correction(3) mp["mp2/dipole"] = ground_state.dipole_moment(level=2) mp.create_dataset("mp1/t_o1o1v1v1", data=ground_state.t2("o1o1v1v1").to_ndarray(), compression=8) mp.create_dataset("mp1/df_o1v1", data=ground_state.df("o1v1").to_ndarray(), compression=8) if "cvs" not in method: # TODO: missing in adcc for cvs mp.create_dataset("mp2/td_o1o1v1v1", data=ground_state.td2("o1o1v1v1").to_ndarray(), compression=8) if ground_state.has_core_occupied_space: mp.create_dataset("mp1/t_o2o2v1v1", data=ground_state.t2("o2o2v1v1").to_ndarray(), compression=8) mp.create_dataset("mp1/t_o1o2v1v1", data=ground_state.t2("o1o2v1v1").to_ndarray(), compression=8) mp.create_dataset("mp1/df_o2v1", data=ground_state.df("o2v1").to_ndarray(), compression=8) for block in [ "dm_o1o1", "dm_o1v1", "dm_v1v1", "dm_bb_a", "dm_bb_b", "dm_o2o1", "dm_o2o2", "dm_o2v1" ]: blk = block.split("_")[-1] if blk in ground_state.mp2_diffdm.blocks: mp.create_dataset("mp2/" + block, compression=8, data=ground_state.mp2_diffdm[blk].to_ndarray()) # # ADC # adc = out.create_group(adc_tree) # Data for matrix tests gmatrix = adc.create_group("matrix") random_vector = adcc.copy(states[0].excitation_vector[0]).set_random() # Compute matvec and block-wise apply matvec = states[0].matrix.compute_matvec(random_vector) result = { "ss": adcc.copy(random_vector["s"]), } states[0].matrix.compute_apply("ss", random_vector["s"], result["ss"]) if "d" in random_vector.blocks: if not ("cvs" in method and "adc3" in method): result["ds"] = adcc.copy(random_vector["d"]) states[0].matrix.compute_apply("ds", random_vector["s"], result["ds"]) result["sd"] = adcc.copy(random_vector["s"]) states[0].matrix.compute_apply("sd", random_vector["d"], result["sd"]) # TODO CVS-ADC(2)-x and CVS-ADC(3) compute_apply("dd") is not implemented if not ("cvs" in method and ("adc2x" in method or "adc3" in method)): result["dd"] = adcc.copy(random_vector["d"]) states[0].matrix.compute_apply("dd", random_vector["d"], result["dd"]) gmatrix["random_singles"] = random_vector["s"].to_ndarray() gmatrix["diagonal_singles"] = states[0].matrix.diagonal("s").to_ndarray() gmatrix["matvec_singles"] = matvec["s"].to_ndarray() gmatrix["result_ss"] = result["ss"].to_ndarray() if 'd' in random_vector.blocks: gmatrix.create_dataset("random_doubles", compression=8, data=random_vector["d"].to_ndarray()) gmatrix.create_dataset( "diagonal_doubles", compression=8, data=states[0].matrix.diagonal("d").to_ndarray()) gmatrix.create_dataset("matvec_doubles", compression=8, data=matvec["d"].to_ndarray()) if "ds" in result: gmatrix.create_dataset("result_ds", compression=8, data=result["ds"].to_ndarray()) if "sd" in result: gmatrix["result_sd"] = result["sd"].to_ndarray() if "dd" in result: gmatrix.create_dataset("result_dd", compression=8, data=result["dd"].to_ndarray()) available_kinds = [] for state in states: assert state.converged available_kinds.append(state.kind) dm_bb_a = [] dm_bb_b = [] tdm_bb_a = [] tdm_bb_b = [] eigenvectors_singles = [] eigenvectors_doubles = [] n_states = state.excitation_energy.size # Up to n_states_extract states we save everything if n_states_full is not None: n_states_extract = min(n_states_full, n_states) else: n_states_extract = n_states for i in range(n_states_extract): bb_a, bb_b = state.state_diffdm[i].to_ao_basis( state.reference_state) dm_bb_a.append(bb_a.to_ndarray()) dm_bb_b.append(bb_b.to_ndarray()) bb_a, bb_b = state.transition_dm[i].to_ao_basis( state.reference_state) tdm_bb_a.append(bb_a.to_ndarray()) tdm_bb_b.append(bb_b.to_ndarray()) eigenvectors_singles.append( state.excitation_vector[i]['s'].to_ndarray()) if 'd' in state.excitation_vector[i].blocks: eigenvectors_doubles.append( state.excitation_vector[i]['d'].to_ndarray()) else: eigenvectors_doubles.clear() kind = state.kind # Transform to numpy array adc[kind + "/state_diffdm_bb_a"] = np.asarray(dm_bb_a) adc[kind + "/state_diffdm_bb_b"] = np.asarray(dm_bb_b) adc[kind + "/ground_to_excited_tdm_bb_a"] = np.asarray(tdm_bb_a) adc[kind + "/ground_to_excited_tdm_bb_b"] = np.asarray(tdm_bb_b) adc[kind + "/state_dipole_moments"] = state.state_dipole_moment adc[kind + "/transition_dipole_moments"] = state.transition_dipole_moment adc[kind + "/transition_dipole_moments_velocity"] = \ state.transition_dipole_moment_velocity adc[kind + "/transition_magnetic_dipole_moments"] = \ state.transition_magnetic_dipole_moment adc[kind + "/eigenvalues"] = state.excitation_energy adc[kind + "/eigenvectors_singles"] = np.asarray(eigenvectors_singles) if eigenvectors_doubles: # For ADC(0) and ADC(1) there are no doubles adc.create_dataset(kind + "/eigenvectors_doubles", compression=8, data=np.asarray(eigenvectors_doubles)) # Store which kinds are available out.create_dataset("available_kinds", shape=(len(available_kinds), ), data=np.array(available_kinds, dtype=h5py.special_dtype(vlen=str))) # TODO: dump state2state once in master return out
def compute(self, input_model: "AtomicInput", config: "TaskConfig") -> "AtomicResult": """ Runs adcc """ self.found(raise_error=True) import adcc import psi4 mol = input_model.molecule model = input_model.model conv_tol = input_model.keywords.get("conv_tol", 1e-6) if input_model.driver not in ["energy", "properties"]: raise InputError( f"Driver {input_model.driver} not implemented for ADCC.") if isinstance(input_model.model.basis, BasisSet): raise InputError( "QCSchema BasisSet for model.basis not implemented. Use string basis name." ) if not input_model.model.basis: raise InputError("Model must contain a basis set.") psi4_molecule = psi4.core.Molecule.from_schema( dict(mol.dict(), fix_symmetry="c1")) psi4.core.clean() psi4.core.be_quiet() psi4.set_options({ "basis": model.basis, "scf_type": "pk", "e_convergence": conv_tol / 100, "d_convergence": conv_tol / 10, # 'maxiter': max_iter, "reference": "RHF" if mol.molecular_multiplicity == 1 else "UHF", }) _, wfn = psi4.energy("HF", return_wfn=True, molecule=psi4_molecule) adcc.set_n_threads(config.ncores) compute_success = False try: adcc_state = adcc.run_adc(wfn, method=model.method, **input_model.keywords) compute_success = adcc_state.converged except adcc.InputError as e: raise InputError(str(e)) except Exception as e: raise UnknownError(str(e)) input_data = input_model.dict(encoding="json") output_data = input_data.copy() output_data["success"] = compute_success if compute_success: output_data["return_result"] = adcc_state.excitation_energy[0] extract_props = input_model.driver == "properties" qcvars = adcc_state.to_qcvars(recurse=True, properties=extract_props) atprop = build_atomicproperties(qcvars) output_data["extras"]["qcvars"] = qcvars output_data["properties"] = atprop provenance = Provenance(creator="adcc", version=self.get_version(), routine="adcc").dict() provenance["nthreads"] = adcc.get_n_threads() output_data["provenance"] = provenance return AtomicResult(**output_data)
from relaxation import relax_cvs # Run SCF in pyscf mol = gto.M(atom=""" O 0 0 0 H 0 0 1.795239827225189 H 1.693194615993441 0 -0.599043184453037 """, basis='cc-pcvdz', unit="Bohr") scfres = scf.RHF(mol) scfres.conv_tol = 1e-12 scfres.conv_tol_grad = 1e-9 scfres.kernel() # Run CVS-ADC(3) singles and relax to ADC(3) for O-edge mat = AdcMatrix("cvs-adc3", ReferenceState(scfres, core_orbitals=1)) mats = AdcBlockView(mat, "s") mats.method = mat.method state = adcc.run_adc(mats, conv_tol=1e-8, n_singlets=10) state_relaxed = relax_cvs(scfres, "adc3", state) # Print results print() print(state.describe(oscillator_strengths=False)) print() print() print(state_relaxed.describe(oscillator_strengths=False)) print() print("Residual norms: ", state_relaxed.residual_norms)
O 7.98000 1.33100 -3.90100 O 9.55600 -0.11000 -3.46600 H 7.74900 2.71100 2.65200 H 8.99100 1.57500 2.99500 """, basis='sto-3g', ) scfres = PE(scf.RHF(mol), {"potfile": "pna_6w.pot"}) scfres.conv_tol = 1e-8 scfres.conv_tol_grad = 1e-6 scfres.max_cycle = 250 scfres.kernel() # model the solvent through perturbative corrections state_pt = adcc.adc2(scfres, n_singlets=5, conv_tol=1e-5, environment=['ptss', 'ptlr']) # now model the solvent through linear-response coupling # in the ADC matrix, re-using the matrix from previous run. # This will modify state_pt.matrix state_lr = adcc.run_adc(state_pt.matrix, n_singlets=5, conv_tol=1e-5, environment='linear_response') print(state_pt.describe()) print(state_lr.describe())