\documentclass[letterpaper]{article}
\usepackage[letterpaper]{geometry}
\usepackage{amsmath}
\usepackage{braket}
\usepackage{hyperref}

\usepackage{listings}
\usepackage{color}

\definecolor{mygreen}{rgb}{0,0.6,0}
\definecolor{mygray}{rgb}{0.5,0.5,0.5}
\definecolor{mymauve}{rgb}{0.58,0,0.82}

\lstset{
  backgroundcolor=\color{white},
  basicstyle=\footnotesize,
  breakatwhitespace=false,
  breaklines=true,
  captionpos=b,
  commentstyle=\color{mygreen},
  deletekeywords={...},
  escapeinside={\%*}{*)},
  extendedchars=true,
  firstnumber=1,
  frame=single,
  keepspaces=true,
  keywordstyle=\color{blue},
  language=Python,
  morekeywords={*,...},
  numbers=left,
  numbersep=5pt,
  numberstyle=\tiny\color{mygray},
  rulecolor=\color{black},
  showspaces=false,
  showstringspaces=false,
  showtabs=false,
  stepnumber=1,
  stringstyle=\color{mymauve},
  tabsize=2,
  title=\lstname,
  belowskip=-14pt,
}


\title{gbasis}
\begin{document}
\tableofcontents

\section{Mandate}
\begin{itemize}
\item summary
\item audience
  \begin{itemize}
  \item Developers in quantum chemistry
  \item Theory people looking for quick implementation of ideas
  \item ChemTools
  \end{itemize}
\item features
\item software
  \begin{itemize}
  \item Pure Python
  \item Multiplatform (Windows, MacOS, Linux)
  \item NumPy and SciPy are the only dependencies
  \item Parallizeable (to the extend that numpy is parallizeable)
  \item Open-source
  \end{itemize}
\end{itemize}

\section{Gaussian Primitive}
A Cartesian Gaussian primitive is
\begin{equation}
  \label{eq:cart_prim}
  g_i(\mathbf{r} | \mathbf{R}_A, \mathbf{a}) =
  N(\alpha_i, \mathbf{a})
  (x - X_A)^{a_x} (y - Y_A)^{a_y} (z - Z_A)^{a_z}
  \exp \left(-\alpha_i |\mathbf{r} - \mathbf{R}_A|^2 \right)
\end{equation}
where $\mathbf{r} = (x, y, z)$, $\mathbf{R}_A = (X_A, Y_A, Z_A)$ is the center
of the primitive, $\mathbf{a} = (a_x, a_y, a_z)$ is the Cartesian components of
the angular momentum, $\ell = a_x + a_y + a_z$, and
\begin{equation}
  \label{eq:cart_norm}
  \begin{split}
    N (\alpha_i, \mathbf{a}) &=
    \sqrt{
      \left(
        \frac{2 \alpha_i}{\pi}
      \right)^{\frac{3}{2}}
      \frac{(4 \alpha_i)^{a_x + a_y + a_z}}{(2 a_x -1)!! (2 a_y -1)!! (2 a_z -1)!!}
    }\\
    &= \sqrt{
      \left(
        \frac{2 \alpha_i}{\pi}
      \right)^{\frac{3}{2}}
      (4 \alpha_i)^{\ell}
    }
    \sqrt{\frac{1}{(2 a_x -1)!! (2 a_y -1)!! (2 a_z -1)!!}}\\
    &= N_1 (\alpha_i, \ell) N_2 (\mathbf{a})
  \end{split}
\end{equation}
is the normalization constant of the Cartesian primitive.
In this module, the primitives are normalized.

A spherical Gaussian primitive is
\begin{equation}
  \label{eq:sph_prim}
  g^s_i(r | \mathbf{R}_A, m, \ell) =
  N_s(\alpha_i, \ell)
  Y_{\ell m} (\phi, \theta)
  r^\ell
  \exp \left(-\alpha_i r^2 \right)
\end{equation}
where
$\ell$ is the angular momentum,
$m$ is the z component of the angular momentum,
$r = |\mathbf{r} - \mathbf{R}_A|$ is the distance from the center $\mathbf{R}_A$,
$Y_{\ell m}$ is a spherical harmonic,
and
\begin{equation}
  \label{eq:sph_norm}
  N_s (\alpha_i, \ell)
  = \sqrt{
    \left(
      \frac{2 \alpha_i}{\pi}
    \right)^{\frac{3}{2}}
    \frac{(4 \alpha_i)^{\ell}}{(2\ell - 1)!!}
  }\\
\end{equation}
is the normalization constant of the spherical primitive.
In this module, we treat all spherical harmonics to be real.

The ``solid harmonic'' (Helgaker 6.4.2), $Y_{\ell m} (\phi, \theta) r^\ell$, can
be transformed into the corresponding Cartesian expression,
$(x - X_A)^{a_x} (y - Y_A)^{a_y} (z - Z_A)^{a_z}$.
Real-valued solid harmonics are denoted with $S_{\ell m}$.
\begin{equation}
  \label{eq:sph_prim_2}
  g^s_i(r | \mathbf{R}_A, m, \ell) =
  N_s(\alpha_i, \ell)
  S_{\ell m} (r, \phi, \theta)
  \exp \left(-\alpha_i r^2 \right)
\end{equation}
In this module, we strictly utilize Cartesian Gaussian primitives at the lower
level and transform to the spherical form whenever needed.
Therefore, primitives will refer to Cartesian primitives unless otherwise stated.

\subsection{Transformation of Spherical Primitives to Cartesian Primitives}
To transform the spherical primitives to Cartesian primitives, the (real) solid
harmonics are first transformed into the Cartesian expressions.
Using the equations from Helgaker 6.4.4,
\begin{equation}
  \label{eq:helgaker_6.4.47}
  S_{\ell m}
  =
  N_{\ell m}^S
  \sum_{t=0}^{\lfloor \frac{\ell - |m|}{2} \rfloor}
  \sum_{u=0}^t \sum_{v=0}^{\lfloor\frac{|m|}{2} \rfloor}
  C^{lm}_{tuv} x^{2t + |m| - 2(u+v_m)} y^{2(u+v_m)} z^{\ell - 2t - |m|}
\end{equation}
where
\begin{equation}
  \label{eq:helgaker_6.4.50}
  v_m =
  \begin{cases}
    v & \mbox {if $m \geq 0$}\\
    v + \frac{1}{2} & \mbox {if $m < 0$}
  \end{cases}
\end{equation}
\begin{equation}
  \label{eq:helgaker_6.4.48}
  C^{lm}_{tuv} =
  (-1)^{t+v}
  \left( \frac{1}{4} \right)^t
  \binom{\ell}{t} \binom{\ell -t}{|m| + t} \binom{t}{u} \binom{|m|}{2 v_m}
\end{equation}
\begin{equation}
  \label{eq:helgaker_6.4.49}
  N_{\ell m}^S =
  \frac{1}{2^{|m|} \ell!}
  \sqrt{
    \frac{2 (\ell + |m|)! (\ell - |m|)!}{2^{\delta_{0m}}}
  }
\end{equation}

By linearly transforming the all of primitives with different Cartesian
expressions, $(x - X_A)^{a_x} (y - Y_A)^{a_y} (z - Z_A)^{a_z}$, for the given
angular momentum using Equation~\ref{eq:helgaker_6.4.47}, spherical primitives
can be obtained, though they are normalized with the Cartesian normalization
constants.

Then, the normalization constant of the Cartesian primitive must be replaced
with the spherical primitive by multiplying the newly formed spherical
primitives with the following factor.
\begin{equation}
  \begin{split}
    \frac{N_s(\alpha_i, \ell)}{N(\alpha_i, \mathbf{a})}
    &= \frac{
      \sqrt{
        \left(\frac{2 \alpha_i}{\pi} \right)^{\frac{3}{2}}
        \frac{(4 \alpha_i)^{\ell}}{(2\ell - 1)!!}
      }
    }{
      \sqrt{
        \left(\frac{2 \alpha_i}{\pi} \right)^{\frac{3}{2}} (4 \alpha_i)^{\ell}
      }
      \sqrt{
        \frac{1}{(2 a_x -1)!! (2 a_y -1)!! (2 a_z -1)!!}
      }
    }\\
    &= \sqrt{\frac{(2 a_x -1)!! (2 a_y -1)!! (2 a_z -1)!!}{(2\ell - 1)!!}}
  \end{split}
\end{equation}

\section{Contractions}
Cartesian contractions are linear combinations of Cartesian primitives.
\begin{equation}
  \label{eq:contraction}
  \begin{split}
    \phi (\mathbf{r} | \mathbf{R}_A, \mathbf{a}, \mathbf{d}, \boldsymbol{\alpha})
    &= N_c(\mathbf{R}_A, \mathbf{a}, \mathbf{d}, \boldsymbol{\alpha})
    \sum_i d_i g_i(\mathbf{r} | \mathbf{R}_A, \mathbf{a})\\
    &= N_c(\mathbf{R}_A, \mathbf{a}, \mathbf{d}, \boldsymbol{\alpha})
    N_2(\mathbf{a}) (x - X_A)^{a_x} (y - Y_A)^{a_y} (z - Z_A)^{a_z}
    \sum_i N_1(\alpha_i, \ell)
    \exp \left(-\alpha_i |\mathbf{r} - \mathbf{R}_A|^2 \right)
  \end{split}
