def read_calc_H(geo_fn, multiplicity=1, charge=0): """ Read and calc the H and rho return: H,rho matrix """ if not isinstance(geo_fn, str): # geo_fn = 'h2.xyz' raise Exception('filename is a string') geo = [] with open(geo_fn) as f: f.readline() f.readline() for line in f: species, x, y, z = line.split() geo.append([species, (float(x), float(y), float(z))]) # meanfield data mol = openfermion.hamiltonians.MolecularData(geo, 'sto-3g', multiplicity, charge) openfermionpyscf.run_pyscf(mol) terms_molecular_hamiltonian = mol.get_molecular_hamiltonian() fermionic_hamiltonian = openfermion.transforms.get_fermion_operator( terms_molecular_hamiltonian) qubit_op = openfermion.transforms.jordan_wigner(fermionic_hamiltonian) # calc H Hamiltonian = Hamiltonian_str_convert(qubit_op) return Hamiltonian, mol.n_qubits
def get_qubit_hamiltonian(mol, geometry, basis, charge=0, multiplicity=1, qubit_transf='bk'): ''' Generating qubit hamiltonina of the given molecules with specified geometry, basis sets, charge and multiplicity Give its qubit form using specified transformation ''' g = get_molecular_data(mol, geometry) mol = MolecularData(g, basis, multiplicity, charge) mol = run_pyscf(mol) ham = mol.get_molecular_hamiltonian() hamf = get_fermion_operator(ham) if qubit_transf == 'bk': hamq = bravyi_kitaev(hamf) elif qubit_transf == 'jw': hamq = jordan_wigner(hamf) else: raise (ValueError(qubit_transf, 'Unknown transformation specified')) return hamq
def exp_hamiltoniantrot_H2(time, atomic_distance, trotter_order): """ Here we are using some packages related to quantum chemistry to obtain hamiltonian of H2 molecule. The we are translating this hamiltonian into sequence of pyquil gates. And finally, we are trotterazing the exponent of the hamiltonian (exp(-iHt)) of our system and returning the obtained pyquil program :param time: is t in the exp(iHt). Note the + sign. :param atomic_distance: the distance between to H atoms in H2 molecule :return: program of the Trotter-Suzuki decomposition of hamiltonian exp(iHt) for H2 molecule """ geometry = [['H', [0, 0, 0]], ['H', [0, 0, atomic_distance]]] # H--H distance = 0.74angstrom basis = 'sto-3g' multiplicity = 1 # (2S+1) charge = 0 h2_molecule = MolecularData(geometry, basis, multiplicity, charge) h2_molecule = run_pyscf(h2_molecule) h2_qubit_hamiltonian = jordan_wigner(get_fermion_operator(h2_molecule.get_molecular_hamiltonian())) pyquil_h2_qubit_hamiltonian = qubitop_to_pyquilpauli(h2_qubit_hamiltonian) return trotterization(pyquil_h2_qubit_hamiltonian, float(time), trotter_order)
def test_run_pyscf(self): new_mole = run_pyscf(self.molecule, run_scf=True, run_mp2=True, run_cisd=True, run_ccsd=True, run_fci=True, verbose=1) self.assertTrue(isinstance(new_mole, PyscfMolecularData))
def run_simulation(bond_lengths): # Load saved file for H3. basis = 'sto-3g' spin = 2 # Set Hamiltonian parameters. active_space_start = 1 active_space_stop = 3 # Set calculation parameters. run_scf = 1 run_mp2 = 1 run_cisd = 0 run_ccsd = 0 run_fci = 1 delete_input = True delete_output = True # Begin Running Simulation, Convert distance_counter to angstroms geometry = [('H', (0., 0., bond_lengths[1][-1] * 0.529177249)), ('H', (0., 0., bond_lengths[2][-1] * 0.529177249)), ('H', (0., 0., bond_lengths[3][-1] * 0.529177249))] # Generate and populate instance of MolecularData. molecule = MolecularData(geometry, basis, spin, description="h3") molecule = run_pyscf(molecule, run_scf=run_scf, run_mp2=run_mp2, run_cisd=run_cisd, run_ccsd=run_ccsd, run_fci=run_fci) # Use a Jordan-Wigner encoding, and compress to remove 0 imaginary components molecular_hamiltonian = molecule.get_molecular_hamiltonian( occupied_indices=range(active_space_start), active_indices=range(active_space_start, active_space_stop)) fermion_hamiltonian = get_fermion_operator(molecular_hamiltonian) qubit_hamiltonian = jordan_wigner(fermion_hamiltonian) qubit_hamiltonian.compress() compiler_engine = uccsd_trotter_engine() initial_energy = energy_objective(opt_amplitudes) # Run VQE Optimization to find new CCSD parameters opt_result = minimize(energy_objective, opt_amplitudes, method="CG", options={'disp': True}) opt_energy, opt_amplitudes = opt_result.fun, opt_result.x return ({ "Name": molecule.name, "UCCSD Energy": opt_energy, "FCI Energy": molecule.fci_energy })
def test_run_pyscf(): new_mole = run_pyscf(molecule, run_scf=True, run_mp2=True, run_cisd=True, run_ccsd=True, run_fci=True, verbose=1) assert isinstance(new_mole, PyscfMolecularData)
def get_BK_ham(distance, basis="sto-3g", multiplicity=1, charge=1): geometry = [["He", [0, 0, 0]], ["H", [0, 0, distance]]] description = str(distance) molecule = MolecularData(geometry, basis, multiplicity, charge, description) molecule = run_pyscf(molecule, run_fci=1) bk_hamiltonian = get_sparse_operator( bravyi_kitaev( get_fermion_operator(molecule.get_molecular_hamiltonian()))) return bk_hamiltonian
def molecule_data(spacing): description = "{}".format(spacing) geometry = [[element_names[0], [0, 0, 0]], [element_names[1], [0, 0, spacing]]] molecule = MolecularData(geometry, basis, multiplicity, charge, description) molecule = run_pyscf(molecule) return molecule
def get_single_two_body(formula, source, basis='sto-3g', multiplicity=1): """ Calculate and return single body and two body integrals for the molecule specified with formula. :param formula: The chemical formula of the molecule in capital letters. E.g. H2O :param source: Can be either 'pubchem' or 'nist'. :param basis: :param multiplicity: :return: one body and two body integrals """ geometry = get_geometry(formula, source) molecule = MolecularData(geometry, basis, multiplicity) molecule = run_pyscf(molecule) # TODO: add proper functionality to save to a file, preferably with specifiable location and filename. # _molecule.save() return molecule.one_body_integrals, molecule.two_body_integrals
def main(): from itertools import product import pyscf import openfermion as of from openfermion.chem.molecular_data import spinorb_from_spatial from openfermionpyscf import run_pyscf from pyscf.cc.addons import spatial2spin import numpy as np basis = 'cc-pvdz' mol = pyscf.M(atom='H 0 0 0; B 0 0 {}'.format(1.6), basis=basis) mf = mol.RHF().run() mycc = mf.CCSD().run() print('CCSD correlation energy', mycc.e_corr) molecule = of.MolecularData(geometry=[['H', (0, 0, 0)], ['B', (0, 0, 1.6)]], basis=basis, charge=0, multiplicity=1) molecule = run_pyscf(molecule, run_ccsd=True) oei, tei = molecule.get_integrals() norbs = int(mf.mo_coeff.shape[1]) occ = mf.mo_occ nele = int(sum(occ)) nocc = nele // 2 assert np.allclose(np.transpose(mycc.t2, [1, 0, 3, 2]), mycc.t2) soei, stei = spinorb_from_spatial(oei, tei) astei = np.einsum('ijkl', stei) - np.einsum('ijlk', stei) # put in physics notation. OpenFermion stores <12|2'1'> gtei = astei.transpose(0, 1, 3, 2) eps = np.kron(molecule.orbital_energies, np.ones(2)) n = np.newaxis o = slice(None, 2 * nocc) v = slice(2 * nocc, None) e_abij = 1 / (-eps[v, n, n, n] - eps[n, v, n, n] + eps[n, n, o, n] + eps[n, n, n, o]) e_ai = 1 / (-eps[v, n] + eps[n, o]) fock = soei + np.einsum('piiq->pq', astei[:, o, o, :]) hf_energy = 0.5 * np.einsum('ii', (fock + soei)[o, o]) hf_energy_test = 1.0 * einsum('ii', fock[o, o]) - 0.5 * einsum( 'ijij', gtei[o, o, o, o]) print(hf_energy_test, hf_energy) assert np.isclose(hf_energy + molecule.nuclear_repulsion, molecule.hf_energy) g = gtei nsvirt = 2 * (norbs - nocc) nsocc = 2 * nocc t1f, t2f = kernel(np.zeros((nsvirt, nsocc)), np.zeros((nsvirt, nsvirt, nsocc, nsocc)), fock, g, o, v, e_ai, e_abij) print(ccsd_energy(t1f, t2f, fock, g, o, v) - hf_energy) t1f, t2f = kernel(np.zeros((nsvirt, nsocc)), np.zeros((nsvirt, nsvirt, nsocc, nsocc)), fock, g, o, v, e_ai, e_abij, diis_size=8, diis_start_cycle=4) print(ccsd_energy(t1f, t2f, fock, g, o, v) - hf_energy)
" --------------------------------------------------------------------------" ) molecules = [] SymbolicAnsatz = None for point in [3.0]: #range(1, n_points + 1): bond_length = point #bond_length_interval * float(point) + 0.2 geometry = [('Li', (0., 0., 0.)), ('H', (0., 0., bond_length))] MolecularMeta = {} molecule = MolecularData(geometry, basis, multiplicity, description=str(round(bond_length, 2))) molecule = run_pyscf(molecule, run_scf=run_scf) # Basic information jim = molecule.name print("===== Molecule {} =====".format(jim)) MolecularMeta['Name'] = jim MolecularMeta['Geo'] = bond_length # Hamiltonian ham_qubit = jordan_wigner(molecule.get_molecular_hamiltonian()) ham_qubit.compress() # Now in QubitOperator form ham_sparse = qubit_operator_sparse(ham_qubit, n_qubits=molecule.n_qubits) print(' HF:', molecule.hf_energy) MolecularMeta['FCI eigenstates'] = run_FCI(molecule, vqd_maxiter + 8)
#for op in pool.pool: # op = -1j*op # new_op = split_into_paulis(op) # op_list = op_list + new_op #simple_op = 0*WeightedPauliOperator.from_list(paulis = [Pauli.from_label('I'*num_qubits)]) #print('simplifying pool') #for op in op_list: # simple_op = simple_op + op #op_list = split_into_paulis(simple_op) #string_list = [] #for op in op_list: # string_list.append(op.print_details()[:num_qubits]) #pool = PauliPool.from_pauli_strings(string_list) pool = GSD_extract() molecule = openfermion.hamiltonians.MolecularData(geometry, "sto-3g", 1) molecule = openfermionpyscf.run_pyscf(molecule, run_fci=True) pool.init(molecule) pool.generate_SQ_Operators() pool = PauliPool().from_openfermion_qubit_operator_list( [-1j * element for element in pool.fermi_ops]) print('getting hamiltonian') ham = get_h_4_hamiltonian(dist, 6, 'jw') qubit_op = ham num_qubits = qubit_op.num_qubits print('num qubits', qubit_op.num_qubits) #start = time.time() #pool = CompletePauliPool.from_num_qubits(num_qubits, 'YX') #pool = PauliPool.from_all_pauli_strings(num_qubits) #all possible pauli strings #pool = PauliPool.from_pauli_strings(['YXII','IYXI','IIYX','IYIX','IIIY','IIYI']) #pool._num_qubits = num_qubits
def do_make_molecule(self, molecule=None) -> MolecularData: if molecule is None: molecule = MolecularData(**self.parameters.molecular_data_param) return run_pyscf(molecule, **self.parameters_pyscf.__dict__)
def dqg_run_bpsdp(): import sys from openfermion.hamiltonians import MolecularData from openfermionpsi4 import run_psi4 from openfermionpyscf import run_pyscf from openfermion.utils import map_one_pdm_to_one_hole_dm, \ map_two_pdm_to_two_hole_dm, map_two_pdm_to_particle_hole_dm print('Running System Setup') basis = 'sto-6g' # basis = '6-31g' multiplicity = 1 # charge = 0 # geometry = [('H', [0.0, 0.0, 0.0]), ('H', [0, 0, 0.75])] # charge = 1 # geometry = [('H', [0.0, 0.0, 0.0]), ('He', [0, 0, 0.75])] charge = 0 bd = 1.2 # geometry = [('H', [0.0, 0.0, 0.0]), ('H', [0, 0, bd]), # ('H', [0.0, 0.0, 2 * bd]), ('H', [0, 0, 3 * bd])] # geometry = [['H', [0, 0, 0]], ['H', [1.2, 0, 0]], # ['H', [0, 1.2, 0]], ['H', [1.2, 1.2, 0]]] # geometry = [['He', [0, 0, 0]], ['H', [0, 0, 1.2]]] # geometry = [['Be' [0, 0, 0]], [['B', [1.2, 0, 0]]]] geometry = [['N', [0, 0, 0]], ['N', [0, 0, 1.1]]] molecule = MolecularData(geometry, basis, multiplicity, charge) # Run Psi4. # molecule = run_psi4(molecule, # run_scf=True, # run_mp2=False, # run_cisd=False, # run_ccsd=False, # run_fci=True, # delete_input=True) molecule = run_pyscf(molecule, run_scf=True, run_mp2=False, run_cisd=False, run_ccsd=False, run_fci=True) print('nuclear_repulsion', molecule.nuclear_repulsion) print('gs energy ', molecule.fci_energy) print("hf energy ", molecule.hf_energy) nuclear_repulsion = molecule.nuclear_repulsion gs_energy = molecule.fci_energy import openfermion as of hamiltonian = molecule.get_molecular_hamiltonian( occupied_indices=[0], active_indices=[1, 2, 3, 4]) print(type(hamiltonian)) print(hamiltonian) nuclear_repulsion = hamiltonian.constant hamiltonian.constant = 0 ham = of.get_sparse_operator(hamiltonian).toarray() w, v = np.linalg.eigh(ham) idx = 0 gs_energy = w[idx] n_density = v[:, [idx]] @ v[:, [idx]].conj().T from representability.fermions.density.antisymm_sz_density import AntiSymmOrbitalDensity density = AntiSymmOrbitalDensity(n_density, 8) opdm_a, opdm_b = density.construct_opdm() tpdm_aa, tpdm_bb, tpdm_ab, _ = density.construct_tpdm() true_tpdm = density.get_tpdm(density.rho, density.dim) true_tpdm = true_tpdm.transpose(0, 1, 3, 2) test_tpdm = unspin_adapt(tpdm_aa, tpdm_bb, tpdm_ab) assert np.allclose(true_tpdm, test_tpdm) tqdm_aa, tqdm_bb, tqdm_ab, _ = density.construct_thdm() phdm_ab, phdm_ba, phdm_aabb = density.construct_phdm() Na = np.round(opdm_a.trace()).real Nb = np.round(opdm_b.trace()).real one_body_ints, two_body_ints = hamiltonian.one_body_tensor, hamiltonian.two_body_tensor two_body_ints = np.einsum('ijkl->ijlk', two_body_ints) n_electrons = Na + Nb print('n_electrons', n_electrons) dim = one_body_ints.shape[0] spatial_basis_rank = dim // 2 bij_bas_aa, bij_bas_ab = geminal_spin_basis(spatial_basis_rank) opdm_a_interaction, opdm_b_interaction, v2aa, v2bb, v2ab = \ spin_adapted_interaction_tensor_rdm_consistent(two_body_ints, one_body_ints) dual_basis = sz_adapted_linear_constraints( spatial_basis_rank, Na, Nb, ['ck', 'kc', 'cckk', 'ckck', 'kkcc'], S=1, M=-1) print("constructed dual basis") opdm_a = Tensor(opdm_a, name='ck_a') opdm_b = Tensor(opdm_b, name='ck_b') oqdm_a = Tensor(np.eye(dim // 2) - opdm_a.data, name='kc_a') oqdm_b = Tensor(np.eye(dim // 2) - opdm_b.data, name='kc_b') tpdm_aa = Tensor(tpdm_aa, name='cckk_aa', basis=bij_bas_aa) tpdm_bb = Tensor(tpdm_bb, name='cckk_bb', basis=bij_bas_aa) tpdm_ab = Tensor(tpdm_ab, name='cckk_ab', basis=bij_bas_ab) tqdm_aa = Tensor(tqdm_aa, name='kkcc_aa', basis=bij_bas_aa) tqdm_bb = Tensor(tqdm_bb, name='kkcc_bb', basis=bij_bas_aa) tqdm_ab = Tensor(tqdm_ab, name='kkcc_ab', basis=bij_bas_ab) phdm_ab = Tensor(phdm_ab, name='ckck_ab', basis=bij_bas_ab) phdm_ba = Tensor(phdm_ba, name='ckck_ba', basis=bij_bas_ab) phdm_aabb = Tensor(phdm_aabb, name='ckck_aabb') dtensor = MultiTensor([ opdm_a, opdm_b, oqdm_a, oqdm_b, tpdm_aa, tpdm_bb, tpdm_ab, tqdm_aa, tqdm_bb, tqdm_ab, phdm_ab, phdm_ba, phdm_aabb ]) copdm_a = opdm_a_interaction copdm_b = opdm_b_interaction coqdm_a = Tensor(np.zeros((spatial_basis_rank, spatial_basis_rank)), name='kc_a') coqdm_b = Tensor(np.zeros((spatial_basis_rank, spatial_basis_rank)), name='kc_b') ctpdm_aa = v2aa ctpdm_bb = v2bb ctpdm_ab = v2ab ctqdm_aa = Tensor(np.zeros_like(v2aa.data), name='kkcc_aa', basis=bij_bas_aa) ctqdm_bb = Tensor(np.zeros_like(v2bb.data), name='kkcc_bb', basis=bij_bas_aa) ctqdm_ab = Tensor(np.zeros_like(v2ab.data), name='kkcc_ab', basis=bij_bas_ab) cphdm_ab = Tensor(np.zeros((spatial_basis_rank**2, spatial_basis_rank**2)), name='ckck_ab', basis=bij_bas_ab) cphdm_ba = Tensor(np.zeros((spatial_basis_rank**2, spatial_basis_rank**2)), name='ckck_ba', basis=bij_bas_ab) cphdm_aabb = Tensor(np.zeros( (2 * spatial_basis_rank**2, 2 * spatial_basis_rank**2)), name='ckck_aabb') ctensor = MultiTensor([ copdm_a, copdm_b, coqdm_a, coqdm_b, ctpdm_aa, ctpdm_bb, ctpdm_ab, ctqdm_aa, ctqdm_bb, ctqdm_ab, cphdm_ab, cphdm_ba, cphdm_aabb ]) print( (ctensor.vectorize_tensors().T @ dtensor.vectorize_tensors())[0, 0].real) print(gs_energy) ctensor.dual_basis = dual_basis A, _, b = ctensor.synthesize_dual_basis() print("size of dual basis", len(dual_basis.elements)) print(A @ dtensor.vectorize_tensors() - b) nc, nv = A.shape A.eliminate_zeros() nnz = A.nnz from sdpsolve.sdp import SDP from sdpsolve.solvers.bpsdp import solve_bpsdp from sdpsolve.solvers.bpsdp.bpsdp_old import solve_bpsdp from sdpsolve.utils.matreshape import vec2block sdp = SDP() sdp.nc = nc sdp.nv = nv sdp.nnz = nnz sdp.blockstruct = list(map(lambda x: int(np.sqrt(x.size)), ctensor.tensors)) sdp.nb = len(sdp.blockstruct) sdp.Amat = A.real sdp.bvec = b.todense().real sdp.cvec = ctensor.vectorize_tensors().real sdp.Initialize() epsilon = 1.0E-7 sdp.epsilon = float(epsilon) sdp.epsilon_inner = float(epsilon) / 100 sdp.disp = True sdp.iter_max = 70000 sdp.inner_solve = 'CG' sdp.inner_iter_max = 2 # # sdp_data = solve_bpsdp(sdp) solve_bpsdp(sdp) # # create all the psd-matrices for the # variable_dictionary = {} # for tensor in ctensor.tensors: # linear_dim = int(np.sqrt(tensor.size)) # variable_dictionary[tensor.name] = cvx.Variable(shape=(linear_dim, linear_dim), PSD=True, name=tensor.name) # print("constructing constraints") # constraints = [] # for dbe in dual_basis: # single_constraint = [] # for tname, v_elements, p_coeffs in dbe: # active_indices = get_var_indices(ctensor.tensors[tname], v_elements) # single_constraint.append(variable_dictionary[tname][active_indices] * p_coeffs) # constraints.append(cvx.sum(single_constraint) == dbe.dual_scalar) # print('constraints constructed') # print("constructing the problem") # objective = cvx.Minimize( # cvx.trace(copdm_a.data @ variable_dictionary['ck_a']) + # cvx.trace(copdm_b.data @ variable_dictionary['ck_b']) + # cvx.trace(ctpdm_aa.data @ variable_dictionary['cckk_aa']) + # cvx.trace(ctpdm_bb.data @ variable_dictionary['cckk_bb']) + # cvx.trace(ctpdm_ab.data @ variable_dictionary['cckk_ab'])) # cvx_problem = cvx.Problem(objective, constraints=constraints) # print('problem constructed') # cvx_problem.solve(solver=cvx.SCS, verbose=True, eps=0.5E-5, max_iters=100000) # rdms_solution = vec2block(sdp.blockstruct, sdp.primal) print(gs_energy) # print(cvx_problem.value + nuclear_repulsion) # print(sdp_data.primal_value() + nuclear_repulsion) print(sdp.primal.T @ sdp.cvec) print(nuclear_repulsion) rdms = vec2block(sdp.blockstruct, sdp.primal) tpdm = unspin_adapt(rdms[4], rdms[5], rdms[6]) print(np.einsum('ijij', tpdm)) tpdm = np.einsum('ijkl->ijlk', tpdm)
def meanfield( name, geometry, charge=0, mult=1, basis="sto-3g", package="pyscf", outpath="." ): # pylint: disable=too-many-arguments r"""Generates a file from which the mean field electronic structure of the molecule can be retrieved. This function uses OpenFermion-PySCF and OpenFermion-Psi4 plugins to perform the Hartree-Fock (HF) calculation for the polyatomic system using the quantum chemistry packages ``PySCF`` and ``Psi4``, respectively. The mean field electronic structure is saved in an hdf5-formatted file in the directory ``os.path.join(outpath, package, basis)``. The charge of the molecule can be given to simulate cationic/anionic systems. Also, the spin multiplicity can be input to determine the number of unpaired electrons occupying the HF orbitals as illustrated in the figure below. | .. figure:: ../../_static/qchem/hf_references.png :align: center :width: 50% | Args: name (str): molecule label geometry (list): list containing the symbol and Cartesian coordinates for each atom charge (int): net charge of the system mult (int): Spin multiplicity :math:`\mathrm{mult}=N_\mathrm{unpaired} + 1` for :math:`N_\mathrm{unpaired}` unpaired electrons occupying the HF orbitals. Possible values for ``mult`` are :math:`1, 2, 3, \ldots`. If not specified, a closed-shell HF state is assumed. basis (str): Atomic basis set used to represent the HF orbitals. Basis set availability per element can be found `here <www.psicode.org/psi4manual/master/basissets_byelement.html#apdx-basiselement>`_ package (str): Quantum chemistry package used to solve the Hartree-Fock equations. Either ``'pyscf'`` or ``'psi4'`` can be used. outpath (str): path to output directory Returns: str: absolute path to the file containing the mean field electronic structure **Example** >>> name = 'h2' >>> geometry = [['H', (0.0, 0.0, -0.35)], ['H', (0.0, 0.0, 0.35)]] >>> meanfield(name, geometry) ./pyscf/sto-3g/h2 """ package = package.strip().lower() if package not in ("psi4", "pyscf"): error_message = ( "Integration with quantum chemistry package '{}' is not available. \n Please set" " 'package' to 'pyscf' or 'psi4'.".format(package) ) raise TypeError(error_message) package_dir = os.path.join(outpath.strip(), package) basis_dir = os.path.join(package_dir, basis.strip()) if not os.path.isdir(package_dir): os.mkdir(package_dir) os.mkdir(basis_dir) elif not os.path.isdir(basis_dir): os.mkdir(basis_dir) path_to_file = os.path.join(basis_dir, name.strip()) molecule = MolecularData(geometry, basis, mult, charge, filename=path_to_file) if package == "psi4": run_psi4(molecule, run_scf=1, verbose=0, tolerate_error=1) if package == "pyscf": run_pyscf(molecule, run_scf=1, verbose=0) return path_to_file
def meanfield_data(mol_name, geometry, charge, multiplicity, basis, qc_package="pyscf", outpath="."): # pylint: disable=too-many-arguments r"""Launches the meanfield (Hartree-Fock) electronic structure calculation. Also builds the path to the directory containing the input data file for quantum simulations. The path to the hdf5-formatted file is ``os.path.join(outpath, qc_package, basis)``. **Example usage:** >>> geometry = read_structure('h2_ref.xyz') >>> meanfield_data('h2', geometry, 0, 1, 'sto-3g', qc_package='pyscf') ./pyscf/sto-3g Args: mol_name (str): name of the molecule geometry (list): list containing the symbol and Cartesian coordinates for each atom charge (int): net charge of the molecule multiplicity (int): spin multiplicity based on the number of unpaired electrons in the Hartree-Fock state basis (str): atomic basis set. Basis set availability per element can be found `here <www.psicode.org/psi4manual/master/basissets_byelement.html#apdx -basiselement>`_ qc_package (str): quantum chemistry package used to solve Hartree-Fock equations. Either ``'pyscf'`` or ``'psi4'`` can be used outpath (str): path to ouput directory Returns: str: path to the directory containing the file with the Hartree-Fock electronic structure """ qc_package = qc_package.strip().lower() if qc_package not in ("psi4", "pyscf"): qc_package_error_message = ( "Integration with quantum chemistry package '{}' is not available. \n Please set" " 'qc_package' to 'pyscf' or 'psi4'.".format(qc_package)) raise TypeError(qc_package_error_message) qcp_dir = os.path.join(outpath.strip(), qc_package) path_to_hf_data = os.path.join(qcp_dir, basis.strip()) if not os.path.isdir(qcp_dir): os.mkdir(qcp_dir) os.mkdir(path_to_hf_data) elif not os.path.isdir(path_to_hf_data): os.mkdir(path_to_hf_data) molecule = MolecularData( geometry, basis, multiplicity, charge, filename=os.path.join(path_to_hf_data, mol_name.strip()), ) if qc_package == "psi4": run_psi4(molecule, run_scf=1, verbose=0, tolerate_error=1) if qc_package == "pyscf": run_pyscf(molecule, run_scf=1, verbose=0) return path_to_hf_data
molecules = [] for point in [1.5]: #range(1, n_points + 1): bond_length = point #bond_length_interval * float(point) + 0.2 geometry = [['H', (0, 0, 0)], ['H', (0, bond_length, 0)], ['H', (bond_length, bond_length, 0)], ['H', (bond_length, 0, 0)]] MolecularMeta = {} molecule = MolecularData(geometry, basis, multiplicity, description=str(round(bond_length, 2))) molecule = run_pyscf(molecule, run_scf=run_scf, run_ccsd=1, run_fci=run_fci) # Generate state preparation circuit (reusable for any geometry!) if pool.n_electrons == 0: # pool not initialised globally pool.init(n_orb=molecule.n_orbitals, n_occ=molecule.get_n_alpha_electrons(), n_vir=molecule.n_orbitals - molecule.get_n_alpha_electrons()) Ansatz = constructor(pool) # Basic information jim = molecule.name print("===== Molecule {} =====".format(jim)) hf = molecule.hf_energy fci = molecule.fci_energy print(" HF: {} /Eh".format(hf))
def main(): """ Example for solving CC3 amplitude equations """ import pyscf import openfermion as of from openfermion.chem.molecular_data import spinorb_from_spatial from openfermionpyscf import run_pyscf from pyscf.cc.addons import spatial2spin from pyscf import cc import numpy as np np.set_printoptions(linewidth=500) # run pyscf for some reason basis = '6-31g' mol = pyscf.M( atom='H 0 0 0; F 0 0 {}'.format(1.6), basis=basis) mf = mol.RHF() mf.verbose = 0 mf.run() # build molecule and run pyscf again for some reason molecule = of.MolecularData(geometry=[['H', (0, 0, 0)], ['F', (0, 0, 1.6)]], basis=basis, charge=0, multiplicity=1) molecule = run_pyscf(molecule,run_ccsd=False) # 1-, 2-electron integrals oei, tei = molecule.get_integrals() # Number of orbitals, number of electrons. apparently only works for closed shells occ = mf.mo_occ nele = int(sum(occ)) nocc = nele // 2 norbs = oei.shape[0] nsvirt = 2 * (norbs - nocc) nsocc = 2 * nocc soei, stei = spinorb_from_spatial(oei, tei) astei = np.einsum('ijkl', stei) - np.einsum('ijlk', stei) gtei = astei.transpose(0, 1, 3, 2) eps = np.kron(molecule.orbital_energies, np.ones(2)) n = np.newaxis o = slice(None, nsocc) v = slice(nsocc, None) e_abcijk = 1 / (- eps[v, n, n, n, n, n] - eps[n, v, n, n, n, n] - eps[n, n, v, n, n, n] + eps[n, n, n, o, n, n] + eps[n, n, n, n, o, n] + eps[n, n, n, n, n, o] ) e_abij = 1 / (-eps[v, n, n, n] - eps[n, v, n, n] + eps[n, n, o, n] + eps[ n, n, n, o]) e_ai = 1 / (-eps[v, n] + eps[n, o]) fock = soei + np.einsum('piiq->pq', astei[:, o, o, :]) hf_energy = 0.5 * np.einsum('ii', (fock + soei)[o, o]) hf_energy_test = 1.0 * einsum('ii', fock[o, o]) -0.5 * einsum('ijij', gtei[o, o, o, o]) print("") print(" SCF Total Energy: {: 20.12f}".format(hf_energy + molecule.nuclear_repulsion)) print("") assert np.isclose(hf_energy, mf.e_tot - molecule.nuclear_repulsion) assert np.isclose(hf_energy_test, hf_energy) g = gtei t1z = np.zeros((nsvirt, nsocc)) t2z = np.zeros((nsvirt, nsvirt, nsocc, nsocc)) t3z = np.zeros((nsvirt, nsvirt, nsvirt, nsocc, nsocc, nsocc)) t1f, t2f, t3f = kernel(t1z, t2z, t3z, fock, g, o, v, e_ai, e_abij,e_abcijk,hf_energy, stopping_eps=1e-10) en = ccsd_energy(t1f, t2f, fock, g, o, v) # determine triples amplitudes residual_triples = triples_residual(t1f, t2f, t3f, fock, g, o, v) fock_e_abcijk = np.reciprocal(e_abcijk) triples_res = residual_triples + fock_e_abcijk * t3f t3f = triples_res * e_abcijk # determine (t) correction ... need to transpose t1 t2 first (TODO: fix) l1 = t1f.transpose(1, 0) l2 = t2f.transpose(2, 3, 0, 1) t_en = t_energy(l1, l2, t3f, fock, g, o, v) print("") print(" CCSD Correlation Energy: {: 20.12f}".format(en - hf_energy)) print(" CCSD Total Energy: {: 20.12f}".format(en + molecule.nuclear_repulsion)) print("") print(" (T) Energy: {: 20.12f}".format(t_en)) print(" CCSD(T) Total Energy: {: 20.12f}".format(en + molecule.nuclear_repulsion + t_en)) print("") assert np.isclose(t_en,-0.003382913092468,atol=1e-9) assert np.isclose(en+molecule.nuclear_repulsion+t_en,-100.009057558929399,atol=1e-9)
bond_lengths = [] for point in range(15, 20): bond_length = bond_length_interval * point bond_lengths += [bond_length] description = str(round(bond_length, 2)) print(description) geometry = [('Cl', (0., 0., 0.)), ('Cl', (0., 0., bond_length))] molecule = MolecularData(geometry, basis, multiplicity, description=description) # Run the calculations. molecule = run_pyscf(molecule, run_mp2=True, run_cisd=True, run_ccsd=True, run_fci=True) # Print out some results of calculation. print('\nAt bond length of {} angstrom, molecular chlorine has:'.format( bond_length)) print('Hartree-Fock energy of {} Hartree.'.format(molecule.hf_energy)) print('MP2 energy of {} Hartree.'.format(molecule.mp2_energy)) print('FCI energy of {} Hartree.'.format(molecule.fci_energy)) print('Nuclear repulsion energy between protons is {} Hartree.'.format( molecule.nuclear_repulsion)) for orbital in range(molecule.n_orbitals): print('Spatial orbital {} has energy of {} Hartree.'.format( orbital, molecule.orbital_energies[orbital])) hf_energies += [molecule.hf_energy]
def old_setup( geometry, basis="sto-3g", multiplicity=1, #same as george, non-degenerate orbitals charge=1, #doesn't seem to matter in hamiltonian (weird) adapt_conver='norm', #doesn't matter for setup, but looks like daniel used a different method to determine convergence, but only in energy-case adapt_thresh=1e-3, #gradient threshold theta_thresh=1e-7, adapt_maxiter=200, #maximum number of iterations pool=operator_pools.singlet_GS( ), #generalized singles and doubles as default, though he's not sure if he changed it- nick seems to think that he used GS reference='rhf', #is default in MolecularData anyway brueckner=0, #mattered for psi4 but is 0 as default anyway ref_state=None, spin_adapt=True, fci_nat_orb=0, cisd_nat_orb=0, hf_stability='none', single_vqe=False, #will be true in our case chk_ops=[], energy_thresh=1e-6, #threshold for single_vqe fci_overlap=False, psi4_filename="psi4_%12.12f" % random.random()): # designed to set up the problem in the same way as Daniel, did have to substitute openfermionpyscf for psi4 but shouldn't make a difference #still need to investiage versioning for the pool init and singlet GSD methods as these require the current version of MolecularData objects to have: # n_orbitals (y) # get_n_alpha_electrons (y) # get_n_beta_electrons (y) # FermionOperator class (y) # requried attributes? (~) # # # hermitian_conjugate function (~) # normal_ordered function (~) # {{{ start_time = time.time() molecule = openfermion.hamiltonians.MolecularData(geometry, basis, multiplicity) if cisd_nat_orb == 1: cisd = 1 else: cisd = 0 molecule = openfermionpyscf.run_pyscf(molecule, run_fci=True) pool.init(molecule) if fci_overlap == False: print(" Basis: ", basis) print(' HF energy %20.16f au' % (molecule.hf_energy)) #print(' MP2 energy %20.16f au' %(molecule.mp2_energy)) #print(' CISD energy %20.16f au' %(molecule.cisd_energy)) #print(' CCSD energy %20.16f au' %(molecule.ccsd_energy)) if brueckner == 1: print(' BCCD energy %20.16f au' % (molecule.bccd_energy)) if cisd == 1: print(' CISD energy %20.16f au' % (molecule.cisd_energy)) if reference == 'rhf': print(' FCI energy %20.16f au' % (molecule.fci_energy)) # if we are going to transform to FCI NOs, it doesn't make sense to transform to CISD NOs if cisd_nat_orb == 1 and fci_nat_orb == 0: print(' Basis transformed to the CISD natural orbitals') if fci_nat_orb == 1: print(' Basis transformed to the FCI natural orbitals') #Build p-h reference and map it to JW transform if ref_state == None: ref_state = list(range(0, molecule.n_electrons)) reference_ket = scipy.sparse.csc_matrix( openfermion.jw_configuration_state(ref_state, molecule.n_qubits)).transpose() reference_bra = reference_ket.transpose().conj() #JW transform Hamiltonian computed classically with OFPsi4 hamiltonian_op = molecule.get_molecular_hamiltonian() hamiltonian = openfermion.transforms.get_sparse_operator(hamiltonian_op) if fci_overlap: e, fci_vec = openfermion.get_ground_state(hamiltonian) fci_state = scipy.sparse.csc_matrix(fci_vec).transpose() index = scipy.sparse.find(reference_ket)[0] print(" Basis: ", basis) print(' HF energy %20.16f au' % (molecule.hf_energy)) if brueckner == 1: print(' BCCD energy %20.16f au' % (molecule.bccd_energy)) print(' FCI energy %20.16f au' % e) print(' <FCI|HF> %20.16f' % np.absolute(fci_vec[index])) print(' Orbitals') print(molecule.canonical_orbitals) #Thetas parameters = [] #pool.generate_SparseMatrix() pool.gradient_print_thresh = theta_thresh ansatz_ops = [] #SQ operator strings in the ansatz ansatz_mat = [] #Sparse Matrices for operators in ansatz op_indices = [] parameters = [] #curr_state = 1.0*reference_ket curr_energy = molecule.hf_energy molecule = openfermion.transforms.jordan_wigner(hamiltonian_op) pool_list = [] for op in pool.fermi_ops: pool_list.append(1j * openfermion.transforms.jordan_wigner(op)) pool_list = PauliPool().from_openfermion_qubit_operator_list(pool_list) qiskit_molecule = openfermion_to_qiskit(molecule) return pool_list, qiskit_molecule
def meanfield( symbols, coordinates, name="molecule", charge=0, mult=1, basis="sto-3g", package="pyscf", outpath=".", ): # pylint: disable=too-many-arguments r"""Generates a file from which the mean field electronic structure of the molecule can be retrieved. This function uses OpenFermion-PySCF and OpenFermion-Psi4 plugins to perform the Hartree-Fock (HF) calculation for the polyatomic system using the quantum chemistry packages ``PySCF`` and ``Psi4``, respectively. The mean field electronic structure is saved in an hdf5-formatted file in the directory ``os.path.join(outpath, package, basis)``. The charge of the molecule can be given to simulate cationic/anionic systems. Also, the spin multiplicity can be input to determine the number of unpaired electrons occupying the HF orbitals as illustrated in the figure below. | .. figure:: ../../_static/qchem/hf_references.png :align: center :width: 50% | Args: symbols (list[str]): symbols of the atomic species in the molecule coordinates (array[float]): 1D array with the atomic positions in Cartesian coordinates. The coordinates must be given in atomic units and the size of the array should be ``3*N`` where ``N`` is the number of atoms. name (str): molecule label charge (int): net charge of the system mult (int): Spin multiplicity :math:`\mathrm{mult}=N_\mathrm{unpaired} + 1` for :math:`N_\mathrm{unpaired}` unpaired electrons occupying the HF orbitals. Possible values for ``mult`` are :math:`1, 2, 3, \ldots`. If not specified, a closed-shell HF state is assumed. basis (str): Atomic basis set used to represent the HF orbitals. Basis set availability per element can be found `here <www.psicode.org/psi4manual/master/basissets_byelement.html#apdx-basiselement>`_ package (str): Quantum chemistry package used to solve the Hartree-Fock equations. Either ``'pyscf'`` or ``'psi4'`` can be used. outpath (str): path to output directory Returns: str: absolute path to the file containing the mean field electronic structure **Example** >>> symbols, coordinates = (['H', 'H'], np.array([0., 0., -0.66140414, 0., 0., 0.66140414])) >>> meanfield(symbols, coordinates, name="h2") ./pyscf/sto-3g/h2 """ if coordinates.size != 3 * len(symbols): raise ValueError( "The size of the array 'coordinates' has to be 3*len(symbols) = {};" " got 'coordinates.size' = {}".format(3 * len(symbols), coordinates.size)) package = package.strip().lower() if package not in ("psi4", "pyscf"): error_message = ( "Integration with quantum chemistry package '{}' is not available. \n Please set" " 'package' to 'pyscf' or 'psi4'.".format(package)) raise TypeError(error_message) package_dir = os.path.join(outpath.strip(), package) basis_dir = os.path.join(package_dir, basis.strip()) if not os.path.isdir(package_dir): os.mkdir(package_dir) os.mkdir(basis_dir) elif not os.path.isdir(basis_dir): os.mkdir(basis_dir) path_to_file = os.path.join(basis_dir, name.strip()) geometry = [[symbol, tuple(coordinates[3 * i:3 * i + 3] * bohr_angs)] for i, symbol in enumerate(symbols)] molecule = openfermion.MolecularData(geometry, basis, mult, charge, filename=path_to_file) if package == "psi4": # pylint: disable=import-outside-toplevel from openfermionpsi4 import run_psi4 run_psi4(molecule, run_scf=1, verbose=0, tolerate_error=1) if package == "pyscf": # pylint: disable=import-outside-toplevel from openfermionpyscf import run_pyscf run_pyscf(molecule, run_scf=1, verbose=0) return path_to_file
run_cisd = 0 run_ccsd = 0 run_fci = 1 delete_input = True delete_output = True for point in range(1, n_points + 1): bond_length = bond_length_interval * float(point) + 0.2 bond_lengths += [bond_length] geometry = [('H', (0., 0., 0.)), ('H', (0., 0., bond_length)), ('H', (0., 0., 3.3))] molecule = MolecularData(geometry, basis, spin, description=str(round(bond_length, 2))) molecule = run_pyscf(molecule, run_scf=run_scf, run_mp2=run_mp2, run_cisd=run_cisd, run_ccsd=run_ccsd, run_fci=run_fci) # Get the Hamiltonian in an active space. molecular_hamiltonian = molecule.get_molecular_hamiltonian( occupied_indices=range(active_space_start), active_indices=range(active_space_start, active_space_stop)) # Map operator to fermions and qubits. fermion_hamiltonian = get_fermion_operator(molecular_hamiltonian) qubit_hamiltonian = jordan_wigner(fermion_hamiltonian) # compress removes 0 entries. qubit_hamiltonian is a qubit_operator qubit_hamiltonian.compress()
error_jf = [] error_jfu = [] # time count elapsed_time = time.time() - start print("elapsed_time:{0}".format(elapsed_time) + "[sec]") print("k={}, d={}".format(k_svd, d)) # molecule declaration distance = d geometry = [(mole1, (0, 0, 0)), (mole2, (0, 0, distance))] #xyz coordinates for atoms description = str(distance) #description for the psi4 output file molecule = MolecularData(geometry, basis, multiplicity, charge, description) molecule = run_pyscf(molecule, run_scf=1, run_fci=1) fermionic_hamiltonian = get_fermion_operator( molecule.get_molecular_hamiltonian()) # matrix for hamiltonian h = np.array([0, [], [[]], [[[]]], [[[[]]]]]) h[0] = fermionic_hamiltonian.terms[()] h[2] = np.zeros((nqubit, nqubit)) h[4] = np.zeros((nqubit, nqubit, nqubit, nqubit)) # input hamiltonian into h for i, j, k, l in itertools.product(range(nqubit), repeat=4): h[4][i][j][k][l] = fermionic_hamiltonian.terms.get( ((i, 1), (j, 1), (k, 0), (l, 0)), 0) # get chemist-ordered matrix (h2_correction unused)
run_ccsd = 1 run_fci = 1 verbose = 1 # Run Diatomic Curve for spacing in spacings: description = "{}".format(spacing) geometry = [[element_names[0], [0, 0, 0]], [element_names[1], [0, 0, spacing]]] molecule = MolecularData(geometry, basis, multiplicity, charge, description) molecule = run_pyscf(molecule, run_scf=run_scf, run_mp2=run_mp2, run_cisd=run_cisd, run_ccsd=run_ccsd, run_fci=run_fci, verbose=verbose) molecule.save() # Run Li H single point description = "1.45" geometry = [['Li', [0, 0, 0]], ['H', [0, 0, 1.45]]] molecule = MolecularData(geometry, basis, multiplicity, charge, description) molecule = run_pyscf(molecule, run_scf=run_scf, run_mp2=run_mp2, run_cisd=run_cisd,
def run_simulation(system, indx, commandprinter=False): # Load saved file for H3. basis = 'sto-3g' spin = 1 # Set Hamiltonian parameters. active_space_start = 1 active_space_stop = 3 # Set calculation parameters. run_scf = 1 run_mp2 = 1 run_cisd = 0 run_ccsd = 1 run_fci = 1 delete_input = True delete_output = True # Begin Running Simulation, Convert distance_counter to angstroms if indx == None: geometry = [ ('H', (0., 0., system.atoms[0].position[-1] * 0.529177249)), ('H', (0., 0., system.atoms[1].position[-1] * 0.529177249)), ('H', (0., 0., system.atoms[2].position[-1] * 0.529177249)) ] elif indx == 0: geometry = [ ('H', (0., 0., system.atoms[0].stand_by_position * 0.529177249)), ('H', (0., 0., system.atoms[1].position[-1] * 0.529177249)), ('H', (0., 0., system.atoms[2].position[-1] * 0.529177249)) ] elif indx == 1: geometry = [ ('H', (0., 0., system.atoms[0].position[-1] * 0.529177249)), ('H', (0., 0., system.atoms[1].stand_by_position * 0.529177249)), ('H', (0., 0., system.atoms[2].position[-1] * 0.529177249)) ] elif indx == 2: geometry = [ ('H', (0., 0., system.atoms[0].position[-1] * 0.529177249)), ('H', (0., 0., system.atoms[1].position[-1] * 0.529177249)), ('H', (0., 0., system.atoms[2].stand_by_position * 0.529177249)) ] # Generate and populate instance of MolecularData. molecule = MolecularData(geometry, basis, spin, charge=1, description="h3") molecule = run_pyscf(molecule, run_scf=run_scf, run_mp2=run_mp2, run_cisd=run_cisd, run_ccsd=run_ccsd, run_fci=run_fci) # Use a Jordan-Wigner encoding, and compress to remove 0 imaginary components molecular_hamiltonian = molecule.get_molecular_hamiltonian() fermion_hamiltonian = get_fermion_operator(molecular_hamiltonian) qubit_hamiltonian = jordan_wigner(fermion_hamiltonian) qubit_hamiltonian.compress() compiler_engine = uccsd_trotter_engine() ' Here we choose how we initialize our amplitudes ' # packed_amplitudes = uccsd_singlet_get_packed_amplitudes( # molecule.ccsd_single_amps, # molecule.ccsd_double_amps, # molecule.n_qubits, # molecule.n_electrons) # # # Initialize the VQE with UCCSD amplitudes # reference_state = array(packed_amplitudes)*(-1.) # print ('Reference State UCCSD amplitudes:', reference_state) # Initialize the VQE with previous optimal amplitudes reference_state = system.opt_amplitudes print(f"Reference State previous optima: {system.opt_amplitudes}") ' # # # # # # # # # # # # # # # # # # # # # # # # # # # ' # Run VQE Optimization to find new CCSD parameters opt_result = minimize(energy_objective, reference_state, (molecule, qubit_hamiltonian, compiler_engine), method="CG", options={'disp': True}) opt_energy, system.opt_amplitudes = opt_result.fun, opt_result.x print(f'VQE Final amplitude: {system.opt_amplitudes}') print(f'VQE energy: {opt_energy}') print(f'FCI energy: {molecule.fci_energy}') print(f'CCSD energy: {molecule.ccsd_energy}') print(f'SCF (Hartree-Fock) energy: {molecule.hf_energy}') if commandprinter: with open('commands.txt', 'a') as f: backend = OpenQASMEngine() # Print commands. But this circuit is only up to the point where you prepare the wavefunction for the optimized amplitudes compiler_engine = uccsd_trotter_engine(backend) wavefunction = compiler_engine.allocate_qureg(molecule.n_qubits) for i in range(molecule.n_electrons): X | wavefunction[i] evolution_operator = uccsd_singlet_evolution( system.opt_amplitudes, molecule.n_qubits, molecule.n_electrons) evolution_operator | wavefunction compiler_engine.flush() print(backend.circuit.qasm()) return ({ "Name": molecule.name, "VQE Energy": opt_energy, "FCI Energy": molecule.fci_energy, "CCSD Energy": molecule.ccsd_energy })