Ejemplo n.º 1
0
  def compute_mo_list(self,ao_spec,mo_matrix,
                      iter_drv=[None, 'x', 'y', 'z']):
    '''Computes the values of the molecular orbitals and, if requested, their 
    derivatives at the nuclear positions for a complete 
    mo_matrix (shape=(Nfiles,NMO,NAO)).'''
    from orbkit.core import ao_creator
    
    shape = numpy.shape(mo_matrix)
    mo_list = numpy.zeros((shape[0],shape[1],4*numpy.shape(self.geo_spec_all)[1]))

    for rr in range(shape[0]):
      geo_spec = self.geo_spec_all[rr]
      x = geo_spec[:,0]
      y = geo_spec[:,1]
      z = geo_spec[:,2]
      N = len(x)
      for i,drv in enumerate(iter_drv):
        ao_list = ao_creator(geo_spec,self.ao_spec,
                             exp_list=False,
                             is_vector=True,
                             drv=drv,
                             x=x,y=y,z=z)
        for i_mo in range(shape[1]):
          for i_ao in range(shape[2]):
            mo_list[rr,i_mo,N*i+numpy.arange(N)] += mo_matrix[rr,i_mo,i_ao] * ao_list[i_ao,:]
      
      return mo_list
Ejemplo n.º 2
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.º 3
0
 def show_selected_mos(self,selected_mos,r0=0,steps=1,select_slice='xz',where=0.0,
                       npts=[26,51],minpts=[-3,-6],maxpts=[3,6],nuclear_pos='x'):
   '''Uses orbkit to compute selected molecular orbitals and plots it with
   :func:`contour_mult_mo`.'''
   from orbkit import grid
   from orbkit.core import ao_creator,mo_creator
   r = range(r0,r0+steps)
   
   grid.N_ = [1,1,1]
   grid.min_ = [0,0,0]
   grid.max_ = [0,0,0]
   if select_slice == 'xy':
     k = [0,1]
     grid.min_[2] += where
     grid.max_[2] += where
   elif select_slice == 'yz':
     k = [1,2]
     grid.min_[0] += where
     grid.max_[0] += where
   elif select_slice == 'xz':
     k = [0,2]
     grid.min_[1] += where
     grid.max_[1] += where
   else:
     raise ValueError('`show_selected_mos` currently only' + 
                      'supports slices parallel to the following planes:' +
                      'select_slice = `xy`, `yz`, or `xz`')
   for i,j in enumerate(k):
     grid.N_[j] = npts[i]
     grid.min_[j] = minpts[i]
     grid.max_[j] = maxpts[i]
   
   # Initialize grid
   grid.is_initialized = False
   grid.grid_init(force=True)
   xyz = grid.x,grid.y,grid.z
   for mo_sel in selected_mos:
     i,j = mo_sel.split('.')
     mo = []
     for rr in r:
       ao_list = ao_creator(self.geo_spec_all[rr],self.ao_spec)
       mo.append(mo_creator(ao_list,mo_coeff_all[self.sym[j]][rr,int(i)-1,numpy.newaxis])[0].reshape(tuple(npts)))
     
     f, pics = contour_mult_mo(xyz[k[0]],xyz[k[1]],mo,
                     xlabel=select_slice[0],ylabel=select_slice[1],
                     title='MO:%s' % mo_sel,r0=r0)
     for i,pic in enumerate(pics):
       pic.plot(self.geo_spec_all[rr,:,k[1]],self.geo_spec_all[rr,:,k[0]],nuclear_pos,
                markersize=10,markeredgewidth=2)
Ejemplo n.º 4
0
def get_ao(x):
  ao_list = core.ao_creator(global_args['geo_spec'],
                            [global_args['ao_spec'][int(x)]],
                            drv=global_args['drv'])
  
  if global_args['otype'] is not None:
    drv = global_args['drv']
    comments = '%03d.lxlylz=%s,at=%d' %(x,
                                         global_args['ao_spec'][x]['exp_list'][0],
                                         global_args['ao_spec'][x]['atom'])
    
    output.main_output(ao_list[0] if drv is None else ao_list,
                       global_args['geo_info'],
                       global_args['geo_spec'],
                       comments=comments,
                       outputname='%s_AO_%03d' % (global_args['ofid'],x),
                       otype=global_args['otype'],
                       omit=['h5','vmd','mayavi'],
                       drv = None if drv is None else [drv])
  return ao_list
Ejemplo n.º 5
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.º 6
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