\end{equation}
where $\mathbf{d}$ is the contraction coefficient, $\mathbf{a}$ are the
exponents of the primitive, and
\begin{equation}
  \label{eq:contraction_norm}
  \begin{split}
    N_c(\mathbf{R}_A, \mathbf{a}, \mathbf{d}, \boldsymbol{\alpha})
    &=
    \left(
      \int
      \left(
        \sum_i d_i g_i(\mathbf{r} |\mathbf{R}_A, \mathbf{a})
      \right)
      \left(
        \sum_j d_j g_j(\mathbf{r} |\mathbf{R}_A, \mathbf{a})
      \right)
      d\mathbf{r}
    \right)^{-\frac{1}{2}}\\
    &=
    \left(
      \sum_i \sum_j d_i d_j
      \int
      g_i(\mathbf{r} |\mathbf{R}_A, \mathbf{a})
      g_j(\mathbf{r} |\mathbf{R}_A, \mathbf{a})
      d\mathbf{r}
    \right)^{-\frac{1}{2}}
\end{split}
\end{equation}
is the L2 normalization constant of the contraction.
In this module, the contractions are L2 normalized.

Since the Cartesian expression,
$(x - X_A)^{a_x} (y - Y_A)^{a_y} (z - Z_A)^{a_z}$, separates out from the
rest of the primitives, the spherical contractions can be created from
Cartesian contractions in the same way that the spherical primitives are
constructed.
In fact, we can group together many contractions of the same angular momentum
and transform the contractions at the same time.
In many cases, it is economical to group together contractions that share
the same properties.
We will denote these groups as shells.

\subsection{Segmented Contractions}
In order to transform the Cartesian contractions into spherical
contractions, all of the Cartesian components are needed, i.e. all
combinations of nonnegative integers $a_x$, $a_y$, and $a_z$ that adds up to
$\ell$.
Segmented contractions is a group of contractions with the same angular momentum
($\ell$), center ($\mathbf{R}_A$), contraction coefficients ($\mathbf{b}$) and
exponents ($\boldsymbol{\alpha}$):
\begin{equation}
  \label{eq:seg_contraction}
  \left\{
    \phi (\mathbf{r} | \mathbf{R}_A, \mathbf{a}_j, \mathbf{d}, \boldsymbol{\alpha})
    \middle|
    (a_j)_x + (a_j)_y + (a_j)_z = \ell
  \right\}
\end{equation}
To avoid confusion with the term contraction, we use the term ``shell of
segmented contractions''.

\subsection{Generalized Contractions}
Generalized contractions are a set of contractions that have the same center
($\mathbf{R}_A$) and exponents
($\boldsymbol{\alpha}$).
\begin{equation}
  \label{eq:gen_contraction}
  \left\{
    \phi (\mathbf{r} | \mathbf{R}_A, \mathbf{a}_{j\ell}, \mathbf{d}_k, \boldsymbol{\alpha})
    \middle|
    (a_{j\ell})_x + (a_{j\ell})_y + (a_{j\ell})_z = \ell
  \right\}
\end{equation}

In this module, we do not group together contractions that differ in angular momentum.
We use the term ``shell of generalized contractions'' to refer to the set of
contractions with the same center ($\mathbf{R}_A$), same angular momentum
($\ell$) and exponents ($\boldsymbol{\alpha}$):
\begin{equation}
  \label{eq:gen_contraction}
  \left\{
    \phi (\mathbf{r} | \mathbf{R}_A, \mathbf{a}_j, \mathbf{d}_k, \boldsymbol{\alpha})
    \middle|
    (a_j)_x + (a_j)_y + (a_j)_z = \ell
  \right\}
\end{equation}
We can think of shell of generalized contractions as a union of shells of
segmented contractions that differ only by the contraction coefficients, i.e.
they use the same set of primitives.

\section{Basis Set}
In this module, basis set is defined to be a list of shells of generalized
contractions.

\subsection{Loading basis sets}
Basis set information is often stored in text format.
In \verb|gbasis|, the Gaussian94 format (.gbs) and the NWChem format (.nwchem) are
supported.

Example:
Supposed we have the following system:
\begin{lstlisting}
  atoms = ["H", "H"]
  coords = np.array([[0, 0, 0], [0, 0, 1]])
  coord_types = "spherical"
\end{lstlisting}
\begin{itemize}
\item To build a basis set from gbs file for the given atoms and coordinates,
  \begin{lstlisting}[xleftmargin=-25pt]
from gbasis.parsers import parse_gbs, make_contractions

all_basis_dict = parse_gbs("./path/to/from_basissetexchange.gbs")
basis = make_contractions(all_basis_dict, atoms, coords, coord_types)
\end{lstlisting}
\item To build a basis set from nwchem file for the given atoms and coordinates,
  \begin{lstlisting}[xleftmargin=-25pt]
from gbasis.parsers import parse_nwchem, make_contractions

all_basis_dict = parse_nwchem("./path/to/from_basissetexchange.nwchem")
basis = make_contractions(all_basis_dict, atoms, coords, coord_types)
\end{lstlisting}
\end{itemize}
The last argument in the \verb|make_contractions| function, \verb|coord_types|, is the type of coordinate system used by the basis. Details about this variable can be found in the next section.

\verb|gbasis| also interfaces to the module \verb|iodata|, which handles the
inputs and outputs for different quantum chemistry formats, such as Gaussian
formatted checkpoint files (.fchk) and AIM wavefunction files (.wfn and .wfx).

Using \verb|iodata|, suppose we have the following system:
\begin{lstlisting}
from iodata import load_one

mol = load_one("molecule.fchk")
\end{lstlisting}
To build a basis set,
\begin{lstlisting}
from gbasis.wrappers import from_iodata

basis = from_iodata(mol)
\end{lstlisting}


\verb|gbasis| also interfaces to \verb|pyscf|, which is an ab initio computational
chemistry program.

Using \verb|pyscf|, suppose we have the following system:
\begin{lstlisting}
from pyscf import gto
mol = gto.Mole()
mol.build(
     atom = "O 0 0 0; H  0 1 0; H 0 0 1",
     basis = "sto-3g"
)
\end{lstlisting}
To build a basis set,
\begin{lstlisting}
from gbasis.wrappers import from_pyscf

basis = from_pyscf(mol)
\end{lstlisting}

\subsection{Types of coordinate systems used by basis functions}
In \verb|gbasis|, user can provide the coordinate system used by each shell of
generalized contractions.
The function \verb|gbasis.parsers.make_contractions| has the positional argument \verb|coord_type| to
specify the coordinate systems used by the basis.
If \verb|coord_type| is \verb|"spherical"| (or \verb|"p"|), all of the shells are treated to be spherical.
If \verb|coord_type| is \verb|"cartesian"| (or \verb|"c"|), all of the shells are treated to be
Cartesian.
If different shells correspond to different coordinate system, then a list/tuple
of the same length as the basis set must be provided with each entry being
\verb|"spherical"| or \verb|"cartesian"| to specify the coordinate system of the
corresponding shell.

Example:
\begin{itemize}
\item To treat all contractions to be spherical
  \begin{lstlisting}[xleftmargin=-25pt]
basis = make_contractions(all_basis_dict, atoms, coords, "spherical")
\end{lstlisting}
\item To treat all contractions to be Cartesian
  \begin{lstlisting}[xleftmargin=-25pt]
basis = make_contractions(all_basis_dict, atoms, coords, "cartesian")
\end{lstlisting}
\item To treat first shell of generalized contractions to be Cartesian and
  second shell to be spherical
  \begin{lstlisting}[xleftmargin=-25pt]
basis = make_contractions(all_basis_dict, ["H", "H"], coords, ["c", "spherical"])
\end{lstlisting}
In this case, each hydrogen atom must contributes exactly one shell of generalized contractions. Otherwise, an error will be raised.
\end{itemize}

\subsection{Linear transformations of basis functions}
In \verb|gbasis|, user can linearly transform the basis functions before
computing the desired properties.
All of the higher level functions have the keyword argument \verb|transform| to
specify the matrix that transforms the basis set.
The transformation is applied to the left, i.e.
\begin{equation}
 \psi_i = \sum_j T_{ij} \phi_j
\end{equation}
where $\{\phi_j\}$ is the basis set before transformation and $\{\psi_i\}$ is
the basis function after transformation.
The number of basis functions depends on the coordinate systems specified for
each shell.
Note that the transformation matrix assumes that the basis functions are ordered
according to Section~\ref{sec:basis_ordering}.

Example:
\begin{lstlisting}
output = high_level_function(basis, transform=transform_mo_ao)
\end{lstlisting}

\subsection{Ordering of basis functions}
\label{sec:basis_ordering}
Since a shell of generalized contractions is a set of contractions, they must be
unpacked.
When unpacked, the basis functions are first ordered by the shells, then by the
segmented contraction, and then by the angular momentum component.
For example, suppose the basis set consists of three shells of generalized
contractions, $G_1$, $G_2$, and $G_3$:
\begin{equation}
  \begin{split}
    G_1 &= \left\{
      \phi (\mathbf{r} | \mathbf{R}_{A}, \mathbf{a}_{1j}, \mathbf{d}_{1k}, \boldsymbol{\alpha}_1)
      \middle|
      (a_{1j})_x + (a_{1j})_y + (a_{1j})_z = 1
    \right\}\\
    G_2 &= \left\{
      \phi (\mathbf{r} | \mathbf{R}_{B}, \mathbf{a}_{2j}, \mathbf{d}_{2k}, \boldsymbol{\alpha}_2)
      \middle|
      (a_{2j})_x + (a_{2j})_y + (a_{2j})_z = 2
    \right\}\\
    G_3 &= \left\{
      \phi (\mathbf{r} | \mathbf{R}_{A}, \mathbf{a}_{3j}, \mathbf{d}_{3k}, \boldsymbol{\alpha}_3)
      \middle|
      (a_{3j})_x + (a_{3j})_y + (a_{3j})_z = 2
    \right\}\\
  \end{split}
