# ao_basis

This module describes the atomic orbitals basis set.

An AO \(\chi\) centered on nucleus A is represented as:

\[\chi_i({\bf r}) = (x-X_A)^a (y-Y_A)^b (z-Z_A)^c \sum_k c_{ki} e^{-\gamma_{ki} |{\bf r} - {\bf R}_A|^2}\]

The AO coefficients are normalized as:

\[{\tilde c}_{ki} = \frac{c_{ki}}{ \int \left( (x-X_A)^a (y-Y_A)^b (z-Z_A)^c e^{-\gamma_{ki} |{\bf r} - {\bf R}_A|^2} \right)^2 dr}\]

Warning: `ao_coef` contains the AO coefficients given in input. These do not include the normalization constant of the AO. The `ao_coef_normalized` provider includes this normalization factor.

The AOs are also sorted by increasing exponent to accelerate the calculation of the two electron integrals.

## EZFIO parameters

`ao_basis```

  Name of the AO basis set

`ao_num```

  Number of AOs

`ao_prim_num```

  Number of primitives per AO

`ao_prim_num_max```

  Maximum number of primitives

  Default: =maxval(ao_basis.ao_prim_num)

`ao_nucl```

  Index of the nucleus on which the AO is centered

`ao_power```

  Powers of x, y and z for each AO

`ao_coef```

  Primitive coefficients, read from input. Those should not be used directly, as the MOs are expressed on the basis of normalized AOs.

`ao_expo```

  Exponents for each primitive of each AO

`ao_md5```

  MD5 key, specific of the AO basis

`ao_cartesian```

  If `true`, use AOs in Cartesian coordinates (6d,10f,…)

  Default: false

## Providers

`ao_coef_normalization_factor`

  File : `ao_basis/aos.irp.f`

      double precision, allocatable   :: ao_coef_normalized   (ao_num,ao_prim_num_max)
      double precision, allocatable   :: ao_coef_normalization_factor (ao_num)

  Coefficients including the AO normalization

  Needs:

  `ao_coef` `ao_expo` | `ao_num` `ao_power` | `ao_prim_num` `ao_prim_num_max`

  Needed by:

  `ao_coef_normalization_libint_factor` | `ao_coef_normalized_ordered` |

`ao_coef_normalization_libint_factor`

  File : `ao_basis/aos.irp.f`

      double precision, allocatable   :: ao_coef_normalization_libint_factor  (ao_num)

  AO normalization for interfacing with libint

  Needs:

  `ao_coef_normalized` `ao_expo` | `ao_l` `ao_num` | `ao_prim_num`

`ao_coef_normalized`

  File : `ao_basis/aos.irp.f`

      double precision, allocatable   :: ao_coef_normalized   (ao_num,ao_prim_num_max)
      double precision, allocatable   :: ao_coef_normalization_factor (ao_num)

  Coefficients including the AO normalization

  Needs:

  `ao_coef` `ao_expo` | `ao_num` `ao_power` | `ao_prim_num` `ao_prim_num_max`

  Needed by:

  `ao_coef_normalization_libint_factor` | `ao_coef_normalized_ordered` |

`ao_coef_normalized_ordered`

  File : `ao_basis/aos.irp.f`

      double precision, allocatable   :: ao_coef_normalized_ordered   (ao_num,ao_prim_num_max)
      double precision, allocatable   :: ao_expo_ordered      (ao_num,ao_prim_num_max)

  Sorted primitives to accelerate 4 index MO transformation

  Needs:

  `ao_coef_normalized` `ao_expo` | `ao_num` `ao_prim_num` | `ao_prim_num_max`

  Needed by:

  `ao_coef_normalized_ordered_transp` | `ao_expo_ordered_transp` |

