LCOV - code coverage report
Current view: top level - src - mo_window.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:92574dc) Lines: 85.3 % 34 29
Test Date: 2026-09-24 01:27:39 Functions: 66.7 % 3 2

            Line data    Source code
       1              : !--------------------------------------------------------------------------------------------------!
       2              : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3              : !   Copyright 2000-2026 CP2K developers group <https://cp2k.org>                                   !
       4              : !                                                                                                  !
       5              : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6              : !--------------------------------------------------------------------------------------------------!
       7              : 
       8              : ! **************************************************************************************************
       9              : !> \brief Common selection and union operations for contiguous molecular-orbital windows.
      10              : ! **************************************************************************************************
      11              : MODULE mo_window
      12              :    USE kinds,                           ONLY: dp
      13              : #include "./base/base_uses.f90"
      14              : 
      15              :    IMPLICIT NONE
      16              : 
      17              :    PRIVATE
      18              : 
      19              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'mo_window'
      20              : 
      21              :    TYPE mo_window_type
      22              :       INTEGER :: first_mo = 1
      23              :       INTEGER :: last_mo = 0
      24              :    END TYPE mo_window_type
      25              : 
      26              :    PUBLIC :: combine_mo_windows, determine_mo_window, mo_window_type
      27              : 
      28              : CONTAINS
      29              : 
      30              : ! **************************************************************************************************
      31              : !> \brief Selects one contiguous MO window from an ordered reference spectrum.
      32              : !>
      33              : !> The input spectrum is supplied by the caller because different workflows may store more
      34              : !> entries than the number of physical MOs to which a cutoff applies. The returned bounds are
      35              : !> absolute, one-based indices in the caller's MO numbering.
      36              : !> \param eigenvalues Reference eigenvalues for one spin channel.
      37              : !> \param n_mo Number of physical MOs covered by the reference spectrum.
      38              : !> \param n_occ Number of occupied MOs in that channel.
      39              : !> \param cutoff_occ Occupied-state energy window; non-positive means no occupied cutoff.
      40              : !> \param cutoff_empty Empty-state energy window; non-positive means no empty-state cutoff.
      41              : !> \param window Selected absolute MO window (OUT).
      42              : ! **************************************************************************************************
      43          114 :    SUBROUTINE determine_mo_window(eigenvalues, n_mo, n_occ, cutoff_occ, cutoff_empty, window)
      44              :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: eigenvalues
      45              :       INTEGER, INTENT(IN)                                :: n_mo, n_occ
      46              :       REAL(KIND=dp), INTENT(IN)                          :: cutoff_occ, cutoff_empty
      47              :       TYPE(mo_window_type), INTENT(OUT)                  :: window
      48              : 
      49              :       INTEGER                                            :: i
      50              : 
      51          114 :       IF (n_mo < 1 .OR. n_mo > SIZE(eigenvalues)) THEN
      52            0 :          CALL cp_abort(__LOCATION__, "determine_mo_window: invalid number of physical MOs")
      53              :       END IF
      54          114 :       IF (n_occ < 1 .OR. n_occ >= n_mo) THEN
      55            0 :          CALL cp_abort(__LOCATION__, "determine_mo_window: invalid occupied-state boundary")
      56              :       END IF
      57              : 
      58          114 :       window%first_mo = 1
      59          114 :       window%last_mo = n_mo
      60              : 
      61          114 :       IF (cutoff_occ > 0.0_dp .OR. cutoff_empty > 0.0_dp) THEN
      62         1900 :          DO i = 2, n_mo
      63         1900 :             IF (eigenvalues(i) < eigenvalues(i - 1)) THEN
      64              :                CALL cp_abort(__LOCATION__, &
      65              :                              "determine_mo_window: reference eigenvalues are not ascending. "// &
      66            0 :                              "Use the DFT/SCF energy axis; the G0W0 axis is not ordered.")
      67              :             END IF
      68              :          END DO
      69              : 
      70           90 :          IF (cutoff_occ > 0.0_dp) THEN
      71           70 :             DO i = 1, n_occ
      72           70 :                IF (eigenvalues(n_occ) - eigenvalues(i) <= cutoff_occ) THEN
      73           70 :                   window%first_mo = i
      74           70 :                   EXIT
      75              :                END IF
      76              :             END DO
      77              :          END IF
      78              : 
      79           90 :          IF (cutoff_empty > 0.0_dp) THEN
      80         1108 :             DO i = n_occ + 1, n_mo
      81         1108 :                IF (eigenvalues(i) - eigenvalues(n_occ + 1) > cutoff_empty) THEN
      82           90 :                   window%last_mo = i - 1
      83           90 :                   EXIT
      84              :                END IF
      85              :             END DO
      86              :          END IF
      87              :       END IF
      88              : 
      89          114 :    END SUBROUTINE determine_mo_window
      90              : 
      91              : ! **************************************************************************************************
      92              : !> \brief Forms the smallest contiguous window covering all supplied spin windows.
      93              : !> \param spin_windows Per-spin absolute MO windows.
      94              : !> \param combined_window Union of the supplied windows (OUT).
      95              : !> \param windows_differ True if at least two input windows have different bounds (OUT).
      96              : ! **************************************************************************************************
      97           10 :    SUBROUTINE combine_mo_windows(spin_windows, combined_window, windows_differ)
      98              :       TYPE(mo_window_type), DIMENSION(:), INTENT(IN)     :: spin_windows
      99              :       TYPE(mo_window_type), INTENT(OUT)                  :: combined_window
     100              :       LOGICAL, INTENT(OUT)                               :: windows_differ
     101              : 
     102              :       INTEGER                                            :: i
     103              : 
     104           10 :       IF (SIZE(spin_windows) < 1) THEN
     105            0 :          CALL cp_abort(__LOCATION__, "combine_mo_windows: no spin windows supplied")
     106              :       END IF
     107              : 
     108           10 :       combined_window%first_mo = spin_windows(1)%first_mo
     109           10 :       combined_window%last_mo = spin_windows(1)%last_mo
     110           10 :       windows_differ = .FALSE.
     111              : 
     112           18 :       DO i = 2, SIZE(spin_windows)
     113            8 :          combined_window%first_mo = MIN(combined_window%first_mo, spin_windows(i)%first_mo)
     114            8 :          combined_window%last_mo = MAX(combined_window%last_mo, spin_windows(i)%last_mo)
     115              :          windows_differ = windows_differ .OR. &
     116              :                           spin_windows(i)%first_mo /= spin_windows(1)%first_mo .OR. &
     117           26 :                           spin_windows(i)%last_mo /= spin_windows(1)%last_mo
     118              :       END DO
     119              : 
     120           10 :    END SUBROUTINE combine_mo_windows
     121              : 
     122            0 : END MODULE mo_window
        

Generated by: LCOV version 2.0-1