\end{equation}
where $\mathbf{d}_1$ corresponds to two sets of contraction coefficients,
$\mathbf{d}_2$ corresponds to three sets of contraction coefficients,
and $\mathbf{d}_3$ corresponds to one set of contraction coefficients.
Then, the basis functions in the Cartesian form will be ordered as follows:
\begin{equation}
  \begin{split}
    \phi&(\mathbf{r} | \mathbf{R}_{A}, (1, 0, 0), \mathbf{d}_{11}, \boldsymbol{\alpha}_1),
    \phi(\mathbf{r} | \mathbf{R}_{A}, (0, 1, 0), \mathbf{d}_{11}, \boldsymbol{\alpha}_1),
    \phi(\mathbf{r} | \mathbf{R}_{A}, (0, 0, 1), \mathbf{d}_{11}, \boldsymbol{\alpha}_1),\\
    -&----------------------------------\\
    \phi&(\mathbf{r} | \mathbf{R}_{A}, (1, 0, 0), \mathbf{d}_{12}, \boldsymbol{\alpha}_1),
    \phi(\mathbf{r} | \mathbf{R}_{A}, (0, 1, 0), \mathbf{d}_{12}, \boldsymbol{\alpha}_1),
    \phi(\mathbf{r} | \mathbf{R}_{A}, (0, 0, 1), \mathbf{d}_{12}, \boldsymbol{\alpha}_1),\\
    =&============================================\\
    \phi&(\mathbf{r} | \mathbf{R}_{B}, (2, 0, 0), \mathbf{d}_{21}, \boldsymbol{\alpha}_2),
    \phi(\mathbf{r} | \mathbf{R}_{B}, (1, 1, 0), \mathbf{d}_{21}, \boldsymbol{\alpha}_2),
    \phi(\mathbf{r} | \mathbf{R}_{B}, (1, 0, 1), \mathbf{d}_{21}, \boldsymbol{\alpha}_2),\\
    \phi&(\mathbf{r} | \mathbf{R}_{B}, (0, 2, 0), \mathbf{d}_{21}, \boldsymbol{\alpha}_2),
    \phi(\mathbf{r} | \mathbf{R}_{B}, (0, 1, 1), \mathbf{d}_{21}, \boldsymbol{\alpha}_2),
    \phi(\mathbf{r} | \mathbf{R}_{B}, (0, 0, 2), \mathbf{d}_{21}, \boldsymbol{\alpha}_2),\\
    -&----------------------------------\\
    \phi&(\mathbf{r} | \mathbf{R}_{B}, (2, 0, 0), \mathbf{d}_{22}, \boldsymbol{\alpha}_2),
    \phi(\mathbf{r} | \mathbf{R}_{B}, (1, 1, 0), \mathbf{d}_{22}, \boldsymbol{\alpha}_2),
    \phi(\mathbf{r} | \mathbf{R}_{B}, (1, 0, 1), \mathbf{d}_{22}, \boldsymbol{\alpha}_2),\\
    \phi&(\mathbf{r} | \mathbf{R}_{B}, (0, 2, 0), \mathbf{d}_{22}, \boldsymbol{\alpha}_2),
    \phi(\mathbf{r} | \mathbf{R}_{B}, (0, 1, 1), \mathbf{d}_{22}, \boldsymbol{\alpha}_2),
    \phi(\mathbf{r} | \mathbf{R}_{B}, (0, 0, 2), \mathbf{d}_{22}, \boldsymbol{\alpha}_2),\\
    -&----------------------------------\\
    \phi&(\mathbf{r} | \mathbf{R}_{B}, (2, 0, 0), \mathbf{d}_{23}, \boldsymbol{\alpha}_2),
    \phi(\mathbf{r} | \mathbf{R}_{B}, (1, 1, 0), \mathbf{d}_{23}, \boldsymbol{\alpha}_2),
    \phi(\mathbf{r} | \mathbf{R}_{B}, (1, 0, 1), \mathbf{d}_{23}, \boldsymbol{\alpha}_2),\\
    \phi&(\mathbf{r} | \mathbf{R}_{B}, (0, 2, 0), \mathbf{d}_{23}, \boldsymbol{\alpha}_2),
    \phi(\mathbf{r} | \mathbf{R}_{B}, (0, 1, 1), \mathbf{d}_{23}, \boldsymbol{\alpha}_2),
    \phi(\mathbf{r} | \mathbf{R}_{B}, (0, 0, 2), \mathbf{d}_{23}, \boldsymbol{\alpha}_2),\\
    =&============================================\\
    \phi&(\mathbf{r} | \mathbf{R}_{A}, (2, 0, 0), \mathbf{d}_{31}, \boldsymbol{\alpha}_3),
    \phi(\mathbf{r} | \mathbf{R}_{A}, (1, 1, 0), \mathbf{d}_{31}, \boldsymbol{\alpha}_3),
    \phi(\mathbf{r} | \mathbf{R}_{A}, (1, 0, 1), \mathbf{d}_{31}, \boldsymbol{\alpha}_3),\\
    \phi&(\mathbf{r} | \mathbf{R}_{A}, (0, 2, 0), \mathbf{d}_{31}, \boldsymbol{\alpha}_3),
    \phi(\mathbf{r} | \mathbf{R}_{A}, (0, 1, 1), \mathbf{d}_{31}, \boldsymbol{\alpha}_3),
    \phi(\mathbf{r} | \mathbf{R}_{A}, (0, 0, 2), \mathbf{d}_{31}, \boldsymbol{\alpha}_3)\\
  \end{split}
\end{equation}
where $,$ delimits the contractions within a shell of segmented contractions,
$-$ delimits the shells of segmented contractions within a shell of generalized
contractions,
and $=$ delimits the shells of generalized contractions.

The basis functions in the spherical form will be ordered as follows:
\begin{equation}
  \begin{split}
    \phi^s&(\mathbf{r} | \mathbf{R}_{A}, -1, 1, \mathbf{d}_{11}, \boldsymbol{\alpha}_1),
    \phi^s(\mathbf{r} | \mathbf{R}_{A}, 0, 1, \mathbf{d}_{11}, \boldsymbol{\alpha}_1),
    \phi^s(\mathbf{r} | \mathbf{R}_{A}, 1, 1, \mathbf{d}_{11}, \boldsymbol{\alpha}_1),\\
    --&-------------------------------\\
    \phi^s&(\mathbf{r} | \mathbf{R}_{A}, -1, 1, \mathbf{d}_{12}, \boldsymbol{\alpha}_1),
    \phi^s(\mathbf{r} | \mathbf{R}_{A}, 0, 1, \mathbf{d}_{12}, \boldsymbol{\alpha}_1),
    \phi^s(\mathbf{r} | \mathbf{R}_{A}, 1, 1, \mathbf{d}_{12}, \boldsymbol{\alpha}_1),\\
    ==&========================================\\
    \phi^s&(\mathbf{r} | \mathbf{R}_{B}, -2, 2, \mathbf{d}_{21}, \boldsymbol{\alpha}_2),
    \phi^s(\mathbf{r} | \mathbf{R}_{B}, -1, 2, \mathbf{d}_{21}, \boldsymbol{\alpha}_2),
    \phi^s(\mathbf{r} | \mathbf{R}_{B}, 0, 2, \mathbf{d}_{21}, \boldsymbol{\alpha}_2),\\
    \phi^s&(\mathbf{r} | \mathbf{R}_{B}, 1, 2, \mathbf{d}_{21}, \boldsymbol{\alpha}_2),
    \phi^s(\mathbf{r} | \mathbf{R}_{B}, 2, 2, \mathbf{d}_{21}, \boldsymbol{\alpha}_2),\\
    -&-------------------------------\\
    \phi^s&(\mathbf{r} | \mathbf{R}_{B}, -2, 2, \mathbf{d}_{22}, \boldsymbol{\alpha}_2),
    \phi^s(\mathbf{r} | \mathbf{R}_{B}, -1, 2, \mathbf{d}_{22}, \boldsymbol{\alpha}_2),
    \phi^s(\mathbf{r} | \mathbf{R}_{B}, 0, 2, \mathbf{d}_{22}, \boldsymbol{\alpha}_2),\\
    \phi^s&(\mathbf{r} | \mathbf{R}_{B}, 1, 2, \mathbf{d}_{22}, \boldsymbol{\alpha}_2),
    \phi^s(\mathbf{r} | \mathbf{R}_{B}, 2, 2, \mathbf{d}_{22}, \boldsymbol{\alpha}_2),\\
    -&-------------------------------\\
    \phi^s&(\mathbf{r} | \mathbf{R}_{B}, -2, 2, \mathbf{d}_{23}, \boldsymbol{\alpha}_2),
    \phi^s(\mathbf{r} | \mathbf{R}_{B}, -1, 2, \mathbf{d}_{23}, \boldsymbol{\alpha}_2),
    \phi^s(\mathbf{r} | \mathbf{R}_{B}, 0, 2, \mathbf{d}_{23}, \boldsymbol{\alpha}_2),\\
    \phi^s&(\mathbf{r} | \mathbf{R}_{B}, 1, 2, \mathbf{d}_{23}, \boldsymbol{\alpha}_2),
    \phi^s(\mathbf{r} | \mathbf{R}_{B}, 2, 2, \mathbf{d}_{23}, \boldsymbol{\alpha}_2),\\
    ==&========================================\\
    \phi^s&(\mathbf{r} | \mathbf{R}_{A}, -2, 2, \mathbf{d}_{31}, \boldsymbol{\alpha}_3),
    \phi^s(\mathbf{r} | \mathbf{R}_{A}, -1, 2, \mathbf{d}_{31}, \boldsymbol{\alpha}_3),
    \phi^s(\mathbf{r} | \mathbf{R}_{A}, 0, 2, \mathbf{d}_{31}, \boldsymbol{\alpha}_3),\\
    \phi^s&(\mathbf{r} | \mathbf{R}_{A}, 1, 2, \mathbf{d}_{31}, \boldsymbol{\alpha}_3),
    \phi^s(\mathbf{r} | \mathbf{R}_{A}, 2, 2, \mathbf{d}_{31}, \boldsymbol{\alpha}_3)\\
  \end{split}
