# scf_utils

The scf_utils module is an abstract module which contains the basics to perform Restricted SCF calculations (the spatial part of the MOs is common for alpha and beta spinorbitals) based on a single-determinant wave function.

This module does not produce any executable and must not do, but instead it contains everything one needs to perform an orbital optimization based on an Fock matrix. The `scf_utils` module is meant to be included in the `NEED` of the various single determinant SCF procedures, such as `hartree_fock` or `kohn_sham`, where a specific definition of the Fock matrix is given (see `hartree_fock fock_matrix_hf.irp.f` for an example).

All SCF programs perform the following actions:

1. Compute/Read all the one- and two-electron integrals, and store them in memory
2. Check in the EZFIO database if there is a set of MOs. If there is, it will read them as initial guess. Otherwise, it will create a guess.
3. Perform the SCF iterations based on the definition of the Fock matrix

The main keywords/options are:

- `scf_utils thresh_scf`
- `scf_utils level_shift`

At each iteration, the MOs are saved in the EZFIO database. Hence, if the calculation crashes for any unexpected reason, the calculation can be restarted by running again the SCF with the same EZFIO database.

The DIIS algorithm is implemented, as well as the level-shifting method. If the SCF does not converge, try again with a higher value of `level_shift`.

To start a calculation from scratch, the simplest way is to remove the `mo_basis` directory from the EZFIO database, and run the SCF again.

## EZFIO parameters

`max_dim_diis```

  Maximum size of the DIIS extrapolation procedure

  Default: 15

`threshold_diis```

  Threshold on the convergence of the DIIS error vector during a Hartree-Fock calculation. If 0. is chosen, the square root of thresh_scf will be used.

  Default: 0.

`thresh_scf```

  Threshold on the convergence of the Hartree Fock energy.

  Default: 1.e-10

`n_it_scf_max```

  Maximum number of SCF iterations

  Default: 500

`level_shift```

  Energy shift on the virtual MOs to improve SCF convergence

  Default: 0.

`scf_algorithm```

  Type of SCF algorithm used. Possible choices are [ Simple | DIIS]

  Default: DIIS

`mo_guess_type```

  Initial MO guess. Can be [ Huckel | HCore ]

  Default: Huckel

`energy```

  Calculated HF energy

`frozen_orb_scf```

  If true, leave untouched all the orbitals defined as core and optimize all the orbitals defined as active with qp_set_mo_class

  Default: False

## Providers

`eigenvalues_fock_matrix_ao`

  File : `scf_utils/diis.irp.f`

      double precision, allocatable   :: eigenvalues_fock_matrix_ao   (AO_num)
      double precision, allocatable   :: eigenvectors_fock_matrix_ao  (AO_num,AO_num)

  Eigenvalues and eigenvectors of the Fock matrix over the AO basis

  Needs:

  `ao_num` | `fock_matrix_ao` | `s_half_inv`

`eigenvectors_fock_matrix_ao`

  File : `scf_utils/diis.irp.f`

      double precision, allocatable   :: eigenvalues_fock_matrix_ao   (AO_num)
      double precision, allocatable   :: eigenvectors_fock_matrix_ao  (AO_num,AO_num)

  Eigenvalues and eigenvectors of the Fock matrix over the AO basis

  Needs:

  `ao_num` | `fock_matrix_ao` | `s_half_inv`

`eigenvectors_fock_matrix_mo`

  File : `scf_utils/diagonalize_fock.irp.f`

      double precision, allocatable   :: eigenvectors_fock_matrix_mo  (ao_num,mo_num)

  Eigenvector of the Fock matrix in the MO basis obtained with level shift.

  Needs:

  `ao_num` `elec_alpha_num` `elec_beta_num` `fock_matrix_mo` | `frozen_orb_scf` `level_shift` `list_inact` | `mo_coef` `mo_num` `n_core_orb`

`extrapolate_fock_matrix:`()

  > File : `scf_utils/roothaan_hall_scf.irp.f`

  >     subroutine extrapolate_Fock_matrix(      &

  error_matrix_DIIS,Fock_matrix_DIIS, & Fock_matrix_AO_,size_Fock_matrix_AO, & iteration_SCF,dim_DIIS &

)

> Compute the extrapolated Fock matrix using the DIIS procedure

> Needs:

> `max_dim_diis` | `ao_num` |

> Called by:

> `roothaan_hall_scf()` |  |

> Calls:

