LCOV - code coverage report
Current view: top level - src - kpoint_mo_dump.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:3db43b4) Lines: 0.0 % 218 0
Test Date: 2026-04-03 06:55:30 Functions: 0.0 % 1 0

            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 K-point MO wavefunction dump to TEXT file for post-processing (PDOS, etc.)
      10              : !> \par History
      11              : !>       2026.02 created
      12              : ! **************************************************************************************************
      13              : 
      14              : MODULE kpoint_mo_dump
      15              : 
      16              :    USE atomic_kind_types,               ONLY: get_atomic_kind
      17              :    USE basis_set_types,                 ONLY: get_gto_basis_set,&
      18              :                                               gto_basis_set_type
      19              :    USE cell_types,                      ONLY: cell_type
      20              :    USE cp_blacs_env,                    ONLY: cp_blacs_env_type
      21              :    USE cp_control_types,                ONLY: dft_control_type
      22              :    USE cp_dbcsr_api,                    ONLY: &
      23              :         dbcsr_create, dbcsr_deallocate_matrix, dbcsr_desymmetrize, dbcsr_p_type, dbcsr_set, &
      24              :         dbcsr_type, dbcsr_type_antisymmetric, dbcsr_type_no_symmetry, dbcsr_type_symmetric
      25              :    USE cp_dbcsr_cp2k_link,              ONLY: cp_dbcsr_alloc_block_from_nbl
      26              :    USE cp_dbcsr_operations,             ONLY: copy_dbcsr_to_fm
      27              :    USE cp_fm_struct,                    ONLY: cp_fm_struct_create,&
      28              :                                               cp_fm_struct_release,&
      29              :                                               cp_fm_struct_type
      30              :    USE cp_fm_types,                     ONLY: cp_fm_create,&
      31              :                                               cp_fm_get_submatrix,&
      32              :                                               cp_fm_release,&
      33              :                                               cp_fm_type
      34              :    USE cp_log_handling,                 ONLY: cp_get_default_logger,&
      35              :                                               cp_logger_get_default_io_unit,&
      36              :                                               cp_logger_type
      37              :    USE cp_output_handling,              ONLY: cp_print_key_finished_output,&
      38              :                                               cp_print_key_unit_nr
      39              :    USE input_section_types,             ONLY: section_vals_type,&
      40              :                                               section_vals_val_get
      41              :    USE kinds,                           ONLY: dp
      42              :    USE kpoint_methods,                  ONLY: rskp_transform
      43              :    USE kpoint_types,                    ONLY: get_kpoint_info,&
      44              :                                               kpoint_env_type,&
      45              :                                               kpoint_type
      46              :    USE mathconstants,                   ONLY: pi
      47              :    USE message_passing,                 ONLY: mp_para_env_type
      48              :    USE particle_methods,                ONLY: get_particle_set
      49              :    USE particle_types,                  ONLY: particle_type
      50              :    USE physcon,                         ONLY: angstrom
      51              :    USE qs_environment_types,            ONLY: get_qs_env,&
      52              :                                               qs_environment_type
      53              :    USE qs_kind_types,                   ONLY: get_qs_kind,&
      54              :                                               get_qs_kind_set,&
      55              :                                               qs_kind_type
      56              :    USE qs_mo_types,                     ONLY: get_mo_set,&
      57              :                                               mo_set_type
      58              :    USE qs_neighbor_list_types,          ONLY: neighbor_list_set_p_type
      59              : #include "./base/base_uses.f90"
      60              : 
      61              :    IMPLICIT NONE
      62              :    PRIVATE
      63              : 
      64              :    PUBLIC :: write_kpoint_mo_data
      65              : 
      66              :    ! Enum values for OVERLAP_EXPORT_TYPE keyword
      67              :    INTEGER, PARAMETER, PUBLIC :: mokp_overlap_gto = 1, &
      68              :                                  mokp_overlap_matrix = 2
      69              : 
      70              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'kpoint_mo_dump'
      71              : 
      72              : CONTAINS
      73              : 
      74              : ! **************************************************************************************************
      75              : !> \brief Write k-point resolved MO data to formatted text file.
      76              : !>
      77              : !>  The output file contains, for each k-point:
      78              : !>    - Eigenvalues and occupations
      79              : !>    - MO coefficient matrix C(k) (real and imaginary parts)
      80              : !>    - Overlap matrix S(k)  (if OVERLAP_EXPORT_TYPE = MATRIX)
      81              : !>  Plus a header with cell, atom info, and either GTO basis set definition
      82              : !>  (OVERLAP_EXPORT_TYPE = GTO) or AO angular momentum map (OVERLAP_EXPORT_TYPE = MATRIX).
      83              : !>
      84              : !>  Parallel strategy:
      85              : !>    MO coefficients:  cp_fm_get_submatrix (collective on kp-group),
      86              : !>                      then para_env_inter_kp%sum to collect across groups.
      87              : !>    S(k):             Built on global communicator using rskp_transform,
      88              : !>                      then copy_dbcsr_to_fm + cp_fm_get_submatrix.
      89              : !>    File write:       Only on ionode (cp_print_key_unit_nr returns -1 elsewhere).
      90              : !>
      91              : !> \param qs_env  the QS environment (after converged SCF with k-points)
      92              : !> \param print_section  the &MO_KP print key section (contains NDIGITS, OVERLAP_EXPORT_TYPE)
      93              : ! **************************************************************************************************
      94            0 :    SUBROUTINE write_kpoint_mo_data(qs_env, print_section)
      95              :       TYPE(qs_environment_type), POINTER                 :: qs_env
      96              :       TYPE(section_vals_type), POINTER                   :: print_section
      97              : 
      98              :       CHARACTER(len=*), PARAMETER :: routineN = 'write_kpoint_mo_data'
      99              :       CHARACTER(LEN=6), PARAMETER                        :: angmom = "spdfgh"
     100              : 
     101              :       CHARACTER(LEN=2)                                   :: element_symbol
     102              :       CHARACTER(LEN=20)                                  :: fmtstr_gto, fmtstr_sparse, fmtstr_vec
     103              :       INTEGER :: handle, i, iatom, ikind, ikp, ikp_loc, ipgf, iset, isgf_global, ishell, ispin, &
     104              :          iw, j, lshell, n, nao, natom, ndigits, nkp, nmo, nset_atom, nspins, output_unit, &
     105              :          overlap_data, unit_choice
     106            0 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: ao_l, first_sgf, last_sgf
     107              :       INTEGER, DIMENSION(2)                              :: kp_range
     108            0 :       INTEGER, DIMENSION(:), POINTER                     :: npgf_set, nshell_set
     109            0 :       INTEGER, DIMENSION(:, :), POINTER                  :: first_sgf_set, l_set, last_sgf_set
     110            0 :       INTEGER, DIMENSION(:, :, :), POINTER               :: cell_to_index
     111              :       LOGICAL                                            :: use_real_wfn, write_overlap
     112              :       REAL(KIND=dp)                                      :: expzet, prefac, scale_factor, thresh, &
     113              :                                                             zeff
     114            0 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: eval_buf, occ_buf
     115            0 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: Cim_buf, Cre_buf, Sim_buf, Sre_buf
     116            0 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: eigenvalues, occupation_numbers, wkp
     117            0 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: xkp, zet
     118            0 :       REAL(KIND=dp), DIMENSION(:, :, :), POINTER         :: gcc
     119              :       TYPE(cell_type), POINTER                           :: cell
     120              :       TYPE(cp_blacs_env_type), POINTER                   :: blacs_env_global
     121              :       TYPE(cp_fm_struct_type), POINTER                   :: fm_struct_S
     122              :       TYPE(cp_fm_type)                                   :: fm_S_global
     123              :       TYPE(cp_fm_type), POINTER                          :: mo_coeff_im, mo_coeff_re
     124              :       TYPE(cp_logger_type), POINTER                      :: logger
     125            0 :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: matrix_s
     126              :       TYPE(dbcsr_type), POINTER                          :: cmatrix, rmatrix, tmpmat
     127              :       TYPE(dft_control_type), POINTER                    :: dft_control
     128              :       TYPE(gto_basis_set_type), POINTER                  :: orb_basis_set
     129              :       TYPE(kpoint_env_type), POINTER                     :: kp
     130              :       TYPE(kpoint_type), POINTER                         :: kpoints
     131            0 :       TYPE(mo_set_type), DIMENSION(:, :), POINTER        :: mos_kp
     132              :       TYPE(mp_para_env_type), POINTER                    :: para_env_global, para_env_inter_kp
     133              :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
     134            0 :          POINTER                                         :: sab_nl
     135            0 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     136            0 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
     137              : 
     138            0 :       CALL timeset(routineN, handle)
     139              : 
     140            0 :       logger => cp_get_default_logger()
     141            0 :       output_unit = cp_logger_get_default_io_unit(logger)
     142              : 
     143              :       ! ================================================================
     144              :       ! Gather all required data from qs_env
     145              :       ! ================================================================
     146            0 :       NULLIFY (cell, dft_control, kpoints, particle_set, qs_kind_set, matrix_s, &
     147            0 :                sab_nl, para_env_global, blacs_env_global)
     148              : 
     149              :       CALL get_qs_env(qs_env, &
     150              :                       cell=cell, &
     151              :                       dft_control=dft_control, &
     152              :                       kpoints=kpoints, &
     153              :                       particle_set=particle_set, &
     154              :                       qs_kind_set=qs_kind_set, &
     155              :                       matrix_s_kp=matrix_s, &
     156              :                       para_env=para_env_global, &
     157            0 :                       blacs_env=blacs_env_global)
     158              : 
     159            0 :       nspins = dft_control%nspins
     160            0 :       natom = SIZE(particle_set)
     161              : 
     162              :       CALL get_kpoint_info(kpoints, nkp=nkp, xkp=xkp, wkp=wkp, &
     163              :                            use_real_wfn=use_real_wfn, kp_range=kp_range, &
     164              :                            sab_nl=sab_nl, cell_to_index=cell_to_index, &
     165            0 :                            para_env_inter_kp=para_env_inter_kp)
     166            0 :       CPASSERT(ASSOCIATED(sab_nl))
     167              : 
     168              :       ! Total number of AOs and MOs
     169            0 :       CALL get_qs_kind_set(qs_kind_set, nsgf=nao)
     170              : 
     171            0 :       nmo = 0
     172            0 :       IF (SIZE(kpoints%kp_env) > 0) THEN
     173            0 :          mos_kp => kpoints%kp_env(1)%kpoint_env%mos
     174            0 :          CALL get_mo_set(mo_set=mos_kp(1, 1), nmo=nmo)
     175              :       END IF
     176            0 :       CALL para_env_inter_kp%max(nmo)
     177              : 
     178            0 :       IF (output_unit > 0) THEN
     179            0 :          WRITE (output_unit, '(/,T3,A)') "KPOINT_MO_DUMP| Writing k-point wavefunction data"
     180              :          WRITE (output_unit, '(T3,A,I6,A,I6,A,I6,A,I4)') &
     181            0 :             "KPOINT_MO_DUMP| nao=", nao, " nmo=", nmo, " nkp=", nkp, " nspins=", nspins
     182              :       END IF
     183              : 
     184              :       ! ================================================================
     185              :       ! Read keywords
     186              :       ! ================================================================
     187            0 :       CALL section_vals_val_get(print_section, "UNIT", i_val=unit_choice)
     188            0 :       IF (unit_choice == 2) THEN
     189              :          scale_factor = angstrom
     190              :       ELSE
     191            0 :          scale_factor = 1.0_dp
     192              :       END IF
     193            0 :       CALL section_vals_val_get(print_section, "NDIGITS", i_val=ndigits)
     194            0 :       ndigits = MIN(MAX(3, ndigits), 30)
     195            0 :       CALL section_vals_val_get(print_section, "OVERLAP_EXPORT_TYPE", i_val=overlap_data)
     196            0 :       write_overlap = (overlap_data == mokp_overlap_matrix)
     197              : 
     198              :       ! Build format strings controlled by NDIGITS
     199            0 :       WRITE (UNIT=fmtstr_sparse, FMT='("(2I6,1X,ES",I0,".",I0,")")') ndigits + 10, ndigits
     200            0 :       WRITE (UNIT=fmtstr_vec, FMT='("(5ES",I0,".",I0,")")') ndigits + 10, ndigits
     201            0 :       WRITE (UNIT=fmtstr_gto, FMT='("(2ES",I0,".",I0,")")') ndigits + 10, ndigits
     202            0 :       thresh = 10.0_dp**(-ndigits)
     203              : 
     204              :       ! ================================================================
     205              :       ! Build atom-to-AO mapping
     206              :       ! ================================================================
     207            0 :       ALLOCATE (first_sgf(natom), last_sgf(natom))
     208              :       CALL get_particle_set(particle_set, qs_kind_set, &
     209            0 :                             first_sgf=first_sgf, last_sgf=last_sgf)
     210              : 
     211              :       ! AO angular momentum map: only needed when overlap is written explicitly,
     212              :       ! since in GTO mode l info is derivable from the basis set definition.
     213            0 :       IF (write_overlap) THEN
     214            0 :          ALLOCATE (ao_l(nao))
     215            0 :          ao_l(:) = -1
     216            0 :          DO iatom = 1, natom
     217            0 :             ikind = particle_set(iatom)%atomic_kind%kind_number
     218            0 :             CALL get_qs_kind(qs_kind_set(ikind), basis_set=orb_basis_set)
     219              :             CALL get_gto_basis_set(orb_basis_set, nset=nset_atom, &
     220              :                                    nshell=nshell_set, l=l_set, &
     221            0 :                                    first_sgf=first_sgf_set, last_sgf=last_sgf_set)
     222            0 :             DO iset = 1, nset_atom
     223            0 :                DO ishell = 1, nshell_set(iset)
     224            0 :                   lshell = l_set(ishell, iset)
     225            0 :                   DO i = first_sgf_set(ishell, iset), last_sgf_set(ishell, iset)
     226            0 :                      isgf_global = first_sgf(iatom) - 1 + i
     227            0 :                      ao_l(isgf_global) = lshell
     228              :                   END DO
     229              :                END DO
     230              :             END DO
     231              :          END DO
     232              :       END IF
     233              : 
     234              :       ! ================================================================
     235              :       ! Allocate work buffers
     236              :       ! ================================================================
     237            0 :       ALLOCATE (Cre_buf(nao, nmo), Cim_buf(nao, nmo))
     238            0 :       ALLOCATE (eval_buf(nmo), occ_buf(nmo))
     239              : 
     240              :       ! S(k) infrastructure: only needed in MATRIX mode
     241            0 :       IF (write_overlap) THEN
     242            0 :          ALLOCATE (Sre_buf(nao, nao), Sim_buf(nao, nao))
     243              : 
     244            0 :          ALLOCATE (rmatrix, cmatrix, tmpmat)
     245              :          CALL dbcsr_create(rmatrix, template=matrix_s(1, 1)%matrix, &
     246            0 :                            matrix_type=dbcsr_type_symmetric)
     247              :          CALL dbcsr_create(cmatrix, template=matrix_s(1, 1)%matrix, &
     248            0 :                            matrix_type=dbcsr_type_antisymmetric)
     249              :          CALL dbcsr_create(tmpmat, template=matrix_s(1, 1)%matrix, &
     250            0 :                            matrix_type=dbcsr_type_no_symmetry)
     251            0 :          CALL cp_dbcsr_alloc_block_from_nbl(rmatrix, sab_nl)
     252            0 :          CALL cp_dbcsr_alloc_block_from_nbl(cmatrix, sab_nl)
     253              : 
     254            0 :          NULLIFY (fm_struct_S)
     255              :          CALL cp_fm_struct_create(fm_struct_S, context=blacs_env_global, &
     256              :                                   nrow_global=nao, ncol_global=nao, &
     257            0 :                                   para_env=para_env_global)
     258            0 :          CALL cp_fm_create(fm_S_global, fm_struct_S, name="S(k) work")
     259            0 :          CALL cp_fm_struct_release(fm_struct_S)
     260              :       END IF
     261              : 
     262              :       ! ================================================================
     263              :       ! Open output file via print key
     264              :       ! ================================================================
     265              :       iw = cp_print_key_unit_nr(logger, print_section, "", &
     266            0 :                                 extension=".mokp", file_status="REPLACE")
     267              : 
     268              :       ! ================================================================
     269              :       ! WRITE HEADER
     270              :       ! ================================================================
     271            0 :       IF (iw > 0) THEN
     272            0 :          WRITE (iw, '(A)') "# CP2K_KPOINT_MO_DUMP, Version 1.1"
     273            0 :          IF (write_overlap) THEN
     274            0 :             WRITE (iw, '(A)') "# EXPORT_MODE: Coefficients + Overlap matrices"
     275              :          ELSE
     276            0 :             WRITE (iw, '(A)') "# EXPORT_MODE: GTO + Coefficients"
     277              :          END IF
     278            0 :          IF (unit_choice == 2) THEN
     279            0 :             WRITE (iw, '(A)') "# All energies in Hartree, lengths in Angstrom, k-points in fractional coords"
     280            0 :             WRITE (iw, '(A)') "# CELL_VECTORS [Angstrom]"
     281              :          ELSE
     282            0 :             WRITE (iw, '(A)') "# All energies in Hartree, lengths in Bohr, k-points in fractional coords"
     283            0 :             WRITE (iw, '(A)') "# CELL_VECTORS [Bohr]"
     284              :          END IF
     285              :          WRITE (iw, '(3(F12.6,3X))') &
     286            0 :             cell%hmat(1, 1)*scale_factor, cell%hmat(2, 1)*scale_factor, cell%hmat(3, 1)*scale_factor
     287              :          WRITE (iw, '(3(F12.6,3X))') &
     288            0 :             cell%hmat(1, 2)*scale_factor, cell%hmat(2, 2)*scale_factor, cell%hmat(3, 2)*scale_factor
     289              :          WRITE (iw, '(3(F12.6,3X))') &
     290            0 :             cell%hmat(1, 3)*scale_factor, cell%hmat(2, 3)*scale_factor, cell%hmat(3, 3)*scale_factor
     291              : 
     292            0 :          WRITE (iw, '(A,4I8)') "# DIMENSIONS: natom nspins nao nkp =", natom, nspins, nao, nkp
     293            0 :          WRITE (iw, '(A,I8)') "# NMO =", nmo
     294            0 :          WRITE (iw, '(A,L2)') "# USE_REAL_WFN =", use_real_wfn
     295            0 :          IF (write_overlap) THEN
     296            0 :             WRITE (iw, '(A)') "# OVERLAP_EXPORT_TYPE = MATRIX"
     297              :          ELSE
     298            0 :             WRITE (iw, '(A)') "# OVERLAP_EXPORT_TYPE = GTO"
     299              :          END IF
     300              : 
     301              :          ! Atom table
     302            0 :          IF (unit_choice == 2) THEN
     303              :             WRITE (iw, '(A)') &
     304            0 :                "# ATOM_LIST: Atom_ID  Element  Z_eff  X [Ang]  Y [Ang]  Z [Ang]  First_AO  Last_AO"
     305              :          ELSE
     306              :             WRITE (iw, '(A)') &
     307            0 :                "# ATOM_LIST: Atom_ID  Element  Z_eff  X [Bohr]  Y [Bohr]  Z [Bohr]  First_AO  Last_AO"
     308              :          END IF
     309            0 :          DO iatom = 1, natom
     310            0 :             ikind = particle_set(iatom)%atomic_kind%kind_number
     311              :             CALL get_atomic_kind(atomic_kind=particle_set(iatom)%atomic_kind, &
     312            0 :                                  element_symbol=element_symbol)
     313            0 :             CALL get_qs_kind(qs_kind_set(ikind), zeff=zeff)
     314              :             WRITE (iw, '(I6,2X,A2,I6,3F15.6,2I10)') &
     315            0 :                iatom, element_symbol, NINT(zeff), particle_set(iatom)%r(:)*scale_factor, &
     316            0 :                first_sgf(iatom), last_sgf(iatom)
     317              :          END DO
     318              : 
     319              :          ! K-point list
     320            0 :          WRITE (iw, '(A)') "# KPOINT_LIST: ikp  kx  ky  kz  weight"
     321            0 :          DO ikp = 1, nkp
     322            0 :             WRITE (iw, '(I6,4ES18.8)') ikp, xkp(1:3, ikp), wkp(ikp)
     323              :          END DO
     324              : 
     325            0 :          IF (write_overlap) THEN
     326              :             ! MATRIX mode: write AO angular momentum map (needed since no GTO info)
     327            0 :             WRITE (iw, '(A)') "# AO_L_MAP: iao  l  (1-based)"
     328            0 :             DO i = 1, nao
     329            0 :                WRITE (iw, '(2I6)') i, ao_l(i)
     330              :             END DO
     331              :          ELSE
     332              :             ! GTO mode: write basis set definition
     333              :             ! Contraction coefficients denormalized to MOLDEN convention
     334              :             ! (i.e. for raw unnormalized primitive Gaussians).
     335              :             ! Shell angular momentum ordering: spherical harmonics,
     336              :             ! CP2K convention m = -l, -l+1, ..., 0, ..., +l
     337            0 :             WRITE (iw, '(A)') "# GTO_BASIS (spherical, MOLDEN convention for contraction coefficients)"
     338            0 :             DO iatom = 1, natom
     339            0 :                ikind = particle_set(iatom)%atomic_kind%kind_number
     340            0 :                CALL get_qs_kind(qs_kind_set(ikind), basis_set=orb_basis_set)
     341            0 :                IF (ASSOCIATED(orb_basis_set)) THEN
     342            0 :                   WRITE (iw, '(I6,I4)') iatom, 0
     343              :                   CALL get_gto_basis_set(gto_basis_set=orb_basis_set, &
     344              :                                          nset=nset_atom, npgf=npgf_set, &
     345              :                                          nshell=nshell_set, l=l_set, &
     346            0 :                                          zet=zet, gcc=gcc)
     347            0 :                   DO iset = 1, nset_atom
     348            0 :                      DO ishell = 1, nshell_set(iset)
     349            0 :                         lshell = l_set(ishell, iset)
     350            0 :                         IF (lshell + 1 > LEN(angmom)) THEN
     351            0 :                            CPWARN("MOKP: Angular momentum l > 5 not supported in GTO output, skipping")
     352            0 :                            CYCLE
     353              :                         END IF
     354              :                         WRITE (iw, '(A2,I6,F8.2)') &
     355            0 :                            angmom(lshell + 1:lshell + 1)//" ", npgf_set(iset), 1.0_dp
     356              :                         ! Denormalize gcc: undo CP2K's internal normalization
     357              :                         ! (same formula as molden_utils.F, reverse of normalise_gcc_orb)
     358            0 :                         prefac = 2.0_dp**lshell*(2.0_dp/pi)**0.75_dp
     359            0 :                         expzet = 0.25_dp*(2*lshell + 3.0_dp)
     360            0 :                         DO ipgf = 1, npgf_set(iset)
     361              :                            WRITE (iw, fmtstr_gto) &
     362            0 :                               zet(ipgf, iset), &
     363            0 :                               gcc(ipgf, ishell, iset)/(prefac*zet(ipgf, iset)**expzet)
     364              :                         END DO
     365              :                      END DO
     366              :                   END DO
     367            0 :                   WRITE (iw, '(A)') ""
     368              :                END IF
     369              :             END DO
     370              :          END IF
     371              :       END IF
     372              : 
     373              :       ! ================================================================
     374              :       ! WRITE PER-KPOINT DATA
     375              :       ! ================================================================
     376            0 :       DO ikp = 1, nkp
     377              : 
     378              :          ! ==============================================================
     379              :          ! A) MO coefficients, eigenvalues, occupations (per spin)
     380              :          ! ==============================================================
     381            0 :          DO ispin = 1, nspins
     382              : 
     383            0 :             Cre_buf(:, :) = 0.0_dp
     384            0 :             Cim_buf(:, :) = 0.0_dp
     385            0 :             eval_buf(:) = 0.0_dp
     386            0 :             occ_buf(:) = 0.0_dp
     387              : 
     388            0 :             IF (ikp >= kp_range(1) .AND. ikp <= kp_range(2)) THEN
     389            0 :                ikp_loc = ikp - kp_range(1) + 1
     390            0 :                kp => kpoints%kp_env(ikp_loc)%kpoint_env
     391            0 :                mos_kp => kp%mos
     392              : 
     393              :                CALL get_mo_set(mos_kp(1, ispin), &
     394              :                                eigenvalues=eigenvalues, &
     395            0 :                                occupation_numbers=occupation_numbers)
     396            0 :                eval_buf(1:nmo) = eigenvalues(1:nmo)
     397            0 :                occ_buf(1:nmo) = occupation_numbers(1:nmo)
     398              : 
     399            0 :                CALL get_mo_set(mos_kp(1, ispin), mo_coeff=mo_coeff_re)
     400            0 :                CALL cp_fm_get_submatrix(mo_coeff_re, Cre_buf)
     401              : 
     402            0 :                IF (.NOT. use_real_wfn) THEN
     403            0 :                   CALL get_mo_set(mos_kp(2, ispin), mo_coeff=mo_coeff_im)
     404            0 :                   CALL cp_fm_get_submatrix(mo_coeff_im, Cim_buf)
     405              :                END IF
     406              :             END IF
     407              : 
     408            0 :             CALL para_env_inter_kp%sum(eval_buf)
     409            0 :             CALL para_env_inter_kp%sum(occ_buf)
     410            0 :             CALL para_env_inter_kp%sum(Cre_buf)
     411            0 :             IF (.NOT. use_real_wfn) THEN
     412            0 :                CALL para_env_inter_kp%sum(Cim_buf)
     413              :             END IF
     414              : 
     415            0 :             IF (iw > 0) THEN
     416            0 :                WRITE (iw, '(A,2I6)') "# BEGIN_KPOINT_SPIN ikp ispin =", ikp, ispin
     417              : 
     418            0 :                WRITE (iw, '(A)') "# EIGENVALUES"
     419            0 :                WRITE (iw, fmtstr_vec) (eval_buf(n), n=1, nmo)
     420              : 
     421            0 :                WRITE (iw, '(A)') "# OCCUPATIONS"
     422            0 :                WRITE (iw, fmtstr_vec) (occ_buf(n), n=1, nmo)
     423              : 
     424            0 :                WRITE (iw, '(A)') "# MO_COEFF_RE (Sparse: i_mo j_ao value)"
     425            0 :                DO i = 1, nmo
     426            0 :                   DO j = 1, nao
     427            0 :                      IF (ABS(Cre_buf(j, i)) >= thresh) THEN
     428            0 :                         WRITE (iw, fmtstr_sparse) i, j, Cre_buf(j, i)
     429              :                      END IF
     430              :                   END DO
     431              :                END DO
     432              : 
     433            0 :                IF (.NOT. use_real_wfn) THEN
     434            0 :                   WRITE (iw, '(A)') "# MO_COEFF_IM (Sparse: i_mo j_ao value)"
     435            0 :                   DO i = 1, nmo
     436            0 :                      DO j = 1, nao
     437            0 :                         IF (ABS(Cim_buf(j, i)) >= thresh) THEN
     438            0 :                            WRITE (iw, fmtstr_sparse) i, j, Cim_buf(j, i)
     439              :                         END IF
     440              :                      END DO
     441              :                   END DO
     442              :                END IF
     443            0 :                WRITE (iw, '(A,2I6)') "# END_KPOINT_SPIN ikp ispin =", ikp, ispin
     444              :             END IF
     445              : 
     446              :          END DO ! ispin
     447              : 
     448              :          ! ==============================================================
     449              :          ! B) Overlap matrix S(k) — only in MATRIX mode
     450              :          ! ==============================================================
     451            0 :          IF (write_overlap) THEN
     452              : 
     453            0 :             CALL dbcsr_set(rmatrix, 0.0_dp)
     454            0 :             IF (use_real_wfn) THEN
     455              :                CALL rskp_transform(rmatrix=rmatrix, rsmat=matrix_s, ispin=1, &
     456              :                                    xkp=xkp(1:3, ikp), cell_to_index=cell_to_index, &
     457            0 :                                    sab_nl=sab_nl)
     458            0 :                CALL dbcsr_desymmetrize(rmatrix, tmpmat)
     459            0 :                CALL copy_dbcsr_to_fm(tmpmat, fm_S_global)
     460            0 :                CALL cp_fm_get_submatrix(fm_S_global, Sre_buf)
     461            0 :                Sim_buf(:, :) = 0.0_dp
     462              :             ELSE
     463            0 :                CALL dbcsr_set(cmatrix, 0.0_dp)
     464              :                CALL rskp_transform(rmatrix=rmatrix, cmatrix=cmatrix, rsmat=matrix_s, &
     465              :                                    ispin=1, xkp=xkp(1:3, ikp), &
     466            0 :                                    cell_to_index=cell_to_index, sab_nl=sab_nl)
     467            0 :                CALL dbcsr_desymmetrize(rmatrix, tmpmat)
     468            0 :                CALL copy_dbcsr_to_fm(tmpmat, fm_S_global)
     469            0 :                CALL cp_fm_get_submatrix(fm_S_global, Sre_buf)
     470            0 :                CALL dbcsr_desymmetrize(cmatrix, tmpmat)
     471            0 :                CALL copy_dbcsr_to_fm(tmpmat, fm_S_global)
     472            0 :                CALL cp_fm_get_submatrix(fm_S_global, Sim_buf)
     473              :             END IF
     474              : 
     475            0 :             IF (iw > 0) THEN
     476            0 :                WRITE (iw, '(A,I6)') "# BEGIN_OVERLAP ikp =", ikp
     477              : 
     478            0 :                WRITE (iw, '(A)') "# OVERLAP_RE (Sparse: i_ao j_ao value)"
     479            0 :                DO i = 1, nao
     480            0 :                   DO j = 1, nao
     481            0 :                      IF (ABS(Sre_buf(i, j)) >= thresh) THEN
     482            0 :                         WRITE (iw, fmtstr_sparse) i, j, Sre_buf(i, j)
     483              :                      END IF
     484              :                   END DO
     485              :                END DO
     486            0 :                IF (.NOT. use_real_wfn) THEN
     487            0 :                   WRITE (iw, '(A)') "# OVERLAP_IM (Sparse: i_ao j_ao value)"
     488            0 :                   DO i = 1, nao
     489            0 :                      DO j = 1, nao
     490            0 :                         IF (ABS(Sim_buf(i, j)) >= thresh) THEN
     491            0 :                            WRITE (iw, fmtstr_sparse) i, j, Sim_buf(i, j)
     492              :                         END IF
     493              :                      END DO
     494              :                   END DO
     495              :                END IF
     496            0 :                WRITE (iw, '(A,I6)') "# END_OVERLAP ikp =", ikp
     497              :             END IF
     498              : 
     499              :          END IF ! write_overlap
     500              : 
     501              :       END DO ! ikp
     502              : 
     503              :       ! ================================================================
     504              :       ! Finalize
     505              :       ! ================================================================
     506            0 :       IF (iw > 0) THEN
     507            0 :          WRITE (iw, '(A)') "# END_OF_FILE"
     508              :       END IF
     509              : 
     510            0 :       CALL cp_print_key_finished_output(iw, logger, print_section, "")
     511              : 
     512            0 :       IF (output_unit > 0) THEN
     513              :          WRITE (output_unit, '(T3,A)') &
     514            0 :             "KPOINT_MO_DUMP| Data written to .mokp file"
     515              :       END IF
     516              : 
     517              :       ! Release work arrays
     518            0 :       IF (write_overlap) THEN
     519            0 :          CALL cp_fm_release(fm_S_global)
     520            0 :          CALL dbcsr_deallocate_matrix(rmatrix)
     521            0 :          CALL dbcsr_deallocate_matrix(cmatrix)
     522            0 :          CALL dbcsr_deallocate_matrix(tmpmat)
     523            0 :          DEALLOCATE (Sre_buf, Sim_buf)
     524            0 :          DEALLOCATE (ao_l)
     525              :       END IF
     526            0 :       DEALLOCATE (Cre_buf, Cim_buf)
     527            0 :       DEALLOCATE (eval_buf, occ_buf)
     528            0 :       DEALLOCATE (first_sgf, last_sgf)
     529              : 
     530            0 :       CALL timestop(handle)
     531              : 
     532            0 :    END SUBROUTINE write_kpoint_mo_data
     533              : 
     534              : END MODULE kpoint_mo_dump
        

Generated by: LCOV version 2.0-1