\end{equation}
where each spherical contraction has the form
$\phi^s(\mathbf{r} | \mathbf{R}_{A}, m, \ell, \mathbf{d}, \boldsymbol{\alpha})$.

The specific ordering of the angular momentum components in the Cartesian and
spherical form is determined by the properties
\begin{lstlisting}
gbasis.contractions.GeneralizedContractionShell.angmom_components_cart
\end{lstlisting}
and
\begin{lstlisting}
gbasis.contractions.GeneralizedContractionShell.angmom_components_sph
\end{lstlisting}
respectively.
To change the ordering, make a child of
\verb|GeneralizedContractionShell|
and overwrite these properties with the desired ordering.

\subsection{Conventions for ordering Cartesian and spherical components}
\label{sec:angmom_components_ordering}

\paragraph{Cartesian components}
A shell of generalized contractions of angular momentum $\ell$ is composed of $(\ell + 1)(\ell + 2)$
Cartesian components of the form $x^{a_x}y^{a_y}z^{a_z}$ such that $a_x + a_y + a_z = \ell$.
In \verb|gbasis|, the ordering of Cartesian components is stored as an $\ell \times 3$ \verb|numpy|
array, where each entry $(i, j)$ corresponds to the exponent $a_j$ for the $i$\textsuperscript{th}
component.
In other programs, like \verb|HORTON2|, a different notation is used, where the components are
written as strings of X, Y, and Z, where the number of times each letter appears corresponds to the
exponent $a$ for that letter.
These notations are easily convertible, for example, the \verb|gbasis| notation for the component
\verb|XXXZZ| is $(3, 0, 2)$

In \verb|gbasis|, all components are sorted by descending $a_x$, then by descending $a_y$,
as generated by the following list comprehension:
\begin{lstlisting}
[(x, y, self.angmom - x - y)
    for x in range(self.angmom, -1, -1)
    for y in range(self.angmom - x, -1, -1)]
\end{lstlisting}
For example, for $\ell = 3$, the default ordering is:
\begin{lstlisting}
[
    (3, 0, 0),
    (2, 1, 0),
    (2, 0, 1),
    (1, 2, 0),
    (1, 1, 1),
    (1, 0, 2),
    (0, 3, 0),
    (0, 2, 1),
    (0, 1, 2),
    (0, 0, 3),
]
\end{lstlisting}

\paragraph{Spherical (pure) components}
A shell of generalized contractions of angular momentum $\ell$ is composed of $2 \ell + 1$ spherical
components that take the form of cosine- and sine-like real regular solid harmonics $C_{\ell, m}$ and
$S_{\ell, m}$.
We can define these cosine- and sine-like functions using the regular solid harmonics
$R_{\ell, m}$ such that
\begin{equation}
  \label{eq:real_reg_solid_harmonics}
  \begin{split}
    R_{\ell, m} &= C_{\ell, m} \quad m = 0, ..., \ell \\
    R_{\ell, -m} &= S_{\ell, m} \quad m = 1, ..., \ell
  \end{split}
\end{equation}
In \verb|gbasis|, we use these definitions to represent spherical components as strings of the form
\verb|c{m}| and \verb|s{m}|,
where $m$ is the magnetic quantum number for the given angular momentum.
N.B.: for sine-like functions, \verb|s{m}| corresponds to $-m$, as per the definition in
equation~\ref{eq:real_reg_solid_harmonics}.
This ordering is stored as a list of these strings,
consistent with the notation found in \verb|IOData|.

Some quantum chemistry programs, such as \verb|ORCA|, use conventions that require changing
the signs of specific spherical (pure) components.
Therefore, the sign of each component must also be encoded in the ordering.
In \verb|gbasis|, this is done by prefixing a negative sign to the string for that component,
e.g. \verb|-s3|.

The standard convention for ordering spherical components in \verb|gbasis| is from $-m$ to $m$.
The ordering is generated by the following list comprehension:
\begin{lstlisting}
['s{}'.format(m) for m in range(self.angmom, 0, -1)]
+ ['c{}'.format(m) for m in range(self.angmom + 1)]
\end{lstlisting}
For example, for $\ell = 3$, the default ordering is:
\begin{lstlisting}
['s3', 's2', 's1', 'c0', 'c1', 'c2', 'c3']
\end{lstlisting}
In \verb|ORCA| Molden files, the convention for $\ell = 3$,
illustrating the use of the negative prefix, is:
\begin{lstlisting}
['c0', 'c1', 's1', 'c2', 's2', '-c3', '-s3']
\end{lstlisting}

\section{Evaluations}
For the examples, suppose we have the following set of points:
\begin{lstlisting}
import numpy as np

grid_1d = np.linspace(-2, 2, num=10)
grid_x, grid_y, grid_z = np.meshgrid(grid_1d, grid_1d, grid_1d)
grid_3d = np.vstack([grid_x.ravel(), grid_y.ravel(), grid_z.ravel()]).T
\end{lstlisting}

\subsection{Evaluation of contractions}
The functions in module \verb|gbasis.evals.eval| return the evaluations of the
contractions at different coordinates:
\begin{equation}
  \phi(\mathbf{r}_n | \mathbf{R}_{A}, \mathbf{a}_j, \mathbf{d}_k, \boldsymbol{\alpha})
\end{equation}
The returned value is an array whose rows corresponds to the basis function and
columns corresponds to the coordinate, $\mathbf{r}_n$.

These functions can be used to find the values of the orbitals at various
points, such as a grid.

Example:
\begin{itemize}
\item To evaluate the atomic orbitals,
  \begin{lstlisting}[xleftmargin=-25pt]
from gbasis.evals.eval import evaluate_basis

output = evaluate_basis(basis, grid_3d)
\end{lstlisting}
\item To evaluate the molecular orbitals,
  \begin{lstlisting}[xleftmargin=-25pt]
from gbasis.evals.eval import evaluate_basis

output = evaluate_basis(basis, grid_3d, transform=transform_mo_ao)
\end{lstlisting}
\end{itemize}

\subsection{Evaluation of derivatives of contractions}
In \verb|gbasis|, contractions can be derivatized to arbitrary orders.
The functions in module \verb|gbasis.evals.eval_deriv| return the evaluations of the
given derivative of the contractions at different coordinates.
\begin{equation}
  \frac{\partial^{m_x + m_y + m_z}}{\partial x^{m_x} \partial y^{m_y} \partial z^{m_z}}
  \phi(\mathbf{r}_n | \mathbf{R}_{A}, \mathbf{a}_j, \mathbf{d}_k, \boldsymbol{\alpha})
\end{equation}
The returned value is an array whose rows corresponds to the basis function and
columns corresponds to the coordinate, $\mathbf{r}_n$.

Example:
Suppose the following derivative of the contraction is desired:
\begin{equation}
  \frac{\partial^3}{\partial x \partial y^2}
\end{equation}
\begin{itemize}
\item To evaluate the derivatives of the atomic orbitals,
  \begin{lstlisting}[xleftmargin=-25pt]
from gbasis.evals.eval_deriv import evaluate_deriv_basis

output = evaluate_deriv_basis(basis, grid_3d, np.array([1, 2, 0]))
\end{lstlisting}
\item To evaluate the derivatives of the molecular orbitals,
  \begin{lstlisting}[xleftmargin=-25pt]
from gbasis.evals.eval_deriv import evaluate_deriv_basis

output = evaluate_deriv_basis(
    basis, grid_3d, np.array([1, 2, 0]), transform=transform_mo_ao
)
\end{lstlisting}
\end{itemize}
\subsection{Evaluations of density related properties}
The functions in module \verb|gbasis.evals.density| return the evaluations of the
density and its derivatives.

Suppose the \verb|one_dm| is the one-electron density matrix.
\subsubsection{Density}
\begin{equation}
  \rho(\mathbf{r}_n) = \sum_{ij} \gamma_{ij} \phi_i(\mathbf{r}_n) \phi_j(\mathbf{r}_n)
\end{equation}

Example:
\begin{itemize}
\item To evaluate the density using density matrix expressed with respect to
  atomic orbitals,
  \begin{lstlisting}[xleftmargin=-25pt]
from gbasis.evals.density import evaluate_density

output = evaluate_density(one_dm, basis, grid_3d)
\end{lstlisting}
\item To evaluate the density using density matrix expressed with respect to
  molecular orbitals,
  \begin{lstlisting}[xleftmargin=-25pt]
from gbasis.evals.density import evaluate_density

