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

Generated by: LCOV version 2.0-1