`ao_coef_normalized_ordered_transp`

  File : `ao_basis/aos.irp.f`

      double precision, allocatable   :: ao_coef_normalized_ordered_transp    (ao_prim_num_max,ao_num)

  Transposed `ao_coef_normalized_ordered`

  Needs:

  `ao_coef_normalized_ordered` | `ao_num` | `ao_prim_num_max`

  Needed by:

  `ao_coef_normalized_ordered_transp_per_nucl` `ao_deriv2_x` `ao_deriv_1_x` `ao_dipole_x` `ao_integrals_n_e` `ao_integrals_n_e_per_atom` | `ao_overlap` `ao_overlap_abs` `ao_pseudo_integrals_local` `ao_pseudo_integrals_non_local` `ao_spread_x` | `ao_two_e_integral_alpha` `ao_two_e_integral_erf_schwartz` `ao_two_e_integral_schwartz` `ao_two_e_integrals_erf_in_map` `ao_two_e_integrals_in_map`

`ao_coef_normalized_ordered_transp_per_nucl`

  File : `ao_basis/aos_transp.irp.f`

      double precision, allocatable   :: ao_coef_normalized_ordered_transp_per_nucl   (ao_prim_num_max,N_AOs_max,nucl_num)

  Needs:

  `ao_coef_normalized_ordered_transp` `ao_prim_num` | `ao_prim_num_max` `nucl_aos_transposed` | `nucl_n_aos` `nucl_num`

`ao_expo_ordered`

  File : `ao_basis/aos.irp.f`

      double precision, allocatable   :: ao_coef_normalized_ordered   (ao_num,ao_prim_num_max)
      double precision, allocatable   :: ao_expo_ordered      (ao_num,ao_prim_num_max)

  Sorted primitives to accelerate 4 index MO transformation

  Needs:

  `ao_coef_normalized` `ao_expo` | `ao_num` `ao_prim_num` | `ao_prim_num_max`

  Needed by:

  `ao_coef_normalized_ordered_transp` | `ao_expo_ordered_transp` |

`ao_expo_ordered_transp`

  File : `ao_basis/aos.irp.f`

      double precision, allocatable   :: ao_expo_ordered_transp       (ao_prim_num_max,ao_num)

  Transposed `ao_expo_ordered`

  Needs:

  `ao_coef_normalized_ordered` | `ao_num` | `ao_prim_num_max`

  Needed by:

  `ao_deriv2_x` `ao_deriv_1_x` `ao_dipole_x` `ao_expo_ordered_transp_per_nucl` `ao_integrals_n_e` `ao_integrals_n_e_per_atom` | `ao_overlap` `ao_overlap_abs` `ao_pseudo_integrals_local` `ao_pseudo_integrals_non_local` `ao_spread_x` | `ao_two_e_integral_alpha` `ao_two_e_integral_erf_schwartz` `ao_two_e_integral_schwartz` `ao_two_e_integrals_erf_in_map` `ao_two_e_integrals_in_map`

`ao_expo_ordered_transp_per_nucl`

  File : `ao_basis/aos_transp.irp.f`

      double precision, allocatable   :: ao_expo_ordered_transp_per_nucl      (ao_prim_num_max,N_AOs_max,nucl_num)

  Needs:

  `ao_expo_ordered_transp` `ao_prim_num` | `ao_prim_num_max` `nucl_aos_transposed` | `nucl_n_aos` `nucl_num`

`ao_l`

  File : `ao_basis/aos.irp.f`

      integer, allocatable    :: ao_l (ao_num)
      integer :: ao_l_max
      character*(128), allocatable    :: ao_l_char    (ao_num)

  \(l\) value of the AO: :math`a+b+c` in \(x^a y^b z^c\)

  Needs:

  `ao_num` | `ao_power` | `l_to_charater`

  Needed by:

  `ao_cart_to_sphe_coef` `ao_coef_normalization_libint_factor` | `ao_l_char_space` | `nucl_list_shell_aos`

`ao_l_char`

  File : `ao_basis/aos.irp.f`

      integer, allocatable    :: ao_l (ao_num)
      integer :: ao_l_max
      character*(128), allocatable    :: ao_l_char    (ao_num)

  \(l\) value of the AO: :math`a+b+c` in \(x^a y^b z^c\)

  Needs:

  `ao_num` | `ao_power` | `l_to_charater`

  Needed by:

  `ao_cart_to_sphe_coef` `ao_coef_normalization_libint_factor` | `ao_l_char_space` | `nucl_list_shell_aos`