output = evaluate_density(one_dm, basis, grid_3d, transform=transform_mo_ao)
\end{lstlisting}
\end{itemize}
\subsubsection{Arbitrary derivatives of density}
\begin{equation}
  \frac{\partial^{L_x + L_y + L_z}}{\partial x^{L_x} \partial y^{L_y} \partial z^{L_z}}
  \rho(\mathbf{r}_n)
  =
  \sum_{l_x=0}^{L_x} \sum_{l_y=0}^{L_y} \sum_{l_z=0}^{L_z}
  \binom{L_x}{l_x} \binom{L_y}{l_y} \binom{L_z}{l_z}
  \sum_{ij} \gamma_{ij}
  \frac{\partial^{l_x + l_y + l_z} \rho(\mathbf{r}_n)}{\partial x^{l_x} \partial y^{l_y} \partial z^{l_z}}
  \frac{
    \partial^{L_x + L_y + L_z - l_x - l_y - l_z} \rho(\mathbf{r}_n)
  }{
    \partial x^{L_x - l_x} \partial y^{L_y - l_y} \partial z^{L_z - l_z}
  }
\end{equation}

Example:
Suppose the following derivative of the density is desired:
\begin{equation}
  \frac{\partial^3}{\partial x \partial y^2}
\end{equation}
\begin{itemize}
\item To evaluate the derivative of the density using density matrix expressed
  with respect to atomic orbitals,
  \begin{lstlisting}[xleftmargin=-25pt]
from gbasis.evals.density import evaluate_deriv_density

output = evaluate_deriv_density(
	np.array([1, 2, 0]), one_dm, basis, grid_3d, deriv_type="general"
)
\end{lstlisting}
\item To evaluate the derivative of the density using density matrix expressed
  with respect to molecular orbitals,
\begin{lstlisting}
from gbasis.evals.density import evaluate_deriv_density

output = evaluate_deriv_density(
    np.array([1, 2, 0]), one_dm, basis, grid_3d, transform=transform_mo_ao,
    deriv_type="general"
)
\end{lstlisting}
Notice the use of the keyword argument \verb|deriv_type|, which allows to choose between a general or a specific function derivative procedure based on the order of derivation. If \verb|deriv_type="general"|, an implementation valid for any order of derivative of the density function is used. However, for first and second order derivatives of the density an optimized procedure can be utilized by setting \verb|deriv_type="direct"| which makes the computation faster.

\end{itemize}
\subsubsection{Gradient of density}
\begin{equation}
  \nabla \rho(\mathbf{r}_n)
  =
  \begin{bmatrix}
    \frac{\partial}{\partial x} \rho(\mathbf{r}_n)\\\\
    \frac{\partial}{\partial y} \rho(\mathbf{r}_n)\\\\
    \frac{\partial}{\partial z} \rho(\mathbf{r}_n)
  \end{bmatrix}\\
\end{equation}

Example:
\begin{itemize}
\item To evaluate the gradient of the density using density matrix expressed
  with respect to atomic orbitals,
  \begin{lstlisting}[xleftmargin=-25pt]
from gbasis.evals.density import evaluate_density_gradient

output = evaluate_density_gradient(one_dm, basis, grid_3d, deriv_type="general")
\end{lstlisting}
\item To evaluate the gradient of the density using the specific procedure for up to second order derivatives and the density matrix expressed
with respect to atomic orbitals,
\begin{lstlisting}[xleftmargin=-25pt]
	from gbasis.evals.density import evaluate_density_gradient

	output = evaluate_density_gradient(one_dm, basis, grid_3d, deriv_type="direct")
\end{lstlisting}
\item To evaluate the gradient of the density using density matrix expressed
  with respect to molecular orbitals,
  \begin{lstlisting}[xleftmargin=-25pt]
from gbasis.evals.density import evaluate_density_gradient

output = evaluate_density_gradient(
    one_dm, basis, grid_3d, transform=transform_mo_ao, deriv_type="general"
)
\end{lstlisting}
\end{itemize}
\subsubsection{Laplacian of density}
\begin{equation}
  \nabla^2 \rho(\mathbf{r}_n)
  =
  \frac{\partial^2}{\partial x^2} \rho(\mathbf{r}_n)
  + \frac{\partial^2}{\partial y^2} \rho(\mathbf{r}_n)
  + \frac{\partial^2}{\partial z^2} \rho(\mathbf{r}_n)
\end{equation}

Example:
\begin{itemize}
\item To evaluate the laplacian of the density using density matrix expressed
  with respect to atomic orbitals,
  \begin{lstlisting}[xleftmargin=-25pt]
from gbasis.evals.density import evaluate_density_laplacian

output = evaluate_density_laplacian(one_dm, basis, grid_3d, deriv_type="general")
\end{lstlisting}
  where
\item To evaluate the laplacian of the density using density matrix expressed
  with respect to molecular orbitals,
  \begin{lstlisting}[xleftmargin=-25pt]
from gbasis.evals.density import evaluate_density_laplacian

output = evaluate_density_laplacian(
    one_dm, basis, grid_3d, transform=transform_mo_ao, deriv_type="general"
)
\end{lstlisting}
\end{itemize}
\subsubsection{Hessian of density}
\begin{equation}
	H[\rho(\mathbf{r}_n)]
	=
	\begin{bmatrix}
		\frac{\partial^2}{\partial x^2} \rho(\mathbf{r}_n) &
		\frac{\partial^2}{\partial x \partial y} \rho(\mathbf{r}_n) &
		\frac{\partial^2}{\partial x \partial z} \rho(\mathbf{r}_n)\\\\
		\frac{\partial^2}{\partial y \partial x} \rho(\mathbf{r}_n) &
		\frac{\partial^2}{\partial y^2} \rho(\mathbf{r}_n)&
		\frac{\partial^2}{\partial y \partial z} \rho(\mathbf{r}_n)\\\\
		\frac{\partial^2}{\partial z \partial x} \rho(\mathbf{r}_n) &
		\frac{\partial^2}{\partial z \partial y} \rho(\mathbf{r}_n)&
		\frac{\partial^2}{\partial z^2} \rho(\mathbf{r}_n)\\
	\end{bmatrix}\\
\end{equation}

Example:
\begin{itemize}
\item To evaluate the Hessian of the density using density matrix expressed
  with respect to atomic orbitals,
  \begin{lstlisting}[xleftmargin=-25pt]
from gbasis.evals.density import evaluate_density_hessian

output = evaluate_density_hessian(one_dm, basis, grid_3d, deriv_type="general")
\end{lstlisting}
\item To evaluate the Hessian of the density using density matrix expressed
  with respect to molecular orbitals,
  \begin{lstlisting}[xleftmargin=-25pt]
from gbasis.evals.density import evaluate_density_hessian

output = evaluate_density_hessian(
    one_dm, basis, grid_3d, transform=transform_mo_ao, deriv_type="general"
)
\end{lstlisting}
\end{itemize}
\subsection{Evaluations of density matrix related properties}
Given the density matrix,
\begin{equation}
  \gamma(\mathbf{r}_1, \mathbf{r}_2)
  = \sum_{ij} \gamma_{ij} \phi_i(\mathbf{r}_1) \phi_j(\mathbf{r}_2)
\end{equation}
many properties can be defined by evaluating the derivatives of the density
matrix at the same coordinate:
\begin{equation}
  \left.
    \frac{\partial^{p_x + p_y + p_z}}{\partial x_1^{p_x} \partial y_1^{p_y} \partial z_1^{p_z}}
    \frac{\partial^{q_x + q_y + q_z}}{\partial x_2^{q_x} \partial y_2^{q_y} \partial z_2^{q_z}}
    \gamma(\mathbf{r}_1, \mathbf{r}_2)
  \right|_{\mathbf{r}_1 = \mathbf{r}_2 = \mathbf{r}_n} =
  \sum_{ij} \gamma_{ij}
  \left.
    \frac{\partial^{p_x + p_y + p_z}}{\partial x_1^{p_x} \partial y_1^{p_y} \partial z_1^{p_z}}
    \phi_i(\mathbf{r}_1)
  \right|_{\mathbf{r}_1 = \mathbf{r}_n}
  \left.
    \frac{\partial^{q_x + q_y + q_z}}{\partial x_2^{q_x} \partial y_2^{q_y} \partial z_2^{q_z}}
    \phi_j(\mathbf{r}_2)
  \right|_{\mathbf{r}_1 = \mathbf{r}_n}
\end{equation}
where $\mathbf{r}_1$ is the first coordinate, $\mathbf{r}_2$ is the second
coordinate, and $\mathbf{r}_n$ is the coordinate at which the derivative is
evaluated.

Since $\gamma_{ij}$ is symmetric,
\begin{equation}
  \left.
    \frac{\partial^{p_x + p_y + p_z}}{\partial x_1^{p_x} \partial y_1^{p_y} \partial z_1^{p_z}}
    \frac{\partial^{q_x + q_y + q_z}}{\partial x_2^{q_x} \partial y_2^{q_y} \partial z_2^{q_z}}
    \gamma(\mathbf{r}_1, \mathbf{r}_2)
  \right|_{\mathbf{r}_1 = \mathbf{r}_2 = \mathbf{r}_n} =
  \left.
    \frac{\partial^{q_x + q_y + q_z}}{\partial x_1^{q_x} \partial y_1^{q_y} \partial z_1^{q_z}}
    \frac{\partial^{p_x + p_y + p_z}}{\partial x_2^{p_x} \partial y_2^{p_y} \partial z_2^{p_z}}
    \gamma(\mathbf{r}_1, \mathbf{r}_2)
  \right|_{\mathbf{r}_1 = \mathbf{r}_2 = \mathbf{r}_n}
\end{equation}

