def run(self, section): properties = section['properties'] if HDF5Driver.KEY_HDF5_INPUT not in properties: raise AquaChemistryError('Missing hdf5 input property') hdf5_file = properties[HDF5Driver.KEY_HDF5_INPUT] if self.work_path is not None and not os.path.isabs(hdf5_file): hdf5_file = os.path.abspath(os.path.join(self.work_path, hdf5_file)) if not os.path.isfile(hdf5_file): raise LookupError('HDF5 file not found: {}'.format(hdf5_file)) molecule = QMolecule(hdf5_file) molecule.load() return molecule
def run(self, section): # create input psi4d_directory = os.path.dirname(os.path.realpath(__file__)) template_file = psi4d_directory + '/_template.txt' aqua_chemistry_directory = os.path.abspath( os.path.join(psi4d_directory, '../..')) molecule = QMolecule() input_text = section['data'] + '\n' input_text += 'import sys\n' syspath = '[\'' + aqua_chemistry_directory + '\',\'' + '\',\''.join( sys.path) + '\']' input_text += 'sys.path = ' + syspath + ' + sys.path\n' input_text += 'from qmolecule import QMolecule\n' input_text += '_q_molecule = QMolecule("{0}")\n'.format( molecule.filename) with open(template_file, 'r') as f: input_text += f.read() fd, input_file = tempfile.mkstemp(suffix='.inp') os.close(fd) with open(input_file, 'w') as stream: stream.write(input_text) fd, output_file = tempfile.mkstemp(suffix='.out') os.close(fd) try: PSI4Driver._run_psi4(input_file, output_file) if logger.isEnabledFor(logging.DEBUG): with open(output_file, 'r') as f: logger.debug('PSI4 output file:\n{}'.format(f.read())) finally: run_directory = os.getcwd() for local_file in os.listdir(run_directory): if local_file.endswith('.clean'): os.remove(run_directory + '/' + local_file) try: os.remove('timer.dat') except: pass try: os.remove(input_file) except: pass try: os.remove(output_file) except: pass _q_molecule = QMolecule(molecule.filename) _q_molecule.load() # remove internal file _q_molecule.remove_file() return _q_molecule
def compute_integrals(config): # Get config from input parameters # Molecule is in this format: # atoms=H .0 .0 .0; H .0 .0 0.2 # units=Angstrom # charge=0 # multiplicity=1 # where we support symbol for atom as well as number if 'atoms' not in config: raise AquaChemistryError('Atoms is missing') val = config['atoms'] if val is None: raise AquaChemistryError('Atoms value is missing') charge = int(config.get('charge', '0')) multiplicity = int(config.get('multiplicity', '1')) units = __checkUnits(config.get('units', 'Angstrom')) mol = __parseMolecule(val, units, charge, multiplicity) basis = config.get('basis', 'sto3g') calc_type = config.get('calc_type', 'rhf').lower() try: ehf, enuke, norbs, mohij, mohijkl, orbs, orbs_energy = _calculate_integrals( mol, basis, calc_type) except Exception as exc: raise AquaChemistryError( 'Failed electronic structure computation') from exc # Create driver level molecule object and populate _q_ = QMolecule() # Energies and orbits _q_._hf_energy = ehf _q_._nuclear_repulsion_energy = enuke _q_._num_orbitals = norbs _q_._num_alpha = mol.nup() _q_._num_beta = mol.ndown() _q_._mo_coeff = orbs _q_._orbital_energies = orbs_energy # Molecule geometry _q_._molecular_charge = mol.charge _q_._multiplicity = mol.multiplicity _q_._num_atoms = len(mol) _q_._atom_symbol = [] _q_._atom_xyz = np.empty([len(mol), 3]) atoms = mol.atoms for _n in range(0, _q_._num_atoms): atuple = atoms[_n].atuple() _q_._atom_symbol.append(QMolecule.symbols[atuple[0]]) _q_._atom_xyz[_n][0] = atuple[1] _q_._atom_xyz[_n][1] = atuple[2] _q_._atom_xyz[_n][2] = atuple[3] # 1 and 2 electron integrals _q_._mo_onee_ints = mohij _q_._mo_eri_ints = mohijkl return _q_
def _calculate_integrals(mol, calc_type='rhf'): """Function to calculate the one and two electron terms. Perform a Hartree-Fock calculation in the given basis. Args: mol : A PySCF gto.Mole object. calc_type: rhf, uhf, rohf Returns: ehf : Hartree-Fock energy enuke : Nuclear repulsion energy norbs : Number of orbitals mohij : One electron terms of the Hamiltonian. mohijkl : Two electron terms of the Hamiltonian. mo_coeff: Orbital coefficients orbs_energy: Orbitals energies x_dip_ints: x dipole moment integrals y_dip_ints: y dipole moment integrals z_dip_ints: z dipole moment integrals nucl_dipl : Nuclear dipole moment """ enuke = gto.mole.energy_nuc(mol) if calc_type == 'rhf': mf = scf.RHF(mol) elif calc_type == 'rohf': mf = scf.ROHF(mol) elif calc_type == 'uhf': mf = scf.UHF(mol) else: raise AquaChemistryError('Invalid calc_type: {}'.format(calc_type)) ehf = mf.kernel() if type(mf.mo_coeff) is tuple: mo_coeff = mf.mo_coeff[0] mo_occ = mf.mo_occ[0] else: mo_coeff = mf.mo_coeff mo_occ = mf.mo_occ norbs = mo_coeff.shape[0] orbs_energy = mf.mo_energy hij = mf.get_hcore() mohij = np.dot(np.dot(mo_coeff.T, hij), mo_coeff) eri = ao2mo.incore.full(mf._eri, mo_coeff, compact=False) mohijkl = eri.reshape(norbs, norbs, norbs, norbs) # dipole integrals mol.set_common_orig((0, 0, 0)) ao_dip = mol.intor_symmetric('int1e_r', comp=3) x_dip_ints = QMolecule.oneeints2mo(ao_dip[0], mo_coeff) y_dip_ints = QMolecule.oneeints2mo(ao_dip[1], mo_coeff) z_dip_ints = QMolecule.oneeints2mo(ao_dip[2], mo_coeff) dm = mf.make_rdm1(mf.mo_coeff, mf.mo_occ) if calc_type == 'rohf' or calc_type == 'uhf': dm = dm[0] elec_dip = np.negative(np.einsum('xij,ji->x', ao_dip, dm).real) elec_dip = np.round(elec_dip, decimals=8) nucl_dip = np.einsum('i,ix->x', mol.atom_charges(), mol.atom_coords()) nucl_dip = np.round(nucl_dip, decimals=8) logger.info("HF Electronic dipole moment: {}".format(elec_dip)) logger.info("Nuclear dipole moment: {}".format(nucl_dip)) logger.info("Total dipole moment: {}".format(nucl_dip+elec_dip)) return ehf, enuke, norbs, mohij, mohijkl, mo_coeff, orbs_energy, x_dip_ints, y_dip_ints, z_dip_ints, nucl_dip
def compute_integrals(config): # Get config from input parameters # molecule is in PySCF atom string format e.g. "H .0 .0 .0; H .0 .0 0.2" # other parameters are as per PySCF got.Mole format if 'atom' not in config: raise AquaChemistryError('Atom is missing') val = config['atom'] if val is None: raise AquaChemistryError('Atom value is missing') atom = val basis = config.get('basis', 'sto3g') unit = config.get('unit', 'Angstrom') charge = int(config.get('charge', '0')) spin = int(config.get('spin', '0')) max_memory = config.get('max_memory') if max_memory is None: max_memory = param.MAX_MEMORY calc_type = config.get('calc_type', 'rhf').lower() try: mol = gto.Mole(atom=atom, unit=unit, basis=basis, max_memory=max_memory, verbose=pylogger.QUIET) mol.symmetry = False mol.charge = charge mol.spin = spin mol.build(parse_arg=False) ehf, enuke, norbs, mohij, mohijkl, mo_coeff, orbs_energy, x_dip, y_dip, z_dip, nucl_dip = _calculate_integrals(mol, calc_type) except Exception as exc: raise AquaChemistryError('Failed electronic structure computation') from exc # Create driver level molecule object and populate _q_ = QMolecule() # Energies and orbits _q_._hf_energy = ehf _q_._nuclear_repulsion_energy = enuke _q_._num_orbitals = norbs _q_._num_alpha = mol.nelec[0] _q_._num_beta = mol.nelec[1] _q_._mo_coeff = mo_coeff _q_._orbital_energies = orbs_energy # Molecule geometry _q_._molecular_charge = mol.charge _q_._multiplicity = mol.spin + 1 _q_._num_atoms = mol.natm _q_._atom_symbol = [] _q_._atom_xyz = np.empty([mol.natm, 3]) atoms = mol.atom_coords() for _n in range(0, _q_._num_atoms): xyz = mol.atom_coord(_n) _q_._atom_symbol.append(mol.atom_pure_symbol(_n)) _q_._atom_xyz[_n][0] = xyz[0] _q_._atom_xyz[_n][1] = xyz[1] _q_._atom_xyz[_n][2] = xyz[2] # 1 and 2 electron integrals. h1 & h2 are ready to pass to FermionicOperator _q_._mo_onee_ints = mohij _q_._mo_eri_ints = mohijkl # dipole integrals _q_._x_dip_mo_ints = x_dip _q_._y_dip_mo_ints = y_dip _q_._z_dip_mo_ints = z_dip # dipole moment _q_._nuclear_dipole_moment = nucl_dip _q_._reverse_dipole_sign = True return _q_
def _parse_matrix_file(self, fname, useAO2E=False): mel = MatEl(file=fname) logger.debug('MatrixElement file:\n{}'.format(mel)) # Create driver level molecule object and populate _q_ = QMolecule() # Energies and orbits _q_._hf_energy = mel.scalar('ETOTAL') _q_._nuclear_repulsion_energy = mel.scalar('ENUCREP') _q_._num_orbitals = 0 # updated below from orbital coeffs size _q_._num_alpha = (mel.ne+mel.multip-1)//2 _q_._num_beta = (mel.ne-mel.multip+1)//2 _q_._molecular_charge = mel.icharg # Molecule geometry _q_._multiplicity = mel.multip _q_._num_atoms = mel.natoms _q_._atom_symbol = [] _q_._atom_xyz = np.empty([mel.natoms, 3]) syms = mel.ian xyz = np.reshape(mel.c, (_q_._num_atoms, 3)) for _n in range(0, _q_._num_atoms): _q_._atom_symbol.append(QMolecule.symbols[syms[_n]]) for _i in range(xyz.shape[1]): coord = xyz[_n][_i] if abs(coord) < 1e-10: coord = 0 _q_._atom_xyz[_n][_i] = coord moc = self._getMatrix(mel, 'ALPHA MO COEFFICIENTS') _q_._num_orbitals = moc.shape[0] _q_._mo_coeff = moc orbs_energy = self._getMatrix(mel, 'ALPHA ORBITAL ENERGIES') _q_._orbital_energies = orbs_energy # 1 and 2 electron integrals hcore = self._getMatrix(mel, 'CORE HAMILTONIAN ALPHA') logger.debug('CORE HAMILTONIAN ALPHA {}'.format(hcore.shape)) mohij = QMolecule.oneeints2mo(hcore, moc) if useAO2E: # These are 2-body in AO. We can convert to MO via the QMolecule # method but using ints in MO already, as in the else here, is better eri = self._getMatrix(mel, 'REGULAR 2E INTEGRALS') logger.debug('REGULAR 2E INTEGRALS {}'.format(eri.shape)) mohijkl = QMolecule.twoeints2mo(eri, moc) else: # These are in MO basis but by default will be reduced in size by # frozen core default so to use them we need to add Window=Full # above when we augment the config mohijkl = self._getMatrix(mel, 'AA MO 2E INTEGRALS') logger.debug('AA MO 2E INTEGRALS {}'.format(mohijkl.shape)) _q_._mo_onee_ints = mohij _q_._mo_eri_ints = mohijkl # dipole moment dipints = self._getMatrix(mel, 'DIPOLE INTEGRALS') dipints = np.einsum('ijk->kji', dipints) _q_._x_dip_mo_ints = QMolecule.oneeints2mo(dipints[0], moc) _q_._y_dip_mo_ints = QMolecule.oneeints2mo(dipints[1], moc) _q_._z_dip_mo_ints = QMolecule.oneeints2mo(dipints[2], moc) nucl_dip = np.einsum('i,ix->x', syms, xyz) nucl_dip = np.round(nucl_dip, decimals=8) _q_._nuclear_dipole_moment = nucl_dip _q_._reverse_dipole_sign = True return _q_