LCOV - code coverage report
Current view: top level - src - qs_mo_io.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:936074a) Lines: 90.1 % 607 547
Test Date: 2025-12-04 06:27:48 Functions: 100.0 % 9 9

            Line data    Source code
       1              : !--------------------------------------------------------------------------------------------------!
       2              : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3              : !   Copyright 2000-2025 CP2K developers group <https://cp2k.org>                                   !
       4              : !                                                                                                  !
       5              : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6              : !--------------------------------------------------------------------------------------------------!
       7              : 
       8              : ! **************************************************************************************************
       9              : !> \brief Definition and initialisation of the mo data type.
      10              : !> \par History
      11              : !>      - adapted to the new QS environment data structure (02.04.2002,MK)
      12              : !>      - set_mo_occupation added (17.04.02,MK)
      13              : !>      - correct_mo_eigenvalues added (18.04.02,MK)
      14              : !>      - calculate_density_matrix moved from qs_scf to here (22.04.02,MK)
      15              : !>      - mo_set_p_type added (23.04.02,MK)
      16              : !>      - PRIVATE attribute set for TYPE mo_set_type (23.04.02,MK)
      17              : !>      - started conversion to LSD (1.2003, Joost VandeVondele)
      18              : !>      - Split of from qs_mo_types (07.2014, JGH)
      19              : !> \author Matthias Krack (09.05.2001,MK)
      20              : ! **************************************************************************************************
      21              : MODULE qs_mo_io
      22              : 
      23              :    USE atomic_kind_types,               ONLY: get_atomic_kind
      24              :    USE basis_set_types,                 ONLY: get_gto_basis_set,&
      25              :                                               gto_basis_set_type
      26              :    USE cp_dbcsr_api,                    ONLY: dbcsr_binary_write,&
      27              :                                               dbcsr_create,&
      28              :                                               dbcsr_p_type,&
      29              :                                               dbcsr_release,&
      30              :                                               dbcsr_type
      31              :    USE cp_dbcsr_contrib,                ONLY: dbcsr_checksum
      32              :    USE cp_dbcsr_operations,             ONLY: copy_dbcsr_to_fm,&
      33              :                                               copy_fm_to_dbcsr
      34              :    USE cp_files,                        ONLY: close_file,&
      35              :                                               open_file
      36              :    USE cp_fm_types,                     ONLY: cp_fm_get_info,&
      37              :                                               cp_fm_get_submatrix,&
      38              :                                               cp_fm_set_all,&
      39              :                                               cp_fm_set_submatrix,&
      40              :                                               cp_fm_to_fm,&
      41              :                                               cp_fm_type,&
      42              :                                               cp_fm_write_unformatted
      43              :    USE cp_log_handling,                 ONLY: cp_get_default_logger,&
      44              :                                               cp_logger_get_default_unit_nr,&
      45              :                                               cp_logger_type,&
      46              :                                               cp_to_string
      47              :    USE cp_output_handling,              ONLY: cp_p_file,&
      48              :                                               cp_print_key_finished_output,&
      49              :                                               cp_print_key_generate_filename,&
      50              :                                               cp_print_key_should_output,&
      51              :                                               cp_print_key_unit_nr
      52              :    USE input_section_types,             ONLY: section_vals_get_subs_vals,&
      53              :                                               section_vals_type,&
      54              :                                               section_vals_val_get
      55              :    USE kahan_sum,                       ONLY: accurate_sum
      56              :    USE kinds,                           ONLY: default_path_length,&
      57              :                                               default_string_length,&
      58              :                                               dp
      59              :    USE message_passing,                 ONLY: mp_para_env_type
      60              :    USE orbital_pointers,                ONLY: indco,&
      61              :                                               nco,&
      62              :                                               nso
      63              :    USE orbital_symbols,                 ONLY: cgf_symbol,&
      64              :                                               sgf_symbol
      65              :    USE orbital_transformation_matrices, ONLY: orbtramat
      66              :    USE particle_types,                  ONLY: particle_type
      67              :    USE physcon,                         ONLY: evolt
      68              :    USE qs_density_matrices,             ONLY: calculate_density_matrix
      69              :    USE qs_dftb_types,                   ONLY: qs_dftb_atom_type
      70              :    USE qs_dftb_utils,                   ONLY: get_dftb_atom_param
      71              :    USE qs_kind_types,                   ONLY: get_qs_kind,&
      72              :                                               get_qs_kind_set,&
      73              :                                               qs_kind_type
      74              :    USE qs_mo_methods,                   ONLY: calculate_subspace_eigenvalues
      75              :    USE qs_mo_occupation,                ONLY: set_mo_occupation
      76              :    USE qs_mo_types,                     ONLY: get_mo_set,&
      77              :                                               mo_set_type
      78              : #include "./base/base_uses.f90"
      79              : 
      80              :    IMPLICIT NONE
      81              : 
      82              :    PRIVATE
      83              : 
      84              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'qs_mo_io'
      85              : 
      86              :    PUBLIC :: wfn_restart_file_name, &
      87              :              write_rt_mos_to_restart, &
      88              :              read_rt_mos_from_restart, &
      89              :              write_dm_binary_restart, &
      90              :              write_mo_set_to_output_unit, &
      91              :              write_mo_set_to_restart, &
      92              :              read_mo_set_from_restart, &
      93              :              read_mos_restart_low, &
      94              :              write_mo_set_low
      95              : 
      96              : CONTAINS
      97              : 
      98              : ! **************************************************************************************************
      99              : !> \brief ...
     100              : !> \param mo_array ...
     101              : !> \param particle_set ...
     102              : !> \param dft_section ...
     103              : !> \param qs_kind_set ...
     104              : !> \param matrix_ks ...
     105              : ! **************************************************************************************************
     106       155421 :    SUBROUTINE write_mo_set_to_restart(mo_array, particle_set, dft_section, qs_kind_set, matrix_ks)
     107              : 
     108              :       TYPE(mo_set_type), DIMENSION(:), INTENT(IN)        :: mo_array
     109              :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     110              :       TYPE(section_vals_type), POINTER                   :: dft_section
     111              :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
     112              :       TYPE(dbcsr_p_type), DIMENSION(:), OPTIONAL, &
     113              :          POINTER                                         :: matrix_ks
     114              : 
     115              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'write_mo_set_to_restart'
     116              :       CHARACTER(LEN=30), DIMENSION(2), PARAMETER :: &
     117              :          keys = ["SCF%PRINT%RESTART_HISTORY", "SCF%PRINT%RESTART        "]
     118              : 
     119              :       INTEGER                                            :: handle, ikey, ires, ispin
     120              :       TYPE(cp_logger_type), POINTER                      :: logger
     121              : 
     122       155421 :       CALL timeset(routineN, handle)
     123              : 
     124       155421 :       logger => cp_get_default_logger()
     125              : 
     126              :       IF (BTEST(cp_print_key_should_output(logger%iter_info, &
     127       155421 :                                            dft_section, keys(1)), cp_p_file) .OR. &
     128              :           BTEST(cp_print_key_should_output(logger%iter_info, &
     129              :                                            dft_section, keys(2)), cp_p_file)) THEN
     130              : 
     131        16719 :          IF (mo_array(1)%use_mo_coeff_b) THEN
     132              :             ! we are using the dbcsr mo_coeff
     133              :             ! we copy it to the fm for anycase
     134        12310 :             DO ispin = 1, SIZE(mo_array)
     135         6675 :                IF (.NOT. ASSOCIATED(mo_array(ispin)%mo_coeff_b)) THEN
     136            0 :                   CPASSERT(.FALSE.)
     137              :                END IF
     138              :                CALL copy_dbcsr_to_fm(mo_array(ispin)%mo_coeff_b, &
     139        12310 :                                      mo_array(ispin)%mo_coeff) !fm->dbcsr
     140              :             END DO
     141              :          END IF
     142              : 
     143        50157 :          DO ikey = 1, SIZE(keys)
     144        33438 :             IF (BTEST(cp_print_key_should_output(logger%iter_info, &
     145       155421 :                                                  dft_section, keys(ikey)), cp_p_file)) THEN
     146              :                ires = cp_print_key_unit_nr(logger, dft_section, keys(ikey), &
     147              :                                            extension=".wfn", file_status="REPLACE", file_action="WRITE", &
     148        16731 :                                            do_backup=.TRUE., file_form="UNFORMATTED")
     149        16731 :                IF (PRESENT(matrix_ks)) THEN
     150              :                   CALL write_mo_set_low(mo_array, particle_set=particle_set, qs_kind_set=qs_kind_set, &
     151         5621 :                                         ires=ires, matrix_ks=matrix_ks)
     152              :                ELSE
     153              :                   CALL write_mo_set_low(mo_array, particle_set=particle_set, qs_kind_set=qs_kind_set, &
     154        11110 :                                         ires=ires)
     155              :                END IF
     156        16731 :                CALL cp_print_key_finished_output(ires, logger, dft_section, TRIM(keys(ikey)))
     157              :             END IF
     158              :          END DO
     159              :       END IF
     160              : 
     161       155421 :       CALL timestop(handle)
     162              : 
     163       155421 :    END SUBROUTINE write_mo_set_to_restart
     164              : 
     165              : ! **************************************************************************************************
     166              : !> \brief calculates density matrix from mo set and writes the density matrix
     167              : !>        into a binary restart file
     168              : !> \param mo_array mos
     169              : !> \param dft_section dft input section
     170              : !> \param tmpl_matrix template dbcsr matrix
     171              : !> \author Mohammad Hossein Bani-Hashemian
     172              : ! **************************************************************************************************
     173         9831 :    SUBROUTINE write_dm_binary_restart(mo_array, dft_section, tmpl_matrix)
     174              : 
     175              :       TYPE(mo_set_type), DIMENSION(:), INTENT(IN)        :: mo_array
     176              :       TYPE(section_vals_type), POINTER                   :: dft_section
     177              :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: tmpl_matrix
     178              : 
     179              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'write_dm_binary_restart'
     180              : 
     181              :       CHARACTER(LEN=default_path_length)                 :: file_name, project_name
     182              :       INTEGER                                            :: handle, ispin, unit_nr
     183              :       LOGICAL                                            :: do_dm_restart
     184              :       REAL(KIND=dp)                                      :: cs_pos
     185              :       TYPE(cp_logger_type), POINTER                      :: logger
     186              :       TYPE(dbcsr_type), POINTER                          :: matrix_p_tmp
     187              : 
     188         9831 :       CALL timeset(routineN, handle)
     189         9831 :       logger => cp_get_default_logger()
     190         9831 :       IF (logger%para_env%is_source()) THEN
     191         5043 :          unit_nr = cp_logger_get_default_unit_nr(logger, local=.TRUE.)
     192              :       ELSE
     193              :          unit_nr = -1
     194              :       END IF
     195              : 
     196         9831 :       project_name = logger%iter_info%project_name
     197         9831 :       CALL section_vals_val_get(dft_section, "SCF%PRINT%DM_RESTART_WRITE", l_val=do_dm_restart)
     198         9831 :       NULLIFY (matrix_p_tmp)
     199              : 
     200         9831 :       IF (do_dm_restart) THEN
     201            0 :          ALLOCATE (matrix_p_tmp)
     202            0 :          DO ispin = 1, SIZE(mo_array)
     203            0 :             CALL dbcsr_create(matrix_p_tmp, template=tmpl_matrix(ispin)%matrix, name="DM RESTART")
     204              : 
     205            0 :             IF (.NOT. ASSOCIATED(mo_array(ispin)%mo_coeff_b)) CPABORT("mo_coeff_b NOT ASSOCIATED")
     206              : 
     207            0 :             CALL copy_fm_to_dbcsr(mo_array(ispin)%mo_coeff, mo_array(ispin)%mo_coeff_b)
     208              :             CALL calculate_density_matrix(mo_array(ispin), matrix_p_tmp, &
     209            0 :                                           use_dbcsr=.TRUE., retain_sparsity=.FALSE.)
     210              : 
     211            0 :             WRITE (file_name, '(A,I0,A)') TRIM(project_name)//"_SCF_DM_SPIN_", ispin, "_RESTART.dm"
     212            0 :             cs_pos = dbcsr_checksum(matrix_p_tmp, pos=.TRUE.)
     213            0 :             IF (unit_nr > 0) THEN
     214            0 :                WRITE (unit_nr, '(T2,A,E20.8)') "Writing restart DM "//TRIM(file_name)//" with checksum: ", cs_pos
     215              :             END IF
     216            0 :             CALL dbcsr_binary_write(matrix_p_tmp, file_name)
     217              : 
     218            0 :             CALL dbcsr_release(matrix_p_tmp)
     219              :          END DO
     220            0 :          DEALLOCATE (matrix_p_tmp)
     221              :       END IF
     222              : 
     223         9831 :       CALL timestop(handle)
     224              : 
     225         9831 :    END SUBROUTINE write_dm_binary_restart
     226              : 
     227              : ! **************************************************************************************************
     228              : !> \brief ...
     229              : !> \param mo_array ...
     230              : !> \param rt_mos ...
     231              : !> \param particle_set ...
     232              : !> \param dft_section ...
     233              : !> \param qs_kind_set ...
     234              : ! **************************************************************************************************
     235          432 :    SUBROUTINE write_rt_mos_to_restart(mo_array, rt_mos, particle_set, dft_section, qs_kind_set)
     236              : 
     237              :       TYPE(mo_set_type), DIMENSION(:), INTENT(IN)        :: mo_array
     238              :       TYPE(cp_fm_type), DIMENSION(:), INTENT(IN)         :: rt_mos
     239              :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     240              :       TYPE(section_vals_type), POINTER                   :: dft_section
     241              :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
     242              : 
     243              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'write_rt_mos_to_restart'
     244              :       CHARACTER(LEN=43), DIMENSION(2), PARAMETER :: keys = [ &
     245              :          "REAL_TIME_PROPAGATION%PRINT%RESTART_HISTORY", &
     246              :          "REAL_TIME_PROPAGATION%PRINT%RESTART        "]
     247              : 
     248              :       INTEGER                                            :: handle, ikey, ires
     249              :       TYPE(cp_logger_type), POINTER                      :: logger
     250              : 
     251          432 :       CALL timeset(routineN, handle)
     252          432 :       logger => cp_get_default_logger()
     253              : 
     254              :       IF (BTEST(cp_print_key_should_output(logger%iter_info, &
     255          432 :                                            dft_section, keys(1)), cp_p_file) .OR. &
     256              :           BTEST(cp_print_key_should_output(logger%iter_info, &
     257              :                                            dft_section, keys(2)), cp_p_file)) THEN
     258              : 
     259          324 :          DO ikey = 1, SIZE(keys)
     260              : 
     261          216 :             IF (BTEST(cp_print_key_should_output(logger%iter_info, &
     262          432 :                                                  dft_section, keys(ikey)), cp_p_file)) THEN
     263              :                ires = cp_print_key_unit_nr(logger, dft_section, keys(ikey), &
     264              :                                            extension=".rtpwfn", file_status="REPLACE", file_action="WRITE", &
     265          108 :                                            do_backup=.TRUE., file_form="UNFORMATTED")
     266              :                CALL write_mo_set_low(mo_array, qs_kind_set=qs_kind_set, particle_set=particle_set, &
     267          108 :                                      ires=ires, rt_mos=rt_mos)
     268          108 :                CALL cp_print_key_finished_output(ires, logger, dft_section, TRIM(keys(ikey)))
     269              :             END IF
     270              :          END DO
     271              :       END IF
     272              : 
     273          432 :       CALL timestop(handle)
     274              : 
     275          432 :    END SUBROUTINE write_rt_mos_to_restart
     276              : 
     277              : ! **************************************************************************************************
     278              : !> \brief ...
     279              : !> \param mo_array ...
     280              : !> \param qs_kind_set ...
     281              : !> \param particle_set ...
     282              : !> \param ires ...
     283              : !> \param rt_mos ...
     284              : !> \param matrix_ks ...
     285              : ! **************************************************************************************************
     286        16847 :    SUBROUTINE write_mo_set_low(mo_array, qs_kind_set, particle_set, ires, rt_mos, matrix_ks)
     287              : 
     288              :       TYPE(mo_set_type), DIMENSION(:), INTENT(IN)        :: mo_array
     289              :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
     290              :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     291              :       INTEGER                                            :: ires
     292              :       TYPE(cp_fm_type), DIMENSION(:), INTENT(IN), &
     293              :          OPTIONAL                                        :: rt_mos
     294              :       TYPE(dbcsr_p_type), DIMENSION(:), OPTIONAL, &
     295              :          POINTER                                         :: matrix_ks
     296              : 
     297              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'write_mo_set_low'
     298              : 
     299              :       INTEGER                                            :: handle, iatom, ikind, imat, iset, &
     300              :                                                             ishell, ispin, lmax, lshell, &
     301              :                                                             max_block, nao, natom, nmo, nset, &
     302              :                                                             nset_max, nshell_max, nspin
     303        16847 :       INTEGER, DIMENSION(:), POINTER                     :: nset_info, nshell
     304        16847 :       INTEGER, DIMENSION(:, :), POINTER                  :: l, nshell_info
     305        16847 :       INTEGER, DIMENSION(:, :, :), POINTER               :: nso_info
     306        16847 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: mo_eigenvalues, mo_occupation_numbers
     307              :       TYPE(cp_fm_type), POINTER                          :: mo_coeff
     308              :       TYPE(gto_basis_set_type), POINTER                  :: orb_basis_set
     309              :       TYPE(qs_dftb_atom_type), POINTER                   :: dftb_parameter
     310              : 
     311        16847 :       CALL timeset(routineN, handle)
     312              : 
     313        16847 :       NULLIFY (mo_coeff)
     314        16847 :       NULLIFY (mo_eigenvalues)
     315        16847 :       NULLIFY (mo_occupation_numbers)
     316              : 
     317        16847 :       nspin = SIZE(mo_array)
     318        16847 :       nao = mo_array(1)%nao
     319              : 
     320        16847 :       IF (ires > 0) THEN
     321              :          ! Create some info about the basis set first
     322         8595 :          natom = SIZE(particle_set, 1)
     323         8595 :          nset_max = 0
     324         8595 :          nshell_max = 0
     325              : 
     326        54872 :          DO iatom = 1, natom
     327        46277 :             NULLIFY (orb_basis_set, dftb_parameter)
     328        46277 :             CALL get_atomic_kind(particle_set(iatom)%atomic_kind, kind_number=ikind)
     329              :             CALL get_qs_kind(qs_kind_set(ikind), &
     330              :                              basis_set=orb_basis_set, &
     331        46277 :                              dftb_parameter=dftb_parameter)
     332       101149 :             IF (ASSOCIATED(orb_basis_set)) THEN
     333              :                CALL get_gto_basis_set(gto_basis_set=orb_basis_set, &
     334              :                                       nset=nset, &
     335              :                                       nshell=nshell, &
     336        38739 :                                       l=l)
     337        38739 :                nset_max = MAX(nset_max, nset)
     338       109695 :                DO iset = 1, nset
     339       109695 :                   nshell_max = MAX(nshell_max, nshell(iset))
     340              :                END DO
     341         7538 :             ELSEIF (ASSOCIATED(dftb_parameter)) THEN
     342         7537 :                CALL get_dftb_atom_param(dftb_parameter, lmax=lmax)
     343         7537 :                nset_max = MAX(nset_max, 1)
     344         7537 :                nshell_max = MAX(nshell_max, lmax + 1)
     345              :             ELSE
     346              :                ! We assume here an atom without a basis set
     347              :                ! CPABORT("Unknown basis type. ")
     348              :             END IF
     349              :          END DO
     350              : 
     351        42975 :          ALLOCATE (nso_info(nshell_max, nset_max, natom))
     352       318415 :          nso_info(:, :, :) = 0
     353              : 
     354        34380 :          ALLOCATE (nshell_info(nset_max, natom))
     355       142786 :          nshell_info(:, :) = 0
     356              : 
     357        25785 :          ALLOCATE (nset_info(natom))
     358        54872 :          nset_info(:) = 0
     359              : 
     360        54872 :          DO iatom = 1, natom
     361        46277 :             NULLIFY (orb_basis_set, dftb_parameter)
     362        46277 :             CALL get_atomic_kind(particle_set(iatom)%atomic_kind, kind_number=ikind)
     363              :             CALL get_qs_kind(qs_kind_set(ikind), &
     364        46277 :                              basis_set=orb_basis_set, dftb_parameter=dftb_parameter)
     365       101149 :             IF (ASSOCIATED(orb_basis_set)) THEN
     366              :                CALL get_gto_basis_set(gto_basis_set=orb_basis_set, &
     367              :                                       nset=nset, &
     368              :                                       nshell=nshell, &
     369        38739 :                                       l=l)
     370        38739 :                nset_info(iatom) = nset
     371       109695 :                DO iset = 1, nset
     372        70956 :                   nshell_info(iset, iatom) = nshell(iset)
     373       210607 :                   DO ishell = 1, nshell(iset)
     374       100912 :                      lshell = l(ishell, iset)
     375       171868 :                      nso_info(ishell, iset, iatom) = nso(lshell)
     376              :                   END DO
     377              :                END DO
     378         7538 :             ELSEIF (ASSOCIATED(dftb_parameter)) THEN
     379         7537 :                CALL get_dftb_atom_param(dftb_parameter, lmax=lmax)
     380         7537 :                nset_info(iatom) = 1
     381         7537 :                nshell_info(1, iatom) = lmax + 1
     382        17656 :                DO ishell = 1, lmax + 1
     383        10119 :                   lshell = ishell - 1
     384        17656 :                   nso_info(ishell, 1, iatom) = nso(lshell)
     385              :                END DO
     386              :             ELSE
     387              :                ! We assume here an atom without a basis set
     388              :                ! CPABORT("Unknown basis type. ")
     389              :             END IF
     390              :          END DO
     391              : 
     392         8595 :          WRITE (ires) natom, nspin, nao, nset_max, nshell_max
     393        54872 :          WRITE (ires) nset_info
     394       142786 :          WRITE (ires) nshell_info
     395       318415 :          WRITE (ires) nso_info
     396              : 
     397         8595 :          DEALLOCATE (nset_info)
     398              : 
     399         8595 :          DEALLOCATE (nshell_info)
     400              : 
     401         8595 :          DEALLOCATE (nso_info)
     402              :       END IF
     403              : 
     404              :       ! Use the ScaLAPACK block size as a default for buffering columns
     405        16847 :       CALL cp_fm_get_info(mo_array(1)%mo_coeff, ncol_block=max_block)
     406        36612 :       DO ispin = 1, nspin
     407        19765 :          mo_coeff => mo_array(ispin)%mo_coeff
     408        19765 :          nmo = mo_array(ispin)%nmo
     409        19765 :          IF (nmo > 0) THEN
     410        19535 :             mo_eigenvalues => mo_array(ispin)%eigenvalues
     411        19535 :             mo_occupation_numbers => mo_array(ispin)%occupation_numbers
     412        19535 :             IF (PRESENT(matrix_ks)) THEN
     413              :                ! With OT: use the Kohn-Sham matrix for the update of the MO eigenvalues
     414              :                CALL calculate_subspace_eigenvalues(orbitals=mo_coeff, &
     415              :                                                    ks_matrix=matrix_ks(ispin)%matrix, &
     416         6619 :                                                    evals_arg=mo_eigenvalues)
     417              :             END IF
     418        19535 :             IF (ires > 0) THEN
     419         9948 :                WRITE (ires) nmo, &
     420         9948 :                   mo_array(ispin)%homo, &
     421         9948 :                   mo_array(ispin)%lfomo, &
     422        19896 :                   mo_array(ispin)%nelectron
     423         9948 :                WRITE (ires) mo_eigenvalues(1:nmo), mo_occupation_numbers(1:nmo)
     424              :             END IF
     425              :          END IF
     426        36612 :          IF (PRESENT(rt_mos)) THEN
     427          414 :             DO imat = 2*ispin - 1, 2*ispin
     428          414 :                CALL cp_fm_write_unformatted(rt_mos(imat), ires)
     429              :             END DO
     430              :          ELSE
     431        19627 :             CALL cp_fm_write_unformatted(mo_coeff, ires)
     432              :          END IF
     433              :       END DO
     434              : 
     435        16847 :       CALL timestop(handle)
     436              : 
     437        16847 :    END SUBROUTINE write_mo_set_low
     438              : 
     439              : ! **************************************************************************************************
     440              : !> \brief ...
     441              : !> \param filename ...
     442              : !> \param exist ...
     443              : !> \param section ...
     444              : !> \param logger ...
     445              : !> \param kp ...
     446              : !> \param xas ...
     447              : !> \param rtp ...
     448              : ! **************************************************************************************************
     449         1214 :    SUBROUTINE wfn_restart_file_name(filename, exist, section, logger, kp, xas, rtp)
     450              :       CHARACTER(LEN=default_path_length), INTENT(OUT)    :: filename
     451              :       LOGICAL, INTENT(OUT)                               :: exist
     452              :       TYPE(section_vals_type), POINTER                   :: section
     453              :       TYPE(cp_logger_type), POINTER                      :: logger
     454              :       LOGICAL, INTENT(IN), OPTIONAL                      :: kp, xas, rtp
     455              : 
     456              :       INTEGER                                            :: n_rep_val
     457              :       LOGICAL                                            :: my_kp, my_rtp, my_xas
     458              :       TYPE(section_vals_type), POINTER                   :: print_key
     459              : 
     460          607 :       my_kp = .FALSE.
     461          607 :       my_xas = .FALSE.
     462          607 :       my_rtp = .FALSE.
     463          607 :       IF (PRESENT(kp)) my_kp = kp
     464          607 :       IF (PRESENT(xas)) my_xas = xas
     465          607 :       IF (PRESENT(rtp)) my_rtp = rtp
     466              : 
     467          607 :       exist = .FALSE.
     468          607 :       CALL section_vals_val_get(section, "WFN_RESTART_FILE_NAME", n_rep_val=n_rep_val)
     469          607 :       IF (n_rep_val > 0) THEN
     470          462 :          CALL section_vals_val_get(section, "WFN_RESTART_FILE_NAME", c_val=filename)
     471              :       ELSE
     472          145 :          IF (my_xas) THEN
     473              :             ! try to read from the filename that is generated automatically from the printkey
     474            4 :             print_key => section_vals_get_subs_vals(section, "PRINT%RESTART")
     475              :             filename = cp_print_key_generate_filename(logger, print_key, &
     476            4 :                                                       extension="", my_local=.FALSE.)
     477          141 :          ELSE IF (my_rtp) THEN
     478              :             ! try to read from the filename that is generated automatically from the printkey
     479            3 :             print_key => section_vals_get_subs_vals(section, "REAL_TIME_PROPAGATION%PRINT%RESTART")
     480              :             filename = cp_print_key_generate_filename(logger, print_key, &
     481            3 :                                                       extension=".rtpwfn", my_local=.FALSE.)
     482          138 :          ELSE IF (my_kp) THEN
     483              :             ! try to read from the filename that is generated automatically from the printkey
     484           14 :             print_key => section_vals_get_subs_vals(section, "SCF%PRINT%RESTART")
     485              :             filename = cp_print_key_generate_filename(logger, print_key, &
     486           14 :                                                       extension=".kp", my_local=.FALSE.)
     487              :          ELSE
     488              :             ! try to read from the filename that is generated automatically from the printkey
     489          124 :             print_key => section_vals_get_subs_vals(section, "SCF%PRINT%RESTART")
     490              :             filename = cp_print_key_generate_filename(logger, print_key, &
     491          124 :                                                       extension=".wfn", my_local=.FALSE.)
     492              :          END IF
     493              :       END IF
     494          607 :       IF (.NOT. my_xas) THEN
     495          601 :          INQUIRE (FILE=filename, exist=exist)
     496              :       END IF
     497              : 
     498          607 :    END SUBROUTINE wfn_restart_file_name
     499              : 
     500              : ! **************************************************************************************************
     501              : !> \brief ...
     502              : !> \param mo_array ...
     503              : !> \param qs_kind_set ...
     504              : !> \param particle_set ...
     505              : !> \param para_env ...
     506              : !> \param id_nr ...
     507              : !> \param multiplicity ...
     508              : !> \param dft_section ...
     509              : !> \param natom_mismatch ...
     510              : !> \param cdft ...
     511              : !> \param out_unit ...
     512              : ! **************************************************************************************************
     513          521 :    SUBROUTINE read_mo_set_from_restart(mo_array, qs_kind_set, particle_set, &
     514              :                                        para_env, id_nr, multiplicity, dft_section, natom_mismatch, &
     515              :                                        cdft, out_unit)
     516              : 
     517              :       TYPE(mo_set_type), DIMENSION(:), INTENT(INOUT)     :: mo_array
     518              :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
     519              :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     520              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     521              :       INTEGER, INTENT(IN)                                :: id_nr, multiplicity
     522              :       TYPE(section_vals_type), POINTER                   :: dft_section
     523              :       LOGICAL, INTENT(OUT), OPTIONAL                     :: natom_mismatch
     524              :       LOGICAL, INTENT(IN), OPTIONAL                      :: cdft
     525              :       INTEGER, INTENT(IN), OPTIONAL                      :: out_unit
     526              : 
     527              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'read_mo_set_from_restart'
     528              : 
     529              :       CHARACTER(LEN=default_path_length)                 :: file_name
     530              :       INTEGER                                            :: handle, ispin, my_out_unit, natom, &
     531              :                                                             nspin, restart_unit
     532              :       LOGICAL                                            :: exist, my_cdft
     533              :       TYPE(cp_logger_type), POINTER                      :: logger
     534              : 
     535          521 :       CALL timeset(routineN, handle)
     536          521 :       logger => cp_get_default_logger()
     537          521 :       my_cdft = .FALSE.
     538          521 :       IF (PRESENT(cdft)) my_cdft = cdft
     539          521 :       my_out_unit = -1
     540          521 :       IF (PRESENT(out_unit)) my_out_unit = out_unit
     541              : 
     542          521 :       nspin = SIZE(mo_array)
     543          521 :       restart_unit = -1
     544              : 
     545          521 :       IF (para_env%is_source()) THEN
     546              : 
     547          279 :          natom = SIZE(particle_set, 1)
     548          279 :          CALL wfn_restart_file_name(file_name, exist, dft_section, logger)
     549          279 :          IF (id_nr /= 0) THEN
     550              :             ! Is it one of the backup files?
     551            1 :             file_name = TRIM(file_name)//".bak-"//ADJUSTL(cp_to_string(id_nr))
     552              :          END IF
     553              : 
     554              :          CALL open_file(file_name=file_name, &
     555              :                         file_action="READ", &
     556              :                         file_form="UNFORMATTED", &
     557              :                         file_status="OLD", &
     558          279 :                         unit_number=restart_unit)
     559              : 
     560              :       END IF
     561              : 
     562              :       CALL read_mos_restart_low(mo_array, para_env=para_env, qs_kind_set=qs_kind_set, &
     563              :                                 particle_set=particle_set, natom=natom, &
     564          521 :                                 rst_unit=restart_unit, multiplicity=multiplicity, natom_mismatch=natom_mismatch)
     565              : 
     566          521 :       IF (PRESENT(natom_mismatch)) THEN
     567              :          ! read_mos_restart_low only the io_node returns natom_mismatch, must broadcast it
     568          491 :          CALL para_env%bcast(natom_mismatch)
     569          491 :          IF (natom_mismatch) THEN
     570            0 :             IF (para_env%is_source()) CALL close_file(unit_number=restart_unit)
     571            0 :             CALL timestop(handle)
     572            0 :             RETURN
     573              :          END IF
     574              :       END IF
     575              : 
     576              :       ! Close restart file
     577          521 :       IF (para_env%is_source()) THEN
     578          279 :          IF (my_out_unit > 0) THEN
     579              :             WRITE (UNIT=my_out_unit, FMT="(T2,A)") &
     580            6 :                "WFN_RESTART| Restart file "//TRIM(file_name)//" read"
     581              :          END IF
     582          279 :          CALL close_file(unit_number=restart_unit)
     583              :       END IF
     584              : 
     585              :       ! CDFT has no real dft_section and does not need to print
     586          521 :       IF (.NOT. my_cdft) THEN
     587         1396 :          DO ispin = 1, nspin
     588              :             CALL write_mo_set_to_output_unit(mo_array(ispin), qs_kind_set, particle_set, &
     589         1396 :                                              dft_section, 4, 0, final_mos=.FALSE.)
     590              :          END DO
     591              :       END IF
     592              : 
     593          521 :       CALL timestop(handle)
     594              : 
     595              :    END SUBROUTINE read_mo_set_from_restart
     596              : 
     597              : ! **************************************************************************************************
     598              : !> \brief ...
     599              : !> \param mo_array ...
     600              : !> \param rt_mos ...
     601              : !> \param qs_kind_set ...
     602              : !> \param particle_set ...
     603              : !> \param para_env ...
     604              : !> \param id_nr ...
     605              : !> \param multiplicity ...
     606              : !> \param dft_section ...
     607              : ! **************************************************************************************************
     608            8 :    SUBROUTINE read_rt_mos_from_restart(mo_array, rt_mos, qs_kind_set, particle_set, para_env, id_nr, multiplicity, dft_section)
     609              : 
     610              :       TYPE(mo_set_type), DIMENSION(:), INTENT(INOUT)     :: mo_array
     611              :       TYPE(cp_fm_type), DIMENSION(:), POINTER            :: rt_mos
     612              :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
     613              :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     614              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     615              :       INTEGER, INTENT(IN)                                :: id_nr, multiplicity
     616              :       TYPE(section_vals_type), POINTER                   :: dft_section
     617              : 
     618              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'read_rt_mos_from_restart'
     619              : 
     620              :       CHARACTER(LEN=default_path_length)                 :: file_name
     621              :       INTEGER                                            :: handle, ispin, natom, nspin, &
     622              :                                                             restart_unit, unit_nr
     623              :       LOGICAL                                            :: exist
     624              :       TYPE(cp_logger_type), POINTER                      :: logger
     625              : 
     626            8 :       CALL timeset(routineN, handle)
     627            8 :       logger => cp_get_default_logger()
     628              : 
     629            8 :       nspin = SIZE(mo_array)
     630            8 :       restart_unit = -1
     631              : 
     632            8 :       IF (para_env%is_source()) THEN
     633              : 
     634            4 :          natom = SIZE(particle_set, 1)
     635            4 :          CALL wfn_restart_file_name(file_name, exist, dft_section, logger, rtp=.TRUE.)
     636            4 :          IF (id_nr /= 0) THEN
     637              :             ! Is it one of the backup files?
     638            0 :             file_name = TRIM(file_name)//".bak-"//ADJUSTL(cp_to_string(id_nr))
     639              :          END IF
     640              : 
     641            4 :          unit_nr = cp_logger_get_default_unit_nr(logger, local=.TRUE.)
     642            4 :          IF (unit_nr > 0) THEN
     643            4 :             WRITE (unit_nr, '(T2,A)') "Read RTP restart from the file: "//TRIM(file_name)
     644              :          END IF
     645              : 
     646              :          CALL open_file(file_name=file_name, &
     647              :                         file_action="READ", &
     648              :                         file_form="UNFORMATTED", &
     649              :                         file_status="OLD", &
     650            4 :                         unit_number=restart_unit)
     651              : 
     652              :       END IF
     653              : 
     654              :       CALL read_mos_restart_low(mo_array, rt_mos=rt_mos, para_env=para_env, &
     655              :                                 particle_set=particle_set, qs_kind_set=qs_kind_set, natom=natom, &
     656            8 :                                 rst_unit=restart_unit, multiplicity=multiplicity)
     657              : 
     658              :       ! Close restart file
     659            8 :       IF (para_env%is_source()) CALL close_file(unit_number=restart_unit)
     660              : 
     661           16 :       DO ispin = 1, nspin
     662              :          CALL write_mo_set_to_output_unit(mo_array(ispin), qs_kind_set, particle_set, &
     663           16 :                                           dft_section, 4, 0, final_mos=.FALSE.)
     664              :       END DO
     665              : 
     666            8 :       CALL timestop(handle)
     667              : 
     668            8 :    END SUBROUTINE read_rt_mos_from_restart
     669              : 
     670              : ! **************************************************************************************************
     671              : !> \brief Reading the mos from apreviously defined restart file
     672              : !> \param mos ...
     673              : !> \param para_env ...
     674              : !> \param qs_kind_set ...
     675              : !> \param particle_set ...
     676              : !> \param natom ...
     677              : !> \param rst_unit ...
     678              : !> \param multiplicity ...
     679              : !> \param rt_mos ...
     680              : !> \param natom_mismatch ...
     681              : !> \par History
     682              : !>      12.2007 created [MI]
     683              : !> \author MI
     684              : ! **************************************************************************************************
     685          585 :    SUBROUTINE read_mos_restart_low(mos, para_env, qs_kind_set, particle_set, natom, rst_unit, &
     686              :                                    multiplicity, rt_mos, natom_mismatch)
     687              : 
     688              :       TYPE(mo_set_type), DIMENSION(:), INTENT(INOUT)     :: mos
     689              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     690              :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
     691              :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     692              :       INTEGER, INTENT(IN)                                :: natom, rst_unit
     693              :       INTEGER, INTENT(in), OPTIONAL                      :: multiplicity
     694              :       TYPE(cp_fm_type), DIMENSION(:), OPTIONAL, POINTER  :: rt_mos
     695              :       LOGICAL, INTENT(OUT), OPTIONAL                     :: natom_mismatch
     696              : 
     697              :       INTEGER :: homo, homo_read, i, iatom, ikind, imat, irow, iset, iset_read, ishell, &
     698              :          ishell_read, iso, ispin, lfomo_read, lmax, lshell, my_mult, nao, nao_read, natom_read, &
     699              :          nelectron, nelectron_read, nmo, nmo_read, nnshell, nset, nset_max, nshell_max, nspin, &
     700              :          nspin_read, offset_read
     701          585 :       INTEGER, DIMENSION(:), POINTER                     :: nset_info, nshell
     702          585 :       INTEGER, DIMENSION(:, :), POINTER                  :: l, nshell_info
     703          585 :       INTEGER, DIMENSION(:, :, :), POINTER               :: nso_info, offset_info
     704              :       LOGICAL                                            :: minbas, natom_match, use_this
     705          585 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: eig_read, occ_read
     706          585 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: vecbuffer, vecbuffer_read
     707              :       TYPE(cp_logger_type), POINTER                      :: logger
     708              :       TYPE(gto_basis_set_type), POINTER                  :: orb_basis_set
     709              :       TYPE(qs_dftb_atom_type), POINTER                   :: dftb_parameter
     710              : 
     711         1170 :       logger => cp_get_default_logger()
     712              : 
     713          585 :       nspin = SIZE(mos)
     714          585 :       nao = mos(1)%nao
     715          585 :       my_mult = 0
     716          585 :       IF (PRESENT(multiplicity)) my_mult = multiplicity
     717              : 
     718          585 :       IF (para_env%is_source()) THEN
     719          311 :          READ (rst_unit) natom_read, nspin_read, nao_read, nset_max, nshell_max
     720          311 :          IF (PRESENT(rt_mos)) THEN
     721            4 :             IF (nspin_read /= nspin) THEN
     722            0 :                CPABORT("To change nspin is not possible. ")
     723              :             END IF
     724              :          ELSE
     725              :             ! we should allow for restarting with different spin settings
     726          307 :             IF (nspin_read /= nspin) THEN
     727              :                WRITE (cp_logger_get_default_unit_nr(logger), *) &
     728            0 :                   "READ RESTART : WARNING : nspin is not equal "
     729              :             END IF
     730              :             ! this case needs fixing of homo/lfomo/nelec/occupations ...
     731          307 :             IF (nspin_read > nspin) THEN
     732            0 :                CPABORT("Reducing nspin is not possible. ")
     733              :             END IF
     734              :          END IF
     735              : 
     736          311 :          natom_match = (natom_read == natom)
     737              : 
     738          311 :          IF (natom_match) THEN ! actually do the read read
     739              : 
     740              :             ! Let's make it possible to change the basis set
     741         1555 :             ALLOCATE (nso_info(nshell_max, nset_max, natom_read))
     742         1244 :             ALLOCATE (nshell_info(nset_max, natom_read))
     743          933 :             ALLOCATE (nset_info(natom_read))
     744         1244 :             ALLOCATE (offset_info(nshell_max, nset_max, natom_read))
     745              : 
     746          311 :             IF (nao_read /= nao) THEN
     747              :                WRITE (cp_logger_get_default_unit_nr(logger), *) &
     748            1 :                   " READ RESTART : WARNING : DIFFERENT # AOs ", nao, nao_read
     749            1 :                IF (PRESENT(rt_mos)) &
     750            0 :                   CPABORT("To change basis is not possible. ")
     751              :             END IF
     752              : 
     753         1140 :             READ (rst_unit) nset_info
     754         2865 :             READ (rst_unit) nshell_info
     755         6943 :             READ (rst_unit) nso_info
     756              : 
     757          311 :             i = 1
     758         1140 :             DO iatom = 1, natom
     759         2681 :                DO iset = 1, nset_info(iatom)
     760         4900 :                   DO ishell = 1, nshell_info(iset, iatom)
     761         2530 :                      offset_info(ishell, iset, iatom) = i
     762         4071 :                      i = i + nso_info(ishell, iset, iatom)
     763              :                   END DO
     764              :                END DO
     765              :             END DO
     766              : 
     767          933 :             ALLOCATE (vecbuffer_read(1, nao_read))
     768              : 
     769              :          END IF ! natom_match
     770              :       END IF ! ionode
     771              : 
     772              :       ! make natom_match and natom_mismatch uniform across all nodes
     773          585 :       CALL para_env%bcast(natom_match)
     774          585 :       IF (PRESENT(natom_mismatch)) natom_mismatch = .NOT. natom_match
     775              :       ! handle natom_match false
     776          585 :       IF (.NOT. natom_match) THEN
     777            0 :          IF (PRESENT(natom_mismatch)) THEN
     778              :             WRITE (cp_logger_get_default_unit_nr(logger), *) &
     779            0 :                " READ RESTART : WARNING : DIFFERENT natom, returning ", natom, natom_read
     780              :             RETURN
     781              :          ELSE
     782            0 :             CPABORT("Incorrect number of atoms in restart file. ")
     783              :          END IF
     784              :       END IF
     785              : 
     786          585 :       CALL para_env%bcast(nspin_read)
     787              : 
     788         1755 :       ALLOCATE (vecbuffer(1, nao))
     789              : 
     790         1602 :       DO ispin = 1, nspin
     791              : 
     792         1017 :          nmo = mos(ispin)%nmo
     793         1017 :          homo = mos(ispin)%homo
     794         5340 :          mos(ispin)%eigenvalues(:) = 0.0_dp
     795         5340 :          mos(ispin)%occupation_numbers(:) = 0.0_dp
     796         1017 :          CALL cp_fm_set_all(mos(ispin)%mo_coeff, 0.0_dp)
     797              : 
     798         1017 :          IF (para_env%is_source() .AND. (nmo > 0)) THEN
     799          536 :             READ (rst_unit) nmo_read, homo_read, lfomo_read, nelectron_read
     800         2144 :             ALLOCATE (eig_read(nmo_read), occ_read(nmo_read))
     801         2749 :             eig_read = 0.0_dp
     802         2749 :             occ_read = 0.0_dp
     803              : 
     804          536 :             nmo = MIN(nmo, nmo_read)
     805              :             IF (nmo_read < nmo) &
     806              :                CALL cp_warn(__LOCATION__, &
     807              :                             "The number of MOs on the restart unit is smaller than the number of "// &
     808              :                             "the allocated MOs. The MO set will be padded with zeros!")
     809          536 :             IF (nmo_read > nmo) &
     810              :                CALL cp_warn(__LOCATION__, &
     811              :                             "The number of MOs on the restart unit is greater than the number of "// &
     812            7 :                             "the allocated MOs. The read MO set will be truncated!")
     813              : 
     814          536 :             READ (rst_unit) eig_read(1:nmo_read), occ_read(1:nmo_read)
     815         2725 :             mos(ispin)%eigenvalues(1:nmo) = eig_read(1:nmo)
     816         2725 :             mos(ispin)%occupation_numbers(1:nmo) = occ_read(1:nmo)
     817          536 :             DEALLOCATE (eig_read, occ_read)
     818              : 
     819          536 :             mos(ispin)%homo = homo_read
     820          536 :             mos(ispin)%lfomo = lfomo_read
     821          536 :             IF (homo_read > nmo) THEN
     822            0 :                IF (nelectron_read == mos(ispin)%nelectron) THEN
     823              :                   CALL cp_warn(__LOCATION__, &
     824              :                                "The number of occupied MOs on the restart unit is larger than "// &
     825            0 :                                "the allocated MOs. The read MO set will be truncated and the occupation numbers recalculated!")
     826            0 :                   CALL set_mo_occupation(mo_set=mos(ispin))
     827              :                ELSE
     828              :                   ! can not make this a warning i.e. homo must be smaller than nmo
     829              :                   ! otherwise e.g. set_mo_occupation will go out of bounds
     830            0 :                   CPABORT("Number of occupied MOs on restart unit larger than allocated MOs. ")
     831              :                END IF
     832              :             END IF
     833              :          END IF
     834              : 
     835         1017 :          CALL para_env%bcast(nmo)
     836         1017 :          CALL para_env%bcast(mos(ispin)%homo)
     837         1017 :          CALL para_env%bcast(mos(ispin)%lfomo)
     838         1017 :          CALL para_env%bcast(mos(ispin)%nelectron)
     839         9663 :          CALL para_env%bcast(mos(ispin)%eigenvalues)
     840         9663 :          CALL para_env%bcast(mos(ispin)%occupation_numbers)
     841              : 
     842         1017 :          IF (PRESENT(rt_mos)) THEN
     843           24 :             DO imat = 2*ispin - 1, 2*ispin
     844           40 :                DO i = 1, nmo
     845           16 :                   IF (para_env%is_source()) THEN
     846          168 :                      READ (rst_unit) vecbuffer
     847              :                   ELSE
     848           88 :                      vecbuffer(1, :) = 0.0_dp
     849              :                   END IF
     850          656 :                   CALL para_env%bcast(vecbuffer)
     851              :                   CALL cp_fm_set_submatrix(rt_mos(imat), &
     852           32 :                                            vecbuffer, 1, i, nao, 1, transpose=.TRUE.)
     853              :                END DO
     854              :             END DO
     855              :          ELSE
     856         5288 :             DO i = 1, nmo
     857         4279 :                IF (para_env%is_source()) THEN
     858       146193 :                   READ (rst_unit) vecbuffer_read
     859              :                   ! now, try to assign the read to the real vector
     860              :                   ! in case the basis set changed this involves some guessing
     861         2185 :                   irow = 1
     862         9774 :                   DO iatom = 1, natom
     863         7589 :                      NULLIFY (orb_basis_set, dftb_parameter, l, nshell)
     864         7589 :                      CALL get_atomic_kind(particle_set(iatom)%atomic_kind, kind_number=ikind)
     865              :                      CALL get_qs_kind(qs_kind_set(ikind), &
     866         7589 :                                       basis_set=orb_basis_set, dftb_parameter=dftb_parameter)
     867         7589 :                      IF (ASSOCIATED(orb_basis_set)) THEN
     868              :                         CALL get_gto_basis_set(gto_basis_set=orb_basis_set, &
     869              :                                                nset=nset, &
     870              :                                                nshell=nshell, &
     871         7541 :                                                l=l)
     872         7541 :                         minbas = .FALSE.
     873           48 :                      ELSEIF (ASSOCIATED(dftb_parameter)) THEN
     874           48 :                         CALL get_dftb_atom_param(dftb_parameter, lmax=lmax)
     875           48 :                         nset = 1
     876           48 :                         minbas = .TRUE.
     877              :                      ELSE
     878              :                         ! assume an atom without basis set
     879              :                         ! CPABORT("Unknown basis set type. ")
     880            0 :                         nset = 0
     881              :                      END IF
     882              : 
     883         7589 :                      use_this = .TRUE.
     884         7589 :                      iset_read = 1
     885        35528 :                      DO iset = 1, nset
     886        18165 :                         ishell_read = 1
     887        18165 :                         IF (minbas) THEN
     888           48 :                            nnshell = lmax + 1
     889              :                         ELSE
     890        18117 :                            nnshell = nshell(iset)
     891              :                         END IF
     892        57458 :                         DO ishell = 1, nnshell
     893        31704 :                            IF (minbas) THEN
     894           72 :                               lshell = ishell - 1
     895              :                            ELSE
     896        31632 :                               lshell = l(ishell, iset)
     897              :                            END IF
     898        31704 :                            IF (iset_read > nset_info(iatom)) use_this = .FALSE.
     899              :                            IF (use_this) THEN ! avoids out of bound access of the lower line if false
     900        31680 :                               IF (nso(lshell) == nso_info(ishell_read, iset_read, iatom)) THEN
     901        31680 :                                  offset_read = offset_info(ishell_read, iset_read, iatom)
     902        31680 :                                  ishell_read = ishell_read + 1
     903        31680 :                                  IF (ishell_read > nshell_info(iset, iatom)) THEN
     904        18161 :                                     ishell_read = 1
     905        18161 :                                     iset_read = iset_read + 1
     906              :                                  END IF
     907              :                               ELSE
     908              :                                  use_this = .FALSE.
     909              :                               END IF
     910              :                            END IF
     911       103852 :                            DO iso = 1, nso(lshell)
     912        72148 :                               IF (use_this) THEN
     913        72004 :                                  IF (offset_read - 1 + iso < 1 .OR. offset_read - 1 + iso > nao_read) THEN
     914            0 :                                     vecbuffer(1, irow) = 0.0_dp
     915              :                                  ELSE
     916        72004 :                                     vecbuffer(1, irow) = vecbuffer_read(1, offset_read - 1 + iso)
     917              :                                  END IF
     918              :                               ELSE
     919          144 :                                  vecbuffer(1, irow) = 0.0_dp
     920              :                               END IF
     921       103852 :                               irow = irow + 1
     922              :                            END DO
     923        49869 :                            use_this = .TRUE.
     924              :                         END DO
     925              :                      END DO
     926              :                   END DO
     927              : 
     928              :                ELSE
     929              : 
     930        72764 :                   vecbuffer(1, :) = 0.0_dp
     931              : 
     932              :                END IF
     933              : 
     934       575551 :                CALL para_env%bcast(vecbuffer)
     935              :                CALL cp_fm_set_submatrix(mos(ispin)%mo_coeff, &
     936         5288 :                                         vecbuffer, 1, i, nao, 1, transpose=.TRUE.)
     937              :             END DO
     938              :          END IF
     939              :          ! Skip extra MOs if there any
     940         1017 :          IF (para_env%is_source()) THEN
     941              :             !ignore nmo = 0
     942          539 :             IF (nmo > 0) THEN
     943          560 :                DO i = nmo + 1, nmo_read
     944         1504 :                   READ (rst_unit) vecbuffer_read
     945              :                END DO
     946              :             END IF
     947              :          END IF
     948              : 
     949         1602 :          IF (.NOT. PRESENT(rt_mos)) THEN
     950         1009 :             IF (ispin == 1 .AND. nspin_read < nspin) THEN
     951              : 
     952            0 :                mos(ispin + 1)%homo = mos(ispin)%homo
     953            0 :                mos(ispin + 1)%lfomo = mos(ispin)%lfomo
     954            0 :                nelectron = mos(ispin)%nelectron
     955            0 :                IF (my_mult /= 1) THEN
     956              :                   CALL cp_abort(__LOCATION__, &
     957            0 :                                 "Restarting an LSD calculation from an LDA wfn only works for multiplicity=1 (singlets).")
     958              :                END IF
     959            0 :                IF (mos(ispin + 1)%nelectron < 0) THEN
     960            0 :                   CPABORT("LSD: too few electrons for this multiplisity. ")
     961              :                END IF
     962            0 :                mos(ispin + 1)%eigenvalues = mos(ispin)%eigenvalues
     963            0 :                mos(ispin)%occupation_numbers = mos(ispin)%occupation_numbers/2.0_dp
     964            0 :                mos(ispin + 1)%occupation_numbers = mos(ispin)%occupation_numbers
     965            0 :                CALL cp_fm_to_fm(mos(ispin)%mo_coeff, mos(ispin + 1)%mo_coeff)
     966            0 :                EXIT
     967              :             END IF
     968              :          END IF
     969              :       END DO ! ispin
     970              : 
     971          585 :       DEALLOCATE (vecbuffer)
     972              : 
     973          585 :       IF (para_env%is_source()) THEN
     974          311 :          DEALLOCATE (vecbuffer_read)
     975          311 :          DEALLOCATE (offset_info)
     976          311 :          DEALLOCATE (nso_info)
     977          311 :          DEALLOCATE (nshell_info)
     978          311 :          DEALLOCATE (nset_info)
     979              :       END IF
     980              : 
     981         1170 :    END SUBROUTINE read_mos_restart_low
     982              : 
     983              : ! **************************************************************************************************
     984              : !> \brief Write MO information to output file (eigenvalues, occupation numbers, coefficients)
     985              : !> \param mo_set ...
     986              : !> \param qs_kind_set ...
     987              : !> \param particle_set ...
     988              : !> \param dft_section ...
     989              : !> \param before Digits before the dot
     990              : !> \param kpoint An integer that labels the current k point, e.g. its index
     991              : !> \param final_mos ...
     992              : !> \param spin ...
     993              : !> \param solver_method ...
     994              : !> \param rtp ...
     995              : !> \param cpart ...
     996              : !> \param sim_step ...
     997              : !> \param umo_set ...
     998              : !> \date    15.05.2001
     999              : !> \par History:
    1000              : !>       - Optionally print Cartesian MOs (20.04.2005, MK)
    1001              : !>       - Revise printout of MO information (05.05.2021, MK)
    1002              : !> \par Variables
    1003              : !>       - after : Number of digits after point.
    1004              : !>       - before: Number of digits before point.
    1005              : !> \author  Matthias Krack (MK)
    1006              : !> \version 1.1
    1007              : ! **************************************************************************************************
    1008         6001 :    SUBROUTINE write_mo_set_to_output_unit(mo_set, qs_kind_set, particle_set, &
    1009              :                                           dft_section, before, kpoint, final_mos, spin, &
    1010              :                                           solver_method, rtp, cpart, sim_step, umo_set)
    1011              : 
    1012              :       TYPE(mo_set_type), INTENT(IN)                      :: mo_set
    1013              :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
    1014              :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
    1015              :       TYPE(section_vals_type), POINTER                   :: dft_section
    1016              :       INTEGER, INTENT(IN)                                :: before, kpoint
    1017              :       LOGICAL, INTENT(IN), OPTIONAL                      :: final_mos
    1018              :       CHARACTER(LEN=*), INTENT(IN), OPTIONAL             :: spin
    1019              :       CHARACTER(LEN=2), INTENT(IN), OPTIONAL             :: solver_method
    1020              :       LOGICAL, INTENT(IN), OPTIONAL                      :: rtp
    1021              :       INTEGER, INTENT(IN), OPTIONAL                      :: cpart, sim_step
    1022              :       TYPE(mo_set_type), INTENT(IN), OPTIONAL            :: umo_set
    1023              : 
    1024              :       CHARACTER(LEN=12)                                  :: symbol
    1025         6001 :       CHARACTER(LEN=12), DIMENSION(:), POINTER           :: bcgf_symbol
    1026              :       CHARACTER(LEN=14)                                  :: fmtstr5
    1027              :       CHARACTER(LEN=15)                                  :: energy_str, orbital_str, step_string
    1028              :       CHARACTER(LEN=2)                                   :: element_symbol, my_solver_method
    1029              :       CHARACTER(LEN=2*default_string_length)             :: name
    1030              :       CHARACTER(LEN=21)                                  :: vector_str
    1031              :       CHARACTER(LEN=22)                                  :: fmtstr4
    1032              :       CHARACTER(LEN=24)                                  :: fmtstr2
    1033              :       CHARACTER(LEN=25)                                  :: fmtstr1
    1034              :       CHARACTER(LEN=29)                                  :: fmtstr6
    1035              :       CHARACTER(LEN=4)                                   :: reim
    1036              :       CHARACTER(LEN=40)                                  :: fmtstr3
    1037         6001 :       CHARACTER(LEN=6), DIMENSION(:), POINTER            :: bsgf_symbol
    1038              :       INTEGER :: after, first_mo, from, homo, iatom, icgf, ico, icol, ikind, imo, irow, iset, &
    1039              :          isgf, ishell, iso, iw, jcol, last_mo, left, lmax, lshell, nao, natom, ncgf, ncol, nmo, &
    1040              :          nset, nsgf, numo, right, scf_step, to, width
    1041         6001 :       INTEGER, DIMENSION(:), POINTER                     :: mo_index_range, nshell
    1042         6001 :       INTEGER, DIMENSION(:, :), POINTER                  :: l
    1043              :       LOGICAL                                            :: ionode, my_final, my_rtp, &
    1044              :                                                             print_cartesian, print_eigvals, &
    1045              :                                                             print_eigvecs, print_occup, &
    1046              :                                                             should_output
    1047              :       REAL(KIND=dp)                                      :: gap, maxocc
    1048         6001 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: mo_eigenvalues, mo_occupation_numbers
    1049         6001 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: cmatrix, smatrix
    1050         6001 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: eigenvalues, occupation_numbers
    1051              :       TYPE(cp_fm_type), POINTER                          :: mo_coeff, umo_coeff
    1052              :       TYPE(cp_logger_type), POINTER                      :: logger
    1053              :       TYPE(gto_basis_set_type), POINTER                  :: orb_basis_set
    1054              :       TYPE(qs_dftb_atom_type), POINTER                   :: dftb_parameter
    1055              : 
    1056         6001 :       NULLIFY (bcgf_symbol)
    1057         6001 :       NULLIFY (bsgf_symbol)
    1058         6001 :       NULLIFY (logger)
    1059         6001 :       NULLIFY (mo_index_range)
    1060         6001 :       NULLIFY (nshell)
    1061         6001 :       NULLIFY (mo_coeff)
    1062              : 
    1063        12002 :       logger => cp_get_default_logger()
    1064         6001 :       ionode = logger%para_env%is_source()
    1065         6001 :       CALL section_vals_val_get(dft_section, "PRINT%MO%EIGENVALUES", l_val=print_eigvals)
    1066         6001 :       CALL section_vals_val_get(dft_section, "PRINT%MO%EIGENVECTORS", l_val=print_eigvecs)
    1067         6001 :       CALL section_vals_val_get(dft_section, "PRINT%MO%OCCUPATION_NUMBERS", l_val=print_occup)
    1068         6001 :       CALL section_vals_val_get(dft_section, "PRINT%MO%CARTESIAN", l_val=print_cartesian)
    1069         6001 :       CALL section_vals_val_get(dft_section, "PRINT%MO%MO_INDEX_RANGE", i_vals=mo_index_range)
    1070         6001 :       CALL section_vals_val_get(dft_section, "PRINT%MO%NDIGITS", i_val=after)
    1071         6001 :       after = MIN(MAX(after, 1), 16)
    1072              : 
    1073              :       ! Do we print the final MO information after SCF convergence is reached (default: no)
    1074         6001 :       IF (PRESENT(final_mos)) THEN
    1075         5993 :          my_final = final_mos
    1076              :       ELSE
    1077              :          my_final = .FALSE.
    1078              :       END IF
    1079              : 
    1080              :       ! complex MOS for RTP, no eigenvalues
    1081         6001 :       my_rtp = .FALSE.
    1082         6001 :       IF (PRESENT(rtp)) THEN
    1083            8 :          my_rtp = rtp
    1084              :          ! print the first time step if MO print required
    1085              :          should_output = BTEST(cp_print_key_should_output(logger%iter_info, dft_section, &
    1086              :                                                           "PRINT%MO"), cp_p_file) &
    1087            8 :                          .OR. (sim_step == 1)
    1088              :       ELSE
    1089              :          should_output = BTEST(cp_print_key_should_output(logger%iter_info, dft_section, &
    1090         6914 :                                                           "PRINT%MO"), cp_p_file) .OR. my_final
    1091              :       END IF
    1092              : 
    1093         6001 :       IF ((.NOT. should_output) .OR. (.NOT. (print_eigvals .OR. print_eigvecs .OR. print_occup))) RETURN
    1094              : 
    1095         5078 :       IF (my_rtp) THEN
    1096            8 :          CPASSERT(PRESENT(sim_step))
    1097            8 :          CPASSERT(PRESENT(cpart))
    1098            8 :          scf_step = sim_step
    1099            8 :          IF (cpart == 0) THEN
    1100            4 :             reim = "IMAG"
    1101              :          ELSE
    1102            4 :             reim = "REAL"
    1103              :          END IF
    1104            8 :          print_eigvals = .FALSE.
    1105              :       ELSE
    1106         5070 :          scf_step = MAX(0, logger%iter_info%iteration(logger%iter_info%n_rlevel) - 1)
    1107              :       END IF
    1108              : 
    1109         5078 :       IF (.NOT. my_final) THEN
    1110         3944 :          IF (.NOT. my_rtp) THEN
    1111         3936 :             step_string = " AFTER SCF STEP"
    1112              :          ELSE
    1113            8 :             step_string = " AFTER RTP STEP"
    1114              :          END IF
    1115              :       END IF
    1116              : 
    1117         5078 :       IF (PRESENT(solver_method)) THEN
    1118         4924 :          my_solver_method = solver_method
    1119              :       ELSE
    1120              :          ! Traditional diagonalization is assumed as default solver method
    1121          154 :          my_solver_method = "TD"
    1122              :       END IF
    1123              : 
    1124              :       ! Retrieve MO information
    1125              :       CALL get_mo_set(mo_set=mo_set, &
    1126              :                       mo_coeff=mo_coeff, &
    1127              :                       eigenvalues=eigenvalues, &
    1128              :                       occupation_numbers=occupation_numbers, &
    1129              :                       homo=homo, &
    1130              :                       maxocc=maxocc, &
    1131              :                       nao=nao, &
    1132         5078 :                       nmo=nmo)
    1133         5078 :       IF (PRESENT(umo_set)) THEN
    1134              :          CALL get_mo_set(mo_set=umo_set, &
    1135              :                          mo_coeff=umo_coeff, &
    1136           20 :                          nmo=numo)
    1137           20 :          nmo = nmo + numo
    1138              :       ELSE
    1139         5058 :          numo = 0
    1140              :       END IF
    1141        15184 :       ALLOCATE (mo_eigenvalues(nmo))
    1142        43484 :       mo_eigenvalues(:) = 0.0_dp
    1143        43374 :       mo_eigenvalues(1:nmo - numo) = eigenvalues(1:nmo - numo)
    1144        10106 :       ALLOCATE (mo_occupation_numbers(nmo))
    1145        43484 :       mo_occupation_numbers(:) = 0.0_dp
    1146        43374 :       mo_occupation_numbers(1:nmo - numo) = occupation_numbers(1:nmo - numo)
    1147         5078 :       IF (numo > 0) THEN
    1148              :          CALL get_mo_set(mo_set=umo_set, &
    1149           20 :                          eigenvalues=eigenvalues)
    1150          130 :          mo_eigenvalues(nmo - numo + 1:nmo) = eigenvalues(1:numo)
    1151              :       END IF
    1152              : 
    1153         5078 :       IF (print_eigvecs) THEN
    1154        13878 :          ALLOCATE (smatrix(nao, nmo))
    1155         3482 :          CALL cp_fm_get_submatrix(mo_coeff, smatrix(1:nao, 1:nmo - numo))
    1156         3482 :          IF (numo > 0) THEN
    1157           14 :             CALL cp_fm_get_submatrix(umo_coeff, smatrix(1:nao, nmo - numo + 1:nmo))
    1158              :          END IF
    1159         3482 :          IF (.NOT. ionode) THEN
    1160         1741 :             DEALLOCATE (smatrix)
    1161              :          END IF
    1162              :       END IF
    1163              : 
    1164              :       iw = cp_print_key_unit_nr(logger, dft_section, "PRINT%MO", &
    1165              :                                 ignore_should_output=should_output, &
    1166         5078 :                                 extension=".MOLog")
    1167              : 
    1168         5078 :       IF (iw > 0) THEN
    1169              : 
    1170         2539 :          natom = SIZE(particle_set)
    1171         2539 :          CALL get_qs_kind_set(qs_kind_set, ncgf=ncgf, nsgf=nsgf)
    1172              : 
    1173              :          ! Definition of the variable formats
    1174              : 
    1175         2539 :          fmtstr1 = "(T2,A,21X,  (  X,I5,  X))"
    1176         2539 :          fmtstr2 = "(T2,A,21X,  (1X,F  .  ))"
    1177         2539 :          fmtstr3 = "(T2,A,I5,1X,I5,1X,A,1X,A6,  (1X,F  .  ))"
    1178              : 
    1179         2539 :          width = before + after + 3
    1180         2539 :          ncol = INT(56/width)
    1181              : 
    1182         2539 :          right = MAX((after - 2), 1)
    1183         2539 :          left = width - right - 5
    1184              : 
    1185         2539 :          WRITE (UNIT=fmtstr1(11:12), FMT="(I2)") ncol
    1186         2539 :          WRITE (UNIT=fmtstr1(14:15), FMT="(I2)") left
    1187         2539 :          WRITE (UNIT=fmtstr1(21:22), FMT="(I2)") right
    1188              : 
    1189         2539 :          WRITE (UNIT=fmtstr2(11:12), FMT="(I2)") ncol
    1190         2539 :          WRITE (UNIT=fmtstr2(18:19), FMT="(I2)") width - 1
    1191         2539 :          WRITE (UNIT=fmtstr2(21:22), FMT="(I2)") after
    1192              : 
    1193         2539 :          WRITE (UNIT=fmtstr3(27:28), FMT="(I2)") ncol
    1194         2539 :          WRITE (UNIT=fmtstr3(34:35), FMT="(I2)") width - 1
    1195         2539 :          WRITE (UNIT=fmtstr3(37:38), FMT="(I2)") after
    1196              : 
    1197         2539 :          IF (my_final .OR. (my_solver_method == "TD")) THEN
    1198         2539 :             energy_str = "EIGENVALUES"
    1199         2539 :             vector_str = "EIGENVECTORS"
    1200              :          ELSE
    1201            0 :             energy_str = "ENERGIES"
    1202            0 :             vector_str = "COEFFICIENTS"
    1203              :          END IF
    1204              : 
    1205         2539 :          IF (my_rtp) THEN
    1206            4 :             energy_str = "ZEROS"
    1207            4 :             vector_str = TRIM(reim)//" RTP COEFFICIENTS"
    1208              :          END IF
    1209              : 
    1210         2539 :          IF (print_eigvecs) THEN
    1211              : 
    1212         1741 :             IF (print_cartesian) THEN
    1213              : 
    1214           85 :                orbital_str = "CARTESIAN"
    1215              : 
    1216          340 :                ALLOCATE (cmatrix(ncgf, ncgf))
    1217        28495 :                cmatrix = 0.0_dp
    1218              : 
    1219              :                ! Transform spherical MOs to Cartesian MOs
    1220           85 :                icgf = 1
    1221           85 :                isgf = 1
    1222          271 :                DO iatom = 1, natom
    1223          186 :                   NULLIFY (orb_basis_set, dftb_parameter)
    1224          186 :                   CALL get_atomic_kind(particle_set(iatom)%atomic_kind, kind_number=ikind)
    1225              :                   CALL get_qs_kind(qs_kind_set(ikind), &
    1226              :                                    basis_set=orb_basis_set, &
    1227          186 :                                    dftb_parameter=dftb_parameter)
    1228          457 :                   IF (ASSOCIATED(orb_basis_set)) THEN
    1229              :                      CALL get_gto_basis_set(gto_basis_set=orb_basis_set, &
    1230              :                                             nset=nset, &
    1231              :                                             nshell=nshell, &
    1232          150 :                                             l=l)
    1233          466 :                      DO iset = 1, nset
    1234          944 :                         DO ishell = 1, nshell(iset)
    1235          478 :                            lshell = l(ishell, iset)
    1236              :                            CALL dgemm("T", "N", nco(lshell), nmo, nso(lshell), 1.0_dp, &
    1237              :                                       orbtramat(lshell)%c2s, nso(lshell), &
    1238              :                                       smatrix(isgf, 1), nsgf, 0.0_dp, &
    1239          478 :                                       cmatrix(icgf, 1), ncgf)
    1240          478 :                            icgf = icgf + nco(lshell)
    1241          794 :                            isgf = isgf + nso(lshell)
    1242              :                         END DO
    1243              :                      END DO
    1244           36 :                   ELSE IF (ASSOCIATED(dftb_parameter)) THEN
    1245           36 :                      CALL get_dftb_atom_param(dftb_parameter, lmax=lmax)
    1246           90 :                      DO ishell = 1, lmax + 1
    1247           54 :                         lshell = ishell - 1
    1248              :                         CALL dgemm("T", "N", nco(lshell), nsgf, nso(lshell), 1.0_dp, &
    1249              :                                    orbtramat(lshell)%c2s, nso(lshell), &
    1250              :                                    smatrix(isgf, 1), nsgf, 0.0_dp, &
    1251           54 :                                    cmatrix(icgf, 1), ncgf)
    1252           54 :                         icgf = icgf + nco(lshell)
    1253           90 :                         isgf = isgf + nso(lshell)
    1254              :                      END DO
    1255              :                   ELSE
    1256              :                      ! assume atom without basis set
    1257              :                      ! CPABORT("Unknown basis set type")
    1258              :                   END IF
    1259              :                END DO ! iatom
    1260              : 
    1261              :             ELSE
    1262              : 
    1263         1656 :                orbital_str = "SPHERICAL"
    1264              : 
    1265              :             END IF ! print_cartesian
    1266              : 
    1267              :             name = TRIM(energy_str)//", OCCUPATION NUMBERS, AND "// &
    1268         1741 :                    TRIM(orbital_str)//" "//TRIM(vector_str)
    1269              : 
    1270         1741 :             IF (.NOT. my_final) &
    1271         1397 :                WRITE (UNIT=name, FMT="(A,1X,I0)") TRIM(name)//step_string, scf_step
    1272              : 
    1273          798 :          ELSE IF (print_occup .OR. print_eigvals) THEN
    1274          798 :             name = TRIM(energy_str)//" AND OCCUPATION NUMBERS"
    1275              : 
    1276          798 :             IF (.NOT. my_final) &
    1277          575 :                WRITE (UNIT=name, FMT="(A,1X,I0)") TRIM(name)//step_string, scf_step
    1278              :          END IF ! print_eigvecs
    1279              : 
    1280              :          ! Print headline
    1281         2539 :          IF (PRESENT(spin) .AND. (kpoint > 0)) THEN
    1282              :             WRITE (UNIT=iw, FMT="(/,T2,A,I0)") &
    1283            0 :                "MO| "//TRIM(spin)//" "//TRIM(name)//" FOR K POINT ", kpoint
    1284              :          ELSE IF (PRESENT(spin)) THEN
    1285              :             WRITE (UNIT=iw, FMT="(/,T2,A)") &
    1286          312 :                "MO| "//TRIM(spin)//" "//TRIM(name)
    1287         2227 :          ELSE IF (kpoint > 0) THEN
    1288              :             WRITE (UNIT=iw, FMT="(/,T2,A,I0)") &
    1289          101 :                "MO| "//TRIM(name)//" FOR K POINT ", kpoint
    1290              :          ELSE
    1291              :             WRITE (UNIT=iw, FMT="(/,T2,A)") &
    1292         2126 :                "MO| "//TRIM(name)
    1293              :          END IF
    1294              : 
    1295              :          ! Check if only a subset of the MOs has to be printed
    1296              :          IF ((mo_index_range(1) > 0) .AND. &
    1297         2539 :              (mo_index_range(2) > 0) .AND. &
    1298              :              (mo_index_range(2) >= mo_index_range(1))) THEN
    1299          142 :             first_mo = MAX(1, mo_index_range(1))
    1300          142 :             last_mo = MIN(nmo, mo_index_range(2))
    1301          142 :             IF (first_mo > nmo) THEN
    1302            0 :                CPWARN("The first MO index is larger than the number of MOs.")
    1303              :             END IF
    1304              :          ELSE
    1305         2397 :             first_mo = 1
    1306         2397 :             last_mo = nmo
    1307              :          END IF
    1308              : 
    1309         2539 :          IF (print_eigvecs) THEN
    1310              : 
    1311              :             ! Print full MO information
    1312              : 
    1313         3928 :             DO icol = first_mo, last_mo, ncol
    1314              : 
    1315         2187 :                from = icol
    1316         2187 :                to = MIN((from + ncol - 1), last_mo)
    1317              : 
    1318         2187 :                WRITE (UNIT=iw, FMT="(T2,A)") "MO|"
    1319              :                WRITE (UNIT=iw, FMT=fmtstr1) &
    1320        10146 :                   "MO|", (jcol, jcol=from, to)
    1321              :                WRITE (UNIT=iw, FMT=fmtstr2) &
    1322         2187 :                   "MO|", (mo_eigenvalues(jcol), jcol=from, to)
    1323         2187 :                WRITE (UNIT=iw, FMT="(T2,A)") "MO|"
    1324              :                WRITE (UNIT=iw, FMT=fmtstr2) &
    1325         2187 :                   "MO|", (mo_occupation_numbers(jcol), jcol=from, to)
    1326         2187 :                WRITE (UNIT=iw, FMT="(T2,A)") "MO|"
    1327              : 
    1328         2187 :                irow = 1
    1329              : 
    1330         8639 :                DO iatom = 1, natom
    1331              : 
    1332         4711 :                   IF (iatom /= 1) WRITE (UNIT=iw, FMT="(T2,A)") "MO|"
    1333              : 
    1334         4711 :                   NULLIFY (orb_basis_set, dftb_parameter)
    1335              :                   CALL get_atomic_kind(particle_set(iatom)%atomic_kind, &
    1336         4711 :                                        element_symbol=element_symbol, kind_number=ikind)
    1337              :                   CALL get_qs_kind(qs_kind_set(ikind), &
    1338              :                                    basis_set=orb_basis_set, &
    1339         4711 :                                    dftb_parameter=dftb_parameter)
    1340              : 
    1341        11609 :                   IF (print_cartesian) THEN
    1342              : 
    1343          852 :                      IF (ASSOCIATED(orb_basis_set)) THEN
    1344              :                         CALL get_gto_basis_set(gto_basis_set=orb_basis_set, &
    1345              :                                                nset=nset, &
    1346              :                                                nshell=nshell, &
    1347              :                                                l=l, &
    1348          744 :                                                cgf_symbol=bcgf_symbol)
    1349              : 
    1350          744 :                         icgf = 1
    1351         2520 :                         DO iset = 1, nset
    1352         4944 :                            DO ishell = 1, nshell(iset)
    1353         2424 :                               lshell = l(ishell, iset)
    1354        10824 :                               DO ico = 1, nco(lshell)
    1355              :                                  WRITE (UNIT=iw, FMT=fmtstr3) &
    1356         6624 :                                     "MO|", irow, iatom, ADJUSTR(element_symbol), bcgf_symbol(icgf), &
    1357        13248 :                                     (cmatrix(irow, jcol), jcol=from, to)
    1358         6624 :                                  icgf = icgf + 1
    1359         9048 :                                  irow = irow + 1
    1360              :                               END DO
    1361              :                            END DO
    1362              :                         END DO
    1363          108 :                      ELSE IF (ASSOCIATED(dftb_parameter)) THEN
    1364          108 :                         CALL get_dftb_atom_param(dftb_parameter, lmax=lmax)
    1365          108 :                         icgf = 1
    1366          270 :                         DO ishell = 1, lmax + 1
    1367          162 :                            lshell = ishell - 1
    1368          540 :                            DO ico = 1, nco(lshell)
    1369          270 :                               symbol = cgf_symbol(1, indco(1:3, icgf))
    1370          270 :                               symbol(1:2) = "  "
    1371              :                               WRITE (UNIT=iw, FMT=fmtstr3) &
    1372          270 :                                  "MO|", irow, iatom, ADJUSTR(element_symbol), symbol, &
    1373          540 :                                  (cmatrix(irow, jcol), jcol=from, to)
    1374          270 :                               icgf = icgf + 1
    1375          432 :                               irow = irow + 1
    1376              :                            END DO
    1377              :                         END DO
    1378              :                      ELSE
    1379              :                         ! assume atom without basis set
    1380              :                         ! CPABORT("Unknown basis set type")
    1381              :                      END IF
    1382              : 
    1383              :                   ELSE
    1384              : 
    1385         3859 :                      IF (ASSOCIATED(orb_basis_set)) THEN
    1386              :                         CALL get_gto_basis_set(gto_basis_set=orb_basis_set, &
    1387              :                                                nset=nset, &
    1388              :                                                nshell=nshell, &
    1389              :                                                l=l, &
    1390         3859 :                                                sgf_symbol=bsgf_symbol)
    1391         3859 :                         isgf = 1
    1392        11027 :                         DO iset = 1, nset
    1393        20499 :                            DO ishell = 1, nshell(iset)
    1394         9472 :                               lshell = l(ishell, iset)
    1395        39040 :                               DO iso = 1, nso(lshell)
    1396              :                                  WRITE (UNIT=iw, FMT=fmtstr3) &
    1397        22400 :                                     "MO|", irow, iatom, ADJUSTR(element_symbol), bsgf_symbol(isgf), &
    1398        44800 :                                     (smatrix(irow, jcol), jcol=from, to)
    1399        22400 :                                  isgf = isgf + 1
    1400        31872 :                                  irow = irow + 1
    1401              :                               END DO
    1402              :                            END DO
    1403              :                         END DO
    1404            0 :                      ELSE IF (ASSOCIATED(dftb_parameter)) THEN
    1405            0 :                         CALL get_dftb_atom_param(dftb_parameter, lmax=lmax)
    1406            0 :                         isgf = 1
    1407            0 :                         DO ishell = 1, lmax + 1
    1408            0 :                            lshell = ishell - 1
    1409            0 :                            DO iso = 1, nso(lshell)
    1410            0 :                               symbol = sgf_symbol(1, lshell, -lshell + iso - 1)
    1411            0 :                               symbol(1:2) = "  "
    1412              :                               WRITE (UNIT=iw, FMT=fmtstr3) &
    1413            0 :                                  "MO|", irow, iatom, ADJUSTR(element_symbol), symbol, &
    1414            0 :                                  (smatrix(irow, jcol), jcol=from, to)
    1415            0 :                               isgf = isgf + 1
    1416            0 :                               irow = irow + 1
    1417              :                            END DO
    1418              :                         END DO
    1419              :                      ELSE
    1420              :                         ! assume atom without basis set
    1421              :                         ! CPABORT("Unknown basis set type")
    1422              :                      END IF
    1423              : 
    1424              :                   END IF ! print_cartesian
    1425              : 
    1426              :                END DO ! iatom
    1427              : 
    1428              :             END DO ! icol
    1429              : 
    1430         1741 :             WRITE (UNIT=iw, FMT="(T2,A)") "MO|"
    1431              : 
    1432              :             ! Release work storage
    1433              : 
    1434         1741 :             DEALLOCATE (smatrix)
    1435         1741 :             IF (print_cartesian) THEN
    1436           85 :                DEALLOCATE (cmatrix)
    1437              :             END IF
    1438              : 
    1439          798 :          ELSE IF (print_occup .OR. print_eigvals) THEN
    1440              : 
    1441          798 :             WRITE (UNIT=iw, FMT="(T2,A)") "MO|"
    1442          798 :             fmtstr4 = "(T2,A,I7,3(1X,F22.  ))"
    1443          798 :             WRITE (UNIT=fmtstr4(19:20), FMT="(I2)") after
    1444          798 :             IF (my_final .OR. (my_solver_method == "TD")) THEN
    1445              :                WRITE (UNIT=iw, FMT="(A)") &
    1446          798 :                   " MO|  Index      Eigenvalue [a.u.]        Eigenvalue [eV]             Occupation"
    1447              :             ELSE
    1448              :                WRITE (UNIT=iw, FMT="(A)") &
    1449            0 :                   " MO|  Index          Energy [a.u.]            Energy [eV]             Occupation"
    1450              :             END IF
    1451        11998 :             DO imo = first_mo, last_mo
    1452              :                WRITE (UNIT=iw, FMT=fmtstr4) &
    1453        11200 :                   "MO|", imo, mo_eigenvalues(imo), &
    1454        11200 :                   mo_eigenvalues(imo)*evolt, &
    1455        23198 :                   mo_occupation_numbers(imo)
    1456              :             END DO
    1457          798 :             fmtstr5 = "(A,T59,F22.  )"
    1458          798 :             WRITE (UNIT=fmtstr5(12:13), FMT="(I2)") after
    1459              :             WRITE (UNIT=iw, FMT=fmtstr5) &
    1460          798 :                " MO| Sum:", accurate_sum(mo_occupation_numbers(:))
    1461              : 
    1462              :          END IF ! print_eigvecs
    1463              : 
    1464         2539 :          IF (.NOT. my_rtp) THEN
    1465         2535 :             fmtstr6 = "(A,T18,F17.  ,A,T41,F17.  ,A)"
    1466         2535 :             WRITE (UNIT=fmtstr6(12:13), FMT="(I2)") after
    1467         2535 :             WRITE (UNIT=fmtstr6(25:26), FMT="(I2)") after
    1468              :             WRITE (UNIT=iw, FMT=fmtstr6) &
    1469         2535 :                " MO| E(Fermi):", mo_set%mu, " a.u.", mo_set%mu*evolt, " eV"
    1470              :          END IF
    1471         2539 :          IF ((homo > 0) .AND. .NOT. my_rtp) THEN
    1472         2510 :             IF ((mo_occupation_numbers(homo) == maxocc) .AND. (last_mo > homo)) THEN
    1473              :                gap = mo_eigenvalues(homo + 1) - &
    1474          351 :                      mo_eigenvalues(homo)
    1475              :                WRITE (UNIT=iw, FMT=fmtstr6) &
    1476          351 :                   " MO| Band gap:", gap, " a.u.", gap*evolt, " eV"
    1477              :             END IF
    1478              :          END IF
    1479         2539 :          WRITE (UNIT=iw, FMT="(A)") ""
    1480              : 
    1481              :       END IF ! iw
    1482              : 
    1483         5078 :       IF (ALLOCATED(mo_eigenvalues)) DEALLOCATE (mo_eigenvalues)
    1484         5078 :       IF (ALLOCATED(mo_occupation_numbers)) DEALLOCATE (mo_occupation_numbers)
    1485              : 
    1486              :       CALL cp_print_key_finished_output(iw, logger, dft_section, "PRINT%MO", &
    1487         5078 :                                         ignore_should_output=should_output)
    1488              : 
    1489        23081 :    END SUBROUTINE write_mo_set_to_output_unit
    1490              : 
    1491              : END MODULE qs_mo_io
        

Generated by: LCOV version 2.0-1