def construct_qc(self, all_mo=True): '''Converts all global variables to a list of `QCinfo` classes. ''' self.QC = [] ilumo = None for rr in range(len(self.geo_spec_all)): qc = QCinfo() qc.geo_spec = self.geo_spec_all[rr] qc.geo_info = self.geo_info qc.ao_spec = self.ao_spec qc.mo_spec = [] for s,ii_s in self.sym.items(): for i,coeffs in enumerate(self.mo_coeff_all[ii_s][rr]): qc.mo_spec.append({'coeffs': coeffs, 'energy' : self.mo_energy_all[ii_s][rr,i], 'occ_num' : self.mo_occ_all[ii_s][rr,i], 'sym': '%d.%s' % (i+1,s)}) qc.ao_spec.update() qc.mo_spec = MOClass(qc.mo_spec) qc.mo_spec.update() if not all_mo: ilumo = max(ilumo or 0, qc.mo_spec.get_lumo()) self.QC.append(qc) if not all_mo: for i in range(len(self.QC)): self.QC[i].mo_spec = self.QC[i].mo_spec[slice(None,ilumo)] return self.QC
def read_gaussian_log(fname, all_mo=False, spin=None, orientation='standard', i_link=-1, i_geo=-1, i_ao=-1, i_mo=-1, interactive=True, **kwargs): '''Reads all information desired from a Gaussian .log file. **Parameters:** fname: str, file descriptor Specifies the filename for the input file. fname can also be used with a file descriptor instad of a filename. all_mo : bool, optional If True, all molecular orbitals are returned. spin : {None, 'alpha', or 'beta'}, optional If not None, returns exclusively 'alpha' or 'beta' molecular orbitals. orientation : string, choices={'input', 'standard'}, optional Specifies orientation of the molecule in Gaussian nomenclature. [#first]_ i_link : int, default=-1 Selects the file for linked Gaussian jobs. i_geo : int, default=-1 Selects the geometry section of the output file. i_ao : int, default=-1 Selects the atomic orbital section of the output file. i_mo : int, default=-1 Selects the molecular orbital section of the output file. interactive : bool If True, the user is asked to select the different sets. **Returns:** qc (class QCinfo) with attributes geo_spec, geo_info, ao_spec, ao_spherical, mo_spec, etot : See :ref:`Central Variables` for details. .. [#first] Attention: The MOs in the output are only valid for the standard orientation! ''' if isinstance(fname, str): filename = fname fname = descriptor_from_file(filename, index=0) else: filename = fname.name flines = fname.readlines() # Read the WHOLE file into RAM if isinstance(fname, str): fname.close() # Leave existing file descriptors alive # Search the file the specific sections count = { 'link': 0, 'geometry': 0, 'geometry_input': 0, 'atomic orbitals': 0, 'molecular orbitals': [], 'state': [] } def check_sel(count, i, interactive=False, default=-1): if count == 0: raise IndexError elif count == 1: return 0 message = '\tPlease give an integer from 0 to {0} (default: {0}): '.format( count - 1) try: if interactive: i = raw_input(message) i = default if i == '' else int(i) i = range(count)[i] except (IndexError, ValueError): raise IOError(message.replace(':', '!')) else: display('\tSelecting the %s' % ('last element.' if (i == count - 1) else 'element %d.' % i)) return i # Go through the file line by line for il in range(len(flines)): line = flines[il] # The current line as string # Check the file for keywords if ' Entering Link 1' in line: count['link'] += 1 try: display('\tFound %d linked GAUSSIAN files.' % count['link']) i_link = check_sel(count['link'], i_link, interactive=interactive) except IndexError: raise IOError('Found no `Entering Link 1` keyword!') cartesian_basis = True c_link = 0 # Go through the file line by line for il in range(len(flines)): line = flines[il] # The current line as string thisline = line.split() # The current line split into segments # Check the file for keywords if ' Entering Link 1' in line: c_link += 1 if i_link == (c_link - 1): if ' orientation:' in line: if '%s orientation:' % orientation in line.lower(): count['geometry'] += 1 if 'input orientation:' in line.lower(): count['geometry_input'] += 1 elif 'Standard basis:' in line or 'General basis read from cards:' in line: # Check if a cartesian basis has been applied if '(5D, 7F)' in line: cartesian_basis = False elif '(6D, 10F)' not in line: raise IOError( 'Please apply a Spherical Harmonics (5D, 7F) or ' + 'a Cartesian Gaussian Basis Set (6D, 10F)!') elif 'AO basis set' in line: count['atomic orbitals'] += 1 elif 'The electronic state is ' in line: count['state'].append(thisline[-1][:-1]) elif 'Orbital Coefficients:' in line: mo_type = thisline[0] if mo_type != 'Beta': count['molecular orbitals'].append(mo_type) else: count['molecular orbitals'][-1] = 'Alpha&Beta' display('\nContent of the GAUSSIAN .log file:') display('\tFound %d geometry section(s). (%s orientation)' % (count['geometry'], orientation)) try: i_geo = check_sel(count['geometry'], i_geo, interactive=interactive) except IndexError: count['geometry'] = count['geometry_input'] orientation = 'input' display('\Looking for "Input orientation": \n' + '\tFound %d geometry section(s). (%s orientation)' % (count['geometry'], orientation)) try: i_geo = check_sel(count['geometry'], i_geo, interactive=interactive) except IndexError: raise IOError('Found no geometry section!' + ' Are you sure this is a GAUSSIAN .log file?') try: display('\tFound %d atomic orbitals section(s) %s.' % (count['atomic orbitals'], '(6D, 10F)' if cartesian_basis else '(5D, 7F)')) i_ao = check_sel(count['atomic orbitals'], i_ao, interactive=interactive) except IndexError: raise IOError('Write GFINPUT in your GAUSSIAN route section to print' + ' the basis set information!') try: display('\tFound the following %d molecular orbitals section(s):' % len(count['molecular orbitals'])) except IndexError: raise IOError( 'Write IOP(6/7=3) in your GAUSSIAN route section to print\n' + ' all molecular orbitals!') for i, j in enumerate(count['molecular orbitals']): string = '\t\tSection %d: %s Orbitals' % (i, j) try: string += ' (electronic state: %s)' % count['state'][i] except IndexError: pass display(string) i_mo = check_sel(len(count['molecular orbitals']), i_mo, interactive=interactive) if spin is not None: if spin != 'alpha' and spin != 'beta': raise IOError('`spin=%s` is not a valid option' % spin) else: display('Reading only molecular orbitals of spin %s.' % spin) # Set a counter for the AOs basis_count = 0 # Initialize some variables sec_flag = None skip = 0 c_link = 0 c_geo = 0 c_ao = 0 c_mo = 0 c_sao = 0 old_ao = -1 orb_sym = [] qc = QCinfo() index = [] # Go through the file line by line for il in range(len(flines)): line = flines[il] # The current line as string thisline = line.split() # The current line split into segments # Check the file for keywords if ' Entering Link 1' in line: c_link += 1 if i_link == (c_link - 1): if '%s orientation:' % orientation in line.lower(): # The section containing information about # the molecular geometry begins if i_geo == c_geo: qc.geo_info = [] qc.geo_spec = [] sec_flag = 'geo_info' c_geo += 1 skip = 4 elif 'Standard basis:' in line or 'General basis read from cards:' in line: # Check if a cartesian basis has been applied if '(5D, 7F)' in line: cartesian_basis = False elif '(6D, 10F)' not in line: raise IOError( 'Please apply a Spherical Harmonics (5D, 7F) or ' + 'a Cartesian Gaussian Basis Sets (6D, 10F)!') elif 'AO basis set' in line: # The section containing information about # the atomic orbitals begins if i_ao == c_ao: qc.ao_spec = [] if not cartesian_basis: qc.ao_spherical = [] sec_flag = 'ao_info' c_ao += 1 basis_count = 0 bNew = True # Indication for start of new AO section elif 'Orbital symmetries:' in line: sec_flag = 'mo_sym' add = '' orb_sym = [] elif 'Orbital Coefficients:' in line: # The section containing information about # the molecular orbitals begins if (i_mo == c_mo): sec_flag = 'mo_info' mo_type = count['molecular orbitals'][i_mo] qc.mo_spec = [] offset = 0 add = '' orb_spin = [] if orb_sym == []: if 'Alpha' in mo_type: add = '_a' orb_spin = ['alpha'] * basis_count orb_sym = ['A1' + add] * basis_count if 'Beta' in mo_type: add = '_b' orb_spin += ['beta'] * basis_count orb_sym += ['A1' + add] * basis_count for i in range(len(orb_sym)): # for numpy version < 1.6 c = ((numpy.array(orb_sym[:i + 1]) == orb_sym[i]) != 0).sum() # for numpy version >= 1.6 this could be used: #c = numpy.count_nonzero(numpy.array(orb_sym[:i+1]) == orb_sym[i]) qc.mo_spec.append({ 'coeffs': numpy.zeros(basis_count), 'energy': 0., 'sym': '%d.%s' % (c, orb_sym[i]) }) if orb_spin != []: qc.mo_spec[-1]['spin'] = orb_spin[i] if mo_type != 'Beta': c_mo += 1 bNew = True # Indication for start of new MO section elif 'E(' in line: qc.etot = float(line.split('=')[1].split()[0]) else: # Check if we are in a specific section if sec_flag == 'geo_info': if not skip: qc.geo_info.append( [thisline[1], thisline[0], thisline[1]]) qc.geo_spec.append([float(ij) for ij in thisline[3:]]) if '-----------' in flines[il + 1]: sec_flag = None else: skip -= 1 if sec_flag == 'ao_info': # Atomic orbital section if ' ****' in line: # There is a line with stars after every AO bNew = True # If there is an additional blank line, the AO section is complete if flines[il + 1].split() == []: sec_flag = None elif bNew: # The following AOs are for which atom? bNew = False at_num = int(thisline[0]) - 1 ao_num = 0 elif len(thisline) == 4: # AO information section # Initialize a new dict for this AO ao_num = 0 # Initialize number of atomic orbiatls ao_type = thisline[0].lower() # Type of atomic orbital pnum = int(thisline[1]) # Number of primatives for i_ao in ao_type: # Calculate the degeneracy of this AO and increase basis_count basis_count += l_deg( lquant[i_ao], cartesian_basis=cartesian_basis) qc.ao_spec.append({ 'atom': at_num, 'type': i_ao, 'pnum': pnum, 'coeffs': numpy.zeros((pnum, 2)) }) else: # Append the AO coefficients coeffs = numpy.array(line.replace('D', 'e').split(), dtype=numpy.float64) for i_ao in range(len(ao_type)): qc.ao_spec[-len(ao_type) + i_ao]['coeffs'][ao_num, :] = [ coeffs[0], coeffs[1 + i_ao] ] ao_num += 1 if sec_flag == 'mo_sym': if 'electronic state' in line: sec_flag = None else: info = line[18:].replace('(', '').replace(')', '').split() if 'Alpha' in line: add = '_a' elif 'Beta' in line: add = '_b' for i in info: orb_sym.append(i + add) if sec_flag == 'mo_info': # Molecular orbital section info = line[:21].split() if info == []: coeffs = line[21:].split() if bNew: index = [offset + i for i in range(len(coeffs))] bNew = False else: for i, j in enumerate(index): qc.mo_spec[j]['occ_num'] = int( 'O' in coeffs[i]) if mo_type not in 'Alpha&Beta': qc.mo_spec[j]['occ_num'] *= 2 elif 'Eigenvalues' in info: coeffs = line[21:].replace('-', ' -').split() if mo_type == 'Natural': key = 'occ_num' else: key = 'energy' for i, j in enumerate(index): qc.mo_spec[j][key] = float(coeffs[i]) else: coeffs = line[21:].replace('-', ' -').split() if not cartesian_basis and offset == 0: if old_ao != line[:14].split()[-1] or len( line[:14].split()) == 4: old_ao = line[:14].split()[-1] c_sao += 1 i = c_sao - 1 l = lquant[line[13].lower()] m = line[14:21].replace(' ', '').lower() p = 'yzx'.find(m) if len(m) == 1 else -1 if p != -1: m = p - 1 elif m == '': m = 0 else: m = int(m) qc.ao_spherical.append([i, (l, m)]) for i, j in enumerate(index): qc.mo_spec[j]['coeffs'][int(info[0]) - 1] = float( coeffs[i]) if int(info[0]) == basis_count: bNew = True offset = index[-1] + 1 if index[-1] + 1 == len(orb_sym): sec_flag = None orb_sym = [] # Are all MOs requested for the calculation? if not all_mo: for i in range(len(qc.mo_spec))[::-1]: if qc.mo_spec[i]['occ_num'] < 0.0000001: del qc.mo_spec[i] if spin is not None: if orb_spin == []: raise IOError( 'You requested `%s` orbitals, but None of them are present.' % spin) else: for i in range(len(qc.mo_spec))[::-1]: if qc.mo_spec[i]['spin'] != spin: del qc.mo_spec[i] # Convert geo_info and geo_spec to numpy.ndarrays qc.format_geo(is_angstrom=True) return qc
def read_wfx(fname, all_mo=False, spin=None, **kwargs): '''Reads all information desired from a wfn file. **Parameters:** fname: str, file descriptor Specifies the filename for the input file. fname can also be used with a file descriptor instad of a filename. all_mo : bool, optional If True, all molecular orbitals are returned. spin : {None, 'alpha', or 'beta'}, optional If not None, returns exclusively 'alpha' or 'beta' molecular orbitals. **Returns:** qc (class QCinfo) with attributes geo_spec, geo_info, ao_spec, mo_spec, etot : See :ref:`Central Variables` for details. ''' # Initialize the variables qc = QCinfo() qc.ao_spec = AOClass([]) qc.mo_spec = MOClass([]) lxlylz = [] for j in exp_wfn: lxlylz.extend(j) lxlylz = numpy.array(lxlylz, dtype=numpy.int64) if isinstance(fname, str): filename = fname fname = descriptor_from_file(filename, index=0) else: filename = fname.name from io import TextIOWrapper if isinstance(fname, TextIOWrapper): flines = fname.readlines() # Read the WHOLE file into RAM else: magic = 'This is an Orbkit magic string' text = fname.read().decode("iso-8859-1").replace( '\n', '\n{}'.format(magic)) flines = text.split(magic) flines.pop() is_valid = False for il in range(len(flines)): if '<Keywords>' in flines[il] and 'GTO' in flines[il + 1]: is_valid = True if not is_valid: raise IOError('No valid .wfx file!\nMissing:\n' + '<Keywords>\n GTO\n</Keywords>') sec_flag = None # A Flag specifying the current section at_num = None mo_num = None ao_num = None restricted = True count = 0 # Go through the file line by line for il in range(len(flines)): line = flines[il] # The current line as string if '<Number of Nuclei>' in line: at_num = int(flines[il + 1]) qc.geo_info = [[None, i + 1, None] for i in range(at_num)] qc.geo_spec = [] elif '<Nuclear Names>' in line: if not at_num: raise IOError('`<Number of Nuclei>` has to be found ' + 'before `<Nuclear Names>`.') for i in range(at_num): qc.geo_info[i][0] = flines[il + i + 1].replace(' ', '').replace( '\n', '') elif '<Atomic Numbers>' in line: if not at_num: raise IOError('`<Number of Nuclei>` has to be found ' + 'before `<Atomic Numbers>`.') for i in range(at_num): qc.geo_info[i][2] = flines[il + i + 1].replace(' ', '').replace( '\n', '') elif '<Nuclear Cartesian Coordinates>' in line: if not at_num: raise IOError('`<Number of Nuclei>` has to be found ' + 'before `<Nuclear Cartesian Coordinates>`.') for i in range(at_num): qc.geo_spec.append(flines[il + i + 1].split()) elif '<Number of Primitives>' in line: ao_num = int(flines[il + 1]) qc.ao_spec = AOClass([ { 'atom': None, 'pnum': -1, 'coeffs': None, 'lxlylz': None, #'lm': None } for i in range(ao_num) ]) elif '<Primitive Centers>' in line: sec_flag = 'ao_center' count = 0 elif '<Primitive Types>' in line: sec_flag = 'ao_type' count = 0 elif '<Primitive Exponents>' in line: sec_flag = 'ao_exp' count = 0 elif '<Number of Occupied Molecular Orbitals>' in line: mo_num = int(flines[il + 1]) qc.mo_spec = MOClass([{ 'coeffs': numpy.zeros(ao_num), 'energy': None, 'occ_num': None, 'spin': None, 'sym': '%s.1' % (i + 1) } for i in range(mo_num)]) elif '<Molecular Orbital Occupation Numbers>' in line: for i in range(mo_num): qc.mo_spec[i]['occ_num'] = float(flines[il + 1 + i]) elif '<Molecular Orbital Energies>' in line: for i in range(mo_num): qc.mo_spec[i]['energy'] = float(flines[il + 1 + i]) elif '<Molecular Orbital Spin Types>' in line: for i in range(mo_num): qc.mo_spec[i]['spin'] = (flines[il + 1 + i].replace( ' ', '').replace('\n', '')).replace('and', '_').lower() restricted = restricted and ('_' in qc.mo_spec[i]['spin']) elif '<MO Number>' in line: index = int(flines[il + 1]) - 1 for i in range(ao_num): qc.mo_spec[index]['coeffs'][i] = float(flines[il + 3 + i]) elif '</' in line: sec_flag = None elif sec_flag is not None: if sec_flag == 'ao_center': for i in line.split(): qc.ao_spec[count]['atom'] = int(i) - 1 count += 1 if sec_flag == 'ao_type': for i in line.split(): qc.ao_spec[count]['lxlylz'] = lxlylz[int(i) - 1][numpy.newaxis] qc.ao_spec[count]['type'] = orbit[sum(lxlylz[int(i) - 1])] count += 1 if sec_flag == 'ao_exp': for i in line.split(): qc.ao_spec[count]['coeffs'] = numpy.array([[float(i), 1.0]]) count += 1 has_alpha = any([i['spin'] == 'alpha' for i in qc.mo_spec]) has_beta = any([i['spin'] == 'beta' for i in qc.mo_spec]) spin_check(spin, restricted, has_alpha, has_beta) qc.select_spin(restricted, spin=spin) # Remove numbers from atom names for i in qc.geo_info: i[0] = ''.join([k for k in i[0] if not k.isdigit()]) # Convert geo_info and geo_spec to numpy.ndarrays qc.format_geo() qc.mo_spec.update() qc.ao_spec.update() return qc
def read_gaussian_fchk(fname, all_mo=False, spin=None, **kwargs): '''Reads all information desired from a Gaussian FChk file. **Parameters:** fname: str, file descriptor Specifies the filename for the input file. fname can also be used with a file descriptor instad of a filename. all_mo : bool, optional If True, all molecular orbitals are returned. **Returns:** qc (class QCinfo) with attributes geo_spec, geo_info, ao_spec, mo_spec, etot : See :ref:`Central Variables` for details. ''' if isinstance(fname, str): filename = fname fname = descriptor_from_file(filename, index=0) else: filename = fname.name flines = fname.readlines() # Read the WHOLE file into RAM if isinstance(fname, str): fname.close() # Leave existing file descriptors alive # Is this an unrestricted calculation? has_beta = False is_6D = False is_10F = False for line in flines: if 'beta mo coefficients' in line.lower(): has_beta = True if 'Pure/Cartesian d shells' in line: is_6D = int(line.split()[-1]) == 1 if 'Pure/Cartesian f shells' in line: is_10F = int(line.split()[-1]) == 1 cartesian_basis = (is_6D and is_10F) if ((not is_6D) and is_10F) or (is_6D and (not is_10F)): raise IOError('Please apply a Spherical Harmonics (5D, 7F) or '+ 'a Cartesian Gaussian Basis Set (6D, 10F)!') if spin is not None: if spin != 'alpha' and spin != 'beta': raise IOError('`spin=%s` is not a valid option' % spin) elif has_beta: display('Reading only molecular orbitals of spin %s.' % spin) else: raise IOError('The keyword `spin` is only supported for unrestricted calculations.') restricted = (not has_beta) sec_flag = None el_num = [0,0] mo_i0 = {'alpha': 0, 'beta': 0} what = 'alpha' index = 0 at_num = 0 ao_num = 0 ao_sp_coeffs = {} switch = 0 qc = QCinfo() qc.geo_info = [[],[],[]] if not cartesian_basis: qc.ao_spherical = [] # Go through the file line by line for il in range(len(flines)): line = flines[il] # The current line as string thisline = line.split() # The current line split into segments # Check the file for keywords if 'Number of alpha electrons' in line: el_num[0] = int(thisline[5]) elif 'Number of beta electrons' in line: el_num[1] = int(thisline[5]) elif 'Number of basis functions' in line: basis_number = int(thisline[5]) elif 'Atomic numbers' in line: sec_flag = 'geo_info' index = 0 at_num = int(thisline[-1]) count = 0 qc.geo_info[1] = list(range(1,at_num+1)) elif 'Nuclear charges' in line: sec_flag = 'geo_info' index = 2 at_num = int(thisline[-1]) count = 0 elif 'Total Energy' in line: qc.etot = float(thisline[3]) elif 'Current cartesian coordinates' in line: at_num = int(thisline[-1])/3 sec_flag = 'geo_pos' qc.geo_spec = [] count = 0 xyz = [] elif 'Shell types' in line: sec_flag = 'ao_info' index = 'type' ao_num = int(thisline[-1]) count = 0 if qc.ao_spec == []: for ii in range(ao_num): qc.ao_spec.append({}) elif 'Number of primitives per shell' in line: sec_flag = 'ao_info' index = 'pnum' ao_num = int(thisline[-1]) count = 0 if qc.ao_spec == []: for ii in range(ao_num): qc.ao_spec.append({}) elif 'Shell to atom map' in line: sec_flag = 'ao_info' index = 'atom' ao_num = int(thisline[-1]) count = 0 if qc.ao_spec == []: for ii in range(ao_num): qc.ao_spec.append({}) elif 'Primitive exponents' in line: sec_flag = 'ao_coeffs' ao_num = int(thisline[-1]) count = 0 switch = 0 index = 0 if qc.ao_spec == []: raise IOError('Shell types need to be defined before the AO exponents!') if not 'coeffs' in qc.ao_spec[0].keys(): for ii in range(len(qc.ao_spec)): pnum = qc.ao_spec[ii]['pnum'] qc.ao_spec[ii]['coeffs'] = numpy.zeros((pnum, 2)) elif 'Contraction coefficients' in line: if 'P(S=P)' not in line: sec_flag = 'ao_coeffs' else: sec_flag = 'ao_sp_coeffs' ao_sp_coeffs = {0: []} ao_num = int(thisline[-1]) count = 0 switch = 1 index = 0 if qc.ao_spec == []: raise IOError('Shell types need to be defined before the AO exponents!') if not 'coeffs' in qc.ao_spec[0].keys(): for ii in range(len(qc.ao_spec)): pnum = qc.ao_spec[ii]['pnum'] qc.ao_spec[ii]['coeffs'] = numpy.zeros((pnum, 2)) elif 'Orbital Energies' in line: sec_flag = 'mo_eorb' mo_num = int(thisline[-1]) mo_i0[thisline[0].lower()] = len(qc.mo_spec) if restricted: if el_num[0] == el_num[1]: i = el_num[0] occ = 2 else: i = el_num[0 if 'Alpha' in line else 1] occ = 1 else: i = el_num[0 if 'Alpha' in line else 1] occ = 1 for ii in range(mo_num): qc.mo_spec.append({'coeffs': numpy.zeros(basis_number), 'energy': 0.0, 'occ_num': float(occ if ii < i else 0), 'sym': '%i.1' % (ii+1), 'spin':thisline[0].lower() }) elif 'MO coefficients' in line: sec_flag = 'mo_coeffs' count = 0 index = 0 mo_num = int(thisline[-1]) what = thisline[0].lower() else: # Check if we are in a specific section if sec_flag == 'geo_info': for ii in thisline: qc.geo_info[index].append(ii) count += 1 if count == at_num: sec_flag = None elif sec_flag == 'geo_pos': for ii in thisline: xyz.append(float(ii)) if len(xyz) == 3: qc.geo_spec.append(xyz) xyz = [] count += 1 if count == at_num: sec_flag = None elif sec_flag == 'ao_info': for ii in thisline: ii = int(ii) if index is 'type': ii = orbit[abs(ii)] l = lquant[ii] if not cartesian_basis: for m in (range(0,l+1) if l != 1 else [1,0]): qc.ao_spherical.append([count,(l,m)]) if m != 0: qc.ao_spherical.append([count,(l,-m)]) elif index is 'atom': ii -= 1 qc.ao_spec[count][index] = ii count += 1 if count == ao_num: sec_flag = None elif sec_flag == 'ao_coeffs': for ii in thisline: qc.ao_spec[index]['coeffs'][count,switch] = float(ii) count += 1 ao_num -= 1 if count == qc.ao_spec[index]['pnum']: index += 1 count = 0 if not ao_num: sec_flag = None elif sec_flag == 'ao_sp_coeffs': for ii in thisline: ao_sp_coeffs[index].append(float(ii)) count += 1 ao_num -= 1 if count == qc.ao_spec[index]['pnum']: index += 1 ao_sp_coeffs[index] = [] count = 0 if not ao_num: sec_flag = None elif sec_flag == 'mo_eorb': for ii in thisline: qc.mo_spec[count]['energy'] = float(ii) count += 1 if index != 0 and not count % basis_number: sec_flag = None elif sec_flag == 'mo_coeffs': for ii in thisline: qc.mo_spec[mo_i0[what]+index]['coeffs'][count] = float(ii) count += 1 if count == basis_number: count = 0 index += 1 if index != 0 and not index % basis_number: sec_flag = None # Look for SP atomic orbitals if ao_sp_coeffs: ao_new = [] for i,ao in enumerate(qc.ao_spec): if ao['type'] == 'p' and sum(numpy.abs(ao_sp_coeffs[i])) > 0: ao_new.append(copy.deepcopy(ao)) ao_new[-1]['type'] = 's' ao_new.append(ao) ao_new[-1]['type'] = 'p' ao_new[-1]['coeffs'][:,1] = numpy.array(ao_sp_coeffs[i]) else: ao_new.append(ao) qc.ao_spec = ao_new # Are all MOs requested for the calculation? if not all_mo: for i in range(len(qc.mo_spec))[::-1]: if qc.mo_spec[i]['occ_num'] < 0.0000001: del qc.mo_spec[i] # Only molecular orbitals of one spin requested? if spin is not None: for i in range(len(qc.mo_spec))[::-1]: if qc.mo_spec[i]['spin'] != spin: del qc.mo_spec[i] if restricted: # Closed shell calculation for mo in qc.mo_spec: del mo['spin'] else: # Rename MOs according to spin for mo in qc.mo_spec: mo['sym'] += '_%s' % mo['spin'][0] # Check for natural orbital occupations energy_sum = sum([abs(i['energy']) for i in qc.mo_spec]) if energy_sum < 0.0000001: display('Attention!\n\tThis FChk file contains natural orbitals. '+ '(There are no energy eigenvalues.)\n\t' + 'In this case, Gaussian does not print the respective natural' + 'occupation numbers!' ) qc.geo_info = numpy.array(qc.geo_info).T # Convert geo_info and geo_spec to numpy.ndarrays qc.format_geo(is_angstrom=False) return qc