Ejemplo n.º 1
0
def save_hdf5(fid,
              variables=[
                  'geo_info', 'geo_spec_all', 'ao_spec', 'ao_spherical',
                  'mo_coeff_all', 'mo_energy_all', 'mo_occ_all', 'sym',
                  'index_list'
              ],
              hdf5mode='w',
              **kwargs):
    '''Writes all global variables specified in :literal:`variables` and all
  additional :literal:`kwargs` to an HDF5 file. 
  '''

    from orbkit.output import hdf5_open, hdf5_append

    # Save HDF5 File
    display('Saving Hierarchical Data Format file (HDF5) to %s...' % fid)
    data_stored = []
    for HDF5_file in hdf5_open(fid, mode=hdf5mode):
        for i in variables:
            if i in globals():
                data = globals()[i]
                if not (data == [] or data is None):
                    if i == 'sym':
                        data = numpy.array([[k, l] for k, l in data.items()])
                    hdf5_append(data, HDF5_file, name=i)
                    data_stored.append(i)
            elif i not in kwargs:
                raise ValueError(
                    'Variable `%s` is not in globals() or in **kwargs' % i)

        for j in kwargs.keys():
            hdf5_append(kwargs[j], HDF5_file, name=j)
            data_stored.append(j)

    display('\tContent: ' + ', '.join(data_stored))
Ejemplo n.º 2
0
def read_hdf5(fid,
              variables=[
                  'geo_info', 'geo_spec_all', 'ao_spec', 'ao_spherical',
                  'mo_coeff_all', 'mo_energy_all', 'mo_occ_all', 'sym',
                  'index_list'
              ]):
    '''Reads all variables specified in :literal:`variables` from an HDF5 file
  created with :literal:`write_hdf5` and appends this data to the globals() of 
  this module. 
  '''

    from orbkit.output import hdf5_open, hdf52dict

    # Read HDF5 File
    display('Reading Hierarchical Data Format file (HDF5) File from %s' % fid)
    data_stored = []
    for HDF5_file in hdf5_open(fid, mode='r'):
        for i in variables:
            try:
                globals()[i] = hdf52dict(i, HDF5_file)
                data_stored.append(i)
                if i == 'sym':
                    s = dict(globals()[i])
                    globals()[i] = {}
                    for k, l in s.items():
                        globals()[i][k] = int(l)
            except KeyError:
                pass

    if not data_stored:
        raise IOError(
            'Could not find any data in `%s` for the selected `variables`.' %
            fid)

    display('\tFound: ' + ', '.join(data_stored))
Ejemplo n.º 3
0
def fermions_stda(fname, select_state=None, threshold=0.0, **kwargs):
    '''Reads FermiONs++ TDDFT output. 
  
  **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.
    select_state : None or list of int, optional
      If not None, specifies the states to be read (0 corresponds to the ground 
      state), else read all electronic states.
    threshold : float, optional
      Specifies a read threshold for the CI coefficients.
  
  **Returns:**
  
    ci : list of CIinfo class instances
      See :ref:`Central Variables` for details.
  '''
    display('\nReading data of simplified TDA calculation from FermiONs++...')
    return fermions_tdscf(fname,
                          td_typ='stda',
                          st_typ='singlet',
                          select_state=select_state,
                          threshold=threshold,
                          **kwargs)
Ejemplo n.º 4
0
def hx_network_creator(rho, filename):
    '''Creates a ZIBAmira hx-network file including a colormap file (.cmap)
  adjusted to the density for the easy depiction of the density.
  '''
    from .hx_network_draft import hx_network
    filename += '.hx' if not filename.endswith('.hx') else ''

    # Create a .cmap colormap file using the default values
    display('\tCreating ZIBAmira colormap file...\n\t\t' +
            filename.replace('.hx', '.cmap'))

    assert (rho.shape != tuple(grid.N_)), 'The grid does not fit the data.'

    colormap_creator(rho, filename.replace('.hx', '.cmap'))

    # Create a .hx network file based on the file orbkit.hx_network_draft.py
    # Open an empty file

    fid = open(filename, 'w')

    # Copy the content of the draft file and replace the keywords
    fid.write(
        hx_network.replace("FILENAME",
                           os.path.splitext(os.path.basename(filename))[0]))

    # Close the file
    fid.close()
Ejemplo n.º 5
0
def hx_network_creator(rho, filename):
    '''Creates a ZIBAmira hx-network file including a colormap file (.cmap)
  adjusted to the density for the easy depiction of the density.
  '''
    from orbkit.hx_network_draft import hx_network
    # Create a .cmap colormap file using the default values
    display('\tCreating ZIBAmira colormap file...\n\t\t%(f)s.cmap' %
            {'f': filename})

    AssertionError(
        rho.shape != tuple(grid.N_)), 'The grid does not fit the data.'

    colormap_creator(rho, filename)

    # Create a .hx network file based on the file orbkit.hx_network_draft.py
    display('\tCreating ZIBAmira network file...\n\t\t%(f)s.hx' %
            {'f': filename})
    # Open an empty file
    fid = open('%(f)s.hx' % {'f': filename}, 'w')

    filename = filename.split('/')[-1]
    # Copy the content of the draft file and replace the keywords
    fid.write(hx_network.replace("FILENAME", filename))

    # Close the file
    fid.close()
