LCOV - code coverage report
Current view: top level - src/emd - rt_propagation_utils.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:936074a) Lines: 95.6 % 384 367
Test Date: 2025-12-04 06:27:48 Functions: 100.0 % 11 11

            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 Routines needed for EMD
      10              : !> \author Florian Schiffmann (02.09)
      11              : ! **************************************************************************************************
      12              : 
      13              : MODULE rt_propagation_utils
      14              :    USE atomic_kind_types,               ONLY: atomic_kind_type
      15              :    USE cell_types,                      ONLY: cell_type
      16              :    USE cp_blacs_env,                    ONLY: cp_blacs_env_type
      17              :    USE cp_control_types,                ONLY: dft_control_type,&
      18              :                                               rtp_control_type
      19              :    USE cp_dbcsr_api,                    ONLY: &
      20              :         dbcsr_add, dbcsr_binary_read, dbcsr_copy, dbcsr_create, dbcsr_deallocate_matrix, &
      21              :         dbcsr_desymmetrize, dbcsr_distribution_type, dbcsr_filter, dbcsr_get_info, &
      22              :         dbcsr_iterator_blocks_left, dbcsr_iterator_next_block, dbcsr_iterator_start, &
      23              :         dbcsr_iterator_stop, dbcsr_iterator_type, dbcsr_p_type, dbcsr_scale, dbcsr_set, dbcsr_type
      24              :    USE cp_dbcsr_contrib,                ONLY: dbcsr_checksum
      25              :    USE cp_dbcsr_operations,             ONLY: cp_dbcsr_plus_fm_fm_t,&
      26              :                                               dbcsr_deallocate_matrix_set
      27              :    USE cp_files,                        ONLY: close_file,&
      28              :                                               file_exists,&
      29              :                                               open_file
      30              :    USE cp_fm_basic_linalg,              ONLY: cp_fm_column_scale
      31              :    USE cp_fm_types,                     ONLY: cp_fm_create,&
      32              :                                               cp_fm_get_info,&
      33              :                                               cp_fm_release,&
      34              :                                               cp_fm_set_all,&
      35              :                                               cp_fm_to_fm,&
      36              :                                               cp_fm_type
      37              :    USE cp_log_handling,                 ONLY: cp_get_default_logger,&
      38              :                                               cp_logger_get_default_io_unit,&
      39              :                                               cp_logger_get_default_unit_nr,&
      40              :                                               cp_logger_type
      41              :    USE cp_output_handling,              ONLY: cp_p_file,&
      42              :                                               cp_print_key_finished_output,&
      43              :                                               cp_print_key_generate_filename,&
      44              :                                               cp_print_key_should_output,&
      45              :                                               cp_print_key_unit_nr
      46              :    USE cp_realspace_grid_cube,          ONLY: cp_pw_to_cube
      47              :    USE efield_utils,                    ONLY: make_field
      48              :    USE input_constants,                 ONLY: use_restart_wfn,&
      49              :                                               use_rt_restart
      50              :    USE input_section_types,             ONLY: section_get_ival,&
      51              :                                               section_get_ivals,&
      52              :                                               section_get_lval,&
      53              :                                               section_vals_get,&
      54              :                                               section_vals_get_subs_vals,&
      55              :                                               section_vals_type,&
      56              :                                               section_vals_val_get
      57              :    USE kinds,                           ONLY: default_path_length,&
      58              :                                               default_string_length,&
      59              :                                               dp
      60              :    USE mathconstants,                   ONLY: zero
      61              :    USE memory_utilities,                ONLY: reallocate
      62              :    USE message_passing,                 ONLY: mp_para_env_type
      63              :    USE orbital_pointers,                ONLY: ncoset
      64              :    USE particle_list_types,             ONLY: particle_list_type
      65              :    USE particle_types,                  ONLY: particle_type
      66              :    USE physcon,                         ONLY: femtoseconds
      67              :    USE pw_env_types,                    ONLY: pw_env_get,&
      68              :                                               pw_env_type
      69              :    USE pw_methods,                      ONLY: pw_multiply,&
      70              :                                               pw_zero
      71              :    USE pw_pool_types,                   ONLY: pw_pool_p_type,&
      72              :                                               pw_pool_type
      73              :    USE pw_types,                        ONLY: pw_c1d_gs_type,&
      74              :                                               pw_r3d_rs_type
      75              :    USE qs_collocate_density,            ONLY: calculate_wavefunction
      76              :    USE qs_density_matrices,             ONLY: calculate_density_matrix
      77              :    USE qs_dftb_matrices,                ONLY: build_dftb_overlap
      78              :    USE qs_environment_types,            ONLY: get_qs_env,&
      79              :                                               qs_environment_type
      80              :    USE qs_kind_types,                   ONLY: qs_kind_type
      81              :    USE qs_ks_types,                     ONLY: qs_ks_did_change,&
      82              :                                               qs_ks_env_type
      83              :    USE qs_mo_io,                        ONLY: read_mo_set_from_restart,&
      84              :                                               read_rt_mos_from_restart,&
      85              :                                               write_mo_set_to_output_unit
      86              :    USE qs_mo_types,                     ONLY: allocate_mo_set,&
      87              :                                               deallocate_mo_set,&
      88              :                                               get_mo_set,&
      89              :                                               init_mo_set,&
      90              :                                               mo_set_type
      91              :    USE qs_neighbor_list_types,          ONLY: neighbor_list_set_p_type
      92              :    USE qs_overlap,                      ONLY: build_overlap_matrix
      93              :    USE qs_rho_methods,                  ONLY: qs_rho_update_rho
      94              :    USE qs_rho_types,                    ONLY: qs_rho_get,&
      95              :                                               qs_rho_set,&
      96              :                                               qs_rho_type
      97              :    USE qs_scf_wfn_mix,                  ONLY: wfn_mix
      98              :    USE qs_subsys_types,                 ONLY: qs_subsys_get,&
      99              :                                               qs_subsys_type
     100              :    USE rt_propagation_types,            ONLY: get_rtp,&
     101              :                                               rt_prop_type
     102              : #include "../base/base_uses.f90"
     103              : 
     104              :    IMPLICIT NONE
     105              :    PRIVATE
     106              : 
     107              :    PUBLIC :: get_restart_wfn, &
     108              :              calc_S_derivs, &
     109              :              calc_update_rho, &
     110              :              calc_update_rho_sparse, &
     111              :              calculate_P_imaginary, &
     112              :              write_rtp_mos_to_output_unit, &
     113              :              write_rtp_mo_cubes, &
     114              :              warn_section_unused, &
     115              :              read_moments, &
     116              :              recalculate_fields
     117              : 
     118              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'rt_propagation_utils'
     119              : 
     120              : CONTAINS
     121              : 
     122              : ! **************************************************************************************************
     123              : !> \brief Calculates dS/dR respectily the velocity weighted derivatves
     124              : !>        only needed for ehrenfest MD.
     125              : !>
     126              : !> \param qs_env the qs environment
     127              : !> \par History
     128              : !>      02.2009 created [Manuel Guidon]
     129              : !>      02.2014 switched to dbcsr matrices [Samuel Andermatt]
     130              : !> \author Florian Schiffmann
     131              : ! **************************************************************************************************
     132         1216 :    SUBROUTINE calc_S_derivs(qs_env)
     133              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     134              : 
     135              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'calc_S_derivs'
     136              :       REAL(KIND=dp), PARAMETER                           :: one = 1.0_dp, zero = 0.0_dp
     137              : 
     138              :       INTEGER                                            :: col_atom, handle, i, j, m, maxder, n, &
     139              :                                                             nder, row_atom
     140              :       INTEGER, DIMENSION(6, 2)                           :: c_map_mat
     141              :       LOGICAL                                            :: return_s_derivatives
     142         1216 :       REAL(dp), DIMENSION(:, :), POINTER                 :: block_values
     143              :       TYPE(dbcsr_iterator_type)                          :: iter
     144         1216 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: C_mat, S_der, s_derivs
     145              :       TYPE(dbcsr_type), POINTER                          :: B_mat, tmp_mat, tmp_mat2
     146              :       TYPE(dft_control_type), POINTER                    :: dft_control
     147              :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
     148         1216 :          POINTER                                         :: sab_orb
     149         1216 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     150              :       TYPE(qs_ks_env_type), POINTER                      :: ks_env
     151              :       TYPE(rt_prop_type), POINTER                        :: rtp
     152              : 
     153         1216 :       CALL timeset(routineN, handle)
     154              : 
     155         1216 :       return_s_derivatives = .TRUE.
     156              : 
     157         1216 :       NULLIFY (particle_set)
     158         1216 :       NULLIFY (rtp)
     159         1216 :       NULLIFY (s_derivs)
     160         1216 :       NULLIFY (dft_control)
     161         1216 :       NULLIFY (ks_env)
     162              : 
     163              :       CALL get_qs_env(qs_env=qs_env, &
     164              :                       rtp=rtp, &
     165              :                       particle_set=particle_set, &
     166              :                       sab_orb=sab_orb, &
     167              :                       dft_control=dft_control, &
     168         1216 :                       ks_env=ks_env)
     169              : 
     170         1216 :       CALL get_rtp(rtp=rtp, B_mat=B_mat, C_mat=C_mat, S_der=S_der)
     171              : 
     172         1216 :       nder = 2
     173         1216 :       maxder = ncoset(nder)
     174              : 
     175              :       NULLIFY (tmp_mat)
     176         1216 :       ALLOCATE (tmp_mat)
     177         1216 :       CALL dbcsr_create(tmp_mat, template=S_der(1)%matrix, matrix_type="N")
     178              : 
     179         1216 :       IF (rtp%iter < 2) THEN
     180              :          ! calculate the overlap derivative matrices
     181          342 :          IF (dft_control%qs_control%dftb) THEN
     182           84 :             CALL build_dftb_overlap(qs_env, nder, s_derivs)
     183              :          ELSE
     184              :             CALL build_overlap_matrix(ks_env, nderivative=nder, matrix_s=s_derivs, &
     185          258 :                                       basis_type_a="ORB", basis_type_b="ORB", sab_nl=sab_orb)
     186              :          END IF
     187              : 
     188              :          NULLIFY (tmp_mat2)
     189          342 :          ALLOCATE (tmp_mat2)
     190          342 :          CALL dbcsr_create(tmp_mat2, template=S_der(1)%matrix, matrix_type="S")
     191         3420 :          DO m = 1, 9
     192         3078 :             CALL dbcsr_copy(tmp_mat2, s_derivs(m + 1)%matrix)
     193         3078 :             CALL dbcsr_desymmetrize(tmp_mat2, S_der(m)%matrix)
     194         3078 :             CALL dbcsr_scale(S_der(m)%matrix, -one)
     195         3078 :             CALL dbcsr_filter(S_der(m)%matrix, rtp%filter_eps)
     196              :             !The diagonal should be zero
     197         3078 :             CALL dbcsr_iterator_start(iter, S_der(m)%matrix)
     198        15038 :             DO WHILE (dbcsr_iterator_blocks_left(iter))
     199        11960 :                CALL dbcsr_iterator_next_block(iter, row_atom, col_atom, block_values)
     200       187460 :                IF (row_atom == col_atom) block_values = 0.0_dp
     201              :             END DO
     202         6498 :             CALL dbcsr_iterator_stop(iter)
     203              :          END DO
     204          342 :          CALL dbcsr_deallocate_matrix_set(s_derivs)
     205          342 :          CALL dbcsr_deallocate_matrix(tmp_mat2)
     206              :       END IF
     207              : 
     208              :       !calculate scalar product v(Rb)*<alpha|d/dRb beta> (B_mat), and store the first derivatives
     209              : 
     210         1216 :       CALL dbcsr_set(B_mat, zero)
     211         4864 :       DO m = 1, 3
     212         3648 :          CALL dbcsr_copy(tmp_mat, S_der(m)%matrix)
     213         3648 :          CALL dbcsr_iterator_start(iter, tmp_mat)
     214        18733 :          DO WHILE (dbcsr_iterator_blocks_left(iter))
     215        15085 :             CALL dbcsr_iterator_next_block(iter, row_atom, col_atom, block_values)
     216       219025 :             IF (row_atom == col_atom) block_values = 0.0_dp
     217       458487 :             block_values = block_values*particle_set(col_atom)%v(m)
     218              :          END DO
     219         3648 :          CALL dbcsr_iterator_stop(iter)
     220         8512 :          CALL dbcsr_add(B_mat, tmp_mat, one, one)
     221              :       END DO
     222         1216 :       CALL dbcsr_filter(B_mat, rtp%filter_eps)
     223              :       !calculate C matrix: v(Rb)*<d/dRa alpha| d/dRb beta>
     224              : 
     225         1216 :       c_map_mat = 0
     226         1216 :       n = 0
     227         4864 :       DO j = 1, 3
     228        12160 :          DO m = j, 3
     229         7296 :             n = n + 1
     230         7296 :             c_map_mat(n, 1) = j
     231         7296 :             IF (m == j) CYCLE
     232        10944 :             c_map_mat(n, 2) = m
     233              :          END DO
     234              :       END DO
     235              : 
     236         4864 :       DO i = 1, 3
     237         4864 :          CALL dbcsr_set(C_mat(i)%matrix, zero)
     238              :       END DO
     239         8512 :       DO m = 1, 6
     240         7296 :          CALL dbcsr_copy(tmp_mat, S_der(m + 3)%matrix)
     241        23104 :          DO j = 1, 2
     242        14592 :             IF (c_map_mat(m, j) == 0) CYCLE
     243        21888 :             CALL dbcsr_add(C_mat(c_map_mat(m, j))%matrix, tmp_mat, one, one)
     244              :          END DO
     245              :       END DO
     246              : 
     247         4864 :       DO m = 1, 3
     248         3648 :          CALL dbcsr_iterator_start(iter, C_mat(m)%matrix)
     249        17683 :          DO WHILE (dbcsr_iterator_blocks_left(iter))
     250        14035 :             CALL dbcsr_iterator_next_block(iter, row_atom, col_atom, block_values)
     251       451536 :             block_values = block_values*particle_set(row_atom)%v(m)
     252              :          END DO
     253         3648 :          CALL dbcsr_iterator_stop(iter)
     254         8512 :          CALL dbcsr_filter(C_mat(m)%matrix, rtp%filter_eps)
     255              :       END DO
     256              : 
     257         1216 :       CALL dbcsr_deallocate_matrix(tmp_mat)
     258         1216 :       CALL timestop(handle)
     259         1216 :    END SUBROUTINE calc_S_derivs
     260              : 
     261              : ! **************************************************************************************************
     262              : !> \brief reads the restart file. At the moment only SCF (means only real)
     263              : !> \param qs_env ...
     264              : !> \author Florian Schiffmann (02.09)
     265              : ! **************************************************************************************************
     266              : 
     267           36 :    SUBROUTINE get_restart_wfn(qs_env)
     268              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     269              : 
     270              :       CHARACTER(LEN=default_path_length)                 :: file_name, project_name
     271              :       INTEGER                                            :: i, id_nr, im, ispin, ncol, nspin, &
     272              :                                                             output_unit, re, unit_nr
     273              :       REAL(KIND=dp)                                      :: alpha, cs_pos
     274           36 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
     275              :       TYPE(cp_fm_type)                                   :: mos_occ
     276           36 :       TYPE(cp_fm_type), DIMENSION(:), POINTER            :: mos_old
     277              :       TYPE(cp_logger_type), POINTER                      :: logger
     278              :       TYPE(dbcsr_distribution_type)                      :: dist
     279           36 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: p_rmpv, rho_new, rho_old
     280              :       TYPE(dft_control_type), POINTER                    :: dft_control
     281           36 :       TYPE(mo_set_type), DIMENSION(:), POINTER           :: mo_array
     282              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     283           36 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     284           36 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
     285              :       TYPE(qs_rho_type), POINTER                         :: rho_struct
     286              :       TYPE(rt_prop_type), POINTER                        :: rtp
     287              :       TYPE(section_vals_type), POINTER                   :: dft_section, input
     288              : 
     289           36 :       NULLIFY (atomic_kind_set, qs_kind_set, mo_array, particle_set, rho_struct, para_env)
     290              : 
     291              :       CALL get_qs_env(qs_env, &
     292              :                       qs_kind_set=qs_kind_set, &
     293              :                       atomic_kind_set=atomic_kind_set, &
     294              :                       particle_set=particle_set, &
     295              :                       mos=mo_array, &
     296              :                       input=input, &
     297              :                       rtp=rtp, &
     298              :                       dft_control=dft_control, &
     299              :                       rho=rho_struct, &
     300           36 :                       para_env=para_env)
     301           36 :       logger => cp_get_default_logger()
     302           36 :       output_unit = cp_logger_get_default_io_unit(logger)
     303              : 
     304           36 :       IF (logger%para_env%is_source()) THEN
     305           18 :          unit_nr = cp_logger_get_default_unit_nr(logger, local=.TRUE.)
     306              :       ELSE
     307              :          unit_nr = -1
     308              :       END IF
     309              : 
     310           36 :       id_nr = 0
     311           36 :       nspin = SIZE(mo_array)
     312           36 :       CALL qs_rho_get(rho_struct, rho_ao=p_rmpv)
     313           36 :       dft_section => section_vals_get_subs_vals(input, "DFT")
     314           62 :       SELECT CASE (dft_control%rtp_control%initial_wfn)
     315              :       CASE (use_restart_wfn)
     316              :          CALL read_mo_set_from_restart(mo_array, qs_kind_set, particle_set, para_env, &
     317              :                                        id_nr=id_nr, multiplicity=dft_control%multiplicity, &
     318           26 :                                        dft_section=dft_section)
     319           26 :          CALL set_uniform_occupation_mo_array(mo_array, nspin)
     320              : 
     321           26 :          IF (dft_control%rtp_control%apply_wfn_mix_init_restart) &
     322              :             CALL wfn_mix(mo_array, particle_set, dft_section, qs_kind_set, para_env, output_unit, &
     323            4 :                          for_rtp=.TRUE.)
     324              : 
     325           70 :          DO ispin = 1, nspin
     326           70 :             CALL calculate_density_matrix(mo_array(ispin), p_rmpv(ispin)%matrix)
     327              :          END DO
     328           26 :          IF (rtp%linear_scaling) THEN
     329           14 :             CALL get_rtp(rtp=rtp, rho_old=rho_old, rho_new=rho_new)
     330           34 :             DO ispin = 1, nspin
     331           20 :                re = 2*ispin - 1
     332           20 :                im = 2*ispin
     333           20 :                CALL cp_fm_get_info(mo_array(ispin)%mo_coeff, ncol_global=ncol)
     334              :                CALL cp_fm_create(mos_occ, &
     335              :                                  matrix_struct=mo_array(ispin)%mo_coeff%matrix_struct, &
     336           20 :                                  name="mos_occ")
     337           20 :                CALL cp_fm_to_fm(mo_array(ispin)%mo_coeff, mos_occ)
     338           20 :                IF (mo_array(ispin)%uniform_occupation) THEN
     339           16 :                   alpha = 3.0_dp - REAL(nspin, dp)
     340           78 :                   CALL cp_fm_column_scale(mos_occ, mo_array(ispin)%occupation_numbers/alpha)
     341              :                   CALL cp_dbcsr_plus_fm_fm_t(sparse_matrix=rho_old(re)%matrix, &
     342              :                                              matrix_v=mos_occ, &
     343              :                                              ncol=ncol, &
     344           16 :                                              alpha=alpha, keep_sparsity=.FALSE.)
     345              :                ELSE
     346            4 :                   alpha = 1.0_dp
     347           88 :                   CALL cp_fm_column_scale(mos_occ, mo_array(ispin)%occupation_numbers/alpha)
     348              :                   CALL cp_dbcsr_plus_fm_fm_t(sparse_matrix=rho_old(re)%matrix, &
     349              :                                              matrix_v=mo_array(ispin)%mo_coeff, &
     350              :                                              matrix_g=mos_occ, &
     351              :                                              ncol=ncol, &
     352            4 :                                              alpha=alpha, keep_sparsity=.FALSE.)
     353              :                END IF
     354           20 :                CALL dbcsr_filter(rho_old(re)%matrix, rtp%filter_eps)
     355           20 :                CALL dbcsr_copy(rho_new(re)%matrix, rho_old(re)%matrix)
     356           54 :                CALL cp_fm_release(mos_occ)
     357              :             END DO
     358           14 :             CALL calc_update_rho_sparse(qs_env)
     359              :          ELSE
     360           12 :             CALL get_rtp(rtp=rtp, mos_old=mos_old)
     361           36 :             DO i = 1, SIZE(qs_env%mos)
     362           24 :                CALL cp_fm_to_fm(mo_array(i)%mo_coeff, mos_old(2*i - 1))
     363           36 :                CALL cp_fm_set_all(mos_old(2*i), zero, zero)
     364              :             END DO
     365              :          END IF
     366              :       CASE (use_rt_restart)
     367           36 :          IF (rtp%linear_scaling) THEN
     368            2 :             CALL get_rtp(rtp=rtp, rho_old=rho_old, rho_new=rho_new)
     369            2 :             project_name = logger%iter_info%project_name
     370            4 :             DO ispin = 1, nspin
     371            2 :                re = 2*ispin - 1
     372            2 :                im = 2*ispin
     373            2 :                WRITE (file_name, '(A,I0,A)') TRIM(project_name)//"_LS_DM_SPIN_RE", ispin, "_RESTART.dm"
     374            2 :                CALL dbcsr_get_info(rho_old(re)%matrix, distribution=dist)
     375            2 :                CALL dbcsr_binary_read(file_name, distribution=dist, matrix_new=rho_old(re)%matrix)
     376            2 :                cs_pos = dbcsr_checksum(rho_old(re)%matrix, pos=.TRUE.)
     377            2 :                IF (unit_nr > 0) THEN
     378            1 :                   WRITE (unit_nr, '(T2,A,E20.8)') "Read restart DM "//TRIM(file_name)//" with checksum: ", cs_pos
     379              :                END IF
     380            2 :                WRITE (file_name, '(A,I0,A)') TRIM(project_name)//"_LS_DM_SPIN_IM", ispin, "_RESTART.dm"
     381            2 :                CALL dbcsr_get_info(rho_old(im)%matrix, distribution=dist)
     382            2 :                CALL dbcsr_binary_read(file_name, distribution=dist, matrix_new=rho_old(im)%matrix)
     383            2 :                cs_pos = dbcsr_checksum(rho_old(im)%matrix, pos=.TRUE.)
     384            8 :                IF (unit_nr > 0) THEN
     385            1 :                   WRITE (unit_nr, '(T2,A,E20.8)') "Read restart DM "//TRIM(file_name)//" with checksum: ", cs_pos
     386              :                END IF
     387              :             END DO
     388            6 :             DO i = 1, SIZE(rho_new)
     389            6 :                CALL dbcsr_copy(rho_new(i)%matrix, rho_old(i)%matrix)
     390              :             END DO
     391            2 :             CALL calc_update_rho_sparse(qs_env)
     392              :          ELSE
     393            8 :             CALL get_rtp(rtp=rtp, mos_old=mos_old)
     394              :             CALL read_rt_mos_from_restart(mo_array, mos_old, qs_kind_set, particle_set, para_env, &
     395            8 :                                           id_nr, dft_control%multiplicity, dft_section)
     396            8 :             CALL set_uniform_occupation_mo_array(mo_array, nspin)
     397           16 :             DO ispin = 1, nspin
     398              :                CALL calculate_density_matrix(mo_array(ispin), &
     399           16 :                                              p_rmpv(ispin)%matrix)
     400              :             END DO
     401              :          END IF
     402              :       END SELECT
     403              : 
     404           36 :    END SUBROUTINE get_restart_wfn
     405              : 
     406              : ! **************************************************************************************************
     407              : !> \brief Set mo_array(ispin)%uniform_occupation after a restart
     408              : !> \param mo_array ...
     409              : !> \param nspin ...
     410              : !> \author Guillaume Le Breton (03.23)
     411              : ! **************************************************************************************************
     412              : 
     413           34 :    SUBROUTINE set_uniform_occupation_mo_array(mo_array, nspin)
     414              : 
     415              :       TYPE(mo_set_type), DIMENSION(:), POINTER           :: mo_array
     416              :       INTEGER                                            :: nspin
     417              : 
     418              :       INTEGER                                            :: ispin, mo
     419              :       LOGICAL                                            :: is_uniform
     420              : 
     421           86 :       DO ispin = 1, nspin
     422           52 :          is_uniform = .TRUE.
     423          274 :          DO mo = 1, mo_array(ispin)%nmo
     424              :             IF (mo_array(ispin)%occupation_numbers(mo) /= 0.0 .AND. &
     425          222 :                 mo_array(ispin)%occupation_numbers(mo) /= 1.0 .AND. &
     426              :                 mo_array(ispin)%occupation_numbers(mo) /= 2.0) &
     427          100 :                is_uniform = .FALSE.
     428              :          END DO
     429           86 :          mo_array(ispin)%uniform_occupation = is_uniform
     430              :       END DO
     431              : 
     432           34 :    END SUBROUTINE set_uniform_occupation_mo_array
     433              : 
     434              : ! **************************************************************************************************
     435              : !> \brief calculates the density from the complex MOs and passes the density to
     436              : !>        qs_env.
     437              : !> \param qs_env ...
     438              : !> \author Florian Schiffmann (02.09)
     439              : ! **************************************************************************************************
     440              : 
     441         2018 :    SUBROUTINE calc_update_rho(qs_env)
     442              : 
     443              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     444              : 
     445              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'calc_update_rho'
     446              :       REAL(KIND=dp), PARAMETER                           :: one = 1.0_dp, zero = 0.0_dp
     447              : 
     448              :       INTEGER                                            :: handle, i, im, ncol, re
     449              :       REAL(KIND=dp)                                      :: alpha
     450              :       TYPE(cp_fm_type)                                   :: mos_occ
     451         2018 :       TYPE(cp_fm_type), DIMENSION(:), POINTER            :: mos_new
     452         2018 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: rho_ao, rho_ao_im
     453         2018 :       TYPE(mo_set_type), DIMENSION(:), POINTER           :: mos
     454              :       TYPE(qs_ks_env_type), POINTER                      :: ks_env
     455              :       TYPE(qs_rho_type), POINTER                         :: rho
     456              :       TYPE(rt_prop_type), POINTER                        :: rtp
     457              : 
     458         2018 :       CALL timeset(routineN, handle)
     459              : 
     460         2018 :       NULLIFY (rho, ks_env, mos_new, rtp)
     461              :       CALL get_qs_env(qs_env, &
     462              :                       ks_env=ks_env, &
     463              :                       rho=rho, &
     464              :                       rtp=rtp, &
     465         2018 :                       mos=mos)
     466         2018 :       CALL get_rtp(rtp=rtp, mos_new=mos_new)
     467         2018 :       CALL qs_rho_get(rho_struct=rho, rho_ao=rho_ao)
     468         4580 :       DO i = 1, SIZE(mos_new)/2
     469         2562 :          re = 2*i - 1; im = 2*i
     470         2562 :          CALL dbcsr_set(rho_ao(i)%matrix, zero)
     471         2562 :          CALL cp_fm_get_info(mos_new(re), ncol_global=ncol)
     472              :          CALL cp_fm_create(mos_occ, &
     473              :                            matrix_struct=mos(i)%mo_coeff%matrix_struct, &
     474         2562 :                            name="mos_occ")
     475         2562 :          CALL cp_fm_to_fm(mos_new(re), mos_occ)
     476         2562 :          IF (mos(i)%uniform_occupation) THEN
     477         2462 :             alpha = 3*one - REAL(SIZE(mos_new)/2, dp)
     478        10286 :             CALL cp_fm_column_scale(mos_occ, mos(i)%occupation_numbers/alpha)
     479              :             CALL cp_dbcsr_plus_fm_fm_t(sparse_matrix=rho_ao(i)%matrix, &
     480              :                                        matrix_v=mos_occ, &
     481              :                                        ncol=ncol, &
     482         2462 :                                        alpha=alpha)
     483              :          ELSE
     484          100 :             alpha = 1.0_dp
     485          660 :             CALL cp_fm_column_scale(mos_occ, mos(i)%occupation_numbers/alpha)
     486              :             CALL cp_dbcsr_plus_fm_fm_t(sparse_matrix=rho_ao(i)%matrix, &
     487              :                                        matrix_v=mos_new(re), &
     488              :                                        matrix_g=mos_occ, &
     489              :                                        ncol=ncol, &
     490          100 :                                        alpha=alpha)
     491              :          END IF
     492              : 
     493              :          ! It is actually complex conjugate but i*i=-1 therefore it must be added
     494         2562 :          CALL cp_fm_to_fm(mos_new(im), mos_occ)
     495         2562 :          IF (mos(i)%uniform_occupation) THEN
     496         2462 :             alpha = 3*one - REAL(SIZE(mos_new)/2, dp)
     497        10286 :             CALL cp_fm_column_scale(mos_occ, mos(i)%occupation_numbers/alpha)
     498              :             CALL cp_dbcsr_plus_fm_fm_t(sparse_matrix=rho_ao(i)%matrix, &
     499              :                                        matrix_v=mos_occ, &
     500              :                                        ncol=ncol, &
     501         2462 :                                        alpha=alpha)
     502              :          ELSE
     503          100 :             alpha = 1.0_dp
     504          660 :             CALL cp_fm_column_scale(mos_occ, mos(i)%occupation_numbers/alpha)
     505              :             CALL cp_dbcsr_plus_fm_fm_t(sparse_matrix=rho_ao(i)%matrix, &
     506              :                                        matrix_v=mos_new(im), &
     507              :                                        matrix_g=mos_occ, &
     508              :                                        ncol=ncol, &
     509          100 :                                        alpha=alpha)
     510              :          END IF
     511         7142 :          CALL cp_fm_release(mos_occ)
     512              :       END DO
     513         2018 :       CALL qs_rho_update_rho(rho, qs_env)
     514              : 
     515         2018 :       IF (rtp%track_imag_density) THEN
     516         1358 :          CALL qs_rho_get(rho_struct=rho, rho_ao_im=rho_ao_im)
     517         1358 :          CALL calculate_P_imaginary(qs_env, rtp, rho_ao_im, keep_sparsity=.TRUE.)
     518         1358 :          CALL qs_rho_set(rho, rho_ao_im=rho_ao_im)
     519              :       END IF
     520              : 
     521         2018 :       CALL qs_ks_did_change(ks_env, rho_changed=.TRUE.)
     522              : 
     523         2018 :       CALL timestop(handle)
     524              : 
     525         2018 :    END SUBROUTINE calc_update_rho
     526              : 
     527              : ! **************************************************************************************************
     528              : !> \brief Copies the density matrix back into the qs_env%rho%rho_ao
     529              : !> \param qs_env ...
     530              : !> \author Samuel Andermatt (3.14)
     531              : ! **************************************************************************************************
     532              : 
     533         1254 :    SUBROUTINE calc_update_rho_sparse(qs_env)
     534              : 
     535              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     536              : 
     537              :       CHARACTER(len=*), PARAMETER :: routineN = 'calc_update_rho_sparse'
     538              :       REAL(KIND=dp), PARAMETER                           :: zero = 0.0_dp
     539              : 
     540              :       INTEGER                                            :: handle, ispin
     541         1254 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: rho_ao, rho_ao_im, rho_new
     542              :       TYPE(dft_control_type), POINTER                    :: dft_control
     543              :       TYPE(qs_ks_env_type), POINTER                      :: ks_env
     544              :       TYPE(qs_rho_type), POINTER                         :: rho
     545              :       TYPE(rt_prop_type), POINTER                        :: rtp
     546              :       TYPE(rtp_control_type), POINTER                    :: rtp_control
     547              : 
     548         1254 :       NULLIFY (rho, ks_env, rtp, dft_control)
     549         1254 :       CALL timeset(routineN, handle)
     550              :       CALL get_qs_env(qs_env, &
     551              :                       ks_env=ks_env, &
     552              :                       rho=rho, &
     553              :                       rtp=rtp, &
     554         1254 :                       dft_control=dft_control)
     555         1254 :       rtp_control => dft_control%rtp_control
     556         1254 :       CALL get_rtp(rtp=rtp, rho_new=rho_new)
     557         1254 :       CALL qs_rho_get(rho_struct=rho, rho_ao=rho_ao)
     558         1254 :       IF (rtp%track_imag_density) CALL qs_rho_get(rho_struct=rho, rho_ao_im=rho_ao_im)
     559         2926 :       DO ispin = 1, SIZE(rho_ao)
     560         1672 :          CALL dbcsr_set(rho_ao(ispin)%matrix, zero)
     561         1672 :          CALL dbcsr_copy(rho_ao(ispin)%matrix, rho_new(ispin*2 - 1)%matrix, keep_sparsity=.TRUE.)
     562         2926 :          IF (rtp%track_imag_density) THEN
     563          482 :             CALL dbcsr_copy(rho_ao_im(ispin)%matrix, rho_new(ispin*2)%matrix, keep_sparsity=.TRUE.)
     564              :          END IF
     565              :       END DO
     566              : 
     567         1254 :       CALL qs_rho_update_rho(rho, qs_env)
     568         1254 :       CALL qs_ks_did_change(ks_env, rho_changed=.TRUE.)
     569              : 
     570         1254 :       CALL timestop(handle)
     571              : 
     572         1254 :    END SUBROUTINE calc_update_rho_sparse
     573              : 
     574              : ! **************************************************************************************************
     575              : !> \brief ...
     576              : !> \param qs_env ...
     577              : !> \param rtp ...
     578              : !> \param matrix_p_im ...
     579              : !> \param keep_sparsity ...
     580              : ! **************************************************************************************************
     581         1358 :    SUBROUTINE calculate_P_imaginary(qs_env, rtp, matrix_p_im, keep_sparsity)
     582              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     583              :       TYPE(rt_prop_type), POINTER                        :: rtp
     584              :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_p_im
     585              :       LOGICAL, OPTIONAL                                  :: keep_sparsity
     586              : 
     587              :       INTEGER                                            :: i, im, ncol, re
     588              :       LOGICAL                                            :: my_keep_sparsity
     589              :       REAL(KIND=dp)                                      :: alpha
     590         1358 :       TYPE(cp_fm_type), DIMENSION(:), POINTER            :: mos_new, mos_occ
     591         1358 :       TYPE(mo_set_type), DIMENSION(:), POINTER           :: mos
     592              : 
     593         1358 :       CALL get_rtp(rtp=rtp, mos_new=mos_new)
     594              : 
     595         1358 :       my_keep_sparsity = .FALSE.
     596         1358 :       IF (PRESENT(keep_sparsity)) my_keep_sparsity = keep_sparsity
     597         1358 :       CALL get_qs_env(qs_env, mos=mos)
     598         7422 :       ALLOCATE (mos_occ(SIZE(mos)*2))
     599              : 
     600         3032 :       DO i = 1, SIZE(mos_new)/2
     601         1674 :          re = 2*i - 1; im = 2*i
     602         1674 :          alpha = 3.0_dp - REAL(SIZE(matrix_p_im), dp)
     603              :          CALL cp_fm_create(mos_occ(re), &
     604              :                            matrix_struct=mos(i)%mo_coeff%matrix_struct, &
     605         1674 :                            name="mos_occ")
     606              :          CALL cp_fm_create(mos_occ(im), &
     607              :                            matrix_struct=mos(i)%mo_coeff%matrix_struct, &
     608         1674 :                            name="mos_occ")
     609         1674 :          CALL dbcsr_set(matrix_p_im(i)%matrix, 0.0_dp)
     610         1674 :          CALL cp_fm_get_info(mos_new(re), ncol_global=ncol)
     611         1674 :          CALL cp_fm_to_fm(mos_new(re), mos_occ(re))
     612         7128 :          CALL cp_fm_column_scale(mos_occ(re), mos(i)%occupation_numbers/alpha)
     613         1674 :          CALL cp_fm_to_fm(mos_new(im), mos_occ(im))
     614         7128 :          CALL cp_fm_column_scale(mos_occ(im), mos(i)%occupation_numbers/alpha)
     615              :          CALL cp_dbcsr_plus_fm_fm_t(sparse_matrix=matrix_p_im(i)%matrix, &
     616              :                                     matrix_v=mos_occ(im), &
     617              :                                     matrix_g=mos_occ(re), &
     618              :                                     ncol=ncol, &
     619              :                                     keep_sparsity=my_keep_sparsity, &
     620              :                                     alpha=2.0_dp*alpha, &
     621         4706 :                                     symmetry_mode=-1)
     622              :       END DO
     623         1358 :       CALL cp_fm_release(mos_occ)
     624              : 
     625         1358 :    END SUBROUTINE calculate_P_imaginary
     626              : 
     627              : ! **************************************************************************************************
     628              : !> \brief ...
     629              : !> \param qs_env ...
     630              : !> \param rtp ...
     631              : ! **************************************************************************************************
     632          624 :    SUBROUTINE write_rtp_mos_to_output_unit(qs_env, rtp)
     633              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     634              :       TYPE(rt_prop_type), POINTER                        :: rtp
     635              : 
     636              :       CHARACTER(len=*), PARAMETER :: routineN = 'write_rtp_mos_to_output_unit'
     637              : 
     638              :       CHARACTER(LEN=10)                                  :: spin
     639              :       CHARACTER(LEN=2*default_string_length)             :: name
     640              :       INTEGER                                            :: handle, i, ispin, nao, nelectron, nmo, &
     641              :                                                             nspins
     642              :       LOGICAL                                            :: print_eigvecs, print_mo_info
     643              :       REAL(KIND=dp)                                      :: flexible_electron_count, maxocc, n_el_f
     644          312 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
     645          312 :       TYPE(cp_fm_type), DIMENSION(:), POINTER            :: mos_new
     646              :       TYPE(cp_logger_type), POINTER                      :: logger
     647              :       TYPE(mo_set_type)                                  :: mo_set_rtp
     648          312 :       TYPE(mo_set_type), DIMENSION(:), POINTER           :: mos
     649          312 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     650          312 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
     651              :       TYPE(section_vals_type), POINTER                   :: dft_section, input
     652              : 
     653          312 :       NULLIFY (atomic_kind_set, particle_set, qs_kind_set, input, mos, dft_section)
     654              : 
     655          312 :       CALL timeset(routineN, handle)
     656              : 
     657              :       CALL get_qs_env(qs_env, &
     658              :                       atomic_kind_set=atomic_kind_set, &
     659              :                       qs_kind_set=qs_kind_set, &
     660              :                       particle_set=particle_set, &
     661              :                       input=input, &
     662          312 :                       mos=mos)
     663              :       ! Quick return, if no printout of MO information is requested
     664          312 :       dft_section => section_vals_get_subs_vals(input, "DFT")
     665          312 :       CALL section_vals_val_get(dft_section, "PRINT%MO%EIGENVECTORS", l_val=print_eigvecs)
     666              : 
     667          312 :       NULLIFY (logger)
     668          312 :       logger => cp_get_default_logger()
     669              :       print_mo_info = (cp_print_key_should_output(logger%iter_info, &
     670              :                                                   dft_section, "PRINT%MO") /= 0) .OR. &
     671          312 :                       (qs_env%sim_step == 1)
     672              : 
     673          100 :       IF ((.NOT. print_mo_info) .OR. (.NOT. print_eigvecs)) THEN
     674          308 :          CALL timestop(handle)
     675          308 :          RETURN
     676              :       END IF
     677              : 
     678            4 :       CALL get_rtp(rtp=rtp, mos_new=mos_new)
     679              : 
     680            4 :       nspins = SIZE(mos_new)/2
     681              : 
     682            8 :       DO ispin = 1, nspins
     683              :          ! initiate mo_set
     684              :          CALL get_mo_set(mo_set=mos(ispin), nao=nao, nmo=nmo, nelectron=nelectron, &
     685            4 :                          n_el_f=n_el_f, maxocc=maxocc, flexible_electron_count=flexible_electron_count)
     686              : 
     687              :          CALL allocate_mo_set(mo_set_rtp, &
     688              :                               nao=nao, &
     689              :                               nmo=nmo, &
     690              :                               nelectron=nelectron, &
     691              :                               n_el_f=n_el_f, &
     692              :                               maxocc=maxocc, &
     693            4 :                               flexible_electron_count=flexible_electron_count)
     694              : 
     695            4 :          WRITE (name, FMT="(A,I6)") "RTP MO SET, SPIN ", ispin
     696            4 :          CALL init_mo_set(mo_set_rtp, fm_ref=mos_new(2*ispin - 1), name=name)
     697              : 
     698            4 :          IF (nspins > 1) THEN
     699            0 :             IF (ispin == 1) THEN
     700            0 :                spin = "ALPHA SPIN"
     701              :             ELSE
     702            0 :                spin = "BETA SPIN"
     703              :             END IF
     704              :          ELSE
     705            4 :             spin = ""
     706              :          END IF
     707              : 
     708            8 :          mo_set_rtp%occupation_numbers = mos(ispin)%occupation_numbers
     709              : 
     710              :          !loop for real (odd) and imaginary (even) parts
     711           12 :          DO i = 1, 0, -1
     712            8 :             CALL cp_fm_to_fm(mos_new(2*ispin - i), mo_set_rtp%mo_coeff)
     713              :             CALL write_mo_set_to_output_unit(mo_set_rtp, qs_kind_set, particle_set, &
     714              :                                              dft_section, 4, 0, rtp=.TRUE., spin=TRIM(spin), &
     715           12 :                                              cpart=MOD(i, 2), sim_step=qs_env%sim_step)
     716              :          END DO
     717              : 
     718           12 :          CALL deallocate_mo_set(mo_set_rtp)
     719              :       END DO
     720              : 
     721            4 :       CALL timestop(handle)
     722              : 
     723          312 :    END SUBROUTINE write_rtp_mos_to_output_unit
     724              : 
     725              : ! **************************************************************************************************
     726              : !> \brief Write the time dependent amplitude of the MOs in real grid.
     727              : !>        Very close to qs_scf_post_gpw/qs_scf_post_occ_cubes subroutine.
     728              : !> \param qs_env ...
     729              : !> \param rtp ...
     730              : !> \author Guillaume Le Breton (11.22)
     731              : ! **************************************************************************************************
     732          312 :    SUBROUTINE write_rtp_mo_cubes(qs_env, rtp)
     733              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     734              :       TYPE(rt_prop_type), POINTER                        :: rtp
     735              : 
     736              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'write_rtp_mo_cubes'
     737              : 
     738              :       CHARACTER(LEN=default_path_length)                 :: filename, my_pos_cube, title
     739              :       INTEGER                                            :: handle, homo, i, ir, ispin, ivector, &
     740              :                                                             n_rep, nhomo, nlist, nspins, &
     741              :                                                             rt_time_step, unit_nr
     742          312 :       INTEGER, DIMENSION(:), POINTER                     :: list, list_index
     743              :       LOGICAL                                            :: append_cube, do_kpoints, mpi_io
     744          312 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
     745              :       TYPE(cell_type), POINTER                           :: cell
     746              :       TYPE(cp_blacs_env_type), POINTER                   :: blacs_env
     747          312 :       TYPE(cp_fm_type), DIMENSION(:), POINTER            :: mos_new
     748              :       TYPE(cp_fm_type), POINTER                          :: mo_coeff
     749              :       TYPE(cp_logger_type), POINTER                      :: logger
     750              :       TYPE(dft_control_type), POINTER                    :: dft_control
     751          312 :       TYPE(mo_set_type), DIMENSION(:), POINTER           :: mos
     752              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     753              :       TYPE(particle_list_type), POINTER                  :: particles
     754          312 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     755              :       TYPE(pw_c1d_gs_type)                               :: wf_g
     756              :       TYPE(pw_env_type), POINTER                         :: pw_env
     757          312 :       TYPE(pw_pool_p_type), DIMENSION(:), POINTER        :: pw_pools
     758              :       TYPE(pw_pool_type), POINTER                        :: auxbas_pw_pool
     759              :       TYPE(pw_r3d_rs_type)                               :: density_r, wf_r
     760          312 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
     761              :       TYPE(qs_subsys_type), POINTER                      :: subsys
     762              :       TYPE(section_vals_type), POINTER                   :: dft_section, input
     763              : 
     764          312 :       CALL timeset(routineN, handle)
     765              : 
     766          312 :       NULLIFY (logger, auxbas_pw_pool, pw_pools, pw_env)
     767              : 
     768              :       ! Get all the info from qs:
     769              :       CALL get_qs_env(qs_env, do_kpoints=do_kpoints, &
     770          312 :                       input=input)
     771              : 
     772              :       ! Kill the run in the case of K points
     773          312 :       IF (do_kpoints) THEN
     774            0 :          CPABORT("K points not handled yet for printing MO_CUBE")
     775              :       END IF
     776              : 
     777          312 :       dft_section => section_vals_get_subs_vals(input, "DFT")
     778          312 :       logger => cp_get_default_logger()
     779              : 
     780              :       ! Quick return if no print required
     781          312 :       IF (.NOT. BTEST(cp_print_key_should_output(logger%iter_info, dft_section, &
     782              :                                                  "PRINT%MO_CUBES"), cp_p_file)) THEN
     783          288 :          CALL timestop(handle)
     784          288 :          RETURN
     785              :       END IF
     786              : 
     787              :       CALL get_qs_env(qs_env, atomic_kind_set=atomic_kind_set, &
     788              :                       mos=mos, &
     789              :                       blacs_env=blacs_env, &
     790              :                       qs_kind_set=qs_kind_set, &
     791              :                       pw_env=pw_env, &
     792              :                       subsys=subsys, &
     793              :                       para_env=para_env, &
     794              :                       particle_set=particle_set, &
     795           24 :                       dft_control=dft_control)
     796           24 :       CALL qs_subsys_get(subsys, particles=particles)
     797              : 
     798           24 :       nspins = dft_control%nspins
     799           24 :       rt_time_step = qs_env%sim_step
     800              : 
     801              :       ! Setup the grids needed to compute a wavefunction given a vector
     802              :       CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool, &
     803           24 :                       pw_pools=pw_pools)
     804           24 :       CALL auxbas_pw_pool%create_pw(wf_r)
     805           24 :       CALL auxbas_pw_pool%create_pw(wf_g)
     806           24 :       CALL auxbas_pw_pool%create_pw(density_r)
     807           24 :       CALL get_rtp(rtp=rtp, mos_new=mos_new)
     808              : 
     809           70 :       DO ispin = 1, nspins
     810           46 :          CALL get_mo_set(mo_set=mos(ispin), homo=homo)
     811              : 
     812           46 :          nhomo = section_get_ival(dft_section, "PRINT%MO_CUBES%NHOMO")
     813           46 :          append_cube = section_get_lval(dft_section, "PRINT%MO_CUBES%APPEND")
     814           46 :          my_pos_cube = "REWIND"
     815           46 :          IF (append_cube) THEN
     816            0 :             my_pos_cube = "APPEND"
     817              :          END IF
     818           46 :          CALL section_vals_val_get(dft_section, "PRINT%MO_CUBES%HOMO_LIST", n_rep_val=n_rep)
     819           46 :          IF (n_rep > 0) THEN ! write the cubes of the list
     820            0 :             nlist = 0
     821            0 :             DO ir = 1, n_rep
     822            0 :                NULLIFY (list)
     823              :                CALL section_vals_val_get(dft_section, "PRINT%MO_CUBES%HOMO_LIST", i_rep_val=ir, &
     824            0 :                                          i_vals=list)
     825            0 :                IF (ASSOCIATED(list)) THEN
     826            0 :                   CALL reallocate(list_index, 1, nlist + SIZE(list))
     827            0 :                   DO i = 1, SIZE(list)
     828            0 :                      list_index(i + nlist) = list(i)
     829              :                   END DO
     830            0 :                   nlist = nlist + SIZE(list)
     831              :                END IF
     832              :             END DO
     833              :          ELSE
     834              : 
     835           46 :             IF (nhomo == -1) nhomo = homo
     836           46 :             nlist = homo - MAX(1, homo - nhomo + 1) + 1
     837          138 :             ALLOCATE (list_index(nlist))
     838          224 :             DO i = 1, nlist
     839          224 :                list_index(i) = MAX(1, homo - nhomo + 1) + i - 1
     840              :             END DO
     841              :          END IF
     842          224 :          DO i = 1, nlist
     843          178 :             ivector = list_index(i)
     844              :             CALL get_qs_env(qs_env=qs_env, &
     845              :                             atomic_kind_set=atomic_kind_set, &
     846              :                             qs_kind_set=qs_kind_set, &
     847              :                             cell=cell, &
     848              :                             particle_set=particle_set, &
     849          178 :                             pw_env=pw_env)
     850              : 
     851              :             ! density_r contains the density of the MOs
     852          178 :             CALL pw_zero(density_r)
     853          178 :             mo_coeff => mos_new(2*ispin - 1)!Real coeff
     854              :             CALL calculate_wavefunction(mo_coeff, ivector, wf_r, wf_g, atomic_kind_set, qs_kind_set, &
     855          178 :                                         cell, dft_control, particle_set, pw_env)
     856              :             ! Adding the real part
     857          178 :             CALL pw_multiply(density_r, wf_r, wf_r, 1.0_dp)
     858              : 
     859          178 :             mo_coeff => mos_new(2*ispin) !Im coeff
     860              :             CALL calculate_wavefunction(mo_coeff, ivector, wf_r, wf_g, atomic_kind_set, qs_kind_set, &
     861          178 :                                         cell, dft_control, particle_set, pw_env)
     862              :             ! Adding the im part
     863          178 :             CALL pw_multiply(density_r, wf_r, wf_r, 1.0_dp)
     864              : 
     865          178 :             WRITE (filename, '(a4,I5.5,a1,I1.1)') "WFN_", ivector, "_", ispin
     866          178 :             mpi_io = .TRUE.
     867              :             unit_nr = cp_print_key_unit_nr(logger, input, "DFT%PRINT%MO_CUBES", extension=".cube", &
     868              :                                            middle_name=TRIM(filename), file_position=my_pos_cube, log_filename=.FALSE., &
     869          178 :                                            mpi_io=mpi_io)
     870          178 :             WRITE (title, *) "DENSITY ", ivector, " spin ", ispin, " i.e. HOMO - ", ivector - homo
     871              :             CALL cp_pw_to_cube(density_r, unit_nr, title, particles=particles, &
     872          178 :                                stride=section_get_ivals(dft_section, "PRINT%MO_CUBES%STRIDE"), mpi_io=mpi_io)
     873          224 :             CALL cp_print_key_finished_output(unit_nr, logger, input, "DFT%PRINT%MO_CUBES", mpi_io=mpi_io)
     874              :          END DO
     875          162 :          IF (ASSOCIATED(list_index)) DEALLOCATE (list_index)
     876              :       END DO
     877              : 
     878              :       ! Deallocate grids needed to compute wavefunctions
     879           24 :       CALL auxbas_pw_pool%give_back_pw(wf_r)
     880           24 :       CALL auxbas_pw_pool%give_back_pw(wf_g)
     881           24 :       CALL auxbas_pw_pool%give_back_pw(density_r)
     882              : 
     883           24 :       CALL timestop(handle)
     884              : 
     885          312 :    END SUBROUTINE write_rtp_mo_cubes
     886              : 
     887              : ! **************************************************************************************************
     888              : !> \brief Warn about unused sections of the print section - only implemented for some of the methods
     889              : !> \param section Parent section
     890              : !> \param subsection_name Name of the subsection which is not used even when explicitly included
     891              : !> \param error_message Message to display as warning
     892              : !> \author Stepan Marek (01.25)
     893              : ! **************************************************************************************************
     894          516 :    SUBROUTINE warn_section_unused(section, subsection_name, error_message)
     895              :       TYPE(section_vals_type), POINTER                   :: section
     896              :       CHARACTER(len=*)                                   :: subsection_name, error_message
     897              : 
     898              :       LOGICAL                                            :: explicit
     899              :       TYPE(section_vals_type), POINTER                   :: target_section
     900              : 
     901          258 :       target_section => section_vals_get_subs_vals(section, subsection_name)
     902          258 :       CALL section_vals_get(target_section, explicit=explicit)
     903          258 :       IF (explicit) CPWARN(error_message)
     904          258 :    END SUBROUTINE warn_section_unused
     905              : ! **************************************************************************************************
     906              : !> \brief Attempt to read the moments from a previously written file
     907              : !> \param moments_section Print key section for the moments trace
     908              : !> \param orig_start Index from which the original calculation started (given by input file)
     909              : !> \param current_start The current start index from which the calculation continues
     910              : !> \param moments Moment trace, where the read entries are overwritten
     911              : !> \param times Optional time trace, where again the read entries are overwritten
     912              : !> \param mom_read Whether moments were actually read
     913              : !> \author Stepan Marek (11.25)
     914              : ! **************************************************************************************************
     915           30 :    SUBROUTINE read_moments(moments_section, orig_start, current_start, moments, times, mom_read)
     916              :       TYPE(section_vals_type), POINTER                   :: moments_section
     917              :       INTEGER                                            :: orig_start, current_start
     918              :       COMPLEX(kind=dp), DIMENSION(:, :, :), POINTER      :: moments
     919              :       REAL(kind=dp), DIMENSION(:), OPTIONAL, POINTER     :: times
     920              :       LOGICAL, OPTIONAL                                  :: mom_read
     921              : 
     922              :       CHARACTER(len=14), DIMENSION(4)                    :: file_extensions
     923              :       CHARACTER(len=default_path_length)                 :: save_name_im, save_name_re
     924              :       INTEGER                                            :: i, k, max_n, n, n_spin, unit_im, unit_re
     925              :       REAL(kind=dp)                                      :: time
     926              :       REAL(kind=dp), DIMENSION(3)                        :: moments_im, moments_re
     927              :       TYPE(cp_logger_type), POINTER                      :: logger
     928              : 
     929              : ! Whether at least some moments where extracted from the files
     930              : 
     931           30 :       file_extensions(1) = "_SPIN_A_RE.dat"
     932           30 :       file_extensions(2) = "_SPIN_A_IM.dat"
     933           30 :       file_extensions(3) = "_SPIN_B_RE.dat"
     934           30 :       file_extensions(4) = "_SPIN_B_IM.dat"
     935              : 
     936           30 :       IF (PRESENT(mom_read)) mom_read = .FALSE.
     937              : 
     938           30 :       n_spin = SIZE(moments, 1)
     939              : 
     940           30 :       logger => cp_get_default_logger()
     941           30 :       max_n = current_start - orig_start + 1
     942              : 
     943           72 :       DO i = 1, n_spin
     944              :          ! Open the relevant files
     945              :          save_name_re = cp_print_key_generate_filename(logger, moments_section, &
     946           42 :                                                        extension=file_extensions(2*i - 1), my_local=.FALSE.)
     947              :          save_name_im = cp_print_key_generate_filename(logger, moments_section, &
     948           42 :                                                        extension=file_extensions(2*i), my_local=.FALSE.)
     949           72 :          IF (file_exists(save_name_re) .AND. file_exists(save_name_im)) THEN
     950              :             CALL open_file(save_name_re, file_status="OLD", file_form="FORMATTED", file_action="READ", &
     951            2 :                            unit_number=unit_re)
     952              :             CALL open_file(save_name_im, file_status="OLD", file_form="FORMATTED", file_action="READ", &
     953            2 :                            unit_number=unit_im)
     954          966 :             DO n = 1, max_n
     955          964 :                READ (unit_re, '(E20.8E3,E20.8E3,E20.8E3,E20.8E3,E20.8E3)') time, &
     956         1928 :                   moments_re(1), moments_re(2), moments_re(3)
     957          964 :                READ (unit_im, '(E20.8E3,E20.8E3,E20.8E3,E20.8E3,E20.8E3)') time, &
     958         1928 :                   moments_im(1), moments_im(2), moments_im(3)
     959         3856 :                DO k = 1, 3
     960         3856 :                   moments(i, k, n) = CMPLX(moments_re(k), moments_im(k), kind=dp)
     961              :                END DO
     962          966 :                IF (PRESENT(times)) THEN
     963          964 :                   times(n) = time/femtoseconds
     964              :                END IF
     965              :             END DO
     966            2 :             IF (PRESENT(mom_read)) mom_read = .TRUE.
     967            2 :             CALL close_file(unit_re)
     968            2 :             CALL close_file(unit_im)
     969              :          ELSE
     970          928 :             moments(i, :, 1:max_n) = CMPLX(0.0, 0.0, kind=dp)
     971           40 :             CPWARN("Could not read at least one moments file - missing trace is set to zero.")
     972              :          END IF
     973              :       END DO
     974           30 :    END SUBROUTINE read_moments
     975              : 
     976              : ! **************************************************************************************************
     977              : !> \brief Recalculates the field for index range given by orig_start and i_start,
     978              : !>        with times taken from the times array
     979              : !> \param fields Array, where relevant indices are recalculated
     980              : !> \param times Array of input times
     981              : !> \param orig_start original start (in case of restarts)
     982              : !> \param i_start current start
     983              : !> \param dft_control DFT parameters
     984              : !> \date 11.2025
     985              : !> \author Stepan Marek
     986              : ! **************************************************************************************************
     987           18 :    SUBROUTINE recalculate_fields(fields, times, orig_start, i_start, dft_control)
     988              :       COMPLEX(kind=dp), DIMENSION(:, :), POINTER         :: fields
     989              :       REAL(kind=dp), DIMENSION(:), POINTER               :: times
     990              :       INTEGER                                            :: orig_start, i_start
     991              :       TYPE(dft_control_type), POINTER                    :: dft_control
     992              : 
     993              :       INTEGER                                            :: i, max_n
     994              :       REAL(kind=dp), DIMENSION(3)                        :: field
     995              : 
     996           18 :       max_n = i_start - orig_start + 1
     997              : 
     998           18 :       IF (dft_control%rtp_control%apply_delta_pulse .OR. &
     999              :           dft_control%rtp_control%apply_delta_pulse_mag) THEN
    1000           90 :          fields(:, 1:max_n) = 0.0_dp
    1001              :       ELSE
    1002            0 :          DO i = 1, max_n
    1003            0 :             CALL make_field(dft_control, field, i + orig_start - 1, times(i))
    1004            0 :             fields(:, i) = field(:)
    1005              :          END DO
    1006              :       END IF
    1007           18 :    END SUBROUTINE recalculate_fields
    1008              : 
    1009              : END MODULE rt_propagation_utils
        

Generated by: LCOV version 2.0-1