`ao_l_char_space`

  File : `ao_basis/aos.irp.f`

      character*(4), allocatable      :: ao_l_char_space      (ao_num)

  Converts an l value to a string

  Needs:

  `ao_l` | `ao_num` | `ao_power`

`ao_l_max`

  File : `ao_basis/aos.irp.f`

      integer, allocatable    :: ao_l (ao_num)
      integer :: ao_l_max
      character*(128), allocatable    :: ao_l_char    (ao_num)

  \(l\) value of the AO: :math`a+b+c` in \(x^a y^b z^c\)

  Needs:

  `ao_num` | `ao_power` | `l_to_charater`

  Needed by:

  `ao_cart_to_sphe_coef` `ao_coef_normalization_libint_factor` | `ao_l_char_space` | `nucl_list_shell_aos`

`ao_power_ordered_transp_per_nucl`

  File : `ao_basis/aos_transp.irp.f`

      integer, allocatable    :: ao_power_ordered_transp_per_nucl     (3,N_AOs_max,nucl_num)

  Needs:

  `ao_power` `nucl_aos_transposed` | `nucl_n_aos` | `nucl_num`

`ao_prim_num_max`

  File : `ao_basis/aos.irp.f`

      integer :: ao_prim_num_max

  Max number of primitives.

  Needs:

  `ao_prim_num` |  |

  Needed by:

  `ao_coef` `ao_coef_normalized` `ao_coef_normalized_ordered` | `ao_coef_normalized_ordered_transp` `ao_coef_normalized_ordered_transp_per_nucl` `ao_expo` | `ao_expo_ordered_transp` `ao_expo_ordered_transp_per_nucl`

`cart_to_sphe_0`

  File : `ao_basis/spherical_to_cartesian.irp.f`

      double precision, allocatable   :: cart_to_sphe_0       (1,1)

  Spherical -> Cartesian Transformation matrix for l=0

`cart_to_sphe_1`

  File : `ao_basis/spherical_to_cartesian.irp.f`

      double precision, allocatable   :: cart_to_sphe_1       (3,3)

  Spherical -> Cartesian Transformation matrix for l=1

  Needed by:

  `ao_cart_to_sphe_coef` |  |

`cart_to_sphe_2`

  File : `ao_basis/spherical_to_cartesian.irp.f`

      double precision, allocatable   :: cart_to_sphe_2       (6,5)

  Spherical -> Cartesian Transformation matrix for l=2

  Needed by:

  `ao_cart_to_sphe_coef` |  |

`cart_to_sphe_3`

  File : `ao_basis/spherical_to_cartesian.irp.f`

      double precision, allocatable   :: cart_to_sphe_3       (10,7)

  Spherical -> Cartesian Transformation matrix for l=3

  Needed by:

  `ao_cart_to_sphe_coef` |  |

`cart_to_sphe_4`

  File : `ao_basis/spherical_to_cartesian.irp.f`

      double precision, allocatable   :: cart_to_sphe_4       (15,9)

  Spherical -> Cartesian Transformation matrix for l=4

  Needed by:

  `ao_cart_to_sphe_coef` |  |

`cart_to_sphe_5`

  File : `ao_basis/spherical_to_cartesian.irp.f`

      double precision, allocatable   :: cart_to_sphe_5       (21,11)

  Spherical -> Cartesian Transformation matrix for l=5

  Needed by:

  `ao_cart_to_sphe_coef` |  |

`cart_to_sphe_6`

  File : `ao_basis/spherical_to_cartesian.irp.f`

      double precision, allocatable   :: cart_to_sphe_6       (28,13)

  Spherical -> Cartesian Transformation matrix for l=6

  Needed by:

  `ao_cart_to_sphe_coef` |  |

`cart_to_sphe_7`

  File : `ao_basis/spherical_to_cartesian.irp.f`

      double precision, allocatable   :: cart_to_sphe_7       (36,15)

  Spherical -> Cartesian Transformation matrix for l=7

  Needed by:

  `ao_cart_to_sphe_coef` |  |

`cart_to_sphe_8`

  File : `ao_basis/spherical_to_cartesian.irp.f`

      double precision, allocatable   :: cart_to_sphe_8       (45,17)

  Spherical -> Cartesian Transformation matrix for l=8

  Needed by:

  `ao_cart_to_sphe_coef` |  |