Ejemplo n.º 6
0
def main_read(fname,
              all_mo=False,
              spin=None,
              itype='auto',
              check_norm=False,
              **kwargs):
    '''
  This is the high-lever interface for the
  orbkit reading routines.
  
  **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.
  itype : str, optional
    Can be used to manually specify the input filetype.
  check_norm : bool, optional
    If True, ORBKIT verifies that molecular orbitals are orthonormal.
    
  **Note:**
  
    All additional keyword arguments are forwarded to the reading functions.
    
  **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
    else:
        filename = fname.name

    if itype == 'auto':
        itype = find_itype(fname)

    display('Loading data from {0} type file {1}\n'.format(itype, filename))

    qc = readers[itype](fname, all_mo=all_mo, spin=spin, **kwargs)

    if check_norm:
        deviation = check_mo_norm(qc)
        if deviation >= 1e-5:
            raise ValueError(
                'Bad molecular orbital norm: {0:%4e}'.format(deviation))

    return qc
Ejemplo n.º 7
0
 def check_sel(count,i,interactive=False):
   if count == 0:
     raise IndexError
   elif count == 1:
     return 0
   message = '\tPlease give an integer from 0 to %d: ' % (count-1)
   
   try:
     if interactive:
       i = int(raw_input(message))
     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
Ejemplo n.º 8
0
def hdf5_attributes(filename, gname='', **attrs):
  warning = []
  for f in hdf5_open(filename,mode='a'):
    for key,value in attrs.items():
      if isinstance(value,dict):
        for k,v in value.items():
          if k in f[gname].keys():
            f[os.path.join(gname,key)].attrs[k] = v
          else:
            warning.append(key)
      else:
        if key in f[gname].keys():
          f[os.path.join(gname,'data')].attrs[key] = value
        else:
          warning.append('data')
  if warning:
    display('Warning: The following attributes are not datasets in '+filename)
    display(', '.join([os.path.join(gname,i) for i in data]))
Ejemplo n.º 9
0
def order_pm(x, y, backward=True, mu=1e-1, use_factor=False):
    '''Outdated function to order exclusively the sign of a data set.
  '''
    if backward:
        st = [-2, 1, -1]
    else:
        st = [1, -2, 1]

    if numpy.ndim(y) == 1:
        diff = numpy.zeros(2)
        for rr in range(len(y))[st[0]:st[1]:st[2]]:
            m = (y[rr + st[2]] - y[rr]) / (x[rr + st[2]] - x[rr])
            epol = m * (x[rr + 2 * st[2]] - x[rr]) + y[rr]
            for ii_d in range(2):
                diff[ii_d] = (((-1)**ii_d * y[rr + 2 * st[2]]) - epol)**2
            if numpy.argmin(numpy.abs(diff)) == 1:
                y[rr + 2 * st[2]] = -y[rr + 2 * st[2]]
    elif numpy.ndim(y) == 2:
        y = numpy.array(y)
        shape = numpy.shape(y)
        for rr in range(shape[0])[st[0]:st[1]:st[2]]:
            for ii_s, sign in [(0, -1), (1, +1)]:
                f = numpy.ones(shape[1])
                if use_factor:
                    f[numpy.abs(y[rr, :]) > mu] = 1 / numpy.abs(
                        y[rr, numpy.abs(y[rr, :]) > mu])
                m = (y[rr + st[2], :] - y[rr, :]) / (x[rr + st[2]] - x[rr])
                epol = f[:] * (m * (x[rr + 2 * st[2]] - x[rr]) + y[rr, :])
                # Euclidean norm (2 norm)
                current = numpy.sum(
                    (f[:] * sign * y[rr + 2 * st[2], :] - epol[:])**2)
                # Current value
                if ii_s == 0:
                    diff = current
                    new_sign = sign
                elif current < diff:
                    new_sign = sign
            y[rr + 2 * st[2], :] *= new_sign

    else:
        display('Function order_pm only works for vectors and 2D matrices')
    return y
Ejemplo n.º 10
0
def test():

    ts = unittest.TestSuite()

    display(
        '----------------------------------------------------------------------'
    )
    display(
        '                     Testing ORBKIT functionality                     '
    )
    display(
        '----------------------------------------------------------------------\n'
    )

    tsrun = unittest.TextTestRunner(verbosity=2)

    tests_home = __file__.split('__')[0] + 'test/'

    for test in tests:
        ts.addTest(ScriptTestCase(filename=os.path.abspath(tests_home + test)))

    testdir = tests_home + 'test_tmp'
    clean(testdir)
    os.mkdir(testdir)
    os.chdir(testdir)

    results = tsrun.run(ts)
    clean(testdir)

    sys.exit(len(results.errors + results.failures))
Ejemplo n.º 11
0
 def plot(self,mo_matrix,symmetry='1',title='All',x_label='index',
          y_label='MO coefficients',output_format='png',
          plt_dir='Plots',ylim=None,thresh=0.1,x0=0,grid=True,x_grid=None,**kwargs):
   '''Plots all molecular orbital coefficients of one self.symmetry.'''
   import pylab as plt
   from matplotlib.ticker import MultipleLocator
   import os
   
   display('Plotting data of self.symmetry %s to %s/' % (symmetry,plt_dir))
   if not os.path.exists(plt_dir):
     os.makedirs(plt_dir)
   
   if numpy.ndim(mo_matrix) == 2:
     mo_matrix = mo_matrix[:,numpy.newaxis,:]
   
   shape = numpy.shape(mo_matrix)
   
   
   def plot_mo(i):
     fig=plt.figure()
     plt.rc('xtick', labelsize=16) 
     plt.rc('ytick', labelsize=16)
     ax = plt.subplot(111)
     curves=[]
     for ij in range(shape[2]):
       Y = mo_matrix[:,i,ij]
       if x_grid is None:
         X = numpy.arange(len(Y))+x0
       else:
         X = x_grid
       if max(numpy.abs(Y)) > thresh:
         curves.append(ax.plot(X,Y, '.-' ,linewidth=1.5))
     
     
     plt.xlabel(x_label, fontsize=16);
     plt.ylabel(y_label, fontsize=16);
     plt.title('%s: %d.%s'%  (title,i+1,symmetry))
     plt.ylim(ylim)
     
     plt.tight_layout()
     return fig
   
   if output_format == 'pdf':
     from matplotlib.backends.backend_pdf import PdfPages
     output_fid = '%s.%s.pdf'% (title,symmetry.replace(' ','_'))
     display('\t%s' % output_fid)
     with PdfPages(os.path.join(plt_dir,output_fid)) as pdf:
       for i in range(shape[1]):
         fig = plot_mo(i)
         pdf.savefig(fig,**kwargs)
         plt.close()
   elif output_format == 'png':
     for i in range(shape[1]):
       fig = plot_mo(i)
       output_fid = '%d.%s.png' % (i+1,symmetry.replace(' ','_'))
       display('\t%s' % output_fid)
       fig.savefig(os.path.join(plt_dir, output_fid),format='png',**kwargs)
       plt.close()
   else:
     raise ValueError('output_format `%s` is not supported' % output_format)
Ejemplo n.º 12
0
def spin_check(spin, restricted, has_alpha, has_beta):
    '''Check if `spin` keyword is valid.
  '''
    if spin is not None:
        if restricted:
            raise IOError(
                'The keyword `spin` is only supported for unrestricted calculations.'
            )
        if spin != 'alpha' and spin != 'beta':
            raise IOError('`spin=%s` is not a valid option' % spin)
        elif spin == 'alpha' and has_alpha:
            display('Reading only molecular orbitals of spin alpha.')
        elif spin == 'beta' and has_beta:
            display('Reading only molecular orbitals of spin beta.')
        elif (not has_alpha) and (not has_beta):
            raise IOError(
                'Molecular orbitals in the input file do not contain `Spin=` keyword'
            )
        elif ((spin == 'alpha' and not has_alpha)
              or (spin == 'beta' and not has_beta)):
            raise IOError(
                'You requested `%s` orbitals, but None of them are present.' %
                spin)
Ejemplo n.º 13
0
def mo_transition_flux_density(i,j,qc,drv='x',
                    ao_list=None,mo_list=None,
                    delta_ao_list=None,delta_mo_list=None):
  '''Calculate one component (e.g. drv='x') of the 
  transition electoronic flux density between the 
  molecular orbitals i and j.
  
  .. math::
  
        moTEFD_{i,j}(r) = <mo_i|\delta(r-r')\\nabla_x|mo_j>
    
  **Parameters:**
  
     i: int
        index of the first mo (Bra)
     j: int
        index of the second mo (Ket)
     drv: {0,1,2,'x','y','z'}
        The desired component of the vector field of the 
        transition electoronic flux density

  **Returns:**
  
     mo_tefd : numpy.ndarray
  '''  
  if mo_list is None:
    if ao_list is None:
      display('\tComputing ao_list and ' +
                    'mo #%d, since it is not given.' % i)
      ao_list = core.ao_creator(qc.geo_spec,qc.ao_spec)  
    else:
      display('\tComputing mo #%d, since it is not given.' % i)
    mo = core.mo_creator(ao_list,[qc.mo_spec[i]])[0]
  else:
    mo = mo_list[i]
  if delta_mo_list is None:
    if delta_ao_list is None:
      display('\tComputing delta_ao_list and the derivative of ' +
                    'mo #%d, since it is not given.' % j)
      delta_ao_list = core.ao_creator(qc.geo_spec,qc.ao_spec,drv=drv)
    else:
      display('\tComputing mo #%d, since it is not given.' % j)
    delta_mo = core.mo_creator(delta_ao_list,[qc.mo_spec[j]])[0]
  else:
    delta_mo = delta_mo_list[i]
  
  return mo*delta_mo
Ejemplo n.º 14
0
def numerical_mulliken_charges(atom,
                               qc,
                               ao_list=None,
                               mo_list=None,
                               rho_atom=None):
    r'''Compute the Mulliken charges and gross atomic populations of the selected 
  atoms *numerically* using the respective gross atomic densities.
  
  .. math::
  
    P^a = \int \rho^a(x,y,z) {\rm d}^3r
  
  **Parameters:**
  
    atom : 'all' or int or list of int
      Specifies the atom (numbering starting from one) to which the numerical 
      Mulliken charges and gross populations will be computed. 
      If (atom == 'all') or (atom == -1), computes the charges and populations 
      for all atoms.
  
  **Returns:**
  
    rho_atom : list of numpy.ndarrays, shape=(len(atoms,) + N)
      Contains the atom gross atomic density on a grid.
    mulliken_num : dict, (present if not is_vector)
      Contains information of Mulliken charge analysis and has following members:
        :population: - Mulliken population for each atom.
        :charges: - Mulliken charges for each atom.
  '''

    if (atom == 'all' or atom == -1 or atom == [-1]):
        atom = range(1, len(qc.geo_info) + 1)

    atom, index = atom2index(atom, geo_info=qc.geo_info)

    rho_atom = gross_atomic_density(atom, qc, ao_list=ao_list, mo_list=mo_list)

    if grid.is_vector:
        display('Warning: You have applied a vector grid.\n' +
                'The integration is not implemented for such a grid!\n' +
                '\nReturning only the gross atomic densities...')
        return rho_atom

    GP_A = numpy.array([core.integration(i) for i in rho_atom])
    mulliken_num = {
        'population': GP_A,
        'charge': numpy.array(qc.geo_info[:, 2], dtype=float) - GP_A
    }

    display('\nNumerical Mulliken Charges Q and Gross Atomic Populations GP:')
    for i, a in enumerate(index):
        a = int(a)
        display('\tAtom %s (%s):\tQ = %+0.4f ( GP = %0.4f )' %
                (qc.geo_info[a][1], qc.geo_info[a][0],
                 mulliken_num['charge'][i], mulliken_num['population'][i]))
    return rho_atom, mulliken_num
Ejemplo n.º 15
0
def order_using_analytical_overlap(fid_list,
                                   itype='molden',
                                   deg=0,
                                   numproc=1,
                                   **kwargs):
    '''Performs an ordering routine using analytical overlap integrals between 
  molecular orbitals. Set fid_list to None to omit the reading of input files.
  
  If :literal:`deg` is set to a value larger than zero, the molecular orbital 
  coefficients are extrapolated with a polynomial of degree :literal:`deg`,
  before computing the molecular orbital overlap matrix.
  
  **Paramerters:**
  
  fid_list : list of str or None
    If not None, it contains the list of input file names.
  itype : str, choices={'molden', 'gamess', 'gaussian.log', 'gaussian.fchk'}
    Specifies the type of the input files.
  deg : int, optional
    If greater than zero, specifies the degree of the extrapolation polynomial
    for the molecular orbital coefficients.  
  
  **Returns:**
  
  index_list : numpy.ndarray, shape=(Nfiles,NMO)
    Contains the new indices of the molecular orbitals. If index < 0, the 
    molecular orbital changes its sign.
  mo_overlap : numpy.ndarray, shape=((Nfiles - 1),NMO,NMO)
    Contains the overlap matrix between the molecular orbitals of two neighboring
    geometries, i.e., mo_overlap[i,j,k] corresponds to overlap between the 
    jth molecular orbital at geometry i to the kth molecular orbital at 
    geometry (i+1).
  
  **Global Variables:**
  
  geo_spec_all, geo_info, ao_spec, ao_spherical, mo_coeff_all, mo_energy_all, mo_occ_all, sym, index_list
  '''
    global geo_spec_all, geo_info, ao_spec, ao_spherical, mo_coeff_all, mo_energy_all, mo_occ_all, sym, index_list

    if fid_list is not None:
        read(fid_list, itype=itype, **kwargs)

    display(
        '\nStarting the ordering routine using the molecular orbital overlap...'
    )

    iterate = list(range(1, len(geo_spec_all)))

    if deg > 0:
        display('\tThe molecular orbital coefficients will be extrapolated')
        display('\tusing a least squares polynomial fit of degree %d.' % deg)
        std = numpy.array(
            [numpy.std(i - geo_spec_all[0]) for i in geo_spec_all])

    mo_overlap = [[] for i in sym.keys()]
    index_list = [[] for i in sym.keys()]

    for s in sym.values():
        shape = numpy.shape(mo_coeff_all[s])
        index_list[s] = numpy.ones((shape[0], shape[1]), dtype=int)
        index_list[s] *= numpy.arange(shape[1], dtype=int)

    c = 0
    t = time()
    for rr in iterate:
        r1 = rr - 1
        r2 = rr

        if (deg is None) or (deg > 0 and r1 >= deg):
            ao_overlap = get_ao_overlap(geo_spec_all[r2],
                                        geo_spec_all[r2],
                                        ao_spec,
                                        ao_spherical=ao_spherical)
        else:
            ao_overlap = get_ao_overlap(geo_spec_all[r1],
                                        geo_spec_all[r2],
                                        ao_spec,
                                        ao_spherical=ao_spherical)

        cs = 0
        for s in sym.values():
            mo_coeff = mo_coeff_all[s]
            shape = numpy.shape(mo_coeff)
            if deg is not None and deg > 0 and r1 >= deg:
                mo_r1 = get_extrapolation(r1,
                                          r2,
                                          mo_coeff,
                                          grid1d=std,
                                          deg=deg)
            else:
                mo_r1 = mo_coeff[r1]
            overlap = get_mo_overlap_matrix(mo_r1,
                                            mo_coeff[r2],
                                            ao_overlap,
                                            numproc=numproc)
            for i in range(shape[1]):
                # Iterate the rows of the overlap matrix
                line_max = None  # variable for maximum value in the current row
                line_sort = numpy.argsort(numpy.abs(
                    overlap[i, :]))[::-1]  # sort the row
                for k in line_sort[::-1]:
                    # Is this value the maximum in the current column?
                    col_max = numpy.argmax(numpy.abs(overlap[:, k]))
                    if i == col_max:
                        line_max = k
                        break
                if line_max is not None:
                    # Interchange the coefficients
                    mo_coeff[r2, [i, line_max], :] = mo_coeff[r2,
                                                              [line_max, i], :]
                    overlap[:, [i, line_max]] = overlap[:, [line_max, i]]
                    index_list[s][r2,
                                  [i, line_max]] = index_list[s][r2,
                                                                 [line_max, i]]

            for i in range(shape[1]):
                # Change the signs
                mo_coeff[r2, i, :] *= numpy.sign(overlap[i, i])
                overlap[:, i] *= numpy.sign(overlap[i, i])
                index_list[s][r2, i] *= numpy.sign(overlap[i, i])

            mo_overlap[cs].append(overlap)
            cs += 1

            mo_coeff_all[s] = mo_coeff

            index = numpy.abs(index_list[s])[r2, :]
            mo_energy_all[s][r2, :] = mo_energy_all[s][r2, index]
            mo_occ_all[s][r2, :] = mo_occ_all[s][r2, index]

        c += 1
        #if not c % int(numpy.ceil(len(iterate)/10.)):
        display('\tFinished %d of %d geometries (%.1f s)' %
                (c, len(iterate), time() - t))
        t = time()

    tmp = []
    for i in mo_overlap:
        tmp.append(numpy.array(i))

    mo_overlap = tmp

    return index_list, mo_overlap
Ejemplo n.º 16
0
def read_gamess(fname,
                all_mo=False,
                spin=None,
                read_properties=False,
                **kwargs):
    '''Reads all information desired from a Gamess-US output 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

    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()

    # Initialize the variables
    qc = QCinfo()
    qc.ao_spec = AOClass([])
    qc.mo_spec = MOClass([])
    has_alpha = False  # Flag for alpha electron set
    has_beta = False  # Flag for beta electron set
    restricted = True  # Flag for restricted calculation
    sec_flag = None  # A Flag specifying the current section
    is_pop_ana = True  # Flag for population analysis for ground state
    keyword = [' ATOM      ATOMIC                      COORDINATES', '']
    # Keywords for single point calculation and
    # geometry optimization
    mokey = 'EIGENVECTORS'  # Keyword for MOs
    unrestopt = False  # Flag for unrestricted optimization
    bopt = False  # Flag for geometry optimization
    sym = {}  # Symmetry of MOs
    geo_skip = 1  # Number of lines to skip in geometry section

    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 'RUNTYP=OPTIMIZE' in line:
            keyword = [
                ' COORDINATES OF ALL ATOMS ARE',
                '***** EQUILIBRIUM GEOMETRY LOCATED *****'
            ]
            geo_skip = 2
            bopt = True
            if 'SCFTYP=UHF' in line:
                mokey = ' SET ****'
                restricted = False
            else:
                mokey = 'EIGENVECTORS'

        elif keyword[0] in line and keyword[1] in flines[il - 1]:
            # The section containing information about
            # the molecular geometry begins
            sec_flag = 'geo_info'
            atom_count = 0  # Counter for Atoms
            angstrom = not '(BOHR)' in line

        elif 'ATOMIC BASIS SET' in line:
            # The section containing information about
            # the atomic orbitals begins
            sec_flag = 'ao_info'
            ao_skip = 6  # Number of lines to skip
            AO = []  # Atomic orbitals

        elif '----- ALPHA SET ' in line:
            # The section for alpha electrons
            has_alpha = True
            has_beta = False
            restricted = False

        elif '----- BETA SET ' in line:
            # The section for alpha electrons
            restricted = False
            has_alpha = False
            has_beta = True

        elif mokey in line and len(thisline) < 3:
            # The section containing information about
            # the molecular orbitals begins
            sec_flag = 'mo_info'
            mo_skip = 1
            len_mo = 0  # Number of MOs
            init_mo = False  # Initialize new MO section
            info_key = None  # A Flag specifying the energy and symmetry section
            lxlylz = []
            if 'ALPHA' in line:
                has_alpha = True
                mo_skip = 0
            elif 'BETA' in line:
                has_beta = True
                has_alpha = False
                mo_skip = 0

        elif 'NATURAL ORBITALS' in line and len(thisline) <= 3:
            display('The natural orbitals are not extracted.')

        elif ' NUMBER OF OCCUPIED ORBITALS (ALPHA)          =' in line:
            occ = []  # occupation number of molecular orbitals
            occ.append(int(thisline[-1]))
        elif ' NUMBER OF OCCUPIED ORBITALS (BETA )          =' in line:
            occ.append(int(thisline[-1]))


#      elif 'ECP POTENTIALS' in line:
#        sec_flag = 'ecp_info'
#        ecp = ''
        elif ' NUMBER OF OCCUPIED ORBITALS (ALPHA) KEPT IS    =' in line:
            occ = []  # occupation number of molecular orbitals
            occ.append(int(thisline[-1]))
        elif ' NUMBER OF OCCUPIED ORBITALS (BETA ) KEPT IS    =' in line:
            occ.append(int(thisline[-1]))
        elif 'NUMBER OF STATES REQUESTED' in line and read_properties:
            # get the number of excited states and initialize variables for
            # transition dipole moment and energies
            exc_states = int(line.split('=')[1])  # Number of excited states
            # Dipole moments matrix: Diagonal elements -> permanent dipole moments
            # Off-diagonal elements -> transition dipole moments
            qc.dipole_moments = numpy.zeros(
                ((exc_states + 1), (exc_states + 1), 3))
            # Multiplicity of ground and excited states
            qc.states['multiplicity'] = numpy.zeros(exc_states + 1)
            # Energies of ground and excited states
            qc.states['energy'] = numpy.zeros(exc_states + 1)
            qc.states['energy'][0] = qc.etot
            qc.states['multiplicity'][0] = gs_multi
            dm_flag = None  # Flag specifying the dipole moments section
        elif 'TRANSITION DIPOLE MOMENTS' in line and read_properties:
            # Section containing energies of excited states
            sec_flag = 'dm_info'
            # Energy and Multiplicity for ground state
        elif 'SPIN MULTIPLICITY' in line and read_properties:
            # odd way to get gound state multiplicity
            gs_multi = int(line.split()[3])
        elif 'FINAL' in line and read_properties:
            # get (last) energy
            qc.etot = float(line.split()[4])
        elif 'TOTAL MULLIKEN AND LOWDIN ATOMIC POPULATIONS' in line and is_pop_ana == True and read_properties:
            # Read Mulliken and Lowdin Atomic Populations
            sec_flag = 'pop_info'
            pop_skip = 1
            is_pop_ana == False
            qc.pop_ana['Lowdin'] = []
            qc.pop_ana['Mulliken'] = []
        else:
            # Check if we are in a specific section
            if sec_flag == 'geo_info':
                if not geo_skip:
                    if len(line) < 2:
                        sec_flag = None
                    else:
                        qc.geo_info.append(
                            [thisline[0], atom_count + 1, thisline[1]])
                        qc.geo_spec.append([float(ii) for ii in thisline[2:]])
                        atom_count += 1
                elif geo_skip:
                    geo_skip -= 1

            elif sec_flag == 'ao_info':
                if not ao_skip:
                    if ' TOTAL NUMBER OF BASIS SET SHELLS' in line:
                        sec_flag = None
                    else:
                        if len(thisline) == 1:
                            # Read atom type
                            at_type = thisline[0]
                            AO.append([])
                            new_ao = False
                        elif len(thisline) == 0 and new_ao == False:
                            new_ao = True
                        else:
                            coeffs = [float(ii) for ii in thisline[3:]]
                            if new_ao:
                                ao_type = thisline[1].lower().replace(
                                    'l', 'sp')
                                for i_ao, t_ao in enumerate(ao_type):
                                    AO[-1].append({
                                        'atom_type':
                                        at_type,
                                        'type':
                                        t_ao,
                                        'pnum':
                                        1,
                                        'coeffs':
                                        [[coeffs[0], coeffs[1 + i_ao]]]
                                    })
                                new_ao = False
                            else:
                                for i_ao in range(len(ao_type)):
                                    AO[-1][-len(ao_type) +
                                           i_ao]['coeffs'].append(
                                               [coeffs[0], coeffs[1 + i_ao]])
                                    AO[-1][-len(ao_type) + i_ao]['pnum'] += 1
                elif ao_skip:
                    ao_skip -= 1
            elif sec_flag == 'mo_info':
                if not mo_skip:
                    if 'END OF' in line and 'CALCULATION' in line or '-----------' in line:
                        sec_flag = None
                        has_alpha = False
                        has_beta = False
                    else:
                        if thisline == []:
                            info_key = None
                            init_mo = True
                            try:
                                int(flines[il + 1].split()[0])
                            except ValueError:
                                sec_flag = None
                                init_mo = False
                        elif init_mo:
                            init_len = len(thisline)
                            lxlylz = []
                            for ii in range(len(thisline)):
                                if has_alpha == True or has_beta == True:
                                    qc.mo_spec.append({
                                        'coeffs': [],
                                        'energy': 0.0,
                                        'occ_num': 0.0,
                                        'sym': '',
                                        'spin': ''
                                    })
                                else:
                                    qc.mo_spec.append({
                                        'coeffs': [],
                                        'energy': 0.0,
                                        'occ_num': 0.0,
                                        'sym': ''
                                    })
                            init_mo = False
                            info_key = 'energy'
                        elif len(
                                thisline) == init_len and info_key == 'energy':
                            for ii in range(init_len, 0, -1):
                                qc.mo_spec[-ii]['energy'] = float(
                                    thisline[init_len - ii])
                            info_key = 'symmetry'
                        elif len(thisline
                                 ) == init_len and info_key == 'symmetry':
                            for ii in range(init_len, 0, -1):
                                len_mo += 1
                                a = thisline[init_len - ii]
                                if a not in sym.keys(): sym[a] = 1
                                else: sym[a] = len_mo
                                if has_alpha:
                                    qc.mo_spec[-ii]['sym'] = '%d.%s_a' % (
                                        sym[a], thisline[init_len - ii])
                                    qc.mo_spec[-ii]['spin'] = 'alpha'
                                elif has_beta:
                                    qc.mo_spec[-ii]['sym'] = '%d.%s_b' % (
                                        sym[a], thisline[init_len - ii])
                                    qc.mo_spec[-ii]['spin'] = 'beta'
                                else:
                                    qc.mo_spec[-ii]['sym'] = '%d.%s' % (
                                        sym[a], thisline[init_len - ii])
                            info_key = 'coeffs'
                        elif thisline != [] and info_key == 'coeffs':
                            lxlylz.append((line[11:17]))
                            for ii, m in enumerate(
                                    re.finditer('-?\d+\.\d+', line[16:])):
                                qc.mo_spec[-init_len + ii]['coeffs'].append(
                                    float(m.group()))
                elif mo_skip:
                    mo_skip -= 1
            elif sec_flag == 'ecp_info':
                if 'THE ECP RUN REMOVES' in line:
                    sec_flag = None
                elif 'PARAMETERS FOR' in line:
                    if line[17:25].split()[0] != ecp:
                        ecp = line[17:25].split()[0]
                        zcore = float(line[51:55].split()[0])
                        ii_geo = int(line[35:41].split()[0]) - 1
                        qc.geo_info[ii_geo][2] = str(
                            float(qc.geo_info[ii_geo][2]) - zcore)
                    else:
                        ii_geo = int(line[35:41].split()[0]) - 1
                        qc.geo_info[ii_geo][2] = str(
                            float(qc.geo_info[ii_geo][2]) - zcore)

            elif sec_flag == 'dm_info':
                # instead of giving the output in a useful human and machine readable
                # way, gamess output syntax differs for transitions involving the
                # ground state compared to transitions between excited states...
                if 'GROUND STATE (SCF) DIPOLE=' in line:
                    # ground state dipole is in debye...convert to atomic units
                    for ii in range(3):
                        qc.dipole_moments[0][0][ii] = float(
                            thisline[ii + 4]) * 0.393430307
                if 'EXPECTATION VALUE DIPOLE MOMENT FOR EXCITED STATE' in line:
                    state = (int(line.replace('STATE', 'STATE ').split()[7]))
                    dm_flag = 'state_info'
                if 'TRANSITION FROM THE GROUND STATE TO EXCITED STATE' in line:
                    state = [
                        0, int(line.replace('STATE', 'STATE ').split()[8])
                    ]
                    dm_flag = 'transition_info'
                if 'TRANSITION BETWEEN EXCITED STATES' in line:
                    state = [
                        int(thisline[4]),
                        int(line.replace('AND', 'AND ').split()[6])
                    ]
                    dm_flag = 'transition_info'
                if 'NATURAL ORBITAL OCCUPATION NUMBERS FOR EXCITED STATE' in line:
                    sec_flag = None
                    dm_flag = None
                if dm_flag == 'state_info':
                    if 'STATE MULTIPLICITY' in line:
                        qc.states['multiplicity'][state] = int(
                            line.split('=')[1])
                    if 'STATE ENERGY' in line:
                        qc.states['energy'][state] = float(line.split('=')[1])
                    if 'STATE DIPOLE' and 'E*BOHR' in line:
                        for ii in range(3):
                            qc.dipole_moments[state][state][ii] = float(
                                thisline[ii + 3])
                elif dm_flag == 'transition_info':
                    if 'TRANSITION DIPOLE' and 'E*BOHR' in line:
                        for ii in range(3):
                            qc.dipole_moments[state[0]][state[1]][ii] = float(
                                thisline[ii + 3])
                            qc.dipole_moments[state[1]][state[0]][ii] = float(
                                thisline[ii + 3])
            elif sec_flag == 'pop_info':
                if not pop_skip:
                    if line == '\n':
                        sec_flag = None
                    else:
                        qc.pop_ana = {}
                        qc.pop_ana['Lowdin'].append(float(thisline[5]))
                        qc.pop_ana['Mulliken'].append(float(thisline[3]))
                elif pop_skip:
                    pop_skip -= 1

    # Check usage of same atomic basis sets
    basis_set = {}
    for ii in range(len(AO)):
        if not AO[ii][0]['atom_type'] in basis_set.keys():
            basis_set[AO[ii][0]['atom_type']] = AO[ii]
        else:
            for jj in range(len(AO[ii])):
                if AO[ii][jj]['coeffs'] != basis_set[
                        AO[ii][0]['atom_type']][jj]['coeffs']:
                    raise IOError('Different basis sets for the same atom.')
    # Numpy array
    for ii in basis_set.keys():
        for jj in range(len(basis_set[ii])):
            basis_set[ii][jj]['coeffs'] = numpy.array(
                basis_set[ii][jj]['coeffs'])

    for kk in range(len(qc.mo_spec)):
        qc.mo_spec[kk]['coeffs'] = numpy.array(qc.mo_spec[kk]['coeffs'])

    # Complement atomic basis sets
    for kk in range(len(qc.geo_info)):
        for ll in range(len(basis_set[qc.geo_info[kk][0]])):
            qc.ao_spec.append({
                'atom':
                qc.geo_info[kk][1] - 1,
                'type':
                basis_set[qc.geo_info[kk][0]][ll]['type'],
                'pnum':
                basis_set[qc.geo_info[kk][0]][ll]['pnum'],
                'coeffs':
                basis_set[qc.geo_info[kk][0]][ll]['coeffs'],
                'lxlylz':
                None
            })
    # Reconstruct exponents list for ao_spec
    count = 0
    for i, j in enumerate(qc.ao_spec):
        l = l_deg(lquant[j['type']])
        j['lxlylz'] = []
        for i in range(l):
            j['lxlylz'].append((lxlylz[count].lower().count('x'),
                                lxlylz[count].lower().count('y'),
                                lxlylz[count].lower().count('z')))
            count += 1
        j['lxlylz'] = numpy.array(j['lxlylz'], dtype=numpy.int64)

    if restricted:
        for ii in range(len(qc.mo_spec)):
            if occ[0] and occ[1]:
                qc.mo_spec[ii]['occ_num'] += 2.0
                occ[0] -= 1
                occ[1] -= 1
            if not occ[0] and occ[1]:
                qc.mo_spec[ii]['occ_num'] += 1.0
                occ[1] -= 1
            if not occ[1] and occ[0]:
                qc.mo_spec[ii]['occ_num'] += 1.0
                occ[0] -= 1

    if restricted == False:
        for ii in range(len(qc.mo_spec)):
            if qc.mo_spec[ii]['spin'] == 'alpha' and occ[0] > 0:
                qc.mo_spec[ii]['occ_num'] += 1.0
                occ[0] -= 1
                has_alpha = True
            elif qc.mo_spec[ii]['spin'] == 'beta' and occ[1] > 0:
                qc.mo_spec[ii]['occ_num'] += 1.0
                occ[1] -= 1
                has_beta = True

    if spin is not None:
        if restricted:
            raise IOError(
                'The keyword `spin` is only supported for unrestricted calculations.'
            )
        if spin != 'alpha' and spin != 'beta':
            raise IOError('`spin=%s` is not a valid option' % spin)
        elif spin == 'alpha' and has_alpha == True:
            display('Reading only molecular orbitals of spin alpha.')
        elif spin == 'beta' and has_beta == True:
            display('Reading only molecular orbitals of spin beta.')
        elif (not has_alpha) and (not has_beta):
            raise IOError('No spin molecular orbitals available')
        elif ((spin == 'alpha' and not has_alpha)
              or (spin == 'beta' and not has_beta)):
            raise IOError(
                'You requested `%s` orbitals, but None of them are present.' %
                spin)

    # 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]

    # Convert geo_info and geo_spec to numpy.ndarrays
    qc.format_geo(is_angstrom=angstrom)

    qc.mo_spec.update()
    qc.ao_spec.update()
    return qc
Ejemplo n.º 17
0
def gaussian_tddft(fname,select_state=None,threshold=0.0,**kwargs):
  '''Reads Gaussian16 TDDFT output. 
  
  **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.
    select_state : None or list of int, optional
      If not None, specifies the states to be read (0 corresponds to the ground 
      state), else read all electronic states.
    threshold : float, optional
      Specifies a read threshold for the CI coefficients.
  
  **Returns:**
  
    ci : list of CIinfo class instances
      See :ref:`Central Variables` for details.
  '''
  display('\nReading data of TDDFT calculation from Gaussian...')
  # Initialize variables
  ci = []
  ci_flag = False
  prttol = False
  init_state = False
  rhfspin = 0
  spin = 'Unknown'
  nel = 0
  deex = []
  
  if isinstance(select_state,int): select_state = [select_state]

  if isinstance(fname, str):
    filename = fname
    fname = descriptor_from_file(filename, index=0, ci_descriptor=True)
  else:
    filename = fname.name

  for line in fname:
    thisline = line.split()             # The current line split into segments
    #--- Check the file for keywords ---
    # Initialize Hartree-Fock ground state
    if ' SCF Done:  E(' in line:
        ci.append(CIinfo(method='tddft'))
        ci[-1].info   = []
        ci[-1].coeffs = []
        ci[-1].occ    = []
        ci[-1].occ.append([0,0])
        ci[-1].coeffs.append(1.0)
        ci[-1].info = {'state': '0',
                       'energy': float(thisline[4]),
		       'energy_nm': 0.0,
                       'fileinfo': filename,
                       'read_threshold': threshold,
                       'spin': spin,
		       'f_0i': 0.0}
    # Initialize new excited state
    elif ' Excited State' in line and 'eV' in line and 'nm' in line:
      if select_state is None or int(thisline[2].replace(':',' ')) in select_state:
        init_state = True
        tddft_skip = 1
        ci.append(CIinfo(method='tddft'))
        ci[-1].info   = []
        ci[-1].coeffs = []
        ci[-1].occ    = []
        ci[-1].info = {'state': thisline[2][:-1],
                       'energy': float(thisline[-6])*ev_to_ha + ci[0].info['energy'],
		       'energy_nm': float(thisline[-4]),
                       'fileinfo': filename,
                       'read_threshold': threshold,
                       'spin': thisline[3].split('-')[0],
		       'f_0i': float(thisline[8].replace('=',' ').split()[-1])}
        deex.append([])
    if init_state == True:
      if not tddft_skip:
        if thisline == [] or '->' not in line and '<-' not in line:
          init_state = False
        else:
          if '->' in line:
            thisline = line.replace('->','-> ').split()
            if abs(float(thisline[-1])) > threshold:
              tmp_occ = [thisline[0],thisline[2]]
              ci[-1].occ.append(tmp_occ)
              ci[-1].coeffs.append(float(thisline[-1])*numpy.sqrt(2))
          elif '<-' in line:
            deex[-1].append(float(thisline[-1])*numpy.sqrt(2))
      elif tddft_skip:
        tddft_skip -= 1

  fname.close()
  deex = numpy.array(deex)

  #--- Calculating norm of CI states
  display('\nIn total, %d states have been read.' % len(ci)) 
  display('Norm of the states:')
  for i in range(len(ci)):
    j = numpy.array(ci[i].coeffs,dtype=float)
    norm = numpy.sum(j**2)
    ci[i].coeffs = j
    # Write Norm to log-file
    display('\tState %s:\tNorm = %0.8f (%d Coefficients)' % (ci[i].info['state'],norm, len(ci[i].coeffs)))
    # Transform to numpy arrays
    ci[i].occ = numpy.array([s for s in ci[i].occ],dtype=numpy.intc)-1
  
  return ci
Ejemplo n.º 18
0
def molpro_mcscf(filename, select_run=0, threshold=0.0, **kwargs):
    '''Reads MOLPRO MCSCF output. 
  
  **Parameters:**
  
    filename : str
      Specifies the filename for the input file.
    select_run : (list of) int
      Specifies the MCSCF calculation (1PROGRAM * MULTI) to be read. 
      For the selected MCSCF calculation, all electronic states will be read.
    threshold : float, optional
      Specifies a read threshold for the CI coefficients.
  
  **Returns:**
  
    ci : list of CIinfo class instances 
      See :ref:`Central Variables` for details.
  

    ..ATTENTION: Changed return value to list of CI classes
  '''
    display('\nReading data of MCSCF calculation from MOLPRO...')
    method = 'mcscf'
    available = {'mcscf': 'MULTI'}
    single_run_selected = isinstance(select_run, int)
    count = 0
    numci = []
    # Go through the file line by line
    with open(filename) as fileobject:
        for line in fileobject:
            if '1PROGRAM * %s' % available[method] in line:
                count += 1
                numci.append(0)
            if '!%s state' % method in line.lower() and 'energy' in line.lower(
            ):
                numci[-1] += 1

    if count == 0:
        display(
            'The input file %s does not contain any DETCI calculations!\n' %
            (filename) +
            'It does not contain the keyword:\n\t1PROGRAM * MULTI')
        raise IOError('Not a valid input file')
    else:
        string = ', '.join(map(str, numci)).rsplit(', ', 1)
        string = ' and '.join(string) if len(
            string[0].split(',')) < 2 else ', and '.join(string)
        display('The input file %s contains' % (filename))
        display('%d MCSCF calculation(s) with %s root(s)%s.' %
                (count, string, ', respectively' if len(numci) > 1 else ''))

        if select_run is None:
            select_run = numpy.arange(count)
        if isinstance(select_run, int) and 0 <= select_run < count:
            select_run = [select_run]
            ci = [[]]
        elif isinstance(select_run, (list, numpy.ndarray)):
            ci = []
            for i in select_run:
                ci.append([])
                if not isinstance(i, int):
                    raise IOError(
                        str(i) + ' is not a valid selection for select_run')
        else:
            raise IOError(
                str(select_run) + ' is a not valid selection for select_run')
    select_run = numpy.array(select_run)

    display('\tYour selection (counting from zero): %s' %
            ', '.join(map(str, select_run)))

    general_information = {'fileinfo': filename, 'read_threshold': threshold}

    ci_skip = 0
    count = 0
    count_runs = 0
    min_c = 1
    start_reading = False
    sec_flag = False

    info_flag = False
    info_sep = False
    info_split = False

    occ_types = ['core', 'closed', 'active', 'external']

    with open(filename) as fileobject:
        for line in fileobject:
            thisline = line.split()  # The current line split into segments

            if '1PROGRAM *' in line:
                start_reading = False
            #--- Number of IRREPs
            if 'Point group' in line or '_PGROUP' in line:
                nIRREP = point_groups()[thisline[-1].lower()]
                rhf_occ = numpy.zeros(nIRREP, dtype=numpy.intc)
            #--- RHF occupation
            elif 'Final occupancy:' in line:
                c_occ = line.split()[2:]
                for ii in range(len(c_occ)):
                    rhf_occ[ii] = int(c_occ[ii])
            #--- A MCSCF Calculation starts ---
            elif '1PROGRAM * %s' % available[method] in line:
                occ_info = {}
                for i in occ_types:
                    occ_info[i] = numpy.zeros(nIRREP, dtype=numpy.intc)
                state_info = []
                i = numpy.argwhere(select_run == count_runs)
                if len(i) > 0:
                    index_run = int(i)
                    start_reading = True
                    count = 0
                    old = 0
                count_runs += 1
            elif start_reading:
                #--- Active space ---
                if 'Number of ' in line and 'orbitals:' in line:
                    line = line.replace('(',
                                        '').replace(')',
                                                    '').replace('-shell', '')
                    c_occ = numpy.array(line.split()[-nIRREP:],
                                        dtype=numpy.intc)
                    occ_info[line.split()[2]] += c_occ
                elif 'State symmetry' in line:
                    fileobject.next()
                    thisline = fileobject.next()
                    if 'State symmetry' in thisline:
                        fileobject.next()
                        thisline = fileobject.next()
                    thisline = thisline.replace('=', ' ').split()
                    data = {
                        'nel': thisline[3],
                        'spin': thisline[6],
                        'sym': thisline[9]
                    }
                    thisline = fileobject.next().split()
                    state_info.extend([data for i in range(int(thisline[-1]))])
                elif '!%s state' % method in line.lower(
                ) and 'energy' in line.lower():
                    ci[index_run].append(CIinfo(method=method))
                    info = state_info[count]
                    thisline = line.lower().replace('state', 'state ').split()
                    ci[index_run][count].info = copy(general_information)
                    ci[index_run][count].info['fileinfo'] += '@%d' % index_run
                    ci[index_run][count].info['state'] = thisline[2]
                    ci[index_run][count].info['energy'] = float(thisline[4])
                    ci[index_run][count].info['spin'] = info['spin']
                    ci[index_run][count].info['nel'] = info['nel']
                    ci[index_run][count].info['occ_info'] = occ_info
                    count += 1
                elif 'CI vector' in line:
                    sec_flag = 'mcscf'
                    info_split = '     '
                    ci_skip = 3
                    info = thisline[-1]
                    count = old
                    first = True
                if not ci_skip:
                    if line == '\n' or '/EOF' in line:
                        sec_flag = False
                    elif sec_flag != False:
                        split_line = filter(None, line.split(info_split))
                        if len(split_line) > 1:
                            occupation = numpy.zeros(
                                (numpy.sum(occ_info['active']), 2),
                                dtype=numpy.intc)
                            for i, j in enumerate(split_line[0].replace(
                                    ' ', '')):
                                if j == '2':
                                    occupation[i, :] = 1
                                elif j == 'a':
                                    occupation[i, 0] = 1
                                elif j == 'b':
                                    occupation[i, 1] = 1
                            c0 = 0
                        coeffs = split_line[-1].split()
                        for i, j in enumerate(coeffs):
                            if first:
                                old += 1
                            min_c = min(min_c, abs(float(j)))
                            if abs(float(j)) > threshold:
                                ci[index_run][count + c0 + i].coeffs.append(
                                    float(j))
                                ci[index_run][count + c0 +
                                              i].occ.append(occupation)
                        c0 += len(coeffs)
                        first = False
                else:
                    ci_skip -= 1

    #--- Calculating norm of CI states
    display('\nIn total, %d states have been read.' % sum([len(i)
                                                           for i in ci]))
    display('Norm of the states:')
    for i in range(len(ci)):
        for j in range(len(ci[i])):
            ci[i][j].coeffs = numpy.array(ci[i][j].coeffs)
            ci[i][j].occ = numpy.array(ci[i][j].occ, dtype=numpy.intc)
            norm = sum(ci[i][j].coeffs**2)
            # Write Norm to log-file
            display('\tState %s (%s):\tNorm = %0.8f (%d Coefficients)' %
                    (ci[i][j].info['state'], ci[i][j].info['spin'], norm,
                     len(ci[i][j].coeffs)))
    display('')
    if min_c > threshold:
        display(
            '\nInfo:' +
            '\n\tSmallest coefficient (|c|=%f) larger than the read threshold (%f).'
            % (min_c, threshold) +
            '\n\tUse `gthresh, printci=0.0` in the MOLPRO input file to print '
            + 'all CI coefficients.\n')

    #if single_run_selected and len(ci) == 1:
    #ci = ci[0]
    ci_new = []
    for i in ci:
        ci_new.extend(i)

    return ci_new
Ejemplo n.º 19
0
def mo_set(qc,
           fid_mo_list,
           drv=None,
           laplacian=None,
           otype=None,
           ofid=None,
           return_all=True,
           numproc=None,
           slice_length=None):
    '''Calculates and saves the density or the derivative thereof 
  using selected molecular orbitals.
  
  **Parameters:**
   
    qc.geo_spec, qc.geo_info, qc.ao_spec, qc.mo_spec :
      See :ref:`Central Variables` for details.
    fid_mo_list : str
      Specifies the filename of the molecular orbitals list or list of molecular
      orbital labels (cf. :mod:`orbkit.orbitals.MOClass.select` for details). 
    otype : str or list of str, optional
      Specifies output file type. See :data:`otypes` for details.
    ofid : str, optional
      Specifies output file name. If None, the filename will be based on
      :mod:`orbkit.options.outputname`.
    drv : string or list of strings {None,'x','y', 'z', 'xx', 'xy', ...}, optional
      If not None, a derivative calculation is requested.
    return_all : bool
      If False, no data will be returned.
    numproc : int, optional
      Specifies number of subprocesses for multiprocessing. 
      If None, uses the value from :mod:`options.numproc`.
    slice_length : int, optional
      Specifies the number of points per subprocess.
      If None, uses the value from :mod:`options.slice_length`.
  
  **Returns:**
    datasets : numpy.ndarray, shape=((NSET,) + N)
      Contains the NSET molecular orbital sets on a grid.
    delta_datasets : numpy.ndarray, shape=((NSET,NDRV) + N)
      Contains the NDRV NSET molecular orbital set on a grid. This is only 
      present if derivatives are requested.
  '''

    #Can be an mo_spec or a list of mo_spec
    # For later iteration we'll make it into a list here if it is not
    mo_info_list = qc.mo_spec.select(fid_mo_list, flatten_input=False)

    drv = options.drv if drv is None else drv
    laplacian = options.laplacian if laplacian is None else laplacian
    slice_length = options.slice_length if slice_length is None else slice_length
    numproc = options.numproc if numproc is None else numproc

    if ofid is None:
        ofid = options.outputname

    datasets = []
    datalabels = []
    delta_datasets = []
    delta_datalabels = []
    cube_files = []

    for i_file, mo_info in enumerate(mo_info_list):
        qc_select = qc.copy()
        qc_select.mo_spec = mo_info
        label = 'mo_set:' + mo_info.selection_string
        display('\nStarting with the molecular orbital list \n\t' + label +
                '\n\t(Only regarding existing and occupied mos.)\n')

        data = core.rho_compute(qc_select,
                                drv=drv,
                                laplacian=laplacian,
                                slice_length=slice_length,
                                numproc=numproc)

        if drv is None:
            rho = data
            delta_datasets = numpy.zeros((0, ) + rho.shape)
        elif laplacian:
            rho, delta_rho, laplacian_rho = data
            delta_datasets.extend(delta_rho)
            delta_datasets.append(laplacian_rho)
            delta_datalabels.extend(
                ['d^2/d%s^2 %s' % (i, label) for i in 'xyz'])
            delta_datalabels.append('laplacian_of_' + label)
        else:
            rho, delta_rho = data
            delta_datasets.extend(delta_rho)
            delta_datalabels.extend(['d/d%s %s' % (i, label) for i in drv])

        datasets.append(rho)
        datalabels.append(label)

    datasets = numpy.array(datasets)
    delta_datasets = numpy.array(delta_datasets)
    delta_datalabels.append('mo_set')
    data = numpy.append(datasets, delta_datasets, axis=0)

    if not options.no_output:
        output_written = main_output(data,
                                     qc,
                                     outputname=ofid,
                                     datalabels=datalabels + delta_datalabels,
                                     otype=otype,
                                     drv=None)
    return data
Ejemplo n.º 20
0
def order_using_extrapolation(fid_list,
                              itype='molden',
                              deg=1,
                              use_mo_values=False,
                              matrix=None,
                              **kwargs):
    '''Performs an ordering routine using extrapolation of quantities related to 
  the molecular orbitals. Set fid_list to None to omit the reading of input 
  files.
  
  The molecular orbital coefficients (If use_mo_values is False) are 
  extrapolated with a polynomial of degree :literal:`deg` and ordered by 
  minimizing a selected norm (default: Euclidian norm).
  
  **Paramerters:**
  
  fid_list : list of str or None
    If not None, it contains the list of input file names.
  itype : str, choices={'molden', 'gamess', 'gaussian.log', 'gaussian.fchk'}
    Specifies the type of the input files.
  deg : int
    Specifies the degree of the extrapolation polynomial.
  use_mo_values : bool, optional
    If True, some molecular orbital values and their derivatives are computed
    at the nuclear positions. The ordering routine is applied for those values
    instead.
  matrix : None or numpy.ndarray with shape=(Nfiles,N,M)
    If not None, contains the data to be ordered.
  
  **Returns:**
  
  :if matrix is None:
    - index_list
  :else:
    - matrix, index_list
    
  index_list : numpy.ndarray, shape=(Nfiles,NMO)
    Contains the new indices of the molecular orbitals. If index < 0, the 
    molecular orbital changes its sign.
  matrix : numpy.ndarray, shape=(Nfiles,N,M)
    Contains the ordered matrix.
  
  **Global Variables:**
  
  geo_spec_all, geo_info, ao_spec, ao_spherical, mo_coeff_all, mo_energy_all, mo_occ_all, sym, index_list
  '''
    global geo_spec_all, geo_info, ao_spec, ao_spherical, mo_coeff_all, mo_energy_all, mo_occ_all, sym, index_list

    # Read all input files
    if fid_list is not None:
        read(fid_list, itype=itype, **kwargs)

    radius = range(len(geo_spec_all))  #: We assume an equally spaced grid

    if deg < 2:
        function = order_mo
    else:
        function = order_mo_higher_deg

    if matrix is not None:
        display('\tOdering backward')
        matrix, index_list = function(matrix,
                                      index_list=index_list[ii_s],
                                      backward=True,
                                      mu=mu,
                                      deg=deg)
        display('\tOdering forward')
        matrix, index_list = function(matrix,
                                      index_list=index_list[ii_s],
                                      backward=False,
                                      mu=mu,
                                      deg=deg)
        return matrix, index_list

    index_list = [None for i in sym.keys()]

    for s, ii_s in sym.items():
        display('Starting ordering of MOs of symmetry %s' % s)

        shape = numpy.shape(mo_coeff_all[ii_s])

        mu = 5e-2

        matrix = mo_coeff_all[ii_s]
        if use_mo_values:
            display('\tComputing molecular orbitals at the nuclear positions')
            matrix = compute_mo_list(geo_spec_all,
                                     ao_spec,
                                     matrix,
                                     ao_spherical=ao_spherical,
                                     iter_drv=[None, 'x', 'y', 'z'])

        display('\tOdering backward')
        matrix, index_list[ii_s] = function(matrix,
                                            index_list=index_list[ii_s],
                                            backward=True,
                                            mu=mu,
                                            deg=deg)
        display('\tOdering forward')
        matrix, index_list[ii_s] = function(matrix,
                                            index_list=index_list[ii_s],
                                            backward=False,
                                            mu=mu,
                                            deg=deg)

        for rr in range(shape[0]):
            index = numpy.abs(index_list[ii_s])[rr, :]
            sign = (-1)**(index_list[ii_s][rr] < 0)
            mo_energy_all[ii_s][rr, :] = mo_energy_all[ii_s][rr, index]
            mo_occ_all[ii_s][rr, :] = mo_occ_all[ii_s][rr, index]
            mo_coeff_all[ii_s][
                rr, :, :] = sign[:, numpy.newaxis] * mo_coeff_all[ii_s][
                    rr, index, :]  # numpy.array(matrix,copy=True)

    return index_list
Ejemplo n.º 21
0
def main_output(data,
                geo_info,
                geo_spec,
                outputname='new',
                otype='h5',
                drv=None,
                omit=[],
                **kwargs):
    '''Creates the requested output.
  
  **Parameters:**
  
  data : numpy.ndarray, shape=N or shape=((NDRV,) + N)
    Contains the output data. The shape (N) depends on the grid and the data, i.e.,
    3d for regular grid, 1d for vector grid. 
  geo_info, geo_spec : 
    See :ref:`Central Variables` for details.
  outputname : str
    Contains the base name of the output file.
  otype : str or list of str
    Contains the output file type. Possible options:
    'h5', 'cb', 'am', 'hx', 'vmd', 'mayavi'
  drv : None or list of str, optional
    If not None, a 4d(regular)/2d(vector) input data array will be expected
    with NDRV = len(drv).
  omit : list of str, optional
    If not empty, the input file types specified here are omitted.
  
  **Note:**
  
    All additional keyword arguments are forwarded to the output functions.
  '''
    print_waring = False
    output_written = []
    if isinstance(otype, str):
        otype = [otype]

    if 'vmd' in otype and not 'cb' in otype:
        otype.append('cb')

    otype = [i for i in otype if i not in omit]

    if otype is None or otype == []:
        return output_written

    # Convert the data to a regular grid, if possible
    output_not_possible = (grid.is_vector and not grid.is_regular)
    is_regular_vector = (grid.is_vector and grid.is_regular)
    if is_regular_vector:
        display(
            '\nConverting the regular 1d vector grid to a 3d regular grid.')
        grid.vector2grid(*grid.N_)
        data = grid.mv2g(data=data)

    if 'mayavi' in otype:
        if output_not_possible: print_waring = True
        else:
            view_with_mayavi(grid.x,
                             grid.y,
                             grid.z,
                             data,
                             geo_spec=geo_spec,
                             **kwargs)

    if drv is not None:
        fid = '%(f)s_d%(d)s'
        it = enumerate(drv)
    else:
        fid = '%(f)s'
        it = [(0, None)]
        data = [data]
    f = {'f': outputname}

    for i, j in it:
        f['d'] = j
        d = data[i]
        if 'h5' in otype:
            display('\nSaving to Hierarchical Data Format file (HDF5)...' +
                    '\n\t%(o)s.h5' % {'o': fid % f})
            HDF5_creator(d, (fid % f), geo_info, geo_spec, **kwargs)
            output_written.append('%s.h5' % (fid % f))
        if 'am' in otype or 'hx' in otype and not print_waring:
            if output_not_possible: print_waring = True
            else:
                display('\nSaving to ZIBAmiraMesh file...' +
                        '\n\t%(o)s.am' % {'o': fid % f})
                amira_creator(d, (fid % f))
                output_written.append('%s.am' % (fid % f))
        if 'hx' in otype and not print_waring:
            if output_not_possible: print_waring = True
            else:
                # Create Amira network incl. Alphamap
                display('\nCreating ZIBAmira network file...')
                hx_network_creator(data, (fid % f))
                output_written.append('%s.hx' % (fid % f))
        if 'cb' in otype or 'vmd' in otype and not print_waring:
            if output_not_possible: print_waring = True
            else:
                display('\nSaving to .cb file...' +
                        '\n\t%(o)s.cb' % {'o': fid % f})
                cube_creator(d, (fid % f), geo_info, geo_spec, **kwargs)
                output_written.append('%s.cb' % (fid % f))
            #else: output_creator(d,(fid % f),geo_info,geo_spec)  # Axel's cube files
        if 'vmd' in otype and not print_waring:
            if output_not_possible: print_waring = True
            else:
                # Create VMD network
                display('\nCreating VMD network file...' +
                        '\n\t%(o)s.vmd' % {'o': fid % f})
                vmd_network_creator((fid % f),
                                    cube_files=['%s.cb' % (fid % f)],
                                    **kwargs)
                output_written.append('%s.vmd' % (fid % f))

    if print_waring:
        display(
            'For a non-regular vector grid (`if grid.is_vector and not grid.is_regular`)'
        )
        display('only HDF5 is available as output format...')
        display('Skipping all other formats...')

    if is_regular_vector:
        # Convert the data back to a regular vector grid
        grid.grid2vector()

    return output_written
Ejemplo n.º 22
0
def vmd_network_creator(filename,
                        cube_files=None,
                        render=False,
                        iso=(-0.01, 0.01),
                        abspath=False,
                        **kwargs):
    '''Creates a VMD script file from a list of cube files provided.
  
  **Parameters:**
  
  filename : str
    Contains the base name of the output file.
  cube_files : None or list of str
    Specifies the cube files which serve as input for the VMD script.
    If None, searches the directory for '.cb' and '.cube' files.
  render : bool
    If True, the VMD script will automatically create '.tga' files for each 
    cube file.
  iso : tuple
    Specifies the isovalue for the blue and the red isosurface, respectively.
  abspath : bool
    If True, the paths of the cube files will be expanded to absolute file paths.
  '''
    from os import path, listdir
    import linecache
    from orbkit import vmd_network_draft
    if cube_files is None:
        display(
            'No list of cube (.cb or .cube) filenames provided. Checking the directory'
            + ' of the outputfile...')
        cube_files = []
        for fid in listdir(path.dirname(filename)):
            if fid.endswith('.cb') or fid.endswith('.cube'):
                cube_files.append(fid)
        if cube_files == []:
            raise IOError('Could not find valid cube files in %s' %
                          path.dirname(filename))
    elif isinstance(cube_files, str):
        cube_files = [cube_files]
    elif not isinstance(cube_files, list):
        raise IOError('`cube_files` has to be a list of strings.')

    title = []
    mo = ''
    for i, f in enumerate(cube_files):
        title = linecache.getline(f, 2)
        if title.split() == []:
            title = path.splitext(path.basename(f))[0]
        else:
            title = title.replace('\n', '').replace(' ', '')
        linecache.clearcache()
        pid = path.abspath(f) if abspath else path.relpath(
            f, path.dirname(filename))
        mo += vmd_network_draft.mo_string % {
            'c': i,
            'n1': pid,
            'n2': title,
            'isored': iso[0],
            'isoblue': iso[1],
            'render': '' if render else '#'
        }

    f = open('%(f)s.vmd' % {'f': filename}, 'w')
    f.write(vmd_network_draft.vmd_string % {'mo': mo})
    f.close()
Ejemplo n.º 23
0
def gamess_cis(filename, select_state=None, threshold=0.0, **kwargs):
    '''Reads GAMESS-US CIS output. 
  
  **Parameters:**
  
    filename : str
      Specifies the filename for the input file.
    select_state : None or list of int, optional
      If not None, specifies the states to be read (0 corresponds to the ground 
      state), else read all electronic states.
    threshold : float, optional
      Specifies a read threshold for the CI coefficients.
  
  **Returns:**
  
    ci : list of CIinfo class instances
      See :ref:`Central Variables` for details.
  '''
    display('\nReading data of CIS calculation from GAMESS-US...')
    # Initialize variables
    ci = []
    ci_flag = False
    prttol = False
    init_state = False
    rhfspin = 0
    min_c = -1

    if isinstance(select_state, int): select_state = [select_state]
    with open(filename) as fileobject:
        for line in fileobject:
            thisline = line.split()  # The current line split into segments
            #--- Check the file for keywords ---
            # Initialize Hartree-Fock ground state
            if 'NUMBER OF ELECTRONS' in line and "=" in line:
                nel = int(thisline[-1])
            elif 'SPIN MULTIPLICITY' in line:
                rhfspin = int(thisline[-1])
            elif ' FINAL RHF ENERGY IS' in line and (select_state is None
                                                     or 0 in select_state):
                ci.append(CIinfo(method='cis'))
                ci[-1].info = []
                ci[-1].coeffs = []
                ci[-1].occ = []
                ci[-1].occ.append([0, 0])
                ci[-1].coeffs.append(1.0)
                ci[-1].info = {
                    'state': '0',
                    'energy': float(thisline[4]),
                    'fileinfo': filename,
                    'read_threshold': threshold,
                    'spin': multiplicity()[rhfspin],
                    'nel': nel
                }
            # Printing parameter
            elif ' PRINTING CIS COEFFICIENTS LARGER THAN' in line:
                min_c = float(thisline[-1])
            # Initialize new excited state
            elif ' EXCITED STATE ' in line and 'ENERGY=' and 'SPACE SYM' in line:
                if select_state is None or int(thisline[2]) in select_state:
                    init_state = True
                    cis_skip = 6
                    ci.append(CIinfo(method='cis'))
                    ci[-1].info = []
                    ci[-1].coeffs = []
                    ci[-1].occ = []
                    ci[-1].info = {
                        'state': thisline[2],
                        'energy': float(thisline[4]),
                        'fileinfo': filename,
                        'read_threshold': threshold,
                        'spin':
                        multiplicity()[int(2 * float(thisline[7]) + 1)],
                        'nel': nel
                    }
            if init_state == True:
                if not cis_skip:
                    if '----------------------------------------------' in line:
                        init_state = False
                    else:
                        if abs(float(thisline[2])) > threshold:
                            ci[-1].occ.append(thisline[:2])
                            ci[-1].coeffs.append(thisline[2])
                elif cis_skip:
                    cis_skip -= 1

    #--- Calculating norm of CI states
    display('\nIn total, %d states have been read.' % len(ci))
    display('Norm of the states:')
    for i in range(len(ci)):
        j = numpy.array(ci[i].coeffs, dtype=float)
        norm = numpy.sum(j**2)
        ci[i].coeffs = j
        # Write Norm to log-file
        display('\tState %s:\tNorm = %0.8f (%d Coefficients)' %
                (ci[i].info['state'], norm, len(ci[i].coeffs)))
        # Transform to numpy arrays
        ci[i].occ = numpy.array([s for s in ci[i].occ], dtype=numpy.intc) - 1
    display('')
    if min_c > threshold:
        display(
            '\nInfo:' +
            '\n\tSmallest coefficient (|c|=%f) is larger than the read threshold (%f).'
            % (min_c, threshold) +
            '\n\tUse `PRTTOL=0.0` in the `$CIS` input card to print ' +
            'all CI coefficients.\n')

    return ci
Ejemplo n.º 24
0
def gamess_tddft(fname, select_state=None, threshold=0.0, **kwargs):
    '''Reads GAMESS-US TDDFT output. 
  
  **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.
    select_state : None or list of int, optional
      If not None, specifies the states to be read (0 corresponds to the ground 
      state), else read all electronic states.
    threshold : float, optional
      Specifies a read threshold for the CI coefficients.
  
  **Returns:**
  
    ci : list of CIinfo class instances
      See :ref:`Central Variables` for details.
  '''
    display('\nReading data of TDDFT calculation from GAMESS-US...')
    # Initialize variables
    ci = []
    ci_flag = False
    prttol = False
    init_state = False
    rhfspin = 0
    spin = 'Unknown'

    if isinstance(select_state, int): select_state = [select_state]

    if isinstance(fname, str):
        filename = fname
        fname = descriptor_from_file(filename, index=0, ci_descriptor=True)
    else:
        filename = fname.name

    for line in fname:
        thisline = line.split()  # The current line split into segments
        #--- Check the file for keywords ---
        # Initialize Hartree-Fock ground state
        if 'NUMBER OF ELECTRONS' in line:
            nel = int(thisline[-1])
        elif 'SPIN MULTIPLICITY' in line:
            rhfspin = int(thisline[-1])
        elif 'SINGLET EXCITATIONS' in line:
            spin = 'Singlet'
        #elif ' FINAL RHF ENERGY IS' in line and (select_state is None or 0 in select_state):
        elif ' FINAL' in line and ' ENERGY IS' in line and (
                select_state is None or 0 in select_state):
            ci.append(CIinfo(method='tddft'))
            ci[-1].info = []
            ci[-1].coeffs = []
            ci[-1].occ = []
            ci[-1].occ.append([0, 0])
            ci[-1].coeffs.append(1.0)
            ci[-1].info = {
                'state': '0',
                'energy': float(thisline[4]),
                'fileinfo': filename,
                'read_threshold': threshold,
                'spin': spin,
                'nel': nel
            }
        # Initialize new excited state
        elif 'STATE #' in line and 'ENERGY =' in line:
            if select_state is None or int(thisline[2]) in select_state:
                init_state = True
                tddft_skip = 8
                ci.append(CIinfo(method='cis'))
                ci[-1].info = []
                ci[-1].coeffs = []
                ci[-1].occ = []
                ci[-1].info = {
                    'state': thisline[2],
                    'energy':
                    float(thisline[-2]) * ev_to_ha + ci[0].info['energy'],
                    'fileinfo': filename,
                    'read_threshold': threshold,
                    'spin': 'Unknown',
                    'nel': nel
                }
        if init_state == True and line != '\n' and 'WARNING:' not in line:
            if not tddft_skip:
                if 'NON-ABELIAN' in line or 'SUMMARY' in line or 'SYMMETRY' in line or 'STATE #' in line:
                    init_state = False
                else:
                    if abs(float(thisline[2])) > threshold:
                        ci[-1].occ.append(thisline[:2])
                        ci[-1].coeffs.append(thisline[2])
            elif tddft_skip:
                tddft_skip -= 1

    fname.close()

    #--- Calculating norm of CI states
    display('\nIn total, %d states have been read.' % len(ci))
    display('Norm of the states:')
    for i in range(len(ci)):
        j = numpy.array(ci[i].coeffs, dtype=float)
        norm = numpy.sum(j**2)
        ci[i].coeffs = j
        # Write Norm to log-file
        display('\tState %s:\tNorm = %0.8f (%d Coefficients)' %
                (ci[i].info['state'], norm, len(ci[i].coeffs)))
        # Transform to numpy arrays
        ci[i].occ = numpy.array([s for s in ci[i].occ], dtype=numpy.intc) - 1

    return ci
Ejemplo n.º 25
0
def order_mo_higher_deg(mo,
                        index_list=None,
                        backward=True,
                        mu=1e-1,
                        deg=2,
                        **kwargs):
    '''Orders a 3d-matrix (shape=(Nfiles,NMO,NAO)) by interchanging the axis=1, 
  i.e., NMO, applying an extrapolation a polynomial fit with a Vandermonde matrix
  as implemented in numpy.'''

    shape = numpy.shape(mo)

    # Check if degree is correctly set
    if not isinstance(deg, int) or deg < 1 or deg > (shape[0] - 1):
        raise IOError('Wrong choice for degree of the fitting polynomial!')

    display('\tusing a least squares polynomial fit of degree %d.' % deg)

    if index_list == None:
        index_list = numpy.ones((shape[0], shape[1]), dtype=int)
        index_list *= numpy.arange(shape[1], dtype=int)

    if 'criterion' in kwargs:
        if kwargs['criterion'] == '1-norm':
            test = lambda x, y: numpy.sum(numpy.abs(x)) < numpy.sum(
                numpy.abs(y))
        if kwargs['criterion'] == '2-norm':
            test = lambda x, y: ((x**2).sum()) < ((y**2).sum())
        elif kwargs['criterion'] == 'infty-norm':
            test = lambda x, y: abs(x).max() < abs(y).max()
        elif kwargs['criterion'] == 'perc':
            test = lambda x, y: (
                (x**2 < y**2).sum() / float(shape[2])) > 1. / 2.
        else:
            raise ValueError('creterion %s is not defined!' %
                             kwargs['criterion'])
    else:
        # Take 2-norm by default
        test = lambda x, y: ((x**2).sum()) < ((y**2).sum())

    if backward:
        st = [-(deg + 1), 0, -1]
        x = numpy.arange(0, deg + 1)
    else:
        st = [deg, -1, 1]
        x = numpy.arange(-deg, 1)

    for i, i_0 in enumerate(range(shape[1])[:-1]):
        for rr in range(shape[0])[st[0]:st[1]:st[2]]:
            epol = numpy.zeros(shape[2])
            for k in range(shape[2]):
                if mo[rr, i_0, k] != 0.:
                    xnew = rr + st[2]
                    y = mo[rr + x, i_0, k]
                    z = numpy.polyfit(rr + x, y, deg)
                    epol[k] = numpy.poly1d(z)(xnew)

            cp = ((mo[rr + st[2], i_0, :] - epol[:])**2)
            cm = ((-1 * mo[rr + st[2], i_0, :] - epol[:])**2)
            is_smaller = test(cm, cp)
            current = cm if is_smaller else cp

            diff = current
            i_1 = i_0
            new_signs = [1, (-1)**is_smaller]
            # Check other molecular orbitals
            for ik_index, ik in enumerate(range(shape[1])[i + 1:]):
                cp = ((mo[rr + st[2], ik, :] - epol[:])**2)
                cm = ((-1 * mo[rr + st[2], ik, :] - epol[:])**2)
                is_smaller = test(cm, cp)
                current = cm if is_smaller else cp

                if test(current, diff):
                    diff = current
                    i_1 = ik
                    new_signs = [1, (-1)**is_smaller]
            if i_0 != i_1:
                mo[rr + st[2], [i_0, i_1], :] = mo[rr + st[2], [i_1, i_0], :]
                index_list[rr + st[2], [i_0, i_1]] = index_list[rr + st[2],
                                                                [i_1, i_0]]
            mo[rr, i_0, :] *= new_signs[0]
            mo[rr + st[2], i_0, :] *= new_signs[1]
            index_list[rr, i_0] *= new_signs[0]
            index_list[rr + st[2], i_0] *= new_signs[1]

    return mo, index_list
Ejemplo n.º 26
0
def run_orbkit(use_qc=None, check_options=True, standalone=False):
    '''Controls the execution of all computational tasks.
  
  **Parameters:**
  
  use_qc : QCinfo, optional
    If not None, the reading of a quantum chemistry output is omitted and
    the given QCinfo class is used for all computational tasks. 
    (See :ref:`Central Variables` in the manual for details on QCinfo.) 
  check_options : bool, optional
    If True, the specified options will be validated. 
  
  **Returns:**
  
  data : type and shape depend on the options.
    Contains orbkit's output. 
    See :ref:`High-Level Interface` in the manual for details.
  '''
    # Set some global variables
    global qc

    # Display program information
    display(lgpl_short)

    # Check for the correctness of orbkit.options
    if check_options:
        display('Checking orbkit.options...\n')
        options.check_options(display=display,
                              interactive=False,
                              info=True,
                              check_io=(use_qc is None))

    # Measurement of required execution time
    t = [time.time()]

    # Do we need to read out the info of all MOs?
    if (options.mo_set or options.calc_mo) is not False:
        options.all_mo = True

    if use_qc is None:
        # Read the input file
        qc = read.main_read(options.filename,
                            itype=options.itype,
                            all_mo=options.all_mo,
                            spin=options.spin,
                            cclib_parser=options.cclib_parser)
    else:
        # Use a user defined QCinfo class.
        qc = use_qc

    display('\nSetting up the grid...')
    if options.grid_file is not None:
        # Read the grid from an external file
        grid.read(options.grid_file)
    elif options.adjust_grid is not None:
        # Adjust the grid to geo_spec
        extend, step = options.adjust_grid
        grid.adjust_to_geo(qc, extend=extend, step=step)
    elif options.random_grid:
        # Create a randomized grid
        grid.random_grid(qc.geo_spec)

    # Initialize grid
    grid.grid_init(is_vector=options.is_vector)
    if options.is_vector:
        grid.is_regular = False
    display(grid.get_grid())  # Display the grid

    if not grid.is_regular and options.center_grid is not None:
        raise IOError(
            'The option --center is only supported for regular grids.')
    elif options.center_grid is not None:
        atom = grid.check_atom_select(options.center_grid,
                                      qc.geo_info,
                                      qc.geo_spec,
                                      interactive=True,
                                      display=display)
        # Center the grid to a specific atom and (0,0,0) if requested
        grid.center_grid(qc.geo_spec[atom - 1], display=display)

    if check_options or standalone:
        options.check_grid_output_compatibilty()

    t.append(time.time())  # A new time step

    # The calculation of all AOs (--calc_ao)
    if options.calc_ao != False:
        data = extras.calc_ao(qc, drv=options.drv, otype=options.otype)

        t.append(time.time())  # Final time
        good_bye_message(t)
        return data

    # The calculation of selected MOs (--calc_mo) or
    # the density formed by selected MOs (--mo_set)
    if (options.mo_set or options.calc_mo) != False:
        # What should the program do?
        if options.calc_mo != False:
            fid_mo_list = options.calc_mo
        elif options.mo_set != False:
            fid_mo_list = options.mo_set

        # Call the function for actual calculation
        if options.calc_mo != False:
            data = extras.calc_mo(qc,
                                  fid_mo_list,
                                  drv=options.drv,
                                  otype=options.otype)
        elif options.mo_set != False:
            data = extras.mo_set(qc,
                                 fid_mo_list,
                                 drv=options.drv,
                                 laplacian=options.laplacian,
                                 otype=options.otype)

        t.append(time.time())  # Final time
        good_bye_message(t)
        return data

    if options.gross_atomic_density is not None:
        atom = options.gross_atomic_density
        rho_atom = extras.numerical_mulliken_charges(atom, qc)

        if not grid.is_vector:
            mulliken_num = rho_atom[1]
            rho_atom = rho_atom[0]

        if not options.no_output:
            fid = '%s.h5' % options.outputname
            display('\nSaving to Hierarchical Data Format file (HDF5)...' +
                    '\n\t%(o)s' % {'o': fid})
            output.hdf5_write(fid,
                              mode='w',
                              gname='',
                              atom=core.numpy.array(atom),
                              geo_info=qc.geo_info,
                              geo_spec=qc.geo_spec,
                              gross_atomic_density=rho_atom,
                              x=grid.x,
                              y=grid.y,
                              z=grid.z)
            if not options.is_vector:
                output.hdf5_write(
                    fid,
                    mode='a',
                    gname='/numerical_mulliken_population_analysis',
                    **mulliken_num)

        t.append(time.time())
        good_bye_message(t)
        return rho_atom

    if options.mo_tefd is not None:
        mos = options.mo_tefd
        ao_list = core.ao_creator(qc.geo_spec, qc.ao_spec)
        mo_tefd = []
        index = []
        for i, j in mos:
            mo_tefd.append([])
            index.append([])
            for ii_d in options.drv:
                display('\nMO-TEFD: %s->%s %s-component' % (i, j, ii_d))
                tefd = extras.mo_transition_flux_density(i,
                                                         j,
                                                         qc,
                                                         drv=ii_d,
                                                         ao_list=ao_list)
                mo_tefd[-1].append(tefd)
                index[-1].append('%s->%s:%s' % (i, j, ii_d))

        if not options.no_output:
            from numpy import array
            fid = '%s.h5' % options.outputname
            display('\nSaving to Hierarchical Data Format file (HDF5)...' +
                    '\n\t%(o)s' % {'o': fid})
            HDF5_File = output.hdf5_open(fid, mode='w')
            data = {
                'geo_info': array(qc.geo_info),
                'geo_spec': array(qc.geo_spec),
                'mo_tefd:info': array(index),
                'mo_tefd': array(mo_tefd),
                'x': grid.x,
                'y': grid.y,
                'z': grid.z
            }
            output.hdf5_append(data, HDF5_File, name='')
            HDF5_File.close()

        t.append(time.time())
        good_bye_message(t)
        return mo_tefd

    t.append(time.time())  # A new time step

    # Compute the (derivative of the) electron density
    if options.no_slice:
        data = core.rho_compute_no_slice(qc,
                                         drv=options.drv,
                                         laplacian=options.laplacian,
                                         return_components=False)

    else:
        data = core.rho_compute(qc,
                                drv=options.drv,
                                slice_length=options.slice_length,
                                laplacian=options.laplacian,
                                numproc=options.numproc)
    if options.drv is None:
        rho = data
    elif options.laplacian:
        rho, delta_rho, laplacian_rho = data
    else:
        rho, delta_rho = data

    # Compute the reduced electron density if requested
    if options.z_reduced_density:
        if grid.is_vector:
            display('\nSo far, reducing the density is not supported for ' +
                    'vector grids.\nSkipping the reduction...\n')
        elif options.drv is not None:
            display(
                '\nSo far, reducing the density is not supported for ' +
                'the derivative of the density.\nSkipping the reduction...\n')
        else:
            from scipy import integrate
            display('\nReducing the density with respect to the z-axis.\n')
            rho = integrate.simps(rho,
                                  grid.x,
                                  dx=grid.delta_[0],
                                  axis=0,
                                  even='avg')
            rho = integrate.simps(rho,
                                  grid.y,
                                  dx=grid.delta_[1],
                                  axis=0,
                                  even='avg')

    t.append(time.time())  # A new time step

    # Generate the output requested
    if not options.no_output:
        output_written = output.main_output(rho,
                                            qc.geo_info,
                                            qc.geo_spec,
                                            outputname=options.outputname,
                                            otype=options.otype,
                                            data_id='rho',
                                            omit=['vmd', 'mayavi'],
                                            mo_spec=qc.mo_spec)
        if options.drv is not None:
            output_written.extend(
                output.main_output(delta_rho,
                                   qc.geo_info,
                                   qc.geo_spec,
                                   outputname=options.outputname,
                                   otype=options.otype,
                                   data_id='delta_rho',
                                   omit=['vmd', 'mayavi'],
                                   mo_spec=qc.mo_spec,
                                   drv=options.drv))
        if options.laplacian:
            output_written.extend(
                output.main_output(laplacian_rho,
                                   qc.geo_info,
                                   qc.geo_spec,
                                   outputname=options.outputname +
                                   '_laplacian',
                                   otype=options.otype,
                                   data_id='laplacian_rho',
                                   omit=['vmd', 'mayavi'],
                                   mo_spec=qc.mo_spec))
        if 'vmd' in options.otype:
            # Create VMD network
            display('\nCreating VMD network file...' +
                    '\n\t%(o)s.vmd' % {'o': options.outputname})
            cube_files = []
            for i in output_written:
                if i.endswith('.cb'):
                    cube_files.append(i)
            output.vmd_network_creator(options.outputname,
                                       cube_files=cube_files)

    t.append(time.time())  # Final time

    good_bye_message(t)

    if 'mayavi' in options.otype:
        plt_data = [rho]
        datalabels = ['rho']
        if options.drv is not None:
            plt_data.extend(delta_rho)
            datalabels.extend(
                ['d/d%s of %s' % (ii_d, 'rho') for ii_d in options.drv])
        if options.laplacian:
            plt_data.append(laplacian_rho)
            datalabels.append('laplacian of rho')
        output.main_output(plt_data,
                           qc.geo_info,
                           qc.geo_spec,
                           otype='mayavi',
                           datalabels=datalabels)

    # Return the computed data, i.e., rho for standard, and (rho,delta_rho)
    # for derivative calculations. For laplacian (rho,delta_rho,laplacian_rho)
    return data
Ejemplo n.º 27
0
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
Ejemplo n.º 28
0
def mo_select(mo_spec, fid_mo_list, strict=False):
    '''Selects molecular orbitals from an external file or a list of molecular 
  orbital labels.

  **Parameters:**
   
    mo_spec :        
      See :ref:`Central Variables` for details.
    strict : bool, optional
      If True, orbkit will follow strictly the fid_mo_list, i.e., the order of 
      the molecular orbitals will be kept and multiple occurrences of items 
      will evoke multiple calculations of the respective molecular orbitals. 
    fid_mo_list : str, `'all_mo'`, or list
      | If fid_mo_list is a str, specifies the filename of the molecular orbitals list.
      | If fid_mo_list is 'all_mo', creates a list containing all molecular orbitals.
      | If fid_mo_list is a list, provides a list (or a list of lists) of molecular 
        orbital labels.

  **Supported Formats:**
  
    Integer List (Counting from **ONE**!)::
    
      1       2       3
      5       4
      h**o    lumo+2:lumo+4
    
    List with Symmetry Labels::
    
      1.1     2.1     1.3
      1.1     4.1
      4.1     2.3     2.1
  
  **Returns:**
  
    Dictionary with following Members:
      :mo: - List of molecular orbital labels.
      :mo_ii: - List of molecular orbital indices.
      :mo_spec: - Selected elements of mo_spec. See :ref:`Central Variables` for details.
      :mo_in_file: - List of molecular orbital labels within the fid_mo_list file.
      :sym_select: - If True, symmetry labels have been used. 
  
  ..attention:
    
    For **unrestricted** calculations, orbkit adds `_a` (alpha) or `_b` (beta) to
    the symmetry labels, e.g., `1.1_a`. 
    If you have specified the option `spin=alpha` or `spin=beta`, only the 
    alpha or the beta orbitals are taken into account for the counting 
    within the Integer List.
  '''
    import re
    display('\nProcessing molecular orbital list...')

    mo_in_file = []
    selected_mo = []
    sym_select = False

    def assign_selected_mo(selected_mo,
                           mo_spec,
                           strict=False,
                           what=lambda x, y: y[x]['sym']):
        selected_mo_spec = []
        selected_mo_ii = []
        for i in selected_mo:
            is_present = False
            for k in range(len(mo_spec)):
                if (what(k, mo_spec) == i):
                    is_present = True
                    if strict or (i not in selected_mo_ii):
                        selected_mo_spec.append(mo_spec[k])
                        selected_mo_ii.append(what(k, mo_spec))
            if not is_present:
                raise IOError('Cannot find %s in mo_spec' % i)
        selected_mo_ii = numpy.array(selected_mo_ii)
        return selected_mo_spec, selected_mo_ii

    def expr2int(expr):
        if isinstance(expr, int):
            return expr
        x = 0
        for i in re.findall(r'\d+|[+-]\d+', expr):
            x += int(i)
        return x

    def get_selection(selected_mo):
        mo_occup = numpy.array([i['occ_num'] for i in mo_spec])
        h**o = (mo_occup > 0.).nonzero()[0][-1] + 1  # molden numbering
        lumo = (mo_occup > 0.).nonzero()[0][-1] + 1 + 1  # molden numbering
        mo_energy = numpy.array([i['energy'] for i in mo_spec])
        last_bound = sum(mo_energy <= 0.0)  # molden numbering
        sel = []
        for i in selected_mo:
            i = i.lower().replace('h**o', str(h**o)).replace('lumo', str(lumo))
            i = i.replace('last_bound', str(last_bound))
            if ':' in i:
                k = [1, len(mo_spec) + 1, 1]
                i = i.split(':')
                for ik, j in enumerate(i):
                    if j != '': k[ik] = j
                i = list(range(*[expr2int(j) for j in k]))
                sel.extend(i)
            else:
                sel.append(int(i))
        return sel

    if isinstance(fid_mo_list, str) and fid_mo_list.lower() == 'all_mo':
        selected_mo = numpy.array(numpy.arange(len(mo_spec)) + 1,
                                  dtype=numpy.str)
        mo_in_file = [selected_mo]
        selected_mo_spec = mo_spec
        selected_mo_ii = numpy.array([i['sym'] for i in selected_mo_spec])
    else:
        if isinstance(fid_mo_list, str) and not path.exists(fid_mo_list):
            if ',' in fid_mo_list:
                fid_mo_list = fid_mo_list.split(',')
            else:
                fid_mo_list = [fid_mo_list]
        if isinstance(fid_mo_list, list):
            for i in fid_mo_list:
                if not isinstance(i, list):
                    i = i.split(',') if isinstance(i, str) else [i]
                selected_mo.extend(list(map(str, i)))
                mo_in_file.append(list(map(str, i)))
        else:
            try:
                fid = open(fid_mo_list, 'r')
                flines = fid.readlines()
                fid.close()
                for line in flines:
                    integer = line.replace(',', ' ').split()
                    mo_in_file.append(integer)
                    selected_mo.extend(integer)
            except:
                raise IOError('The selected mo-list (%(m)s) is not valid!' %
                              {'m': fid_mo_list} +
                              '\ne.g.\n\t1\t3\n\t2\t7\t9\n')

        # Print some information
        for i, j in enumerate(mo_in_file):
            display('\tLine %d: %s' % (i + 1, ', '.join(j)))

        # Check if the molecular orbitals are specified by symmetry
        # (e.g. 1.1 in MOLPRO nomenclature) or
        # by the number in the input file (e.g. 1)

        try:  # Try to convert selections into integer
            for i in selected_mo:
                if isinstance(i, int):
                    continue
                i = i.replace('h**o',
                              '1').replace('lumo',
                                           '2').replace('last_bound', '3')
                for r in ['-', '+', ':']:
                    i = i.replace(r, '')
                int(i)
        except ValueError:
            sym_select = True
            errors = []
            for i in range(len(selected_mo)):
                if not '.' in selected_mo[i]:
                    errors.append(i)
            if errors:
                err = [selected_mo[i] for i in errors]
                raise IOError(
                    '`%s` are no valid labels according ' % ', '.join(err) +
                    'to the MOLPRO nomenclature, e.g., `5.1` or `5.A1`.' +
                    '\n\tHint: You cannot mix integer numbering and MOLPRO\'s '
                    + 'symmetry labels')

        if sym_select:
            what = lambda x, y: y[x]['sym']
            selected_mo_spec, selected_mo_ii = assign_selected_mo(
                selected_mo, mo_spec, strict=strict, what=what)
        else:
            selected_mo = get_selection(selected_mo)

            if not strict:
                selected_mo = list(map(int, selected_mo))
                selected_mo.sort()
            selected_mo = list(map(str, selected_mo))
            what = lambda x, y: str(x + 1)
            selected_mo_spec, selected_mo_ii = assign_selected_mo(
                selected_mo, mo_spec, strict=strict, what=what)
            selected_mo = selected_mo_ii
            for i in range(len(mo_in_file)):
                mo_in_file[i] = list(map(str, get_selection(mo_in_file[i])))

        # Print some information
        display('\nThe following orbitals will be considered...')
        for i, j in enumerate(mo_in_file):
            display('\tLine %d: %s' % (i + 1, ', '.join(j)))

    display('')
    return {
        'mo': selected_mo,
        'mo_ii': selected_mo_ii,
        'mo_spec': selected_mo_spec,
        'mo_in_file': mo_in_file,
        'sym_select': sym_select
    }
Ejemplo n.º 29
0
def main_output(data,
                qc=None,
                outputname='data',
                otype='auto',
                gname='',
                drv=None,
                omit=[],
                datalabels='',
                mode='w',
                **kwargs):
    '''Creates the requested output.
  
  **Parameters:**
  
  data : numpy.ndarray, shape=N, shape=((NDRV,) + N), shape=(n, (NDRV,) + N) or list of numpy.ndarrays
    Contains the output data. The shape (N) depends on the grid and the data, i.e.,
    3d for regular grid, 1d for vector grid. 
  qc : class or dict
    QCinfo class or dictionary containing the following attributes/keys.
    See :ref:`Central Variables` for details.
  outputname : str or list of str
    Contains the base name of the output file. If outputname contains @, string will be split and first 
    part interpreted as outputname and second as gname (cf. Parameters:gname). 
  otype : str or list of str, optional
    Contains the output file type. Possible options:
    'auto', 'h5', 'cb', 'am', 'hx', 'vmd', 'mayavi'
    
    If otype='native', a native input file will be written, the type of which may be specifie by
    ftype='numpy'.
  gname : str, optional
    For native, HDF5, or npz output, specifies the group, where the data will be stored.
  drv : None, list of str or list of list of str, optional
    If not None, a 4d(regular)/2d(vector) input data array will be expected
    with NDRV = len(drv). Specifies the file labels, i.e. e.g., data_d{drv}.cube for 4d array.
    For 5d arrays i.e., data_0_d{drv}.cube
  datalabels : list of str, optional
    If not empty, the output file types specified here are omitted.
  omit : list of str, optional
    If not empty, the output file types specified here are omitted.
  mode : str={'r', 'w', 'a'}, optional
    Specifies the mode used to open the file (native, HDF5, or npz). 
  
  **Note:**
  
    All additional keyword arguments are forwarded to the output functions.
  '''
    if otype is None or otype == []:
        return []

    if isinstance(outputname, str):
        if '@' in outputname:
            outputname, gname = outputname.split('@')
    if isinstance(otype, str):
        if otype == 'auto':
            outputname, otype = path.splitext(outputname)
            otype = otype[1:]
        otype = [otype]
    elif isinstance(otype, list) and len(otype) == 1:
        if otype[0] == 'auto':
            outputname, otype = path.splitext(outputname)
            otype = [otype[1:]]
    else:
        for iot in range(len(otype)):
            if otype[iot] == 'auto':
                outputname, tmp = path.splitext(outputname)
                if tmp != '':
                    otype[iot] = tmp[1:]

    # Catch our native format before all else
    # We can't figure this out by the file ending alone
    # as we support hdf5 for output of both grid-based data
    # as well as our internal format

    output_written = []
    internals = [i for i in range(len(otype)) if otype[i] == 'native']

    if len(internals) > 0:
        if not isinstance(data, list):
            data = [data]

        if isinstance(outputname, str):
            outputname = [outputname for _ in data]

        if 'ftype' in kwargs.keys():
            if isinstance(kwargs['ftype'], str):
                ftype = [kwargs['ftype'] for _ in data]
        else:
            ftype = ['numpy' for _ in data]

        if 'group' in kwargs.keys():
            if isinstance(kwargs['group'], str):
                group = [kwargs['group'] for _ in data]
        else:
            group = [i.__class__.__name__.lower() for i in data]

        display('Writing native input file...')
        for i, oname in enumerate(outputname):
            output_written.append(
                write_native(data[i],
                             oname,
                             ftype[i],
                             mode=mode,
                             gname=path.join(gname, group[i])))
        display('\n'.join(['\t' + i for i in output_written]))

    else:
        print_waring = False
        output_not_possible = (grid.is_vector and not grid.is_regular)

        # Shape shall be (Ndrv,Ndata,Nx,Ny,Nz) or (Ndrv,Ndata,Nxyz)
        data = numpy.array(data)
        dims = 1 if grid.is_vector else 3
        shape = data.shape

        if drv is not None and isinstance(drv, str):
            drv = [drv]

        if data.ndim < dims:
            output_not_possible = True
            display('data.ndim < ndim of grid')
        elif data.ndim == dims:  # 3d data set
            data = data[numpy.newaxis, numpy.newaxis]
        elif data.ndim == dims + 1:  # 4d data set
            if drv is not None:
                data = data[:, numpy.newaxis]
            else:
                data = data[numpy.newaxis]
        elif data.ndim == dims + 2:  # 5d data set check if drv matches Ndrv
            if drv is None or len(drv) != data.shape[0]:
                drv = list(range(data.shape[0]))
        elif data.ndim > dims + 2:
            output_not_possible = True
            display('data.ndim > (ndim of grid) +2')

        if 'vmd' in otype and not ('cb' in otype or 'cube' in otype):
            otype.append('cube')
        if 'hx' in otype and not 'am' in otype:
            otype.append('am')

        otype = [i for i in otype if i not in omit]
        otype_synonyms = [synonyms[i] for i in otype]
        otype_ext = dict(zip(otype_synonyms, otype))

        # Convert the data to a regular grid, if possible
        is_regular_vector = (grid.is_vector and grid.is_regular)

        if is_regular_vector:
            display(
                '\nConverting the regular 1d vector grid to a 3d regular grid.'
            )
            grid.vector2grid(*grid.N_)
            data = numpy.array(grid.mv2g(data))

        isstr = isinstance(outputname, str)
        if isinstance(datalabels, str):
            if data.shape[1] > 1:
                datalabels = numpy.array([
                    str(idata) + ',' + datalabels
                    for idata in range(data.shape[1])
                ])
            else:
                datalabels = numpy.array([datalabels])
        elif isinstance(datalabels, list):
            datalabels = numpy.array(datalabels)

        if drv is not None:
            fid = '%(f)s_d%(d)s.'
            datalabel_id = 'd/d%(d)s %(f)s'
            contents = {
                'axis:0':
                numpy.array(
                    ['d/d%s' % i if i is not None else str(i) for i in drv]),
                'axis:1':
                datalabels
            }
            it = enumerate(drv)
        elif data.shape[0] > 1:
            fid = '%(f)s_%(d)s.'
            datalabel_id = '%(d)s %(f)s'
            it = enumerate(data.shape[0])
            contents = {
                'axis:0': numpy.arange(data.shape[0]).astype(str),
                'axis:1': datalabels
            }
        else:
            fid = '%(f)s.'
            datalabel_id = '%(f)s'
            it = [(0, None)]
            if data.shape[1] > 1:
                contents = {'axis:0': datalabels}
            else:
                contents = datalabels

        cube_files = []
        all_datalabels = []
        for idrv, jdrv in it:
            datasetlabels = []
            for idata in range(data.shape[1]):
                if isstr:
                    f = {
                        'f':
                        outputname + '_' +
                        str(idata) if data.shape[1] > 1 else outputname,
                        'd':
                        jdrv
                    }
                else:
                    f = {'f': outputname[idata], 'd': jdrv}
                c = {'f': datalabels[idata], 'd': jdrv}
                datalabel = datalabel_id % c
                datasetlabels.append(datalabel)

                if 'am' in otype_synonyms and not print_waring:
                    if output_not_possible: print_waring = True
                    else:
                        filename = fid % f + otype_ext['am']
                        display('\nSaving to ZIBAmiraMesh file...\n\t' +
                                filename)
                        amira_creator(data[idrv, idata], filename)
                        output_written.append(filename)
                if 'hx' in otype_synonyms and not print_waring:
                    if output_not_possible: print_waring = True
                    else:
                        filename = fid % f + otype_ext['hx']
                        display('\nCreating ZIBAmira network file...\n\t' +
                                filename)
                        hx_network_creator(data[idrv, idata], filename)
                        output_written.append(filename)
                if 'cube' in otype_synonyms and not print_waring:
                    if output_not_possible: print_waring = True
                    elif qc is None:
                        display(
                            '\nFor cube file output `qc` is a required keyword parameter in `main_output`.'
                        )
                    else:
                        filename = fid % f + otype_ext['cube']
                        display('\nSaving to cube file...\n\t' + filename)
                        cube_creator(data[idrv, idata],
                                     filename,
                                     qc.geo_info,
                                     qc.geo_spec,
                                     comments=datalabel,
                                     **kwargs)
                        output_written.append(filename)
                        cube_files.append(filename)

            all_datalabels.extend(datasetlabels)

        if 'vmd' in otype_synonyms and not print_waring:
            if output_not_possible: print_waring = True
            else:
                filename = (outputname if isstr else
                            outputname[-1]) + '.' + otype_ext['vmd']
                display('\nCreating VMD network file...\n\t' + filename)
                vmd_network_creator(filename, cube_files=cube_files, **kwargs)
                output_written.append(filename)

        if 'h5' in otype_synonyms:
            filename = (outputname
                        if isstr else outputname[-1]) + '.' + otype_ext['h5']
            display('\nSaving to Hierarchical Data Format file (HDF5)...\n\t' +
                    filename)

            hdf5_creator(data.reshape(shape),
                         filename,
                         qcinfo=qc,
                         gname=gname,
                         ftype='hdf5',
                         contents=contents,
                         mode=mode,
                         **kwargs)
            output_written.append(filename)

        if 'npz' in otype_synonyms:
            filename = (outputname if isstr else outputname[-1])
            display('\nSaving to a compressed .npz archive...\n\t' + filename +
                    '.npz')
            hdf5_creator(data.reshape(shape),
                         filename,
                         qcinfo=qc,
                         gname=gname,
                         ftype='numpy',
                         contents=contents,
                         mode=mode,
                         **kwargs)
            output_written.append(filename)

        if 'mayavi' in otype_synonyms:
            if output_not_possible: print_waring = True
            else:
                display('\nDepicting the results with MayaVi...\n\t')
                if drv == ['x', 'y', 'z'] or drv == [0, 1, 2]:
                    is_vectorfield = True
                    data = numpy.swapaxes(data, 0, 1)
                    datalabels = datalabels
                else:
                    is_vectorfield = False
                    data = data.reshape((-1, ) + grid.get_shape())
                    datalabels = all_datalabels

                view_with_mayavi(grid.x,
                                 grid.y,
                                 grid.z,
                                 data,
                                 is_vectorfield=is_vectorfield,
                                 geo_spec=qc.geo_spec,
                                 datalabels=datalabels,
                                 **kwargs)

        if print_waring:
            display(
                'For a non-regular vector grid (`if grid.is_vector and not grid.is_regular`)'
            )
            display('only HDF5 is available as output format...')
            display('Skipping all other formats...')

        if is_regular_vector:
            # Convert the data back to a regular vector grid
            grid.grid2vector()

    return output_written
Ejemplo n.º 30
0
def gross_atomic_density(atom,
                         qc,
                         bReturnmo=False,
                         ao_list=None,
                         mo_list=None,
                         drv=None):
    r'''Computes the gross atomic density with respect to the selected atoms.
  
  .. math::
  
    \rho^a = \sum_i^{N_{\rm MO}} {\rm occ}_i \cdot \varphi_i^a \cdot \varphi_i
  
  
  **Parameters:**
  
    atom : 'all' or int or list of int
      Specifies the atoms (counting from one) for which the gross atomic density
      will be computed.  
      If (atom == 'all') or (atom == -1), computes the gross atomic density  
      for all atoms.
    qc.geo_spec, qc.geo_info, qc.ao_spec, qc.mo_spec :
      See :ref:`Central Variables` for details.
    bReturnmo : bool, optional
      If True, the gross atomic molecular orbitals are additionally returned.

  **Returns:**
  
    rho_atom : list of numpy.ndarrays, shape=(len(atoms,) + N)
      Contains the atom gross atomic density on a grid.
    mo_atom : list of numpy.ndarrays, shape=(len(atoms,NMO) + N)
      Contains the NMO=len(mo_spec) gross atomic molecular orbitals on a grid. 
  '''

    if (atom == 'all' or atom == -1):
        atom = range(1, len(qc.geo_info) + 1)

    atom, index = atom2index(atom, geo_info=qc.geo_info)

    display('Computing the gross atomic density with respect to ' +
            'the atom(s) (internal numbering)')
    outp = '\t['
    for i, a in enumerate(atom):
        if not i % 10 and i != 0:
            outp += '\n\t'
        outp += '%d,\t' % a
    display('%s]\n' % outp[:-2])

    display('\tCalculating ao_list & mo_list')
    if ao_list is None:
        ao_list = core.ao_creator(qc.geo_spec, qc.ao_spec, drv=drv)
    if mo_list is None:
        mo_list = core.mo_creator(ao_list, qc.mo_spec)

    display('\tCalculating the gross atomic density')
    N = mo_list.shape[1:]
    if bReturnmo: mo_atom = [[] for a in index]
    rho_atom = [numpy.zeros(N) for a in index]
    for i, a in enumerate(index):
        display('\t\tFinished %d of %d' % (i + 1, len(index)))
        ao_index = []
        ao = []
        ll = 0
        for ii in qc.ao_spec:
            for l in range(core.l_deg(l=ii['type'])):
                if ii['atom'] == a:
                    ao_index.append(ll)
                    ao.append(ao_list[ll])
                ll += 1

        for ii_mo, spec in enumerate(qc.mo_spec):
            mo_info = numpy.zeros(N)
            for jj in range(len(ao_index)):
                mo_info += spec['coeffs'][ao_index[jj]] * ao[jj]
            rho_atom[i] += spec['occ_num'] * mo_list[ii_mo] * mo_info
            if bReturnmo: mo_atom[i].append(mo_info)

    string = 'Returning the gross atomic density'
    if bReturnmo:
        display(string + ' and\n\tthe gross atomic molecular orbitals')
        return rho_atom, mo_atom
    else:
        display(string)
        return rho_atom