.. _module_scf_utils: 
 
.. program:: scf_utils 
 
.. default-role:: option 
 
=========
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 :file:`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 :file:`hartree_fock fock_matrix_hf.irp.f` for an example).

All SCF programs perform the following actions:


#. Compute/Read all the one- and two-electron integrals, and store them in memory

#. 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.
#. Perform the |SCF| iterations based on the definition of the Fock matrix


The main keywords/options are:

* :option:`scf_utils thresh_scf`
* :option:`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 :option:`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.

.. _DIIS: https://en.wikipedia.org/w/index.php?title=DIIS
.. _level-shifting: https://doi.org/10.1002/qua.560070407

 
 
 
EZFIO parameters 
---------------- 
 
.. option:: max_dim_diis
 
    Maximum size of the DIIS extrapolation procedure
 
    Default: 15
 
.. option:: 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.
 
.. option:: thresh_scf
 
    Threshold on the convergence of the Hartree Fock energy.
 
    Default: 1.e-10
 
.. option:: n_it_scf_max
 
    Maximum number of SCF iterations
 
    Default: 500
 
.. option:: level_shift
 
    Energy shift on the virtual MOs to improve SCF convergence
 
    Default: 0.
 
.. option:: scf_algorithm
 
    Type of SCF algorithm used. Possible choices are [ Simple | DIIS]
 
    Default: DIIS
 
.. option:: mo_guess_type
 
    Initial MO guess. Can be [ Huckel | HCore ]
 
    Default: Huckel
 
.. option:: energy
 
    Calculated HF energy
 
 
.. option:: 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 
--------- 
 
.. c:var:: eigenvalues_fock_matrix_ao


    File : :file:`scf_utils/diis.irp.f`

    .. code:: fortran

        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:

    .. hlist::
       :columns: 3

       * :c:data:`ao_num`
       * :c:data:`fock_matrix_ao`
       * :c:data:`s_half_inv`


 
.. c:var:: eigenvectors_fock_matrix_ao


    File : :file:`scf_utils/diis.irp.f`

    .. code:: fortran

        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:

    .. hlist::
       :columns: 3

       * :c:data:`ao_num`
       * :c:data:`fock_matrix_ao`
       * :c:data:`s_half_inv`


 
.. c:var:: eigenvectors_fock_matrix_mo


    File : :file:`scf_utils/diagonalize_fock.irp.f`

    .. code:: fortran

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


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

    Needs:

    .. hlist::
       :columns: 3

       * :c:data:`ao_num`
       * :c:data:`elec_alpha_num`
       * :c:data:`elec_beta_num`
       * :c:data:`fock_matrix_mo`
       * :c:data:`frozen_orb_scf`
       * :c:data:`level_shift`
       * :c:data:`list_inact`
       * :c:data:`mo_coef`
       * :c:data:`mo_num`
       * :c:data:`n_core_orb`


 
.. c:function:: extrapolate_fock_matrix:


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

    .. code:: fortran

        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:

    .. hlist::
       :columns: 3

       * :c:data:`max_dim_diis`
       * :c:data:`ao_num`

    Called by:

    .. hlist::
       :columns: 3

       * :c:func:`roothaan_hall_scf`

    Calls:

    .. hlist::
       :columns: 3

       * :c:func:`dgemm`
       * :c:func:`dsysvx`

 
.. c:var:: fock_matrix_ao


    File : :file:`scf_utils/fock_matrix.irp.f`

    .. code:: fortran

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


    Fock matrix in AO basis set

    Needs:

    .. hlist::
       :columns: 3

       * :c:data:`ao_num`
       * :c:data:`elec_alpha_num`
       * :c:data:`elec_beta_num`
       * :c:data:`fock_matrix_ao_alpha`
       * :c:data:`fock_matrix_mo`
       * :c:data:`frozen_orb_scf`
       * :c:data:`level_shift`
       * :c:data:`mo_num`
       * :c:data:`s_mo_coef`

    Needed by:

    .. hlist::
       :columns: 3

       * :c:data:`eigenvalues_fock_matrix_ao`
       * :c:data:`fps_spf_matrix_ao`

 
.. c:var:: fock_matrix_diag_mo


    File : :file:`scf_utils/fock_matrix.irp.f`

    .. code:: fortran

        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:

    .. hlist::
       :columns: 3

       * :c:data:`elec_alpha_num`
       * :c:data:`elec_beta_num`
       * :c:data:`fock_matrix_mo_alpha`
       * :c:data:`fock_matrix_mo_beta`
       * :c:data:`frozen_orb_scf`
       * :c:data:`list_inact`
       * :c:data:`mo_num`
       * :c:data:`n_core_orb`

    Needed by:

    .. hlist::
       :columns: 3

       * :c:data:`eigenvectors_fock_matrix_mo`
       * :c:data:`fock_matrix_ao`

 
.. c:var:: fock_matrix_mo


    File : :file:`scf_utils/fock_matrix.irp.f`

    .. code:: fortran

        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:

    .. hlist::
       :columns: 3

       * :c:data:`elec_alpha_num`
       * :c:data:`elec_beta_num`
       * :c:data:`fock_matrix_mo_alpha`
       * :c:data:`fock_matrix_mo_beta`
       * :c:data:`frozen_orb_scf`
       * :c:data:`list_inact`
       * :c:data:`mo_num`
       * :c:data:`n_core_orb`

    Needed by:

    .. hlist::
       :columns: 3

       * :c:data:`eigenvectors_fock_matrix_mo`
       * :c:data:`fock_matrix_ao`

 
.. c:var:: fock_matrix_mo_alpha


    File : :file:`scf_utils/fock_matrix.irp.f`

    .. code:: fortran

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


    Fock matrix on the MO basis

    Needs:

    .. hlist::
       :columns: 3

       * :c:data:`ao_num`
       * :c:data:`fock_matrix_ao_alpha`
       * :c:data:`mo_coef`
       * :c:data:`mo_num`

    Needed by:

    .. hlist::
       :columns: 3

       * :c:data:`fock_matrix_mo`

 
.. c:var:: fock_matrix_mo_beta


    File : :file:`scf_utils/fock_matrix.irp.f`

    .. code:: fortran

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


    Fock matrix on the MO basis

    Needs:

    .. hlist::
       :columns: 3

       * :c:data:`ao_num`
       * :c:data:`fock_matrix_ao_alpha`
       * :c:data:`mo_coef`
       * :c:data:`mo_num`

    Needed by:

    .. hlist::
       :columns: 3

       * :c:data:`fock_matrix_mo`

 
.. c:var:: fps_spf_matrix_ao


    File : :file:`scf_utils/diis.irp.f`

    .. code:: fortran

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


    Commutator FPS - SPF

    Needs:

    .. hlist::
       :columns: 3

       * :c:data:`ao_num`
       * :c:data:`ao_overlap`
       * :c:data:`fock_matrix_ao`
       * :c:data:`scf_density_matrix_ao`

    Needed by:

    .. hlist::
       :columns: 3

       * :c:data:`fps_spf_matrix_mo`

 
.. c:var:: fps_spf_matrix_mo


    File : :file:`scf_utils/diis.irp.f`

    .. code:: fortran

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


    Commutator FPS - SPF in MO basis

    Needs:

    .. hlist::
       :columns: 3

       * :c:data:`ao_num`
       * :c:data:`fps_spf_matrix_ao`
       * :c:data:`mo_coef`
       * :c:data:`mo_num`


 
.. c:var:: scf_density_matrix_ao


    File : :file:`scf_utils/scf_density_matrix_ao.irp.f`

    .. code:: fortran

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


    Sum of :math:`\alpha`  and :math:`\beta`  density matrices

    Needs:

    .. hlist::
       :columns: 3

       * :c:data:`ao_num`
       * :c:data:`elec_alpha_num`
       * :c:data:`elec_beta_num`
       * :c:data:`scf_density_matrix_ao_alpha`
       * :c:data:`scf_density_matrix_ao_beta`

    Needed by:

    .. hlist::
       :columns: 3

       * :c:data:`fps_spf_matrix_ao`

 
.. c:var:: scf_density_matrix_ao_alpha


    File : :file:`scf_utils/scf_density_matrix_ao.irp.f`

    .. code:: fortran

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


    :math:`C.C^t`  over :math:`\alpha`  MOs

    Needs:

    .. hlist::
       :columns: 3

       * :c:data:`ao_num`
       * :c:data:`elec_alpha_num`
       * :c:data:`mo_coef`

    Needed by:

    .. hlist::
       :columns: 3

       * :c:data:`ao_two_e_integral_alpha`
       * :c:data:`hf_energy`
       * :c:data:`scf_density_matrix_ao`
       * :c:data:`scf_energy`

 
.. c:var:: scf_density_matrix_ao_beta


    File : :file:`scf_utils/scf_density_matrix_ao.irp.f`

    .. code:: fortran

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


    :math:`C.C^t`  over :math:`\beta`  MOs

    Needs:

    .. hlist::
       :columns: 3

       * :c:data:`ao_num`
       * :c:data:`elec_beta_num`
       * :c:data:`mo_coef`

    Needed by:

    .. hlist::
       :columns: 3

       * :c:data:`ao_two_e_integral_alpha`
       * :c:data:`hf_energy`
       * :c:data:`scf_density_matrix_ao`
       * :c:data:`scf_energy`

 
.. c:var:: scf_energy


    File : :file:`scf_utils/fock_matrix.irp.f`

    .. code:: fortran

        double precision	:: scf_energy	


    Hartree-Fock energy

    Needs:

    .. hlist::
       :columns: 3

       * :c:data:`ao_num`
       * :c:data:`ao_one_e_integrals`
       * :c:data:`extra_e_contrib_density`
       * :c:data:`fock_matrix_ao_alpha`
       * :c:data:`nuclear_repulsion`
       * :c:data:`scf_density_matrix_ao_alpha`
       * :c:data:`scf_density_matrix_ao_beta`


 
.. c:var:: threshold_diis_nonzero


    File : :file:`scf_utils/diis.irp.f`

    .. code:: fortran

        double precision	:: threshold_diis_nonzero	


    If threshold_DIIS is zero, choose sqrt(thresh_scf)

    Needs:

    .. hlist::
       :columns: 3

       * :c:data:`thresh_scf`
       * :c:data:`threshold_diis`


 
 
Subroutines / functions 
----------------------- 
 
.. c:function:: damping_scf:


    File : :file:`scf_utils/damping_scf.irp.f`

    .. code:: fortran

        subroutine damping_SCF



    Needs:

    .. hlist::
       :columns: 3

       * :c:data:`mo_coef`
       * :c:data:`eigenvectors_fock_matrix_mo`
       * :c:data:`scf_energy`
       * :c:data:`scf_density_matrix_ao_beta`
       * :c:data:`fock_matrix_mo`
       * :c:data:`ao_num`
       * :c:data:`scf_density_matrix_ao_alpha`
       * :c:data:`fock_matrix_ao`
       * :c:data:`mo_label`
       * :c:data:`n_it_scf_max`
       * :c:data:`thresh_scf`
       * :c:data:`frozen_orb_scf`

    Calls:

    .. hlist::
       :columns: 3

       * :c:func:`ezfio_set_hartree_fock_energy`
       * :c:func:`initialize_mo_coef_begin_iteration`
       * :c:func:`mo_as_eigvectors_of_mo_matrix`
       * :c:func:`reorder_core_orb`
       * :c:func:`save_mos`
       * :c:func:`write_double`
       * :c:func:`write_time`

    Touches:

    .. hlist::
       :columns: 3

       * :c:data:`scf_density_matrix_ao_alpha`
       * :c:data:`scf_density_matrix_ao_beta`
       * :c:data:`mo_coef`

 
.. c:function:: huckel_guess:


    File : :file:`scf_utils/huckel.irp.f`

    .. code:: fortran

        subroutine huckel_guess


    Build the MOs using the extended Huckel model

    Needs:

    .. hlist::
       :columns: 3

       * :c:data:`ao_one_e_integrals`
       * :c:data:`mo_coef`
       * :c:data:`eigenvectors_fock_matrix_mo`
       * :c:data:`ao_overlap`
       * :c:data:`ao_num`
       * :c:data:`ao_two_e_integral_alpha`
       * :c:data:`fock_matrix_ao_alpha`
       * :c:data:`fock_matrix_ao_alpha`

    Called by:

    .. hlist::
       :columns: 3

       * :c:func:`create_guess`

    Calls:

    .. hlist::
       :columns: 3

       * :c:func:`save_mos`

    Touches:

    .. hlist::
       :columns: 3

       * :c:data:`fock_matrix_ao_alpha`
       * :c:data:`fock_matrix_ao_alpha`
       * :c:data:`mo_coef`

 
.. c:function:: roothaan_hall_scf:


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

    .. code:: fortran

        subroutine Roothaan_Hall_SCF


    Roothaan-Hall algorithm for SCF Hartree-Fock calculation

    Needs:

    .. hlist::
       :columns: 3

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

    Called by:

    .. hlist::
       :columns: 3

       * :c:func:`run`

    Calls:

    .. hlist::
       :columns: 3

       * :c:func:`extrapolate_fock_matrix`
       * :c:func:`initialize_mo_coef_begin_iteration`
       * :c:func:`mo_as_eigvectors_of_mo_matrix`
       * :c:func:`reorder_core_orb`
       * :c:func:`save_mos`
       * :c:func:`write_double`
       * :c:func:`write_time`

    Touches:

    .. hlist::
       :columns: 3

       * :c:data:`fock_matrix_ao_alpha`
       * :c:data:`fock_matrix_ao_alpha`
       * :c:data:`mo_coef`
       * :c:data:`level_shift`
       * :c:data:`mo_coef`