`cart_to_sphe_9`

  File : `ao_basis/spherical_to_cartesian.irp.f`

      double precision, allocatable   :: cart_to_sphe_9       (55,19)

  Spherical -> Cartesian Transformation matrix for l=9

  Needed by:

  `ao_cart_to_sphe_coef` |  |

`l_to_charater`

  File : `ao_basis/aos.irp.f`

      character*(128), allocatable    :: l_to_charater        (0:7)

  Character corresponding to the “l” value of an AO

  Needed by:

  `ao_l` |  |

`n_aos_max`

  File : `ao_basis/aos.irp.f`

      integer, allocatable    :: nucl_n_aos   (nucl_num)
      integer :: n_aos_max

  Number of AOs per atom

  Needs:

  `ao_nucl` | `ao_num` | `nucl_num`

  Needed by:

  `ao_coef_normalized_ordered_transp_per_nucl` `ao_expo_ordered_transp_per_nucl` | `ao_power_ordered_transp_per_nucl` `nucl_aos` | `nucl_aos_transposed` `nucl_list_shell_aos`

`n_pt_max_i_x`

  File : `ao_basis/dimensions_integrals.irp.f`

      integer :: n_pt_max_integrals
      integer :: n_pt_max_i_x

  Number of points used in the numerical integrations.

  Needs:

  `ao_power` |  |

  Needed by:

  `ao_integrals_n_e` `ao_integrals_n_e_per_atom` `ao_two_e_integral_alpha` | `ao_two_e_integral_erf_schwartz` `ao_two_e_integral_schwartz` `ao_two_e_integrals_erf_in_map` | `ao_two_e_integrals_in_map` `gauleg_t2`

`n_pt_max_integrals`

  File : `ao_basis/dimensions_integrals.irp.f`

      integer :: n_pt_max_integrals
      integer :: n_pt_max_i_x

  Number of points used in the numerical integrations.

  Needs:

  `ao_power` |  |

  Needed by:

  `ao_integrals_n_e` `ao_integrals_n_e_per_atom` `ao_two_e_integral_alpha` | `ao_two_e_integral_erf_schwartz` `ao_two_e_integral_schwartz` `ao_two_e_integrals_erf_in_map` | `ao_two_e_integrals_in_map` `gauleg_t2`

`nucl_aos`

  File : `ao_basis/aos.irp.f`

      integer, allocatable    :: nucl_aos     (nucl_num,N_AOs_max)

  List of AOs centered on each atom

  Needs:

  `ao_nucl` `ao_num` | `nucl_n_aos` | `nucl_num`

  Needed by:

  `nucl_aos_transposed` | `nucl_list_shell_aos` |

`nucl_aos_transposed`

  File : `ao_basis/aos_transp.irp.f`

      integer, allocatable    :: nucl_aos_transposed  (N_AOs_max,nucl_num)

  List of AOs attached on each atom

  Needs:

  `ao_nucl` `ao_num` | `nucl_aos` `nucl_n_aos` | `nucl_num`

  Needed by:

  `ao_coef_normalized_ordered_transp_per_nucl` | `ao_expo_ordered_transp_per_nucl` | `ao_power_ordered_transp_per_nucl`

`nucl_list_shell_aos`

  File : `ao_basis/aos.irp.f`

      integer, allocatable    :: nucl_list_shell_aos  (nucl_num,N_AOs_max)
      integer, allocatable    :: nucl_num_shell_aos   (nucl_num)

  Index of the shell type AOs and of the corresponding AOs By convention, for p,d,f and g AOs, we take the index of the AO with the the corresponding power in the x axis

  Needs:

  `ao_l` `ao_power` | `nucl_aos` `nucl_n_aos` | `nucl_num`

`nucl_n_aos`

  File : `ao_basis/aos.irp.f`

      integer, allocatable    :: nucl_n_aos   (nucl_num)
      integer :: n_aos_max

  Number of AOs per atom

  Needs:

  `ao_nucl` | `ao_num` | `nucl_num`

  Needed by:

  `ao_coef_normalized_ordered_transp_per_nucl` `ao_expo_ordered_transp_per_nucl` | `ao_power_ordered_transp_per_nucl` `nucl_aos` | `nucl_aos_transposed` `nucl_list_shell_aos`