> `dgemm()` | `dsysvx()` |

`fock_matrix_ao`

  File : `scf_utils/fock_matrix.irp.f`

      double precision, allocatable   :: fock_matrix_ao       (ao_num,ao_num)

  Fock matrix in AO basis set

  Needs:

  `ao_num` `elec_alpha_num` `elec_beta_num` | `fock_matrix_ao_alpha` `fock_matrix_mo` `frozen_orb_scf` | `level_shift` `mo_num` `s_mo_coef`

  Needed by:

  `eigenvalues_fock_matrix_ao` | `fps_spf_matrix_ao` |

`fock_matrix_diag_mo`

  File : `scf_utils/fock_matrix.irp.f`

      double precision, allocatable   :: fock_matrix_mo       (mo_num,mo_num)
      double precision, allocatable   :: fock_matrix_diag_mo  (mo_num)

  Fock matrix on the MO basis. For open shells, the ROHF Fock Matrix is

      |   F-K    |  F + K/2  |    F     |
      |---------------------------------|
      | F + K/2  |     F     |  F - K/2 |
      |---------------------------------|
      |    F     |  F - K/2  |  F + K   |

  F = 1/2 (Fa + Fb)

  K = Fb - Fa

  Needs:

  `elec_alpha_num` `elec_beta_num` `fock_matrix_mo_alpha` | `fock_matrix_mo_beta` `frozen_orb_scf` `list_inact` | `mo_num` `n_core_orb`

  Needed by:

  `eigenvectors_fock_matrix_mo` | `fock_matrix_ao` |

`fock_matrix_mo`

  File : `scf_utils/fock_matrix.irp.f`

      double precision, allocatable   :: fock_matrix_mo       (mo_num,mo_num)
      double precision, allocatable   :: fock_matrix_diag_mo  (mo_num)

  Fock matrix on the MO basis. For open shells, the ROHF Fock Matrix is

      |   F-K    |  F + K/2  |    F     |
      |---------------------------------|
      | F + K/2  |     F     |  F - K/2 |
      |---------------------------------|
      |    F     |  F - K/2  |  F + K   |

  F = 1/2 (Fa + Fb)

  K = Fb - Fa

  Needs:

  `elec_alpha_num` `elec_beta_num` `fock_matrix_mo_alpha` | `fock_matrix_mo_beta` `frozen_orb_scf` `list_inact` | `mo_num` `n_core_orb`

  Needed by:

  `eigenvectors_fock_matrix_mo` | `fock_matrix_ao` |

`fock_matrix_mo_alpha`

  File : `scf_utils/fock_matrix.irp.f`

      double precision, allocatable   :: fock_matrix_mo_alpha (mo_num,mo_num)

  Fock matrix on the MO basis

  Needs:

  `ao_num` `fock_matrix_ao_alpha` | `mo_coef` | `mo_num`

  Needed by:

  `fock_matrix_mo` |  |

`fock_matrix_mo_beta`

  File : `scf_utils/fock_matrix.irp.f`

      double precision, allocatable   :: fock_matrix_mo_beta  (mo_num,mo_num)

  Fock matrix on the MO basis

  Needs:

  `ao_num` `fock_matrix_ao_alpha` | `mo_coef` | `mo_num`

  Needed by:

  `fock_matrix_mo` |  |

`fps_spf_matrix_ao`

  File : `scf_utils/diis.irp.f`

      double precision, allocatable   :: fps_spf_matrix_ao    (AO_num,AO_num)

  Commutator FPS - SPF

  Needs:

  `ao_num` `ao_overlap` | `fock_matrix_ao` | `scf_density_matrix_ao`

  Needed by:

  `fps_spf_matrix_mo` |  |

`fps_spf_matrix_mo`

  File : `scf_utils/diis.irp.f`

      double precision, allocatable   :: fps_spf_matrix_mo    (mo_num,mo_num)

  Commutator FPS - SPF in MO basis

  Needs:

  `ao_num` `fps_spf_matrix_ao` | `mo_coef` | `mo_num`

`scf_density_matrix_ao`

  File : `scf_utils/scf_density_matrix_ao.irp.f`

      double precision, allocatable   :: scf_density_matrix_ao        (ao_num,ao_num)

  S^{-1}.P.S^{-1} where P = C.C^t

  Needs:

  `ao_num` `elec_alpha_num` | `elec_beta_num` `scf_density_matrix_ao_alpha` | `scf_density_matrix_ao_beta`

  Needed by:

  `fps_spf_matrix_ao` |  |

