LCOV - code coverage report
Current view: top level - src - floquet_types.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:9ccafda) Lines: 90.5 % 63 57
Test Date: 2026-10-15 00:55:44 Functions: 66.7 % 6 4

            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 Environment type holding the work and accumulation arrays of the Floquet-Bloch
      10              : !>        band-structure calculation (floquet_main), plus the derived sizes.
      11              : !> \par History
      12              : !> \author Shridhar Shanbhag (27.01.2026)
      13              : ! **************************************************************************************************
      14              : MODULE floquet_types
      15              :    USE kinds,                           ONLY: dp
      16              :    USE post_scf_bandstructure_types,    ONLY: post_scf_bandstructure_type
      17              : #include "./base/base_uses.f90"
      18              : 
      19              :    IMPLICIT NONE
      20              : 
      21              :    PRIVATE
      22              : 
      23              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'floquet_types'
      24              : 
      25              :    PUBLIC :: floquet_env_type, &
      26              :              floquet_env_create, &
      27              :              floquet_env_release, &
      28              :              floquet_active_band_count, &
      29              :              floquet_band_window
      30              : 
      31              : ! **************************************************************************************************
      32              : !> \brief Work and accumulation arrays for one Floquet-Bloch band-structure run, plus the derived
      33              : !>        sizes. The per-(k-point,spin) buffers are overwritten each iteration; the all_* arrays
      34              : !>        accumulate the results over all DOS k-points and spins.
      35              : !> \param max_f_index Floquet truncation index M
      36              : !> \param n_f_size size of the truncated Floquet Hamiltonian, n_mo*(1 + 2*M)
      37              : !> \param n_E number of points on the DOS energy grid
      38              : !> \param nkp_only_bs number of band-structure k-points (the k-points the Floquet loop runs over)
      39              : !> \param n_mo number of active bands used by the Floquet calculation (the MAX_NMO band window,
      40              : !>        or the full molecular-orbital count when MAX_NMO <= 0); all work/output arrays are sized
      41              : !>        with this
      42              : !> \param n_mo_full total number of molecular orbitals (full band count before windowing)
      43              : !> \param n_lo lowest full-band index of the active window, per spin (n_spin)
      44              : !> \param n_hi highest full-band index of the active window, per spin (n_spin)
      45              : !> \param n_spin number of spin channels
      46              : !> \param eigenvalues Floquet eigenvalues for the current (k-point,spin) (n_f_size)
      47              : !> \param w0 central-sector weights (n_f_size)
      48              : !> \param wE outermost-sector weights (n_f_size)
      49              : !> \param a_k spectral function A(k,E) on the energy grid (n_E)
      50              : !> \param quasi_energies quasi-energies (n_mo)
      51              : !> \param m0_energies m=0 band energies (n_mo)
      52              : !> \param m0_weights central-sector weight of each m=0 band (n_mo)
      53              : !> \param e_k_kp_spin band energies for the current (k-point,spin) (n_mo)
      54              : !> \param p_k_kp_spin momentum matrix elements for the current (k-point,spin) (3, n_mo, n_mo)
      55              : !> \param all_quasi_energies quasi-energies for every (band, spin, bs k-point) (n_mo, n_spin, nkp_only_bs)
      56              : !> \param all_a_k spectral function for every (energy, spin, bs k-point) (n_E, n_spin, nkp_only_bs)
      57              : !> \param all_m0_energies m=0 band energies for every (band, spin, bs k-point) (n_mo, n_spin, nkp_only_bs)
      58              : !> \param all_m0_weights central-sector weights for every (band, spin, bs k-point) (n_mo, n_spin, nkp_only_bs)
      59              : ! **************************************************************************************************
      60              :    TYPE floquet_env_type
      61              :       INTEGER                                          :: max_f_index = -1, &
      62              :                                                           n_f_size = -1, &
      63              :                                                           n_E = -1, &
      64              :                                                           nkp_only_bs = -1, &
      65              :                                                           n_mo = -1, &
      66              :                                                           n_mo_full = -1, &
      67              :                                                           n_spin = -1
      68              :       INTEGER, ALLOCATABLE, DIMENSION(:)               :: n_lo, n_hi
      69              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)         :: eigenvalues, w0, wE, a_k, &
      70              :                                                           quasi_energies, m0_energies, &
      71              :                                                           m0_weights, e_k_kp_spin
      72              :       COMPLEX(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :) :: p_k_kp_spin
      73              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :)   :: all_quasi_energies, all_a_k, &
      74              :                                                           all_m0_energies, all_m0_weights
      75              :    END TYPE floquet_env_type
      76              : 
      77              : CONTAINS
      78              : 
      79              : ! **************************************************************************************************
      80              : !> \brief Number of active bands used by the Floquet calculation: the MAX_NMO band window closest
      81              : !>        to the VBM, clamped to the full molecular-orbital count, or the full count when MAX_NMO <= 0.
      82              : !> \param bs_env ...
      83              : !> \return the active band count
      84              : ! **************************************************************************************************
      85            6 :    FUNCTION floquet_active_band_count(bs_env) RESULT(n_active)
      86              :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
      87              :       INTEGER                                            :: n_active
      88              : 
      89            6 :       IF (bs_env%max_nmo_floquet <= 0 .OR. bs_env%max_nmo_floquet >= bs_env%n_ao) THEN
      90            6 :          n_active = bs_env%n_ao
      91              :       ELSE
      92              :          n_active = bs_env%max_nmo_floquet
      93              :       END IF
      94              : 
      95            6 :    END FUNCTION floquet_active_band_count
      96              : 
      97              : ! **************************************************************************************************
      98              : !> \brief Full-band index bounds [n_lo, n_hi] of the active window for one spin, selecting the
      99              : !>        MAX_NMO Kohn-Sham eigenstates closest to the VBM. Mirrors the HOMO-centred windowing of
     100              : !>        qs_moment_kpoints (qs_moments.F), with a final reclamp so the window holds exactly
     101              : !>        floquet_active_band_count(bs_env) states regardless of the per-spin HOMO index.
     102              : !> \param bs_env ...
     103              : !> \param ispin spin channel
     104              : !> \param n_lo lowest full-band index of the window
     105              : !> \param n_hi highest full-band index of the window
     106              : ! **************************************************************************************************
     107            2 :    SUBROUTINE floquet_band_window(bs_env, ispin, n_lo, n_hi)
     108              :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
     109              :       INTEGER, INTENT(IN)                                :: ispin
     110              :       INTEGER, INTENT(OUT)                               :: n_lo, n_hi
     111              : 
     112              :       INTEGER                                            :: homo, max_nmo, n_mo_full
     113              : 
     114            2 :       n_mo_full = bs_env%n_ao
     115            2 :       max_nmo = bs_env%max_nmo_floquet
     116              : 
     117            2 :       IF (max_nmo <= 0 .OR. max_nmo >= n_mo_full) THEN
     118            2 :          n_lo = 1
     119            2 :          n_hi = n_mo_full
     120              :       ELSE
     121            0 :          homo = bs_env%n_occ(ispin)
     122            0 :          n_lo = MAX(1, homo - (max_nmo - 1)/2)
     123            0 :          n_hi = MIN(n_mo_full, n_lo + max_nmo - 1)
     124              :          ! reclamp so the window holds exactly max_nmo states (keeps the fixed-size buffers valid
     125              :          ! when n_occ(1) /= n_occ(2)); a no-op away from the band edges
     126            0 :          n_lo = MAX(1, n_hi - max_nmo + 1)
     127              :       END IF
     128              : 
     129            2 :    END SUBROUTINE floquet_band_window
     130              : 
     131              : ! **************************************************************************************************
     132              : !> \brief Set the derived sizes from bs_env and allocate all work and accumulation arrays.
     133              : !> \param floquet_env ...
     134              : !> \param bs_env ...
     135              : ! **************************************************************************************************
     136            2 :    SUBROUTINE floquet_env_create(floquet_env, bs_env)
     137              :       TYPE(floquet_env_type), INTENT(OUT)                :: floquet_env
     138              :       TYPE(post_scf_bandstructure_type), POINTER         :: bs_env
     139              : 
     140              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'floquet_env_create'
     141              : 
     142              :       INTEGER                                            :: handle, ispin, n_mo, nE, nf, nk, ns
     143              : 
     144            2 :       CALL timeset(routineN, handle)
     145              : 
     146            2 :       floquet_env%n_spin = bs_env%n_spin
     147            2 :       floquet_env%n_mo_full = bs_env%n_ao
     148              :       ! n_mo is the active band count (the MAX_NMO window, or the full count when MAX_NMO <= 0);
     149              :       ! every work/output array below is sized with it
     150            2 :       floquet_env%n_mo = floquet_active_band_count(bs_env)
     151            2 :       floquet_env%max_f_index = bs_env%max_floquet_index
     152            2 :       floquet_env%n_f_size = floquet_env%n_mo*(1 + 2*floquet_env%max_f_index)
     153            2 :       floquet_env%n_E = NINT(2*bs_env%energy_window_floquet/bs_env%energy_step_floquet)
     154            2 :       floquet_env%nkp_only_bs = bs_env%nkp_only_bs
     155              : 
     156              :       ! Per-spin full-band index bounds of the active window (used to slice the full-band data)
     157            8 :       ALLOCATE (floquet_env%n_lo(floquet_env%n_spin), floquet_env%n_hi(floquet_env%n_spin))
     158            4 :       DO ispin = 1, floquet_env%n_spin
     159            4 :          CALL floquet_band_window(bs_env, ispin, floquet_env%n_lo(ispin), floquet_env%n_hi(ispin))
     160              :       END DO
     161              : 
     162            2 :       n_mo = floquet_env%n_mo
     163            2 :       nf = floquet_env%n_f_size
     164            2 :       nE = floquet_env%n_E
     165            2 :       ns = floquet_env%n_spin
     166            2 :       nk = floquet_env%nkp_only_bs
     167              : 
     168              :       ! per-(k-point,spin) work buffers
     169           10 :       ALLOCATE (floquet_env%eigenvalues(nf), floquet_env%w0(nf), floquet_env%wE(nf))
     170            6 :       ALLOCATE (floquet_env%a_k(nE))
     171            0 :       ALLOCATE (floquet_env%quasi_energies(n_mo), floquet_env%m0_energies(n_mo), &
     172           10 :                 floquet_env%m0_weights(n_mo))
     173           10 :       ALLOCATE (floquet_env%e_k_kp_spin(n_mo), floquet_env%p_k_kp_spin(3, n_mo, n_mo))
     174              : 
     175              :       ! per-(spin,k-point) accumulation arrays, filled once by the owning subgroup source and
     176              :       ! summed across the global communicator after the k-point loop
     177           30 :       ALLOCATE (floquet_env%all_quasi_energies(n_mo, ns, nk), source=0.0_dp)
     178           18 :       ALLOCATE (floquet_env%all_a_k(nE, ns, nk), source=0.0_dp)
     179           28 :       ALLOCATE (floquet_env%all_m0_energies(n_mo, ns, nk), source=0.0_dp)
     180           28 :       ALLOCATE (floquet_env%all_m0_weights(n_mo, ns, nk), source=0.0_dp)
     181              : 
     182            2 :       CALL timestop(handle)
     183              : 
     184            2 :    END SUBROUTINE floquet_env_create
     185              : 
     186              : ! **************************************************************************************************
     187              : !> \brief Deallocate all arrays held by floquet_env.
     188              : !> \param floquet_env ...
     189              : ! **************************************************************************************************
     190            2 :    SUBROUTINE floquet_env_release(floquet_env)
     191              :       TYPE(floquet_env_type), INTENT(INOUT)              :: floquet_env
     192              : 
     193              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'floquet_env_release'
     194              : 
     195              :       INTEGER                                            :: handle
     196              : 
     197            2 :       CALL timeset(routineN, handle)
     198              : 
     199            2 :       IF (ALLOCATED(floquet_env%n_lo)) DEALLOCATE (floquet_env%n_lo)
     200            2 :       IF (ALLOCATED(floquet_env%n_hi)) DEALLOCATE (floquet_env%n_hi)
     201            2 :       IF (ALLOCATED(floquet_env%eigenvalues)) DEALLOCATE (floquet_env%eigenvalues)
     202            2 :       IF (ALLOCATED(floquet_env%w0)) DEALLOCATE (floquet_env%w0)
     203            2 :       IF (ALLOCATED(floquet_env%wE)) DEALLOCATE (floquet_env%wE)
     204            2 :       IF (ALLOCATED(floquet_env%a_k)) DEALLOCATE (floquet_env%a_k)
     205            2 :       IF (ALLOCATED(floquet_env%quasi_energies)) DEALLOCATE (floquet_env%quasi_energies)
     206            2 :       IF (ALLOCATED(floquet_env%m0_energies)) DEALLOCATE (floquet_env%m0_energies)
     207            2 :       IF (ALLOCATED(floquet_env%m0_weights)) DEALLOCATE (floquet_env%m0_weights)
     208            2 :       IF (ALLOCATED(floquet_env%e_k_kp_spin)) DEALLOCATE (floquet_env%e_k_kp_spin)
     209            2 :       IF (ALLOCATED(floquet_env%p_k_kp_spin)) DEALLOCATE (floquet_env%p_k_kp_spin)
     210            2 :       IF (ALLOCATED(floquet_env%all_quasi_energies)) DEALLOCATE (floquet_env%all_quasi_energies)
     211            2 :       IF (ALLOCATED(floquet_env%all_a_k)) DEALLOCATE (floquet_env%all_a_k)
     212            2 :       IF (ALLOCATED(floquet_env%all_m0_energies)) DEALLOCATE (floquet_env%all_m0_energies)
     213            2 :       IF (ALLOCATED(floquet_env%all_m0_weights)) DEALLOCATE (floquet_env%all_m0_weights)
     214              : 
     215            2 :       CALL timestop(handle)
     216              : 
     217            2 :    END SUBROUTINE floquet_env_release
     218              : 
     219            0 : END MODULE floquet_types
        

Generated by: LCOV version 2.0-1