Again, suppose \verb|one_dm| is the one-electron density matrix.
\subsubsection{Stress tensor}
\begin{equation}
  \begin{split}
    \boldsymbol{\sigma}_{ij}(\mathbf{r}_n | \alpha, \beta)
    =&
    -\frac{1}{2} \alpha
    \left(
      \frac{\partial^2}{\partial r_i \partial r'_j} \gamma(\mathbf{r}, \mathbf{r}')
      + \frac{\partial^2}{\partial r_j \partial r'_i} \gamma(\mathbf{r}, \mathbf{r}')
    \right)_{\mathbf{r} = \mathbf{r}' = \mathbf{r}_n}\\
    & +\frac{1}{2} (1 - \alpha)
    \left(
      \frac{\partial^2}{\partial r_i \partial r_j} \gamma(\mathbf{r}, \mathbf{r})
      + \frac{\partial^2}{\partial r'_i \partial r'_j} \gamma(\mathbf{r}, \mathbf{r}')
    \right)_{\mathbf{r} = \mathbf{r}' = \mathbf{r}_n}\\
    & - \frac{1}{2} \delta_{ij} \beta \nabla^2 \rho(\mathbf{r}_n)\\
    =&
    - \alpha
    \left.
      \frac{\partial^2}{\partial r_i \partial r'_j} \gamma(\mathbf{r}, \mathbf{r}')
    \right|_{\mathbf{r} = \mathbf{r}' = \mathbf{r}_n}
    + (1 - \alpha)
    \left.
      \frac{\partial^2}{\partial r_i \partial r_j} \gamma(\mathbf{r}, \mathbf{r})
    \right|_{\mathbf{r} = \mathbf{r}' = \mathbf{r}_n}
    - \frac{1}{2} \delta_{ij} \beta \nabla^2 \rho(\mathbf{r}_n)\\
  \end{split}
\end{equation}

Example:
\begin{itemize}
\item To evaluate the stress tensor ($\alpha=1$ and $\beta=0$)
  using density matrix expressed with respect to atomic orbitals,
  \begin{lstlisting}[xleftmargin=-25pt]
from gbasis.evals.stress_tensor import evaluate_stress_tensor

output = evaluate_stress_tensor(one_dm, basis, grid_3d)
\end{lstlisting}
\item To evaluate the stress tensor ($\alpha=0.5$ and $\beta=1$)
  using density matrix expressed with respect to atomic orbitals,
  \begin{lstlisting}[xleftmargin=-25pt]
from gbasis.evals.stress_tensor import evaluate_stress_tensor

output = evaluate_stress_tensor(one_dm, basis, grid_3d, alpha=0.5, beta=1)
\end{lstlisting}
\item To evaluate the stress tensor ($\alpha=1$ and $\beta=0$)
  using density matrix expressed with respect to molecular orbitals,
  \begin{lstlisting}[xleftmargin=-25pt]
from gbasis.evals.stress_tensor import evaluate_stress_tensor

output = evaluate_stress_tensor(
    one_dm, basis, grid_3d, transform=transform_mo_ao
)
\end{lstlisting}
\end{itemize}
\subsubsection{Ehrenfest force}
Ehrenfest force is defined as the negative of the divergence of the stress tensor
\begin{equation}
  \hspace{-4em}
  \begin{split}
    F_{j}(\mathbf{r}_n | \alpha, \beta)
    =&
    - \sum_i \frac{\partial}{\partial r_i} \boldsymbol{\sigma}_{ij}\\
    =&
    \alpha
    \sum_i
    \left.
      \frac{\partial^3}{\partial r^2_i \partial r'_j} \gamma(\mathbf{r}, \mathbf{r}')
    \right|_{\mathbf{r} = \mathbf{r}' = \mathbf{r}_n}
    + \alpha
    \sum_i
    \left.
      \frac{\partial^3}{\partial r_i \partial r'_i \partial r'_j} \gamma(\mathbf{r}, \mathbf{r}')
    \right|_{\mathbf{r} = \mathbf{r}' = \mathbf{r}_n}\\
    &- (1 - \alpha)
    \sum_i
    \left.
      \frac{\partial^3}{\partial r^2_i \partial r_j} \gamma(\mathbf{r}, \mathbf{r})
    \right|_{\mathbf{r} = \mathbf{r}' = \mathbf{r}_n}
    - (1 - \alpha)
    \sum_i
    \left.
      \frac{\partial^3}{\partial r_i \partial r_j \partial r'_i} \gamma(\mathbf{r}, \mathbf{r})
    \right|_{\mathbf{r} = \mathbf{r}' = \mathbf{r}_n}
    + \frac{1}{2} \sum_i \delta_{ij} \beta
    \frac{\partial}{\partial r_i} \nabla^2 \rho(\mathbf{r}_n)\\
    =&
    \alpha
    \sum_i
    \left.
      \frac{\partial^3}{\partial r^2_i \partial r'_j} \gamma(\mathbf{r}, \mathbf{r}')
    \right|_{\mathbf{r} = \mathbf{r}' = \mathbf{r}_n}\\
    &- (1 - \alpha)
    \sum_i
    \left.
      \frac{\partial^3}{\partial r^2_i \partial r_j} \gamma(\mathbf{r}, \mathbf{r})
    \right|_{\mathbf{r} = \mathbf{r}' = \mathbf{r}_n}
    - (1 - 2\alpha)
    \sum_i
    \left.
      \frac{\partial^3}{\partial r_i \partial r_j \partial r'_i} \gamma(\mathbf{r}, \mathbf{r})
    \right|_{\mathbf{r} = \mathbf{r}' = \mathbf{r}_n}
    + \frac{1}{2} \sum_i \delta_{ij} \beta
    \frac{\partial}{\partial r_i} \nabla^2 \rho(\mathbf{r}_n)\\
  \end{split}
\end{equation}


Example:
\begin{itemize}
\item To evaluate the Ehrenfest force ($\alpha=1$ and $\beta=0$)
  using density matrix expressed with respect to atomic orbitals,
  \begin{lstlisting}[xleftmargin=-25pt]
from gbasis.evals.stress_tensor import evaluate_ehrenfest_force

output = evaluate_ehrenfest_force(one_dm, basis, grid_3d)
\end{lstlisting}
\item To evaluate the Ehrenfest force ($\alpha=0.5$ and $\beta=1$)
  using density matrix expressed with respect to atomic orbitals,
  \begin{lstlisting}[xleftmargin=-25pt]
from gbasis.evals.stress_tensor import evaluate_ehrenfest_force

output = evaluate_ehrenfest_force(one_dm, basis, grid_3d, alpha=0.5, beta=1)
\end{lstlisting}
\item To evaluate the Ehrenfest force ($\alpha=1$ and $\beta=0$)
  using density matrix expressed with respect to molecular orbitals,
  \begin{lstlisting}[xleftmargin=-25pt]
from gbasis.evals.stress_tensor import evaluate_ehrenfest_force

output = evaluate_ehrenfest_force(
    one_dm, basis, grid_3d, transform=transform_mo_ao
)
\end{lstlisting}
\end{itemize}
\subsubsection{Ehrenfest Hessian}
\begin{equation}
  \begin{split}
    H_{jk}(\mathbf{r}_n | \alpha, \beta)
    =&
    - \frac{\partial}{\partial r_k} F_j(\mathbf{r}_n | \alpha, \beta)\\
    =&
    \alpha
    \sum_i
    \left(
      \frac{\partial^4}{\partial r^2_i \partial r_k \partial r'_j} \gamma(\mathbf{r}, \mathbf{r}')
      +\frac{\partial^4}{\partial r^2_i \partial r'_j \partial r'_k} \gamma(\mathbf{r}, \mathbf{r}')
    \right)_{\mathbf{r} = \mathbf{r}' = \mathbf{r}_n}\\
    &- (1 - \alpha)
    \sum_i
    \left(
      \frac{\partial^4}{\partial r^2_i \partial r_j \partial r_k} \gamma(\mathbf{r}, \mathbf{r})
      + \frac{\partial^4}{\partial r^2_i \partial r_j \partial r'_k} \gamma(\mathbf{r}, \mathbf{r})
    \right)_{\mathbf{r} = \mathbf{r}' = \mathbf{r}_n}\\
    &- (1 - 2\alpha)
    \sum_i
    \left(
      \frac{\partial^4}{\partial r_i \partial r_j \partial r_k \partial r'_i} \gamma(\mathbf{r}, \mathbf{r})
      + \frac{\partial^4}{\partial r_i \partial r_j \partial r'_i \partial r'_k} \gamma(\mathbf{r}, \mathbf{r})
    \right)_{\mathbf{r} = \mathbf{r}' = \mathbf{r}_n}\\
    &+ \frac{1}{2} \sum_i \delta_{ij} \beta
    \frac{\partial^2}{\partial r_i \partial r_k} \nabla^2 \rho(\mathbf{r}_n)\\
  \end{split}
\end{equation}

Example:
\begin{itemize}
\item To evaluate the Ehrenfest Hessian ($\alpha=1$ and $\beta=0$)
  using density matrix expressed with respect to atomic orbitals,
  \begin{lstlisting}[xleftmargin=-25pt]
from gbasis.evals.stress_tensor import evaluate_ehrenfest_hessian

output = evaluate_ehrenfest_hessian(one_dm, basis, grid_3d)
\end{lstlisting}
\item To evaluate the Ehrenfest Hessian ($\alpha=0.5$ and $\beta=1$)
  using density matrix expressed with respect to atomic orbitals,
  \begin{lstlisting}[xleftmargin=-25pt]
from gbasis.evals.stress_tensor import evaluate_ehrenfest_hessian

output = evaluate_ehrenfest_hessian(
    one_dm, basis, grid_3d, alpha=0.5, beta=1
)
\end{lstlisting}
\item To evaluate the Ehrenfest Hessian ($\alpha=1$ and $\beta=0$)
  using density matrix expressed with respect to molecular orbitals,
  \begin{lstlisting}[xleftmargin=-25pt]
from gbasis.evals.stress_tensor import evaluate_ehrenfest_hessian

output = evaluate_ehrenfest_hessian(
    one_dm, basis, grid_3d, transform=transform_mo_ao
)
\end{lstlisting}
\end{itemize}
\subsubsection{Positive-definite kinetic energy density}
\begin{equation}
  \begin{split}
    t_+ (\mathbf{r}_n)
    &= \frac{1}{2} \left.
      \nabla_{\mathbf{r}} \cdot \nabla_{\mathbf{r}'} \gamma(\mathbf{r}, \mathbf{r}')
    \right|_{\mathbf{r} = \mathbf{r}' = \mathbf{r}_n}\\
    &= \frac{1}{2} \left(
      \frac{\partial^2}{\partial x \partial x'} \gamma(\mathbf{r}, \mathbf{r}')
      + \frac{\partial^2}{\partial y \partial y'} \gamma(\mathbf{r}, \mathbf{r}')
      + \frac{\partial^2}{\partial z \partial z'} \gamma(\mathbf{r}, \mathbf{r}')
    \right)_{\mathbf{r} = \mathbf{r}' = \mathbf{r}_n}\\
  \end{split}
\end{equation}

Example:
\begin{itemize}
\item To evaluate the positive-definite kinetic energy density using density
  matrix expressed with respect to atomic orbitals,
  \begin{lstlisting}[xleftmargin=-25pt]
from gbasis.evals.density import evaluate_posdef_kinetic_energy_density

output = evaluate_posdef_kinetic_energy_density(
	one_dm, basis, grid_3d, deriv_type="general"
)
\end{lstlisting}
\item To evaluate the positive-definite kinetic energy density using density
  matrix expressed with respect to molecular orbitals,
  \begin{lstlisting}[xleftmargin=-25pt]
from gbasis.evals.density import evaluate_posdef_kinetic_energy_density

output = evaluate_posdef_kinetic_energy_density(
    one_dm, basis, grid_3d, transform=transform_mo_ao, deriv_type="general"
)
\end{lstlisting}
\end{itemize}
\subsubsection{General form of kinetic energy density}
\begin{equation}
  t_{\alpha} (\mathbf{r}_n) = t_+(\mathbf{r}_n) + \alpha \nabla^2 \rho(\mathbf{r}_n)
\end{equation}

Example:
\begin{itemize}
\item To evaluate the general form of the kinetic energy density ($\alpha=1$)
  using density matrix expressed with respect to atomic orbitals,
  \begin{lstlisting}[xleftmargin=-25pt]
from gbasis.evals.density import evaluate_general_kinetic_energy_density

output = evaluate_general_kinetic_energy_density(
	one_dm, basis, grid_3d, deriv_type="general"
)
\end{lstlisting}
\item To evaluate the general form of the kinetic energy density ($\alpha=0.5$)
  using density matrix expressed with respect to atomic orbitals,
  \begin{lstlisting}[xleftmargin=-25pt]
from gbasis.evals.density import evaluate_general_kinetic_energy_density

output = evaluate_general_kinetic_energy_density(
	one_dm, basis, grid_3d, alpha=0.5, deriv_type="general"
)
\end{lstlisting}
\item To evaluate the general form of the kinetic energy density ($\alpha=1$)
  using density matrix expressed with respect to molecular orbitals,
  \begin{lstlisting}[xleftmargin=-25pt]
from gbasis.evals.density import evaluate_general_kinetic_energy_density

output = evaluate_general_kinetic_energy_density(
    one_dm, basis, grid_3d, transform=transform_mo_ao, deriv_type="general"
)
\end{lstlisting}
\end{itemize}
\section{Integrals}

\subsection{Overlap integral}
\begin{equation}
  \label{eq:overlap}
  \int \phi_a (\mathbf{r}) \phi_b (\mathbf{r}) d\mathbf{r}
\end{equation}

Example:
\begin{itemize}
\item To compute the overlap of a set of atomic orbitals
  \begin{lstlisting}[xleftmargin=-25pt]
from gbasis.integrals.overlap import overlap_integral

output = overlap_integral(basis)
\end{lstlisting}
\item To compute the overlap of a set of molecular orbitals
  \begin{lstlisting}[xleftmargin=-25pt]
from gbasis.integrals.overlap import overlap_integral

output = overlap_integral(basis, transform=transform_mo_ao)
\end{lstlisting}
\end{itemize}
\subsubsection{Overlap integral between two different basis sets}
Overlap integrals between two different basis sets are supported i.e.
\begin{equation}
  \label{eq:overlap}
  \int \phi_a (\mathbf{r}) \psi_b (\mathbf{r}) d\mathbf{r}
\end{equation}

Example:
\begin{itemize}
\item To compute the overlap between twos sets of atomic orbitals
  \begin{lstlisting}[xleftmargin=-25pt]
from gbasis.integrals.overlap_asymm import overlap_integral_asymmetric

output = overlap_integral_asymmetric(basis_one, basis_two)
\end{lstlisting}
\item To compute the overlap between a set of molecular orbitals and a set of
  atomic orbitals
\begin{lstlisting}[xleftmargin=-25pt]
from gbasis.integrals.overlap_asymm import overlap_integral_asymmetric

output = overlap_integral_asymmetric(
    basis_one, basis_two, transform_one=transform_ao_mo
)
\end{lstlisting}
\end{itemize}
\subsection{Multipole moment integral}
Multipole moment integral can be obtained for arbitrary moments.
\begin{equation}
  \label{eq:multipole}
  \int \phi_a (\mathbf{r}) (x - X_C)^{c_x} (y - Y_C)^{c_y} (z - Z_C)^{c_z} \phi_b (\mathbf{r}) d\mathbf{r}
\end{equation}

Example:
Suppose the integral of the following moments is desired:
\begin{equation}
  (x - 1.5)^2 (y - 2.5)^3 (z - 3.5)
\end{equation}
\begin{equation}
  (x - 1.5) (y - 2.5)^2 (z - 3.5)^3
\end{equation}
\begin{itemize}
\item To compute the moment of a set of atomic orbitals
  \begin{lstlisting}[xleftmargin=-25pt]
from gbasis.integrals.moment import moment_integral

output = moment_integral(
    basis, np.array([1.5, 2.5, 3.5]), np.array([[2, 3, 1], [1, 2, 3]])
)
\end{lstlisting}
\item To compute the moment of a set of molecular orbitals
  \begin{lstlisting}[xleftmargin=-25pt]
from gbasis.integrals.moment import moment_integral

output = moment_integral(
    basis,
    np.array([1.5, 2.5, 3.5]),
    np.array([[2, 3, 1], [1, 2, 3]]),
    transform=transform_mo_ao
)
\end{lstlisting}
\end{itemize}

\subsection{Integrals over differential operator}
Integrals over arbitrary differential operator (for Cartesian coordinates) are
supported.
\begin{equation}
  \int
  \phi_a(\mathbf{r}) \frac{\partial^{e+f+g}}{\partial x^e \partial y^f \partial z^g} \phi_b(\mathbf{r})
  d\mathbf{r}
\end{equation}

\subsubsection{Kinetic energy integral}
\begin{equation}
  \label{eq:kinetic_energy}
  \begin{split}
    \left< \hat{T} \right>
    &= \int \phi_a(\mathbf{r}) \left( -\frac{1}{2} \nabla^2 \right) \phi_b(\mathbf{r}) d\mathbf{r}\\
    &= -\frac{1}{2}
    \left(
      \int \phi_a(\mathbf{r}) \frac{\partial^2}{\partial x^2} \phi_b(\mathbf{r}) d\mathbf{r}
      + \int \phi_a(\mathbf{r}) \frac{\partial^2}{\partial y^2} \phi_b(\mathbf{r}) d\mathbf{r}
      + \int \phi_a(\mathbf{r}) \frac{\partial^2}{\partial z^2} \phi_b(\mathbf{r}) d\mathbf{r}
    \right)
  \end{split}
\end{equation}

Example:
\begin{itemize}
\item To compute the kinetic energy integral of a set of atomic orbitals
  \begin{lstlisting}[xleftmargin=-25pt]
from gbasis.integrals.kinetic_energy import kinetic_energy_integral

output = kinetic_energy_integral(basis)
\end{lstlisting}
\item To compute the kinetic energy integral of a set of molecular orbitals
  \begin{lstlisting}[xleftmargin=-25pt]
from gbasis.integrals.kinetic_energy import kinetic_energy_integral

output = kinetic_energy_integral(basis, transform=transform_mo_ao)
\end{lstlisting}
\end{itemize}
\subsubsection{Momentum integral}
\begin{equation}
  \label{eq:momentum}
  \begin{split}
    \left< \hat{\mathbf{p}} \right>
    &= \int \phi_a(\mathbf{r}) \left( -i \nabla \right) \phi_b(\mathbf{r}) d\mathbf{r}\\
    &= -i
    \begin{bmatrix}
      \int \phi_a(\mathbf{r}) \frac{\partial}{\partial x} \phi_b(\mathbf{r}) d\mathbf{r}\\\\
      \int \phi_a(\mathbf{r}) \frac{\partial}{\partial y} \phi_b(\mathbf{r}) d\mathbf{r}\\\\
      \int \phi_a(\mathbf{r}) \frac{\partial}{\partial z} \phi_b(\mathbf{r}) d\mathbf{r}
    \end{bmatrix}
  \end{split}
\end{equation}

Example:
\begin{itemize}
\item To compute the momentum integral of a set of atomic orbitals
  \begin{lstlisting}[xleftmargin=-25pt]
from gbasis.integrals.momentum import momentum_integral

output = momentum_integral(basis)
\end{lstlisting}
\item To compute the momentum integral of a set of molecular orbitals
  \begin{lstlisting}[xleftmargin=-25pt]
from gbasis.integrals.momentum import momentum_integral

output = momentum_integral(basis, transform=transform_mo_ao)
\end{lstlisting}
\end{itemize}
\subsubsection{Angular momentum integral}
\begin{equation}
  \label{eq:angular_momentum}
  \begin{split}
    \left< \hat{\mathbf{L}} \right>
    &= \int \phi_a(\mathbf{r}) \left( -i \mathbf{r} \times \nabla \right) \phi_b(\mathbf{r}) d\mathbf{r}\\
    &= -i
    \begin{bmatrix}
      \int \phi_a(\mathbf{r}) y\frac{\partial}{\partial z} \phi_b(\mathbf{r}) d\mathbf{r}
      - \int \phi_a(\mathbf{r}) z\frac{\partial}{\partial y} \phi_b(\mathbf{r}) d\mathbf{r}\\\\
      \int \phi_a(\mathbf{r}) z\frac{\partial}{\partial x} \phi_b(\mathbf{r}) d\mathbf{r}
      - \int \phi_a(\mathbf{r}) x\frac{\partial}{\partial z} \phi_b(\mathbf{r}) d\mathbf{r}\\\\
      \int \phi_a(\mathbf{r}) x\frac{\partial}{\partial y} \phi_b(\mathbf{r}) d\mathbf{r}
      - \int \phi_a(\mathbf{r}) y\frac{\partial}{\partial x} \phi_b(\mathbf{r}) d\mathbf{r}\\\\
    \end{bmatrix}
  \end{split}
\end{equation}

Example:
\begin{itemize}
\item To compute the angular momentum integral of a set of atomic orbitals
  \begin{lstlisting}[xleftmargin=-25pt]
from gbasis.integrals.angular_momentum import angular_momentum_integral

output = angular_momentum_integral(basis)
\end{lstlisting}
\item To compute the angular momentum integral of a set of molecular orbitals
  \begin{lstlisting}[xleftmargin=-25pt]
from gbasis.integrals.angular_momentum import angular_momentum_integral

output = angular_momentum_integral(basis, transform=transform_mo_ao)
\end{lstlisting}
\end{itemize}
\subsection{Integral for interaction with point-charge}
\begin{equation}
  \label{eq:point_charge}
  \int \phi_a(\mathbf{r}) \frac{1}{|\mathbf{r} - \mathbf{R}_C|} \phi_b(\mathbf{r}) d\mathbf{r}
\end{equation}

Example:
Suppose there are two point charges: $-3$ charge at $(0, 1, 2)$ and $5$ charge
at $(3, 4, 6)$
\begin{itemize}
\item To compute the integral for interaction between these point-charges and
  the set of atomic orbital
  \begin{lstlisting}[xleftmargin=-25pt]
from gbasis.integrals.point_charge import point_charge_integral

output = point_charge_integral(
    basis, np.array([[0, 1, 2], [3, 4, 6]]), np.array([-3, 5])
)
\end{lstlisting}
\item To compute the integral for interaction between these point-charges and
  the set of molecular orbital
  \begin{lstlisting}[xleftmargin=-25pt]
from gbasis.integrals.point_charge import point_charge_integral

output = point_charge_integral(
    basis,
    np.array([[0, 1, 2], [3, 4, 6]]),
    np.array([-3, 5]),
    transform=transform_mo_ao
)
\end{lstlisting}
\end{itemize}
\subsubsection{Nuclear-electron attraction integral}
\begin{equation}
  \label{eq:nuclear_electron_attraction}
  \int \phi_a(\mathbf{r}) \frac{-Z_c}{|\mathbf{r} - \mathbf{R}_C|} \phi_b(\mathbf{r}) d\mathbf{r}
  =
  -Z_C \int \phi_a(\mathbf{r}) \frac{1}{|\mathbf{r} - \mathbf{R}_C|} \phi_b(\mathbf{r}) d\mathbf{r}
\end{equation}

Example:
Suppose there are two nuclei: He at $(0, 1, 2)$ and Al at $(3, 4, 6)$
\begin{itemize}
\item To compute the nuclear-electron attraction integral of the set of atomic
  orbital
  \begin{lstlisting}[xleftmargin=-25pt]
from gbasis.integrals.nuclear_electron_attraction import nuclear_electron_attraction_integral

output = nuclear_electron_attraction_integral(
    basis, np.array([[0, 1, 2], [3, 4, 6]]), np.array([2, 13])
)
\end{lstlisting}
\item To compute the nuclear-electron attraction integral of the set of molecular
  orbital
  \begin{lstlisting}[xleftmargin=-25pt]
from gbasis.integrals.nuclear_electron_attraction import nuclear_electron_attraction_integral

output = nuclear_electron_attraction_integral(
    basis,
    np.array([[0, 1, 2], [3, 4, 6]]),
    np.array([2, 13]),
    transform=transform_mo_ao
)
\end{lstlisting}
\end{itemize}
\subsubsection{Electrostatic potential}
\begin{equation}
  \label{eq:nuclear_electron_attraction}
  \hspace{-3em}
  - \left(
    - \sum_A \frac{Z_A}{|\mathbf{R}_C - \mathbf{R}_A|}
    + \sum_{ab} \gamma_{ab} \int \phi_a(\mathbf{r}) \frac{-1}{|\mathbf{r} - \mathbf{R}_C|} \phi_b(\mathbf{r}) d\mathbf{r}
  \right)
  =
  \sum_A \frac{Z_A}{|\mathbf{R}_C - \mathbf{R}_A|}
  - \sum_{ab} \gamma_{ab} \int \phi_a(\mathbf{r}) \frac{1}{|\mathbf{r} - \mathbf{R}_C|} \phi_b(\mathbf{r}) d\mathbf{r}
\end{equation}

Example:
Suppose there are two nuclei, He at $(0, 1, 2)$ and Al at $(3, 4, 6)$
$(0, 1, 2)$ and $(3, 4, 6)$, the electrostatic potential is measured at
points $(0.5, 1.5, 2.5)$ and $(2.5, 3.5, 5.5)$, and the one-electron density
matrix is given by \verb|one_dm|.
\begin{itemize}
\item To compute the electrostatic potential using density matrix expressed with
  respect to atomic orbitals
  \begin{lstlisting}[xleftmargin=-25pt]
from gbasis.evals.electrostatic_potential import electrostatic_potential

output = electrostatic_potential(
    basis,
    one_dm,
    np.array([[0.5, 1.5, 2.5], [2.5, 3.5, 5.5]]),
    np.array([[0, 1, 2], [3, 4, 6]]),
    np.array([2, 13])
)
\end{lstlisting}
\item To compute the electrostatic potential using density matrix expressed with
  respect to molecular orbitals
  \begin{lstlisting}[xleftmargin=-25pt]
from gbasis.evals.electrostatic_potential import electrostatic_potential

output = electrostatic_potential(
    basis,
    one_dm,
    np.array([[0.5, 1.5, 2.5], [2.5, 3.5, 5.5]]),
    np.array([[0, 1, 2], [3, 4, 6]]),
    np.array([2, 13]),
    transform=transform_mo_ao
)
\end{lstlisting}
\end{itemize}
\subsection{Electron-electron repulsion integral}
In the Chemists' notation,
\begin{equation}
  \label{eq:elec_repulsion}
  \int \phi^*_a(\mathbf{r}_1) \phi_b(\mathbf{r}_1)
  \frac{1}{|\mathbf{r}_1 - \mathbf{r}_2|}
  \phi^*_c(\mathbf{r}_2) \phi_d(\mathbf{r}_2) d\mathbf{r}
\end{equation}
In the Physicists' notation
\begin{equation}
  \label{eq:elec_repulsion_phys}
  \int \phi^*_a(\mathbf{r}_1) \phi^*_b(\mathbf{r}_2)
  \frac{1}{|\mathbf{r}_1 - \mathbf{r}_2|}
  \phi_c(\mathbf{r}_1) \phi_d(\mathbf{r}_2) d\mathbf{r}
\end{equation}

Though both conventions are supported at the higher level, lower level code uses
the Chemists' notation.

Example:
\begin{itemize}
\item To compute the electron repulsion integral of a set of atomic orbitals in
  Physicists' notation
  \begin{lstlisting}[xleftmargin=-25pt]
from gbasis.integrals.electron_repulsion import electron_repulsion_integral

output = electron_repulsion_integral(basis)
\end{lstlisting}
\item To compute the electron repulsion integral of a set of molecular orbitals in
  Physicists' notation
  \begin{lstlisting}[xleftmargin=-25pt]
from gbasis.integrals.electron_repulsion import electron_repulsion_integral

output = electron_repulsion_integral(basis, transform=transform_mo_ao)
\end{lstlisting}
\item To compute the electron repulsion integral of a set of molecular orbitals in
  Chemists' notation
  \begin{lstlisting}[xleftmargin=-25pt]
from gbasis.integrals.electron_repulsion import electron_repulsion_integral

output = electron_repulsion_integral(
    basis, transform=transform_mo_ao, notation="chemist"
)
\end{lstlisting}
\end{itemize}

\section{Future Development}
\begin{itemize}
\item screening (overlap)
\item screening (two electron integrals)
\item improve performance in two electron integral
\item zeroth order regular approximation (zora) for relativistic effects
\item density fitting
\item derivative of contractions with respect to the center
\item derivative of integrals with respect to center
\item periodic boundary condition
\item damped two electron integral
\end{itemize}

\section{Not sure where to put this}
\begin{itemize}
\item Feature requests via github
\item Contributions are welcome
\end{itemize}
\end{document}