`scf_density_matrix_ao_alpha`

  File : `scf_utils/scf_density_matrix_ao.irp.f`

      double precision, allocatable   :: scf_density_matrix_ao_alpha  (ao_num,ao_num)

  S^{-1}.P_alpha.S^{-1}

  Needs:

  `ao_num` | `elec_alpha_num` | `mo_coef`

  Needed by:

  `ao_two_e_integral_alpha` `hf_energy` | `scf_density_matrix_ao` | `scf_energy`

`scf_density_matrix_ao_beta`

  File : `scf_utils/scf_density_matrix_ao.irp.f`

      double precision, allocatable   :: scf_density_matrix_ao_beta   (ao_num,ao_num)

  S^{-1}.P_beta.S^{-1}

  Needs:

  `ao_num` | `elec_beta_num` | `mo_coef`

  Needed by:

  `ao_two_e_integral_alpha` `hf_energy` | `scf_density_matrix_ao` | `scf_energy`

`scf_energy`

  File : `scf_utils/fock_matrix.irp.f`

      double precision        :: scf_energy

  Hartree-Fock energy

  Needs:

  `ao_num` `ao_one_e_integrals` `extra_e_contrib_density` | `fock_matrix_ao_alpha` `nuclear_repulsion` | `scf_density_matrix_ao_alpha` `scf_density_matrix_ao_beta`

`threshold_diis_nonzero`

  File : `scf_utils/diis.irp.f`

      double precision        :: threshold_diis_nonzero

  If threshold_DIIS is zero, choose sqrt(thresh_scf)

  Needs:

  `thresh_scf` | `threshold_diis` |

## Subroutines / functions

`damping_scf:`()

  File : `scf_utils/damping_scf.irp.f`

      subroutine damping_SCF

  Needs:

  `mo_coef` `eigenvectors_fock_matrix_mo` `scf_energy` `scf_density_matrix_ao_beta` | `fock_matrix_mo` `ao_num` `scf_density_matrix_ao_alpha` `fock_matrix_ao` | `mo_label` `n_it_scf_max` `thresh_scf` `frozen_orb_scf`

  Calls:

  `ezfio_set_hartree_fock_energy()` `initialize_mo_coef_begin_iteration()` `mo_as_eigvectors_of_mo_matrix()` | `reorder_core_orb()` `save_mos()` | `write_double()` `write_time()`

  Touches:

  `scf_density_matrix_ao_alpha` | `scf_density_matrix_ao_beta` | `mo_coef`

`huckel_guess:`()

  File : `scf_utils/huckel.irp.f`

      subroutine huckel_guess

  Build the MOs using the extended Huckel model

  Needs:

  `ao_one_e_integrals` `mo_coef` `eigenvectors_fock_matrix_mo` | `ao_overlap` `ao_num` `ao_two_e_integral_alpha` | `fock_matrix_ao_alpha` `fock_matrix_ao_alpha`

  Called by:

  `create_guess()` |  |

  Calls:

  `save_mos()` |  |

  Touches:

  `fock_matrix_ao_alpha` | `fock_matrix_ao_alpha` | `mo_coef`

`roothaan_hall_scf:`()

  File : `scf_utils/roothaan_hall_scf.irp.f`

      subroutine Roothaan_Hall_SCF

  Roothaan-Hall algorithm for SCF Hartree-Fock calculation

  Needs:

  `max_dim_diis` `mo_occ` `ao_md5` `mo_coef` `level_shift` `fps_spf_matrix_mo` `eigenvectors_fock_matrix_mo` | `scf_energy` `mo_num` `thresh_scf` `scf_algorithm` `fock_matrix_mo` `ao_num` `fock_matrix_ao` | `mo_label` `n_it_scf_max` `threshold_diis_nonzero` `frozen_orb_scf` `fock_matrix_ao_alpha` `fock_matrix_ao_alpha` `fps_spf_matrix_ao`

  Called by:

  `run()` |  |

  Calls:

  `extrapolate_fock_matrix()` `initialize_mo_coef_begin_iteration()` `mo_as_eigvectors_of_mo_matrix()` | `reorder_core_orb()` `save_mos()` | `write_double()` `write_time()`

  Touches:

  `fock_matrix_ao_alpha` `fock_matrix_ao_alpha` | `mo_coef` `level_shift` | `mo_coef`