# ORBKIT’s Low-Level Interface¶

This section is addressed to more advanced users, who want to use the modules of ORBKIT in their own programs.

Please refer to the Function Reference to get information about all modules and functions available.

Hint

Complete examples of using ORBKIT’s modules can be found in orbkit/examples, e.g., use_as_module.py and calculate_derivatives.py)

The tutorials Tutorial for the Integration with Cubature and Tutorial for Processing Multiple Input Files show further practical applications.

All reading processes are handled by the module orbkit.read, i.e.:

from orbkit import read


Here, you have one function for each quantum chemistry input type converting the input to the QCinfo class (cf. Central Variables). These functions are managed by:

qc = read.main_read(filename,itype='molden',all_mo=False,spin=None,**kwargs)


Besides choosing the filename and the input type, you can specify, if the function should read the occupied and the virtual molecular orbitals (all_mo). Moreover, read.main_read forwards all additional keyword arguments (**kwargs) to the specific reading function, e.g., you can disable the interactive mode in read.read_molden. For unrestricted calculations, the spin keyword can specify, if only molecular orbitals of alpha or beta spin shall be read.

Hint

The main computational functions are not restricted to the QCinfo class. They also accept dictionaries having the same members.

You can convert the QCinfo class to a dictionaries containing only the essential members by:

qc_dict = qc.todict()


## Initializing the Grid¶

The orbkit.grid module organizes all grid related features of ORBKIT, of which some will be discussed in this section.

If you want to initialize a standard regular (vector) grid you have to set the grid parameters which are global values within this module:

from orbkit import grid
grid.min_ = [-8.0, -8.0, -8.0]   #: Specifies minimum grid values (regular grid).
grid.max_ = [ 8.0,  8.0,  8.0]   #: Specifies maximum grid values (regular grid).
grid.N_   = [ 101,  101,  101]   #: Specifies the number of grid points (regular grid).


Note

If you prefer setting the grid spacing instead of the number of data points, you may set this parameters by:

ok.grid.delta_ = [0.1, 0.2, 0.1]


Now, you can initialize the grid:

grid.grid_init(is_vector=False, force=False)


To invoke the creation of a vector grid, i.e., $$N_{\sf data points} = N_{\sf x} = N_{\sf y} = N_{\sf z}$$ (see Grid Related Options (Usage via the Terminal)), the variable is_vector has to set to True. If you want to change the grid, e.g., for a subsequent calculation, you have either to set:

grid.is_initialized=False


or to call:

grid.grid_init(force=True)


Hint

The current grid parameters can be displayed with:

print(grid.get_grid())


Another way to automatically set the grid parameters according to the molecular geometry is calling:

grid.adjust_to_geo(qc,extend=5.0,step=0.1)


Here, ORBKIT creates grid parameters (grid.min_, grid.max_, grid.N_) with a grid spacing of 0.1 a0 and the size of the molecule plus 5 a0 in each direction. After calling this function you have to initialize the grid using grid.grid_init().

The last way to initialize a grid is by setting the x, y, z coordinates manually:

import numpy
grid.x = numpy.linspace(-10,10,201)
grid.y = numpy.array([0],dtype=float)
grid.z = numpy.array([-1.0,1.1])
# We have already initialized a grid for orbkit:
grid.is_initialized = True


Here, x, y and z have to be one-dimensional numpy.array of type float (numpy.float64).

If you have set a regular grid, please be sure that you set the following variables:

grid.is_vector = False
grid.is_regualar = True


Attention

The last line is mandatory, i.e., we have to tell ORBKIT, that there is no need to initialize the grid.

Hint

For your convenience, you may also set the variable grid.is_vector = True, if you have initialized a vector grid manually. You can use this standard variable as input parameter in other ORBKIT functions.

## Operations on the Grid¶

The module orbkit.grid has some more features. For instance, starting from a regular grid, you can always convert between regular and a vector grid:

from orbkit import grid
# Initialize the grid
grid.grid_init(is_vector=False, force=False)

# Convert the grid to a vector grid
grid.grid2vector()
print(grid.get_grid())        # Display the new grid parameters

# Convert it back to a regular grid
grid.vector2grid(*grid.N_)
# Display the new grid parameters
print(grid.get_grid())        # Display the new grid parameters


The same can be done for matrices of the specific shapes, e.g.:

import numpy
from orbkit import grid

# Initialize a vector grid
grid.grid_init(is_vector=True)

# Create an array of the same shape, i.e., Nx=Ny=Nz=shape(matrix)
matrix = numpy.arange(len(grid.x))
Nx, Ny, Nz = grid.N_
matrix = grid.matrix_vector2grid(matrix=matrix,Nx=Nx,Ny=Ny,Nz=Nz)


## Computational Functions¶

All major computational processes are carried out by the module orbkit.core. The function rho_compute manages the computational tasks, slices the grid, and distributes the slices to the subprocesses:

from orbkit import core
data = core.rho_compute(qc,calc_mo=False,slice_length=1e4,
drv=None,laplacian=False,numproc=1)


If you set calc_mo=True, all molecular orbitals will be computed and returned. The variable slice_length contains an integer value specifying the number of grid points per subprocess.

Derivatives can be computed by changing the variable drv, e.g., drv=['x','zz','xy'] will invoke the computation of the first derivative with respect to $$x$$, the second derivative with respect to $$z$$, and the mixed derivative $$xy$$.

If the number of processes (numproc) is smaller or equal one, no subprocesses will be started, i.e., ORBKIT uses only a single CPU. If you even want to omit the slicing of the grid, you can use:

data = core.rho_compute_no_slice(qc,calc_mo=False,drv=None,laplacian=False
return_components=False,
is_vector=None,x=None,y=None,z=None)


Here, you can even return the atomic orbitals (and/or their derivatives) as well with return_components. Furthermore, you can specify the grid (x, y, z, and is_vector) without using the orbkit.grid module.

If you do not want to use those functions, you can go further to the function computing the atomic orbitals and the function combining these orbitals to molecular orbitals:

ao_list = core.ao_creator(geo_spec,ao_spec,ao_spherical=ao_spherical,drv=None,
is_vector=None,x=None,y=None,z=None)
mo_list = core.mo_creator(ao_list,mo_spec)


Those functions use the only specific members of the QCinfo class. Again, you can specify the grid (x, y, z, and is_vector) without using the orbkit.grid module.

The functionalities calc_mo and mo_set, i.e., the computation of selected molecular orbitals and the calculation of the density with a selected set of molecular orbitals, are handled by two functions of the module orbkit.extras:

mo_list, mo_info = extras.calc_mo(qc, fid_mo_list, drv=None, otype=None, ofid=None)


and:

data = extras.mo_set(qc, fid_mo_list, drv=None, laplacian=False,
otype=None, ofid=None, return_all=True)


fid_mo_list is a list molecular orbital labels, cf. Molecular Orbital Selection (High-Level Interface). Here, slice_length and numproc are read from the respective orbkit.options variables.

## Output Functions¶

The output functionalities of ORBKIT are handled by the module orbkit.output.

In this module, there are functions for every output type. These functions are managed by:

output.main_output(data,geo_info,geo_spec,outputname='new',otype='h5',
drv=None,omit=[],**kwargs)