LCOV - code coverage report
Current view: top level - src - qs_mo_types.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:936074a) Lines: 94.3 % 174 164
Test Date: 2025-12-04 06:27:48 Functions: 81.8 % 11 9

            Line data    Source code
       1              : !--------------------------------------------------------------------------------------------------!
       2              : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3              : !   Copyright 2000-2025 CP2K developers group <https://cp2k.org>                                   !
       4              : !                                                                                                  !
       5              : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6              : !--------------------------------------------------------------------------------------------------!
       7              : 
       8              : ! **************************************************************************************************
       9              : !> \brief Definition and initialisation of the mo data type.
      10              : !> \par History
      11              : !>      - adapted to the new QS environment data structure (02.04.2002,MK)
      12              : !>      - set_mo_occupation added (17.04.02,MK)
      13              : !>      - correct_mo_eigenvalues added (18.04.02,MK)
      14              : !>      - calculate_density_matrix moved from qs_scf to here (22.04.02,MK)
      15              : !>      - mo_set_p_type added (23.04.02,MK)
      16              : !>      - PRIVATE attribute set for TYPE mo_set_type (23.04.02,MK)
      17              : !>      - started conversion to LSD (1.2003, Joost VandeVondele)
      18              : !>      - set_mo_occupation moved to qs_mo_occupation (11.12.14 MI)
      19              : !>      - correct_mo_eigenvalues moved to qs_scf_methods (03.2016, Sergey Chulkov)
      20              : !> \author Matthias Krack (09.05.2001,MK)
      21              : ! **************************************************************************************************
      22              : MODULE qs_mo_types
      23              : 
      24              :    USE cp_dbcsr_api,                    ONLY: dbcsr_copy,&
      25              :                                               dbcsr_init_p,&
      26              :                                               dbcsr_release_p,&
      27              :                                               dbcsr_type
      28              :    USE cp_dbcsr_operations,             ONLY: dbcsr_copy_columns_hack
      29              :    USE cp_fm_pool_types,                ONLY: cp_fm_pool_type,&
      30              :                                               fm_pool_create_fm
      31              :    USE cp_fm_struct,                    ONLY: cp_fm_struct_type
      32              :    USE cp_fm_types,                     ONLY: cp_fm_create,&
      33              :                                               cp_fm_get_info,&
      34              :                                               cp_fm_release,&
      35              :                                               cp_fm_set_all,&
      36              :                                               cp_fm_to_fm,&
      37              :                                               cp_fm_type
      38              :    USE kinds,                           ONLY: dp
      39              : #include "./base/base_uses.f90"
      40              : 
      41              :    IMPLICIT NONE
      42              : 
      43              :    PRIVATE
      44              : 
      45              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'qs_mo_types'
      46              : 
      47              :    TYPE mo_set_type
      48              :       ! The actual MO coefficients as a matrix
      49              :       TYPE(cp_fm_type), POINTER                          :: mo_coeff => NULL()
      50              :       TYPE(dbcsr_type), POINTER                          :: mo_coeff_b => NULL()
      51              :       ! we are using the dbcsr mo_coeff_b
      52              :       LOGICAL                                            :: use_mo_coeff_b = .FALSE.
      53              :       ! Number of molecular orbitals (# cols in mo_coeff)
      54              :       INTEGER                                            :: nmo = -1
      55              :       ! Number of atomic orbitals (# rows in mo_coeff)
      56              :       INTEGER                                            :: nao = -1
      57              :       ! MO occupation numbers and MO eigenvalues (if eigenstates)
      58              :       REAL(KIND=dp), DIMENSION(:), POINTER               :: eigenvalues => NULL(), &
      59              :                                                             occupation_numbers => NULL()
      60              :       ! Maximum allowed occupation number of an MO, i.e.
      61              :       ! 1 for spin unrestricted (polarized) and 2 for spin restricted
      62              :       REAL(KIND=dp)                                      :: maxocc = -1
      63              :       ! Number of electrons (taking occupations into account)
      64              :       INTEGER                                            :: nelectron = -1
      65              :       REAL(KIND=dp)                                      :: n_el_f = -1.0_dp
      66              :       ! Highest orbital with non-zero occupation
      67              :       INTEGER                                            :: homo = -1
      68              :       ! lowest non maxocc occupied orbital (e.g. fractional or zero)
      69              :       INTEGER                                            :: lfomo = -1
      70              :       ! True, if all allocated MOs have the same occupation number.
      71              :       ! This is not the case for fractional occupations or for added MOs
      72              :       ! with zero occupation.
      73              :       LOGICAL                                            :: uniform_occupation = .FALSE.
      74              :       ! The entropic energy contribution
      75              :       REAL(KIND=dp)                                      :: kTS = -1.0_dp
      76              :       ! Fermi energy level
      77              :       REAL(KIND=dp)                                      :: mu = 0.0_dp
      78              :       ! Threshold value for multiplicity change
      79              :       REAL(KIND=dp)                                      :: flexible_electron_count = -1.0_dp
      80              :    END TYPE mo_set_type
      81              : 
      82              :    TYPE mo_set_p_type
      83              :       TYPE(mo_set_type), POINTER :: mo_set => NULL()
      84              :    END TYPE mo_set_p_type
      85              : 
      86              :    PUBLIC :: mo_set_p_type, &
      87              :              mo_set_type
      88              : 
      89              :    PUBLIC :: allocate_mo_set, &
      90              :              deallocate_mo_set, &
      91              :              duplicate_mo_set, &
      92              :              get_mo_set, &
      93              :              has_uniform_occupation, &
      94              :              init_mo_set, &
      95              :              mo_set_restrict, &
      96              :              reassign_allocated_mos, &
      97              :              set_mo_set
      98              : 
      99              : CONTAINS
     100              : 
     101              : ! **************************************************************************************************
     102              : !> \brief reassign an already allocated mo_set
     103              : !> \param mo_set_new ...
     104              : !> \param mo_set_old ...
     105              : !> \date 2019-05-16
     106              : !> \par History
     107              : !> \author Soumya Ghosh
     108              : ! **************************************************************************************************
     109            8 :    SUBROUTINE reassign_allocated_mos(mo_set_new, mo_set_old)
     110              :       TYPE(mo_set_type), INTENT(INOUT)                   :: mo_set_new, mo_set_old
     111              : 
     112              :       INTEGER                                            :: nmo
     113              : 
     114            8 :       mo_set_new%maxocc = mo_set_old%maxocc
     115            8 :       mo_set_new%nelectron = mo_set_old%nelectron
     116            8 :       mo_set_new%n_el_f = mo_set_old%n_el_f
     117            8 :       mo_set_new%nao = mo_set_old%nao
     118            8 :       mo_set_new%nmo = mo_set_old%nmo
     119            8 :       mo_set_new%homo = mo_set_old%homo
     120            8 :       mo_set_new%lfomo = mo_set_old%lfomo
     121            8 :       mo_set_new%uniform_occupation = mo_set_old%uniform_occupation
     122            8 :       mo_set_new%kTS = mo_set_old%kTS
     123            8 :       mo_set_new%mu = mo_set_old%mu
     124            8 :       mo_set_new%flexible_electron_count = mo_set_old%flexible_electron_count
     125              : 
     126            8 :       nmo = mo_set_new%nmo
     127              : 
     128            8 :       CALL cp_fm_to_fm(mo_set_old%mo_coeff, mo_set_new%mo_coeff)
     129              : 
     130              :       !IF (ASSOCIATED(mo_set_old%mo_coeff_b)) THEN
     131              :       !   CALL dbcsr_copy(mo_set_new%mo_coeff_b, mo_set_old%mo_coeff_b)
     132              :       !END IF
     133              :       !mo_set_new%use_mo_coeff_b = mo_set_old%use_mo_coeff_b
     134              : 
     135          332 :       mo_set_new%eigenvalues = mo_set_old%eigenvalues
     136              : 
     137          332 :       mo_set_new%occupation_numbers = mo_set_old%occupation_numbers
     138              : 
     139            8 :    END SUBROUTINE reassign_allocated_mos
     140              : 
     141              : ! **************************************************************************************************
     142              : !> \brief allocate a new mo_set, and copy the old data
     143              : !> \param mo_set_new ...
     144              : !> \param mo_set_old ...
     145              : !> \date 2009-7-19
     146              : !> \par History
     147              : !> \author Joost VandeVondele
     148              : ! **************************************************************************************************
     149          464 :    SUBROUTINE duplicate_mo_set(mo_set_new, mo_set_old)
     150              :       TYPE(mo_set_type), INTENT(OUT)                     :: mo_set_new
     151              :       TYPE(mo_set_type), INTENT(IN)                      :: mo_set_old
     152              : 
     153              :       INTEGER                                            :: nmo
     154              : 
     155          464 :       mo_set_new%maxocc = mo_set_old%maxocc
     156          464 :       mo_set_new%nelectron = mo_set_old%nelectron
     157          464 :       mo_set_new%n_el_f = mo_set_old%n_el_f
     158          464 :       mo_set_new%nao = mo_set_old%nao
     159          464 :       mo_set_new%nmo = mo_set_old%nmo
     160          464 :       mo_set_new%homo = mo_set_old%homo
     161          464 :       mo_set_new%lfomo = mo_set_old%lfomo
     162          464 :       mo_set_new%uniform_occupation = mo_set_old%uniform_occupation
     163          464 :       mo_set_new%kTS = mo_set_old%kTS
     164          464 :       mo_set_new%mu = mo_set_old%mu
     165          464 :       mo_set_new%flexible_electron_count = mo_set_old%flexible_electron_count
     166              : 
     167          464 :       nmo = mo_set_new%nmo
     168              : 
     169              :       NULLIFY (mo_set_new%mo_coeff)
     170          464 :       ALLOCATE (mo_set_new%mo_coeff)
     171          464 :       CALL cp_fm_create(mo_set_new%mo_coeff, mo_set_old%mo_coeff%matrix_struct)
     172          464 :       CALL cp_fm_to_fm(mo_set_old%mo_coeff, mo_set_new%mo_coeff)
     173              : 
     174          464 :       NULLIFY (mo_set_new%mo_coeff_b)
     175          464 :       IF (ASSOCIATED(mo_set_old%mo_coeff_b)) THEN
     176          452 :          CALL dbcsr_init_p(mo_set_new%mo_coeff_b)
     177          452 :          CALL dbcsr_copy(mo_set_new%mo_coeff_b, mo_set_old%mo_coeff_b)
     178              :       END IF
     179          464 :       mo_set_new%use_mo_coeff_b = mo_set_old%use_mo_coeff_b
     180              : 
     181         1392 :       ALLOCATE (mo_set_new%eigenvalues(nmo))
     182         1604 :       mo_set_new%eigenvalues = mo_set_old%eigenvalues
     183              : 
     184         1392 :       ALLOCATE (mo_set_new%occupation_numbers(nmo))
     185         1604 :       mo_set_new%occupation_numbers = mo_set_old%occupation_numbers
     186              : 
     187          464 :    END SUBROUTINE duplicate_mo_set
     188              : 
     189              : ! **************************************************************************************************
     190              : !> \brief Allocates a mo set and partially initializes it (nao,nmo,nelectron,
     191              : !>        and flexible_electron_count are valid).
     192              : !>        For the full initialization you need to call init_mo_set
     193              : !> \param mo_set the mo_set to allocate
     194              : !> \param nao number of atom orbitals
     195              : !> \param nmo number of molecular orbitals
     196              : !> \param nelectron number of electrons
     197              : !> \param n_el_f ...
     198              : !> \param maxocc maximum occupation of an orbital (LDA: 2, LSD:1)
     199              : !> \param flexible_electron_count the number of electrons can be changed
     200              : !> \date 15.05.2001
     201              : !> \par History
     202              : !>      11.2002 splitted initialization in two phases [fawzi]
     203              : !> \author Matthias Krack
     204              : ! **************************************************************************************************
     205        16483 :    SUBROUTINE allocate_mo_set(mo_set, nao, nmo, nelectron, n_el_f, maxocc, &
     206              :                               flexible_electron_count)
     207              : 
     208              :       TYPE(mo_set_type), INTENT(INOUT)                   :: mo_set
     209              :       INTEGER, INTENT(IN)                                :: nao, nmo, nelectron
     210              :       REAL(KIND=dp), INTENT(IN)                          :: n_el_f, maxocc, flexible_electron_count
     211              : 
     212        16483 :       mo_set%maxocc = maxocc
     213        16483 :       mo_set%nelectron = nelectron
     214        16483 :       mo_set%n_el_f = n_el_f
     215        16483 :       mo_set%nao = nao
     216        16483 :       mo_set%nmo = nmo
     217        16483 :       mo_set%homo = 0
     218        16483 :       mo_set%lfomo = 0
     219        16483 :       mo_set%uniform_occupation = .TRUE.
     220        16483 :       mo_set%kTS = 0.0_dp
     221        16483 :       mo_set%mu = 0.0_dp
     222        16483 :       mo_set%flexible_electron_count = flexible_electron_count
     223              : 
     224        16483 :       NULLIFY (mo_set%eigenvalues)
     225        16483 :       NULLIFY (mo_set%occupation_numbers)
     226        16483 :       NULLIFY (mo_set%mo_coeff)
     227        16483 :       NULLIFY (mo_set%mo_coeff_b)
     228        16483 :       mo_set%use_mo_coeff_b = .FALSE.
     229              : 
     230        16483 :    END SUBROUTINE allocate_mo_set
     231              : 
     232              : ! **************************************************************************************************
     233              : !> \brief initializes an allocated mo_set.
     234              : !>      eigenvalues, mo_coeff, occupation_numbers are valid only
     235              : !>      after this call.
     236              : !> \param mo_set the mo_set to initialize
     237              : !> \param fm_pool a pool out which you initialize the mo_set
     238              : !> \param fm_ref  a reference  matrix from which you initialize the mo_set
     239              : !> \param fm_struct ...
     240              : !> \param name ...
     241              : !> \par History
     242              : !>      11.2002 revamped [fawzi]
     243              : !> \author Fawzi Mohamed
     244              : ! **************************************************************************************************
     245        15583 :    SUBROUTINE init_mo_set(mo_set, fm_pool, fm_ref, fm_struct, name)
     246              : 
     247              :       TYPE(mo_set_type), INTENT(INOUT)                   :: mo_set
     248              :       TYPE(cp_fm_pool_type), INTENT(IN), OPTIONAL        :: fm_pool
     249              :       TYPE(cp_fm_type), INTENT(IN), OPTIONAL             :: fm_ref
     250              :       TYPE(cp_fm_struct_type), OPTIONAL, POINTER         :: fm_struct
     251              :       CHARACTER(LEN=*), INTENT(in)                       :: name
     252              : 
     253              :       INTEGER                                            :: nao, nmo, nomo
     254              : 
     255        15583 :       CPASSERT(.NOT. ASSOCIATED(mo_set%eigenvalues))
     256        15583 :       CPASSERT(.NOT. ASSOCIATED(mo_set%occupation_numbers))
     257        15583 :       CPASSERT(.NOT. ASSOCIATED(mo_set%mo_coeff))
     258              : 
     259        15583 :       CPASSERT(PRESENT(fm_pool) .NEQV. (PRESENT(fm_ref) .NEQV. PRESENT(fm_struct)))
     260        15583 :       NULLIFY (mo_set%mo_coeff)
     261        15583 :       IF (PRESENT(fm_pool)) THEN
     262        11739 :          ALLOCATE (mo_set%mo_coeff)
     263        11739 :          CALL fm_pool_create_fm(fm_pool, mo_set%mo_coeff, name=name)
     264         3844 :       ELSE IF (PRESENT(fm_ref)) THEN
     265          646 :          ALLOCATE (mo_set%mo_coeff)
     266          646 :          CALL cp_fm_create(mo_set%mo_coeff, fm_ref%matrix_struct, name=name)
     267         3198 :       ELSE IF (PRESENT(fm_struct)) THEN
     268         3198 :          ALLOCATE (mo_set%mo_coeff)
     269         3198 :          CPASSERT(ASSOCIATED(fm_struct))
     270         3198 :          CALL cp_fm_create(mo_set%mo_coeff, fm_struct, name=name)
     271              :       END IF
     272        15583 :       CALL cp_fm_set_all(mo_set%mo_coeff, 0.0_dp)
     273        15583 :       CALL cp_fm_get_info(mo_set%mo_coeff, nrow_global=nao, ncol_global=nmo)
     274              : 
     275        15583 :       CPASSERT(nao >= mo_set%nao)
     276        15583 :       CPASSERT(nmo >= mo_set%nmo)
     277              : 
     278        46589 :       ALLOCATE (mo_set%eigenvalues(nmo))
     279       210388 :       mo_set%eigenvalues(:) = 0.0_dp
     280              : 
     281        31006 :       ALLOCATE (mo_set%occupation_numbers(nmo))
     282              :       ! Initialize MO occupations
     283       210388 :       mo_set%occupation_numbers(:) = 0.0_dp
     284              :       ! Quick return, if no electrons are available
     285        15583 :       IF (mo_set%nelectron == 0) THEN
     286          846 :          RETURN
     287              :       END IF
     288              : 
     289        14737 :       IF (MODULO(mo_set%nelectron, INT(mo_set%maxocc)) == 0) THEN
     290        14725 :          nomo = NINT(mo_set%nelectron/mo_set%maxocc)
     291       127026 :          mo_set%occupation_numbers(1:nomo) = mo_set%maxocc
     292              :       ELSE
     293           12 :          nomo = INT(mo_set%nelectron/mo_set%maxocc) + 1
     294              :          ! Initialize MO occupations
     295          146 :          mo_set%occupation_numbers(1:nomo - 1) = mo_set%maxocc
     296           12 :          mo_set%occupation_numbers(nomo) = mo_set%nelectron - (nomo - 1)*mo_set%maxocc
     297              :       END IF
     298              : 
     299        14737 :       CPASSERT(nmo >= nomo)
     300        14737 :       CPASSERT((SIZE(mo_set%occupation_numbers) == nmo))
     301              : 
     302        14737 :       mo_set%homo = nomo
     303        14737 :       mo_set%lfomo = nomo + 1
     304        14737 :       mo_set%mu = mo_set%eigenvalues(nomo)
     305              : 
     306        15583 :    END SUBROUTINE init_mo_set
     307              : 
     308              : ! **************************************************************************************************
     309              : !> \brief make the beta orbitals explicitly equal to the alpha orbitals
     310              : !>       effectively copying the orbital data
     311              : !> \param mo_array ...
     312              : !> \param convert_dbcsr ...
     313              : !> \par History
     314              : !>      10.2004 created [Joost VandeVondele]
     315              : ! **************************************************************************************************
     316          946 :    SUBROUTINE mo_set_restrict(mo_array, convert_dbcsr)
     317              :       TYPE(mo_set_type), DIMENSION(2), INTENT(IN)        :: mo_array
     318              :       LOGICAL, INTENT(in), OPTIONAL                      :: convert_dbcsr
     319              : 
     320              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'mo_set_restrict'
     321              : 
     322              :       INTEGER                                            :: handle
     323              :       LOGICAL                                            :: my_convert_dbcsr
     324              : 
     325          946 :       CALL timeset(routineN, handle)
     326              : 
     327          946 :       my_convert_dbcsr = .FALSE.
     328          946 :       IF (PRESENT(convert_dbcsr)) my_convert_dbcsr = convert_dbcsr
     329              : 
     330          946 :       CPASSERT(mo_array(1)%nmo >= mo_array(2)%nmo)
     331              : 
     332              :       ! first nmo_beta orbitals are copied from alpha to beta
     333          946 :       IF (my_convert_dbcsr) THEN !fm->dbcsr
     334              :          CALL dbcsr_copy_columns_hack(mo_array(2)%mo_coeff_b, mo_array(1)%mo_coeff_b, & !fm->dbcsr
     335              :                                       mo_array(2)%nmo, 1, 1, & !fm->dbcsr
     336              :                                       para_env=mo_array(1)%mo_coeff%matrix_struct%para_env, & !fm->dbcsr
     337          902 :                                       blacs_env=mo_array(1)%mo_coeff%matrix_struct%context) !fm->dbcsr
     338              :       ELSE !fm->dbcsr
     339           44 :          CALL cp_fm_to_fm(mo_array(1)%mo_coeff, mo_array(2)%mo_coeff, mo_array(2)%nmo)
     340              :       END IF
     341              : 
     342          946 :       CALL timestop(handle)
     343              : 
     344          946 :    END SUBROUTINE mo_set_restrict
     345              : 
     346              : ! **************************************************************************************************
     347              : !> \brief   Deallocate a wavefunction data structure.
     348              : !> \param mo_set ...
     349              : !> \date    15.05.2001
     350              : !> \author  MK
     351              : !> \version 1.0
     352              : ! **************************************************************************************************
     353        17101 :    SUBROUTINE deallocate_mo_set(mo_set)
     354              : 
     355              :       TYPE(mo_set_type), INTENT(INOUT)                   :: mo_set
     356              : 
     357        17101 :       IF (ASSOCIATED(mo_set%eigenvalues)) THEN
     358        16207 :          DEALLOCATE (mo_set%eigenvalues)
     359              :          NULLIFY (mo_set%eigenvalues)
     360              :       END IF
     361        17101 :       IF (ASSOCIATED(mo_set%occupation_numbers)) THEN
     362        16207 :          DEALLOCATE (mo_set%occupation_numbers)
     363              :          NULLIFY (mo_set%occupation_numbers)
     364              :       END IF
     365        17101 :       IF (ASSOCIATED(mo_set%mo_coeff)) THEN
     366        16207 :          CALL cp_fm_release(mo_set%mo_coeff)
     367        16207 :          DEALLOCATE (mo_set%mo_coeff)
     368              :          NULLIFY (mo_set%mo_coeff)
     369              :       END IF
     370        17101 :       IF (ASSOCIATED(mo_set%mo_coeff_b)) CALL dbcsr_release_p(mo_set%mo_coeff_b)
     371              : 
     372        17101 :    END SUBROUTINE deallocate_mo_set
     373              : 
     374              : ! **************************************************************************************************
     375              : !> \brief   Get the components of a MO set data structure.
     376              : !> \param mo_set ...
     377              : !> \param maxocc ...
     378              : !> \param homo ...
     379              : !> \param lfomo ...
     380              : !> \param nao ...
     381              : !> \param nelectron ...
     382              : !> \param n_el_f ...
     383              : !> \param nmo ...
     384              : !> \param eigenvalues ...
     385              : !> \param occupation_numbers ...
     386              : !> \param mo_coeff ...
     387              : !> \param mo_coeff_b ...
     388              : !> \param uniform_occupation ...
     389              : !> \param kTS ...
     390              : !> \param mu ...
     391              : !> \param flexible_electron_count ...
     392              : !> \date    22.04.2002
     393              : !> \author  MK
     394              : !> \version 1.0
     395              : ! **************************************************************************************************
     396       878714 :    SUBROUTINE get_mo_set(mo_set, maxocc, homo, lfomo, nao, nelectron, n_el_f, nmo, &
     397              :                          eigenvalues, occupation_numbers, mo_coeff, mo_coeff_b, &
     398              :                          uniform_occupation, kTS, mu, flexible_electron_count)
     399              : 
     400              :       TYPE(mo_set_type), INTENT(IN)                      :: mo_set
     401              :       REAL(KIND=dp), INTENT(OUT), OPTIONAL               :: maxocc
     402              :       INTEGER, INTENT(OUT), OPTIONAL                     :: homo, lfomo, nao, nelectron
     403              :       REAL(KIND=dp), INTENT(OUT), OPTIONAL               :: n_el_f
     404              :       INTEGER, INTENT(OUT), OPTIONAL                     :: nmo
     405              :       REAL(KIND=dp), DIMENSION(:), OPTIONAL, POINTER     :: eigenvalues, occupation_numbers
     406              :       TYPE(cp_fm_type), OPTIONAL, POINTER                :: mo_coeff
     407              :       TYPE(dbcsr_type), OPTIONAL, POINTER                :: mo_coeff_b
     408              :       LOGICAL, INTENT(OUT), OPTIONAL                     :: uniform_occupation
     409              :       REAL(KIND=dp), INTENT(OUT), OPTIONAL               :: kTS, mu, flexible_electron_count
     410              : 
     411       878714 :       IF (PRESENT(maxocc)) maxocc = mo_set%maxocc
     412       878714 :       IF (PRESENT(homo)) homo = mo_set%homo
     413       878714 :       IF (PRESENT(lfomo)) lfomo = mo_set%lfomo
     414       878714 :       IF (PRESENT(nao)) nao = mo_set%nao
     415       878714 :       IF (PRESENT(nelectron)) nelectron = mo_set%nelectron
     416       878714 :       IF (PRESENT(n_el_f)) n_el_f = mo_set%n_el_f
     417       878714 :       IF (PRESENT(nmo)) nmo = mo_set%nmo
     418       878714 :       IF (PRESENT(eigenvalues)) eigenvalues => mo_set%eigenvalues
     419       878714 :       IF (PRESENT(occupation_numbers)) THEN
     420       317607 :          occupation_numbers => mo_set%occupation_numbers
     421              :       END IF
     422       878714 :       IF (PRESENT(mo_coeff)) mo_coeff => mo_set%mo_coeff
     423       878714 :       IF (PRESENT(mo_coeff_b)) mo_coeff_b => mo_set%mo_coeff_b
     424       878714 :       IF (PRESENT(uniform_occupation)) uniform_occupation = mo_set%uniform_occupation
     425       878714 :       IF (PRESENT(kTS)) kTS = mo_set%kTS
     426       878714 :       IF (PRESENT(mu)) mu = mo_set%mu
     427       878714 :       IF (PRESENT(flexible_electron_count)) flexible_electron_count = mo_set%flexible_electron_count
     428              : 
     429       878714 :    END SUBROUTINE get_mo_set
     430              : 
     431              : ! **************************************************************************************************
     432              : !> \brief   Set the components of a MO set data structure.
     433              : !> \param mo_set ...
     434              : !> \param maxocc ...
     435              : !> \param homo ...
     436              : !> \param lfomo ...
     437              : !> \param nao ...
     438              : !> \param nelectron ...
     439              : !> \param n_el_f ...
     440              : !> \param nmo ...
     441              : !> \param eigenvalues ...
     442              : !> \param occupation_numbers ...
     443              : !> \param uniform_occupation ...
     444              : !> \param kTS ...
     445              : !> \param mu ...
     446              : !> \param flexible_electron_count ...
     447              : !> \date    22.04.2002
     448              : !> \author  MK
     449              : !> \version 1.0
     450              : ! **************************************************************************************************
     451         1916 :    SUBROUTINE set_mo_set(mo_set, maxocc, homo, lfomo, nao, nelectron, n_el_f, nmo, &
     452              :                          eigenvalues, occupation_numbers, uniform_occupation, &
     453              :                          kTS, mu, flexible_electron_count)
     454              : 
     455              :       TYPE(mo_set_type), INTENT(INOUT)                   :: mo_set
     456              :       REAL(KIND=dp), INTENT(IN), OPTIONAL                :: maxocc
     457              :       INTEGER, INTENT(IN), OPTIONAL                      :: homo, lfomo, nao, nelectron
     458              :       REAL(KIND=dp), INTENT(IN), OPTIONAL                :: n_el_f
     459              :       INTEGER, INTENT(IN), OPTIONAL                      :: nmo
     460              :       REAL(KIND=dp), DIMENSION(:), OPTIONAL, POINTER     :: eigenvalues, occupation_numbers
     461              :       LOGICAL, INTENT(IN), OPTIONAL                      :: uniform_occupation
     462              :       REAL(KIND=dp), INTENT(IN), OPTIONAL                :: kTS, mu, flexible_electron_count
     463              : 
     464         1916 :       IF (PRESENT(maxocc)) mo_set%maxocc = maxocc
     465         1916 :       IF (PRESENT(homo)) mo_set%homo = homo
     466         1916 :       IF (PRESENT(lfomo)) mo_set%lfomo = lfomo
     467         1916 :       IF (PRESENT(nao)) mo_set%nao = nao
     468         1916 :       IF (PRESENT(nelectron)) mo_set%nelectron = nelectron
     469         1916 :       IF (PRESENT(n_el_f)) mo_set%n_el_f = n_el_f
     470         1916 :       IF (PRESENT(nmo)) mo_set%nmo = nmo
     471         1916 :       IF (PRESENT(eigenvalues)) THEN
     472            0 :          IF (ASSOCIATED(mo_set%eigenvalues)) THEN
     473            0 :             DEALLOCATE (mo_set%eigenvalues)
     474              :          END IF
     475            0 :          mo_set%eigenvalues => eigenvalues
     476              :       END IF
     477         1916 :       IF (PRESENT(occupation_numbers)) THEN
     478            0 :          IF (ASSOCIATED(mo_set%occupation_numbers)) THEN
     479            0 :             DEALLOCATE (mo_set%occupation_numbers)
     480              :          END IF
     481            0 :          mo_set%occupation_numbers => occupation_numbers
     482              :       END IF
     483         1916 :       IF (PRESENT(uniform_occupation)) mo_set%uniform_occupation = uniform_occupation
     484         1916 :       IF (PRESENT(kTS)) mo_set%kTS = kTS
     485         1916 :       IF (PRESENT(mu)) mo_set%mu = mu
     486         1916 :       IF (PRESENT(flexible_electron_count)) mo_set%flexible_electron_count = flexible_electron_count
     487              : 
     488         1916 :    END SUBROUTINE set_mo_set
     489              : 
     490              : ! **************************************************************************************************
     491              : !> \brief   Check if the set of MOs in mo_set specifed by the MO index range [first_mo,last_mo]
     492              : !>          an integer occupation within a tolerance.
     493              : !> \param   mo_set :: MO set for which the uniform occupation will be checked
     494              : !> \param   first_mo :: Index of first MO for the checked MO range
     495              : !> \param   last_mo :: Index of last MO for the checked MO range
     496              : !> \param   occupation :: Requested uniform MO occupation with the MO range
     497              : !> \param   tolerance :: Requested numerical tolerance for an integer occupation
     498              : !> \return  has_uniform_occupation :: boolean, true if an integer occupation is found otherwise false
     499              : !> \par History
     500              : !>      04.08.2021 Created (MK)
     501              : !> \author  Matthias Krack (MK)
     502              : !> \version 1.0
     503              : ! **************************************************************************************************
     504       162534 :    FUNCTION has_uniform_occupation(mo_set, first_mo, last_mo, occupation, tolerance)
     505              : 
     506              :       TYPE(mo_set_type), INTENT(IN)                      :: mo_set
     507              :       INTEGER, INTENT(IN), OPTIONAL                      :: first_mo, last_mo
     508              :       REAL(KIND=dp), INTENT(IN), OPTIONAL                :: occupation, tolerance
     509              :       LOGICAL                                            :: has_uniform_occupation
     510              : 
     511              :       INTEGER                                            :: my_first_mo, my_last_mo
     512              :       REAL(KIND=dp)                                      :: my_occupation, my_tolerance
     513              : 
     514       162534 :       has_uniform_occupation = .FALSE.
     515              : 
     516       162534 :       IF (PRESENT(first_mo)) THEN
     517            0 :          CPASSERT(first_mo >= LBOUND(mo_set%eigenvalues, 1))
     518              :          my_first_mo = first_mo
     519              :       ELSE
     520       162534 :          my_first_mo = LBOUND(mo_set%eigenvalues, 1)
     521              :       END IF
     522              : 
     523       162534 :       IF (PRESENT(last_mo)) THEN
     524         7194 :          CPASSERT(last_mo <= UBOUND(mo_set%eigenvalues, 1))
     525              :          my_last_mo = last_mo
     526              :       ELSE
     527       158842 :          my_last_mo = UBOUND(mo_set%eigenvalues, 1)
     528              :       END IF
     529              : 
     530       162534 :       IF (PRESENT(occupation)) THEN
     531            0 :          my_occupation = occupation
     532              :       ELSE
     533       162534 :          my_occupation = mo_set%maxocc
     534              :       END IF
     535              : 
     536       162534 :       IF (PRESENT(tolerance)) THEN
     537            0 :          my_tolerance = tolerance
     538              :       ELSE
     539              :          my_tolerance = EPSILON(0.0_dp)
     540              :       END IF
     541              : 
     542      1425142 :       has_uniform_occupation = ALL(ABS(mo_set%occupation_numbers(my_first_mo:my_last_mo) - my_occupation) < my_tolerance)
     543              : 
     544       162534 :    END FUNCTION has_uniform_occupation
     545              : 
     546            0 : END MODULE qs_mo_types
        

Generated by: LCOV version 2.0-1