`nucl_num_shell_aos`

  File : `ao_basis/aos.irp.f`

      integer, allocatable    :: nucl_list_shell_aos  (nucl_num,N_AOs_max)
      integer, allocatable    :: nucl_num_shell_aos   (nucl_num)

  Index of the shell type AOs and of the corresponding AOs By convention, for p,d,f and g AOs, we take the index of the AO with the the corresponding power in the x axis

  Needs:

  `ao_l` `ao_power` | `nucl_aos` `nucl_n_aos` | `nucl_num`

## Subroutines / functions

`ao_power_index:`()

  File : `ao_basis/aos.irp.f`

      integer function ao_power_index(nx,ny,nz)

  Unique index given to a triplet of powers:

  \(\frac{1}{2} (l-n_x) (l-n_x+1) + n_z + 1\)

`ao_value:`()

  File : `ao_basis/aos_value.irp.f`

      double precision function ao_value(i,r)

  return the value of the ith ao at point r

  Needs:

  `ao_coef_normalized_ordered_transp` `ao_power` | `ao_expo_ordered_transp` `ao_prim_num` | `ao_nucl` `nucl_coord`

`give_all_aos_and_grad_and_lapl_at_r:`()

  File : `ao_basis/aos_value.irp.f`

      subroutine give_all_aos_and_grad_and_lapl_at_r(r,aos_array,aos_grad_array,aos_lapl_array)

  input : r(1) ==> r(1) = x, r(2) = y, r(3) = z output : aos_array(i) = ao(i) evaluated at r

  > : aos_grad_array(1,i) = gradient X of the ao(i) evaluated at r

  Needs:

  `ao_expo_ordered_transp_per_nucl` `ao_power_ordered_transp_per_nucl` `nucl_n_aos` | `ao_num` `ao_prim_num` `ao_coef_normalized_ordered_transp_per_nucl` | `nucl_aos_transposed` `nucl_coord` `nucl_num`

  Called by:

  `give_all_mos_and_grad_and_lapl_at_r()` |  |

`give_all_aos_and_grad_at_r:`()

  File : `ao_basis/aos_value.irp.f`

      subroutine give_all_aos_and_grad_at_r(r,aos_array,aos_grad_array)

  input : r(1) ==> r(1) = x, r(2) = y, r(3) = z output : aos_array(i) = ao(i) evaluated at r

  > : aos_grad_array(1,i) = gradient X of the ao(i) evaluated at r

  Needs:

  `ao_expo_ordered_transp_per_nucl` `ao_power_ordered_transp_per_nucl` `nucl_n_aos` | `ao_num` `ao_prim_num` `ao_coef_normalized_ordered_transp_per_nucl` | `nucl_aos_transposed` `nucl_coord` `nucl_num`

  Called by:

  `give_all_mos_and_grad_at_r()` |  |

`give_all_aos_at_r:`()

  File : `ao_basis/aos_value.irp.f`

      subroutine give_all_aos_at_r(r,aos_array)

  input : r == r(1) = x and so on aos_array(i) = aos(i) evaluated in r

  Needs:

  `ao_expo_ordered_transp_per_nucl` `ao_power_ordered_transp_per_nucl` `nucl_n_aos` | `ao_num` `ao_prim_num` `ao_coef_normalized_ordered_transp_per_nucl` | `nucl_aos_transposed` `nucl_coord` `nucl_num`

  Called by:

  `give_all_mos_at_r()` |  |

`give_all_aos_at_r_old:`()

  File : `ao_basis/aos_value.irp.f`

      subroutine give_all_aos_at_r_old(r,aos_array)

  gives the values of aos at a given point r

  Needs:

  `ao_num` |  |

`primitive_value:`()

  File : `ao_basis/aos_value.irp.f`

      double precision function primitive_value(i,j,r)

  return the value of the jth primitive of ith ao at point r WITHOUT THE COEF

  Needs:

  `ao_expo_ordered_transp` `ao_nucl` | `nucl_coord` | `ao_power`