LCOV - code coverage report
Current view: top level - src/emd - rt_propagation_methods.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:7641cd9) Lines: 99.1 % 444 440
Test Date: 2026-05-25 07:16:39 Functions: 100.0 % 10 10

            Line data    Source code
       1              : !--------------------------------------------------------------------------------------------------!
       2              : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3              : !   Copyright 2000-2026 CP2K developers group <https://cp2k.org>                                   !
       4              : !                                                                                                  !
       5              : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6              : !--------------------------------------------------------------------------------------------------!
       7              : 
       8              : ! **************************************************************************************************
       9              : !> \brief Routines for propagating the orbitals
      10              : !> \author Florian Schiffmann (02.09)
      11              : ! **************************************************************************************************
      12              : MODULE rt_propagation_methods
      13              :    USE bibliography,                    ONLY: Kolafa2004,&
      14              :                                               Kuhne2007,&
      15              :                                               Schreder2021,&
      16              :                                               cite_reference
      17              :    USE cell_types,                      ONLY: cell_type
      18              :    USE cp_array_utils,                  ONLY: cp_1d_r_p_type
      19              :    USE cp_cfm_basic_linalg,             ONLY: cp_cfm_triangular_multiply
      20              :    USE cp_cfm_cholesky,                 ONLY: cp_cfm_cholesky_decompose
      21              :    USE cp_cfm_types,                    ONLY: cp_cfm_create,&
      22              :                                               cp_cfm_release,&
      23              :                                               cp_cfm_type
      24              :    USE cp_control_types,                ONLY: dft_control_type,&
      25              :                                               rtp_control_type
      26              :    USE cp_dbcsr_api,                    ONLY: &
      27              :         dbcsr_add, dbcsr_copy, dbcsr_create, dbcsr_deallocate_matrix, dbcsr_desymmetrize, &
      28              :         dbcsr_filter, dbcsr_get_block_p, dbcsr_init_p, dbcsr_iterator_blocks_left, &
      29              :         dbcsr_iterator_next_block, dbcsr_iterator_start, dbcsr_iterator_stop, dbcsr_iterator_type, &
      30              :         dbcsr_multiply, dbcsr_p_type, dbcsr_release, dbcsr_scale, dbcsr_set, dbcsr_transposed, &
      31              :         dbcsr_type, dbcsr_type_antisymmetric
      32              :    USE cp_dbcsr_cholesky,               ONLY: cp_dbcsr_cholesky_decompose,&
      33              :                                               cp_dbcsr_cholesky_invert
      34              :    USE cp_dbcsr_contrib,                ONLY: dbcsr_frobenius_norm
      35              :    USE cp_dbcsr_operations,             ONLY: cp_dbcsr_sm_fm_multiply,&
      36              :                                               dbcsr_allocate_matrix_set,&
      37              :                                               dbcsr_deallocate_matrix_set
      38              :    USE cp_fm_basic_linalg,              ONLY: cp_fm_scale_and_add
      39              :    USE cp_fm_struct,                    ONLY: cp_fm_struct_create,&
      40              :                                               cp_fm_struct_double,&
      41              :                                               cp_fm_struct_release,&
      42              :                                               cp_fm_struct_type
      43              :    USE cp_fm_types,                     ONLY: cp_fm_create,&
      44              :                                               cp_fm_get_info,&
      45              :                                               cp_fm_release,&
      46              :                                               cp_fm_to_fm,&
      47              :                                               cp_fm_type
      48              :    USE cp_log_handling,                 ONLY: cp_get_default_logger,&
      49              :                                               cp_logger_get_default_io_unit,&
      50              :                                               cp_logger_get_default_unit_nr,&
      51              :                                               cp_logger_type,&
      52              :                                               cp_to_string
      53              :    USE cp_output_handling,              ONLY: cp_p_file,&
      54              :                                               cp_print_key_should_output
      55              :    USE efield_utils,                    ONLY: efield_potential_lengh_gauge
      56              :    USE input_constants,                 ONLY: do_arnoldi,&
      57              :                                               do_bch,&
      58              :                                               do_em,&
      59              :                                               do_pade,&
      60              :                                               do_taylor
      61              :    USE input_section_types,             ONLY: section_vals_get_subs_vals,&
      62              :                                               section_vals_type
      63              :    USE iterate_matrix,                  ONLY: matrix_sqrt_Newton_Schulz
      64              :    USE kinds,                           ONLY: dp
      65              :    USE ls_matrix_exp,                   ONLY: cp_complex_dbcsr_gemm_3
      66              :    USE mathlib,                         ONLY: binomial
      67              :    USE parallel_gemm_api,               ONLY: parallel_gemm
      68              :    USE particle_list_types,             ONLY: particle_list_type
      69              :    USE pw_env_types,                    ONLY: pw_env_get,&
      70              :                                               pw_env_type
      71              :    USE pw_pool_types,                   ONLY: pw_pool_type
      72              :    USE pw_types,                        ONLY: pw_c1d_gs_type,&
      73              :                                               pw_r3d_rs_type
      74              :    USE qs_energy_init,                  ONLY: qs_energies_init
      75              :    USE qs_energy_types,                 ONLY: qs_energy_type
      76              :    USE qs_environment_types,            ONLY: get_qs_env,&
      77              :                                               qs_environment_type
      78              :    USE qs_ks_methods,                   ONLY: qs_ks_update_qs_env
      79              :    USE qs_ks_types,                     ONLY: set_ks_env
      80              :    USE qs_loc_dipole,                   ONLY: loc_dipole
      81              :    USE qs_loc_states,                   ONLY: get_localization_info
      82              :    USE qs_loc_types,                    ONLY: qs_loc_env_create,&
      83              :                                               qs_loc_env_release,&
      84              :                                               qs_loc_env_type
      85              :    USE qs_loc_utils,                    ONLY: qs_loc_control_init,&
      86              :                                               qs_loc_init
      87              :    USE qs_mo_types,                     ONLY: get_mo_set,&
      88              :                                               mo_set_type
      89              :    USE rt_make_propagators,             ONLY: propagate_arnoldi,&
      90              :                                               propagate_bch,&
      91              :                                               propagate_exp,&
      92              :                                               propagate_exp_density
      93              :    USE rt_propagation_output,           ONLY: report_density_occupation,&
      94              :                                               rt_convergence,&
      95              :                                               rt_convergence_density
      96              :    USE rt_propagation_types,            ONLY: get_rtp,&
      97              :                                               rt_prop_type
      98              :    USE rt_propagation_utils,            ONLY: calc_S_derivs,&
      99              :                                               calc_update_rho,&
     100              :                                               calc_update_rho_sparse
     101              :    USE rt_propagation_velocity_gauge,   ONLY: update_vector_potential,&
     102              :                                               velocity_gauge_ks_matrix
     103              : #include "../base/base_uses.f90"
     104              : 
     105              :    IMPLICIT NONE
     106              : 
     107              :    PRIVATE
     108              : 
     109              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'rt_propagation_methods'
     110              : 
     111              :    PUBLIC :: propagation_step, &
     112              :              s_matrices_create, &
     113              :              calc_sinvH, &
     114              :              put_data_to_history, &
     115              :              rtp_localize
     116              : 
     117              : CONTAINS
     118              : 
     119              : ! **************************************************************************************************
     120              : !> \brief performs a single propagation step a(t+Dt)=U(t+Dt,t)*a(0)
     121              : !>        and calculates the new exponential
     122              : !> \param qs_env ...
     123              : !> \param rtp ...
     124              : !> \param rtp_control ...
     125              : !> \author Florian Schiffmann (02.09)
     126              : ! **************************************************************************************************
     127              : 
     128         2316 :    SUBROUTINE propagation_step(qs_env, rtp, rtp_control)
     129              : 
     130              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     131              :       TYPE(rt_prop_type), POINTER                        :: rtp
     132              :       TYPE(rtp_control_type), POINTER                    :: rtp_control
     133              : 
     134              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'propagation_step'
     135              : 
     136              :       INTEGER                                            :: aspc_order, handle, i, im, re, unit_nr
     137              :       TYPE(cell_type), POINTER                           :: cell
     138         2316 :       TYPE(cp_fm_type), DIMENSION(:), POINTER            :: delta_mos, mos_new
     139              :       TYPE(cp_logger_type), POINTER                      :: logger
     140         2316 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: delta_P, H_last_iter, ks_mix, ks_mix_im, &
     141         2316 :                                                             matrix_ks, matrix_ks_im, matrix_s, &
     142         2316 :                                                             rho_new
     143              :       TYPE(dft_control_type), POINTER                    :: dft_control
     144              : 
     145         2316 :       CALL timeset(routineN, handle)
     146              : 
     147         2316 :       logger => cp_get_default_logger()
     148         2316 :       IF (logger%para_env%is_source()) THEN
     149         1158 :          unit_nr = cp_logger_get_default_unit_nr(logger, local=.TRUE.)
     150              :       ELSE
     151              :          unit_nr = -1
     152              :       END IF
     153              : 
     154         2316 :       NULLIFY (cell, delta_P, rho_new, delta_mos, mos_new)
     155         2316 :       NULLIFY (ks_mix, ks_mix_im)
     156              :       ! get everything needed and set some values
     157         2316 :       CALL get_qs_env(qs_env, cell=cell, matrix_s=matrix_s, dft_control=dft_control)
     158              : 
     159         2316 :       IF (rtp%iter == 1) THEN
     160          626 :          CALL qs_energies_init(qs_env, .FALSE.)
     161              :          !the above recalculates matrix_s, but matrix not changed if ions are fixed
     162          626 :          IF (rtp_control%fixed_ions) CALL set_ks_env(qs_env%ks_env, s_mstruct_changed=.FALSE.)
     163              : 
     164              :          ! add additional terms to matrix_h and matrix_h_im in the case of applied electric field,
     165              :          ! either in the lengh or velocity gauge.
     166              :          ! should be called  after qs_energies_init and before qs_ks_update_qs_env
     167          626 :          IF (dft_control%apply_efield_field) THEN
     168          216 :             IF (ANY(cell%perd(1:3) /= 0)) &
     169            0 :                CPABORT("Length gauge (efield) and periodicity are not compatible")
     170           54 :             CALL efield_potential_lengh_gauge(qs_env)
     171          572 :          ELSE IF (rtp_control%velocity_gauge) THEN
     172           32 :             IF (dft_control%apply_vector_potential) &
     173           32 :                CALL update_vector_potential(qs_env, dft_control)
     174           32 :             CALL velocity_gauge_ks_matrix(qs_env, subtract_nl_term=.FALSE.)
     175              :          END IF
     176              : 
     177          626 :          CALL get_qs_env(qs_env, matrix_s=matrix_s)
     178          626 :          IF (.NOT. rtp_control%fixed_ions) THEN
     179          274 :             CALL s_matrices_create(matrix_s, rtp)
     180              :          END IF
     181          626 :          rtp%delta_iter = 100.0_dp
     182          626 :          rtp%mixing_factor = 1.0_dp
     183          626 :          rtp%mixing = .FALSE.
     184          626 :          aspc_order = rtp_control%aspc_order
     185          626 :          CALL aspc_extrapolate(rtp, matrix_s, aspc_order)
     186          626 :          IF (rtp%linear_scaling) THEN
     187          182 :             CALL calc_update_rho_sparse(qs_env)
     188              :          ELSE
     189          444 :             CALL calc_update_rho(qs_env)
     190              :          END IF
     191          626 :          CALL qs_ks_update_qs_env(qs_env, calculate_forces=.FALSE.)
     192              :       END IF
     193         2316 :       IF (.NOT. rtp_control%fixed_ions) THEN
     194         1144 :          CALL calc_S_derivs(qs_env)
     195              :       END IF
     196         2316 :       rtp%converged = .FALSE.
     197              : 
     198         2316 :       IF (rtp%linear_scaling) THEN
     199              :          ! keep temporary copy of the starting density matrix to check for convergence
     200          806 :          CALL get_rtp(rtp=rtp, rho_new=rho_new)
     201          806 :          NULLIFY (delta_P)
     202          806 :          CALL dbcsr_allocate_matrix_set(delta_P, SIZE(rho_new))
     203         2910 :          DO i = 1, SIZE(rho_new)
     204         2104 :             CALL dbcsr_init_p(delta_P(i)%matrix)
     205         2104 :             CALL dbcsr_create(delta_P(i)%matrix, template=rho_new(i)%matrix)
     206         2910 :             CALL dbcsr_copy(delta_P(i)%matrix, rho_new(i)%matrix)
     207              :          END DO
     208              :       ELSE
     209              :          ! keep temporary copy of the starting mos to check for convergence
     210         1510 :          CALL get_rtp(rtp=rtp, mos_new=mos_new)
     211         8390 :          ALLOCATE (delta_mos(SIZE(mos_new)))
     212         5370 :          DO i = 1, SIZE(mos_new)
     213              :             CALL cp_fm_create(delta_mos(i), &
     214              :                               matrix_struct=mos_new(i)%matrix_struct, &
     215         3860 :                               name="delta_mos"//TRIM(ADJUSTL(cp_to_string(i))))
     216         5370 :             CALL cp_fm_to_fm(mos_new(i), delta_mos(i))
     217              :          END DO
     218              :       END IF
     219              : 
     220              :       CALL get_qs_env(qs_env, &
     221              :                       matrix_ks=matrix_ks, &
     222         2316 :                       matrix_ks_im=matrix_ks_im)
     223              : 
     224         2316 :       CALL get_rtp(rtp=rtp, H_last_iter=H_last_iter)
     225         2316 :       IF (rtp%mixing) THEN
     226           96 :          IF (unit_nr > 0) THEN
     227           48 :             WRITE (unit_nr, '(t3,a,2f16.8)') "Mixing the Hamiltonians to improve robustness, mixing factor: ", rtp%mixing_factor
     228              :          END IF
     229           96 :          CALL dbcsr_allocate_matrix_set(ks_mix, SIZE(matrix_ks))
     230           96 :          CALL dbcsr_allocate_matrix_set(ks_mix_im, SIZE(matrix_ks))
     231          192 :          DO i = 1, SIZE(matrix_ks)
     232           96 :             CALL dbcsr_init_p(ks_mix(i)%matrix)
     233           96 :             CALL dbcsr_create(ks_mix(i)%matrix, template=matrix_ks(1)%matrix)
     234           96 :             CALL dbcsr_init_p(ks_mix_im(i)%matrix)
     235          192 :             CALL dbcsr_create(ks_mix_im(i)%matrix, template=matrix_ks(1)%matrix, matrix_type=dbcsr_type_antisymmetric)
     236              :          END DO
     237          192 :          DO i = 1, SIZE(matrix_ks)
     238           96 :             re = 2*i - 1
     239           96 :             im = 2*i
     240           96 :             CALL dbcsr_add(ks_mix(i)%matrix, matrix_ks(i)%matrix, 0.0_dp, rtp%mixing_factor)
     241           96 :             CALL dbcsr_add(ks_mix(i)%matrix, H_last_iter(re)%matrix, 1.0_dp, 1.0_dp - rtp%mixing_factor)
     242          192 :             IF (rtp%propagate_complex_ks) THEN
     243            0 :                CALL dbcsr_add(ks_mix_im(i)%matrix, matrix_ks_im(i)%matrix, 0.0_dp, rtp%mixing_factor)
     244            0 :                CALL dbcsr_add(ks_mix_im(i)%matrix, H_last_iter(im)%matrix, 1.0_dp, 1.0_dp - rtp%mixing_factor)
     245              :             END IF
     246              :          END DO
     247           96 :          CALL calc_SinvH(rtp, ks_mix, ks_mix_im, rtp_control)
     248          192 :          DO i = 1, SIZE(matrix_ks)
     249           96 :             re = 2*i - 1
     250           96 :             im = 2*i
     251           96 :             CALL dbcsr_copy(H_last_iter(re)%matrix, ks_mix(i)%matrix)
     252          192 :             IF (rtp%propagate_complex_ks) THEN
     253            0 :                CALL dbcsr_copy(H_last_iter(im)%matrix, ks_mix_im(i)%matrix)
     254              :             END IF
     255              :          END DO
     256           96 :          CALL dbcsr_deallocate_matrix_set(ks_mix)
     257           96 :          CALL dbcsr_deallocate_matrix_set(ks_mix_im)
     258              :       ELSE
     259         2220 :          CALL calc_SinvH(rtp, matrix_ks, matrix_ks_im, rtp_control)
     260         5106 :          DO i = 1, SIZE(matrix_ks)
     261         2886 :             re = 2*i - 1
     262         2886 :             im = 2*i
     263         2886 :             CALL dbcsr_copy(H_last_iter(re)%matrix, matrix_ks(i)%matrix)
     264         5106 :             IF (rtp%propagate_complex_ks) THEN
     265          438 :                CALL dbcsr_copy(H_last_iter(im)%matrix, matrix_ks_im(i)%matrix)
     266              :             END IF
     267              :          END DO
     268              :       END IF
     269              : 
     270         2316 :       CALL compute_propagator_matrix(rtp, rtp_control%propagator)
     271              : 
     272         4016 :       SELECT CASE (rtp_control%mat_exp)
     273              :       CASE (do_pade, do_taylor)
     274         1700 :          IF (rtp%linear_scaling) THEN
     275          622 :             CALL propagate_exp_density(rtp, rtp_control)
     276          622 :             CALL calc_update_rho_sparse(qs_env)
     277              :          ELSE
     278         1078 :             CALL propagate_exp(rtp, rtp_control)
     279         1078 :             CALL calc_update_rho(qs_env)
     280              :          END IF
     281              :       CASE (do_arnoldi)
     282          432 :          CALL propagate_arnoldi(rtp, rtp_control)
     283          432 :          CALL calc_update_rho(qs_env)
     284              :       CASE (do_bch)
     285          184 :          CALL propagate_bch(rtp, rtp_control)
     286         2500 :          CALL calc_update_rho_sparse(qs_env)
     287              :       END SELECT
     288         2316 :       CALL step_finalize(qs_env, rtp_control, delta_mos, delta_P)
     289         2316 :       IF (rtp%linear_scaling) THEN
     290          806 :          CALL dbcsr_deallocate_matrix_set(delta_P)
     291              :       ELSE
     292         1510 :          CALL cp_fm_release(delta_mos)
     293              :       END IF
     294              : 
     295         2316 :       CALL timestop(handle)
     296              : 
     297         2316 :    END SUBROUTINE propagation_step
     298              : 
     299              : ! **************************************************************************************************
     300              : !> \brief Performs all the stuff to finish the step:
     301              : !>        convergence checks
     302              : !>        copying stuff into right place for the next step
     303              : !>        updating the history for extrapolation
     304              : !> \param qs_env ...
     305              : !> \param rtp_control ...
     306              : !> \param delta_mos ...
     307              : !> \param delta_P ...
     308              : !> \author Florian Schiffmann (02.09)
     309              : ! **************************************************************************************************
     310              : 
     311         2316 :    SUBROUTINE step_finalize(qs_env, rtp_control, delta_mos, delta_P)
     312              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     313              :       TYPE(rtp_control_type), POINTER                    :: rtp_control
     314              :       TYPE(cp_fm_type), DIMENSION(:), POINTER            :: delta_mos
     315              :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: delta_P
     316              : 
     317              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'step_finalize'
     318              : 
     319              :       INTEGER                                            :: handle, i, ihist
     320         2316 :       TYPE(cp_fm_type), DIMENSION(:), POINTER            :: mos_new, mos_old
     321         2316 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: exp_H_new, exp_H_old, matrix_ks, &
     322         2316 :                                                             matrix_ks_im, rho_new, rho_old, s_mat
     323              :       TYPE(qs_energy_type), POINTER                      :: energy
     324              :       TYPE(rt_prop_type), POINTER                        :: rtp
     325              : 
     326         2316 :       CALL timeset(routineN, handle)
     327              : 
     328              :       CALL get_qs_env(qs_env=qs_env, rtp=rtp, matrix_s=s_mat, &
     329         2316 :                       matrix_ks=matrix_ks, matrix_ks_im=matrix_ks_im, energy=energy)
     330         2316 :       CALL get_rtp(rtp=rtp, exp_H_old=exp_H_old, exp_H_new=exp_H_new)
     331              : 
     332         2316 :       IF (rtp_control%sc_check_start < rtp%iter) THEN
     333         2316 :          rtp%delta_iter_old = rtp%delta_iter
     334         2316 :          IF (rtp%linear_scaling) THEN
     335          806 :             CALL rt_convergence_density(rtp, delta_P, rtp%delta_iter)
     336              :          ELSE
     337         1510 :             CALL rt_convergence(rtp, s_mat(1)%matrix, delta_mos, rtp%delta_iter)
     338              :          END IF
     339         2316 :          rtp%converged = (rtp%delta_iter < rtp_control%eps_ener)
     340              :          !Apply mixing if scf loop is not converging
     341              : 
     342              :          !It would be better to redo the current step with mixixng,
     343              :          !but currently the decision is made to use mixing from the next step on
     344         2316 :          IF (rtp_control%sc_check_start < rtp%iter + 1) THEN
     345         2316 :             IF (rtp%delta_iter/rtp%delta_iter_old > 0.9) THEN
     346            6 :                rtp%mixing_factor = MAX(rtp%mixing_factor/2.0_dp, 0.125_dp)
     347            6 :                rtp%mixing = .TRUE.
     348              :             END IF
     349              :          END IF
     350              :       END IF
     351              : 
     352         2316 :       IF (rtp%converged) THEN
     353          626 :          IF (rtp%linear_scaling) THEN
     354          182 :             CALL get_rtp(rtp=rtp, rho_old=rho_old, rho_new=rho_new)
     355              :             CALL purify_mcweeny_complex_nonorth(rho_new, s_mat, rtp%filter_eps, rtp%filter_eps_small, &
     356          182 :                                                 rtp_control%mcweeny_max_iter, rtp_control%mcweeny_eps)
     357          182 :             IF (rtp_control%mcweeny_max_iter > 0) CALL calc_update_rho_sparse(qs_env)
     358          182 :             CALL report_density_occupation(rtp%filter_eps, rho_new)
     359          686 :             DO i = 1, SIZE(rho_new)
     360          686 :                CALL dbcsr_copy(rho_old(i)%matrix, rho_new(i)%matrix)
     361              :             END DO
     362              :          ELSE
     363          444 :             CALL get_rtp(rtp=rtp, mos_old=mos_old, mos_new=mos_new)
     364         1544 :             DO i = 1, SIZE(mos_new)
     365         1544 :                CALL cp_fm_to_fm(mos_new(i), mos_old(i))
     366              :             END DO
     367              :          END IF
     368          626 :          IF (rtp_control%propagator == do_em) CALL calc_SinvH(rtp, matrix_ks, matrix_ks_im, rtp_control)
     369         2230 :          DO i = 1, SIZE(exp_H_new)
     370         2230 :             CALL dbcsr_copy(exp_H_old(i)%matrix, exp_H_new(i)%matrix)
     371              :          END DO
     372          626 :          ihist = MOD(rtp%istep, rtp_control%aspc_order) + 1
     373          626 :          IF (rtp_control%fixed_ions) THEN
     374          352 :             CALL put_data_to_history(rtp, rho=rho_new, mos=mos_new, ihist=ihist)
     375              :          ELSE
     376          274 :             CALL put_data_to_history(rtp, rho=rho_new, mos=mos_new, s_mat=s_mat, ihist=ihist)
     377              :          END IF
     378              :       END IF
     379              : 
     380         2316 :       rtp%energy_new = energy%total
     381              : 
     382         2316 :       CALL timestop(handle)
     383              : 
     384         2316 :    END SUBROUTINE step_finalize
     385              : 
     386              : ! **************************************************************************************************
     387              : !> \brief computes the propagator matrix for EM/ETRS, RTP/EMD
     388              : !> \param rtp ...
     389              : !> \param propagator ...
     390              : !> \author Florian Schiffmann (02.09)
     391              : ! **************************************************************************************************
     392              : 
     393         4632 :    SUBROUTINE compute_propagator_matrix(rtp, propagator)
     394              :       TYPE(rt_prop_type), POINTER                        :: rtp
     395              :       INTEGER                                            :: propagator
     396              : 
     397              :       CHARACTER(len=*), PARAMETER :: routineN = 'compute_propagator_matrix'
     398              : 
     399              :       INTEGER                                            :: handle, i
     400              :       REAL(Kind=dp)                                      :: dt, prefac
     401         2316 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: exp_H_new, exp_H_old, propagator_matrix
     402              : 
     403         2316 :       CALL timeset(routineN, handle)
     404              :       CALL get_rtp(rtp=rtp, exp_H_new=exp_H_new, exp_H_old=exp_H_old, &
     405         2316 :                    propagator_matrix=propagator_matrix, dt=dt)
     406              : 
     407         2316 :       prefac = -0.5_dp*dt
     408              : 
     409         8280 :       DO i = 1, SIZE(exp_H_new)
     410         5964 :          CALL dbcsr_add(propagator_matrix(i)%matrix, exp_H_new(i)%matrix, 0.0_dp, prefac)
     411         5964 :          IF (propagator == do_em) &
     412         2380 :             CALL dbcsr_add(propagator_matrix(i)%matrix, exp_H_old(i)%matrix, 1.0_dp, prefac)
     413              :       END DO
     414              : 
     415         2316 :       CALL timestop(handle)
     416              : 
     417         2316 :    END SUBROUTINE compute_propagator_matrix
     418              : 
     419              : ! **************************************************************************************************
     420              : !> \brief computes S_inv*H, if needed Sinv*B and S_inv*H_imag and store these quantities to the
     421              : !> \brief exp_H for the real and imag part (for RTP and EMD)
     422              : !> \param rtp ...
     423              : !> \param matrix_ks ...
     424              : !> \param matrix_ks_im ...
     425              : !> \param rtp_control ...
     426              : !> \author Florian Schiffmann (02.09)
     427              : ! **************************************************************************************************
     428              : 
     429         2532 :    SUBROUTINE calc_SinvH(rtp, matrix_ks, matrix_ks_im, rtp_control)
     430              :       TYPE(rt_prop_type), POINTER                        :: rtp
     431              :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_ks, matrix_ks_im
     432              :       TYPE(rtp_control_type), POINTER                    :: rtp_control
     433              : 
     434              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'calc_SinvH'
     435              :       REAL(KIND=dp), PARAMETER                           :: one = 1.0_dp, zero = 0.0_dp
     436              : 
     437              :       INTEGER                                            :: handle, im, ispin, re
     438         2532 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: exp_H, SinvB, SinvH, SinvH_imag
     439              :       TYPE(dbcsr_type)                                   :: matrix_ks_nosym
     440              :       TYPE(dbcsr_type), POINTER                          :: B_mat, S_inv
     441              : 
     442         2532 :       CALL timeset(routineN, handle)
     443         2532 :       CALL get_rtp(rtp=rtp, S_inv=S_inv, exp_H_new=exp_H)
     444         5800 :       DO ispin = 1, SIZE(matrix_ks)
     445         3268 :          re = ispin*2 - 1
     446         3268 :          im = ispin*2
     447         3268 :          CALL dbcsr_set(exp_H(re)%matrix, zero)
     448         5800 :          CALL dbcsr_set(exp_H(im)%matrix, zero)
     449              :       END DO
     450         2532 :       CALL dbcsr_create(matrix_ks_nosym, template=matrix_ks(1)%matrix, matrix_type="N")
     451              : 
     452              :       ! Real part of S_inv x H -> imag part of exp_H
     453         5800 :       DO ispin = 1, SIZE(matrix_ks)
     454         3268 :          re = ispin*2 - 1
     455         3268 :          im = ispin*2
     456         3268 :          CALL dbcsr_desymmetrize(matrix_ks(ispin)%matrix, matrix_ks_nosym)
     457              :          CALL dbcsr_multiply("N", "N", one, S_inv, matrix_ks_nosym, zero, exp_H(im)%matrix, &
     458         3268 :                              filter_eps=rtp%filter_eps)
     459         5800 :          IF (.NOT. rtp_control%fixed_ions) THEN
     460         1478 :             CALL get_rtp(rtp=rtp, SinvH=SinvH)
     461         1478 :             CALL dbcsr_copy(SinvH(ispin)%matrix, exp_H(im)%matrix)
     462              :          END IF
     463              :       END DO
     464              : 
     465              :       ! Imag part of S_inv x H -> real part of exp_H
     466         2532 :       IF (rtp%propagate_complex_ks) THEN
     467          940 :          DO ispin = 1, SIZE(matrix_ks)
     468          486 :             re = ispin*2 - 1
     469          486 :             im = ispin*2
     470          486 :             CALL dbcsr_set(matrix_ks_nosym, 0.0_dp)
     471          486 :             CALL dbcsr_desymmetrize(matrix_ks_im(ispin)%matrix, matrix_ks_nosym)
     472              :             ! - SinvH_imag is added to exp_H(re)%matrix
     473              :             CALL dbcsr_multiply("N", "N", -one, S_inv, matrix_ks_nosym, zero, exp_H(re)%matrix, &
     474          486 :                                 filter_eps=rtp%filter_eps)
     475          940 :             IF (.NOT. rtp_control%fixed_ions) THEN
     476          286 :                CALL get_rtp(rtp=rtp, SinvH_imag=SinvH_imag)
     477              :                ! -SinvH_imag is saved
     478          286 :                CALL dbcsr_copy(SinvH_imag(ispin)%matrix, exp_H(re)%matrix)
     479              :             END IF
     480              :          END DO
     481              :       END IF
     482              :       ! EMD case: the real part of exp_H should be updated with B
     483         2532 :       IF (.NOT. rtp_control%fixed_ions) THEN
     484         1226 :          CALL get_rtp(rtp=rtp, B_mat=B_mat, SinvB=SinvB)
     485         1226 :          CALL dbcsr_set(matrix_ks_nosym, 0.0_dp)
     486         1226 :          CALL dbcsr_multiply("N", "N", one, S_inv, B_mat, zero, matrix_ks_nosym, filter_eps=rtp%filter_eps)
     487         2704 :          DO ispin = 1, SIZE(matrix_ks)
     488         1478 :             re = ispin*2 - 1
     489         1478 :             im = ispin*2
     490              :             ! + SinvB is added to exp_H(re)%matrix
     491         1478 :             CALL dbcsr_add(exp_H(re)%matrix, matrix_ks_nosym, 1.0_dp, 1.0_dp)
     492              :             ! + SinvB is saved
     493         2704 :             CALL dbcsr_copy(SinvB(ispin)%matrix, matrix_ks_nosym)
     494              :          END DO
     495              :       END IF
     496              :       ! Otherwise no real part for exp_H
     497              : 
     498         2532 :       CALL dbcsr_release(matrix_ks_nosym)
     499         2532 :       CALL timestop(handle)
     500              : 
     501         2532 :    END SUBROUTINE calc_SinvH
     502              : 
     503              : ! **************************************************************************************************
     504              : !> \brief calculates the needed overlap-like matrices
     505              : !>        depending on the way the exponential is calculated, only S^-1 is needed
     506              : !> \param s_mat ...
     507              : !> \param rtp ...
     508              : !> \author Florian Schiffmann (02.09)
     509              : ! **************************************************************************************************
     510              : 
     511          478 :    SUBROUTINE s_matrices_create(s_mat, rtp)
     512              : 
     513              :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: s_mat
     514              :       TYPE(rt_prop_type), POINTER                        :: rtp
     515              : 
     516              :       CHARACTER(len=*), PARAMETER                        :: routineN = 's_matrices_create'
     517              :       REAL(KIND=dp), PARAMETER                           :: one = 1.0_dp, zero = 0.0_dp
     518              : 
     519              :       INTEGER                                            :: handle
     520              :       TYPE(dbcsr_type), POINTER                          :: S_half, S_inv, S_minus_half
     521              : 
     522          478 :       CALL timeset(routineN, handle)
     523              : 
     524          478 :       CALL get_rtp(rtp=rtp, S_inv=S_inv)
     525              : 
     526          478 :       IF (rtp%linear_scaling) THEN
     527          136 :          CALL get_rtp(rtp=rtp, S_half=S_half, S_minus_half=S_minus_half)
     528              :          CALL matrix_sqrt_Newton_Schulz(S_half, S_minus_half, s_mat(1)%matrix, rtp%filter_eps, &
     529          136 :                                         rtp%newton_schulz_order, rtp%lanzcos_threshold, rtp%lanzcos_max_iter)
     530              :          CALL dbcsr_multiply("N", "N", one, S_minus_half, S_minus_half, zero, S_inv, &
     531          136 :                              filter_eps=rtp%filter_eps)
     532              :       ELSE
     533          342 :          CALL dbcsr_copy(S_inv, s_mat(1)%matrix)
     534              :          CALL cp_dbcsr_cholesky_decompose(S_inv, para_env=rtp%ao_ao_fmstruct%para_env, &
     535          342 :                                           blacs_env=rtp%ao_ao_fmstruct%context)
     536              :          CALL cp_dbcsr_cholesky_invert(S_inv, para_env=rtp%ao_ao_fmstruct%para_env, &
     537          342 :                                        blacs_env=rtp%ao_ao_fmstruct%context, uplo_to_full=.TRUE.)
     538              :       END IF
     539              : 
     540          478 :       CALL timestop(handle)
     541          478 :    END SUBROUTINE s_matrices_create
     542              : 
     543              : ! **************************************************************************************************
     544              : !> \brief Calculates the frobenius norm of a complex matrix represented by two real matrices
     545              : !> \param frob_norm ...
     546              : !> \param mat_re ...
     547              : !> \param mat_im ...
     548              : !> \author Samuel Andermatt (04.14)
     549              : ! **************************************************************************************************
     550              : 
     551          568 :    SUBROUTINE complex_frobenius_norm(frob_norm, mat_re, mat_im)
     552              : 
     553              :       REAL(KIND=dp), INTENT(out)                         :: frob_norm
     554              :       TYPE(dbcsr_type), POINTER                          :: mat_re, mat_im
     555              : 
     556              :       CHARACTER(len=*), PARAMETER :: routineN = 'complex_frobenius_norm'
     557              :       REAL(KIND=dp), PARAMETER                           :: one = 1.0_dp, zero = 0.0_dp
     558              : 
     559              :       INTEGER                                            :: col_atom, handle, row_atom
     560              :       LOGICAL                                            :: found
     561          284 :       REAL(dp), DIMENSION(:, :), POINTER                 :: block_values, block_values2
     562              :       TYPE(dbcsr_iterator_type)                          :: iter
     563              :       TYPE(dbcsr_type), POINTER                          :: tmp
     564              : 
     565          284 :       CALL timeset(routineN, handle)
     566              : 
     567              :       NULLIFY (tmp)
     568          284 :       ALLOCATE (tmp)
     569          284 :       CALL dbcsr_create(tmp, template=mat_re)
     570              :       !make sure the tmp has the same sparsity pattern as the real and the complex part combined
     571          284 :       CALL dbcsr_add(tmp, mat_re, zero, one)
     572          284 :       CALL dbcsr_add(tmp, mat_im, zero, one)
     573          284 :       CALL dbcsr_set(tmp, zero)
     574              :       !calculate the hadamard product
     575          284 :       CALL dbcsr_iterator_start(iter, tmp)
     576         1804 :       DO WHILE (dbcsr_iterator_blocks_left(iter))
     577         1520 :          CALL dbcsr_iterator_next_block(iter, row_atom, col_atom, block_values)
     578         1520 :          CALL dbcsr_get_block_p(mat_re, row_atom, col_atom, block_values2, found=found)
     579         1520 :          IF (found) THEN
     580       264788 :             block_values = block_values2*block_values2
     581              :          END IF
     582         1520 :          CALL dbcsr_get_block_p(mat_im, row_atom, col_atom, block_values2, found=found)
     583         1520 :          IF (found) THEN
     584       250308 :             block_values = block_values + block_values2*block_values2
     585              :          END IF
     586       133438 :          block_values = SQRT(block_values)
     587              :       END DO
     588          284 :       CALL dbcsr_iterator_stop(iter)
     589          284 :       frob_norm = dbcsr_frobenius_norm(tmp)
     590              : 
     591          284 :       CALL dbcsr_deallocate_matrix(tmp)
     592              : 
     593          284 :       CALL timestop(handle)
     594              : 
     595          284 :    END SUBROUTINE complex_frobenius_norm
     596              : 
     597              : ! **************************************************************************************************
     598              : !> \brief Does McWeeny for complex matrices in the non-orthogonal basis
     599              : !> \param P ...
     600              : !> \param s_mat ...
     601              : !> \param eps ...
     602              : !> \param eps_small ...
     603              : !> \param max_iter ...
     604              : !> \param threshold ...
     605              : !> \author Samuel Andermatt (04.14)
     606              : ! **************************************************************************************************
     607              : 
     608          182 :    SUBROUTINE purify_mcweeny_complex_nonorth(P, s_mat, eps, eps_small, max_iter, threshold)
     609              : 
     610              :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: P, s_mat
     611              :       REAL(KIND=dp), INTENT(in)                          :: eps, eps_small
     612              :       INTEGER, INTENT(in)                                :: max_iter
     613              :       REAL(KIND=dp), INTENT(in)                          :: threshold
     614              : 
     615              :       CHARACTER(len=*), PARAMETER :: routineN = 'purify_mcweeny_complex_nonorth'
     616              :       REAL(KIND=dp), PARAMETER                           :: one = 1.0_dp, zero = 0.0_dp
     617              : 
     618              :       INTEGER                                            :: handle, i, im, imax, ispin, re, unit_nr
     619              :       REAL(KIND=dp)                                      :: frob_norm
     620              :       TYPE(cp_logger_type), POINTER                      :: logger
     621          182 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: PS, PSP, tmp
     622              : 
     623          182 :       CALL timeset(routineN, handle)
     624              : 
     625          182 :       logger => cp_get_default_logger()
     626          182 :       IF (logger%para_env%is_source()) THEN
     627           91 :          unit_nr = cp_logger_get_default_unit_nr(logger, local=.TRUE.)
     628              :       ELSE
     629              :          unit_nr = -1
     630              :       END IF
     631              : 
     632          182 :       NULLIFY (tmp, PS, PSP)
     633          182 :       CALL dbcsr_allocate_matrix_set(tmp, SIZE(P))
     634          182 :       CALL dbcsr_allocate_matrix_set(PSP, SIZE(P))
     635          182 :       CALL dbcsr_allocate_matrix_set(PS, SIZE(P))
     636          686 :       DO i = 1, SIZE(P)
     637          504 :          CALL dbcsr_init_p(PS(i)%matrix)
     638          504 :          CALL dbcsr_create(PS(i)%matrix, template=P(1)%matrix)
     639          504 :          CALL dbcsr_init_p(PSP(i)%matrix)
     640          504 :          CALL dbcsr_create(PSP(i)%matrix, template=P(1)%matrix)
     641          504 :          CALL dbcsr_init_p(tmp(i)%matrix)
     642          686 :          CALL dbcsr_create(tmp(i)%matrix, template=P(1)%matrix)
     643              :       END DO
     644          182 :       IF (SIZE(P) == 2) THEN
     645          112 :          CALL dbcsr_scale(P(1)%matrix, one/2)
     646          112 :          CALL dbcsr_scale(P(2)%matrix, one/2)
     647              :       END IF
     648          434 :       DO ispin = 1, SIZE(P)/2
     649          252 :          re = 2*ispin - 1
     650          252 :          im = 2*ispin
     651          252 :          imax = MAX(max_iter, 1) !if max_iter is 0 then only the deviation from idempotency needs to be calculated
     652          516 :          DO i = 1, imax
     653              :             CALL dbcsr_multiply("N", "N", one, P(re)%matrix, s_mat(1)%matrix, &
     654          284 :                                 zero, PS(re)%matrix, filter_eps=eps_small)
     655              :             CALL dbcsr_multiply("N", "N", one, P(im)%matrix, s_mat(1)%matrix, &
     656          284 :                                 zero, PS(im)%matrix, filter_eps=eps_small)
     657              :             CALL cp_complex_dbcsr_gemm_3("N", "N", one, PS(re)%matrix, PS(im)%matrix, &
     658              :                                          P(re)%matrix, P(im)%matrix, zero, PSP(re)%matrix, PSP(im)%matrix, &
     659          284 :                                          filter_eps=eps_small)
     660          284 :             CALL dbcsr_copy(tmp(re)%matrix, PSP(re)%matrix)
     661          284 :             CALL dbcsr_copy(tmp(im)%matrix, PSP(im)%matrix)
     662          284 :             CALL dbcsr_add(tmp(re)%matrix, P(re)%matrix, 1.0_dp, -1.0_dp)
     663          284 :             CALL dbcsr_add(tmp(im)%matrix, P(im)%matrix, 1.0_dp, -1.0_dp)
     664          284 :             CALL complex_frobenius_norm(frob_norm, tmp(re)%matrix, tmp(im)%matrix)
     665          284 :             IF (unit_nr > 0) WRITE (unit_nr, '(t3,a,2f16.8)') "Deviation from idempotency: ", frob_norm
     666          800 :             IF (frob_norm > threshold .AND. max_iter > 0) THEN
     667          264 :                CALL dbcsr_copy(P(re)%matrix, PSP(re)%matrix)
     668          264 :                CALL dbcsr_copy(P(im)%matrix, PSP(im)%matrix)
     669              :                CALL cp_complex_dbcsr_gemm_3("N", "N", -2.0_dp, PS(re)%matrix, PS(im)%matrix, &
     670              :                                             PSP(re)%matrix, PSP(im)%matrix, 3.0_dp, P(re)%matrix, P(im)%matrix, &
     671          264 :                                             filter_eps=eps_small)
     672          264 :                CALL dbcsr_filter(P(re)%matrix, eps)
     673          264 :                CALL dbcsr_filter(P(im)%matrix, eps)
     674              :                !make sure P is exactly hermitian
     675          264 :                CALL dbcsr_transposed(tmp(re)%matrix, P(re)%matrix)
     676          264 :                CALL dbcsr_add(P(re)%matrix, tmp(re)%matrix, one/2, one/2)
     677          264 :                CALL dbcsr_transposed(tmp(im)%matrix, P(im)%matrix)
     678          264 :                CALL dbcsr_add(P(im)%matrix, tmp(im)%matrix, one/2, -one/2)
     679              :             ELSE
     680              :                EXIT
     681              :             END IF
     682              :          END DO
     683              :          !make sure P is hermitian
     684          252 :          CALL dbcsr_transposed(tmp(re)%matrix, P(re)%matrix)
     685          252 :          CALL dbcsr_add(P(re)%matrix, tmp(re)%matrix, one/2, one/2)
     686          252 :          CALL dbcsr_transposed(tmp(im)%matrix, P(im)%matrix)
     687          434 :          CALL dbcsr_add(P(im)%matrix, tmp(im)%matrix, one/2, -one/2)
     688              :       END DO
     689          182 :       IF (SIZE(P) == 2) THEN
     690          112 :          CALL dbcsr_scale(P(1)%matrix, one*2)
     691          112 :          CALL dbcsr_scale(P(2)%matrix, one*2)
     692              :       END IF
     693          182 :       CALL dbcsr_deallocate_matrix_set(tmp)
     694          182 :       CALL dbcsr_deallocate_matrix_set(PS)
     695          182 :       CALL dbcsr_deallocate_matrix_set(PSP)
     696              : 
     697          182 :       CALL timestop(handle)
     698              : 
     699          182 :    END SUBROUTINE purify_mcweeny_complex_nonorth
     700              : 
     701              : ! **************************************************************************************************
     702              : !> \brief ...
     703              : !> \param rtp ...
     704              : !> \param matrix_s ...
     705              : !> \param aspc_order ...
     706              : ! **************************************************************************************************
     707          626 :    SUBROUTINE aspc_extrapolate(rtp, matrix_s, aspc_order)
     708              :       TYPE(rt_prop_type), POINTER                        :: rtp
     709              :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_s
     710              :       INTEGER, INTENT(in)                                :: aspc_order
     711              : 
     712              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'aspc_extrapolate'
     713              :       COMPLEX(KIND=dp), PARAMETER                        :: cone = (1.0_dp, 0.0_dp), &
     714              :                                                             czero = (0.0_dp, 0.0_dp)
     715              :       REAL(KIND=dp), PARAMETER                           :: one = 1.0_dp, zero = 0.0_dp
     716              : 
     717              :       INTEGER                                            :: handle, i, iaspc, icol_local, ihist, &
     718              :                                                             imat, k, kdbl, n, naspc, ncol_local, &
     719              :                                                             nmat
     720              :       REAL(KIND=dp)                                      :: alpha
     721              :       TYPE(cp_cfm_type)                                  :: cfm_tmp, cfm_tmp1, csc
     722              :       TYPE(cp_fm_struct_type), POINTER                   :: matrix_struct, matrix_struct_new
     723              :       TYPE(cp_fm_type)                                   :: fm_tmp, fm_tmp1, fm_tmp2
     724          626 :       TYPE(cp_fm_type), DIMENSION(:), POINTER            :: mos_new
     725          626 :       TYPE(cp_fm_type), DIMENSION(:, :), POINTER         :: mo_hist
     726          626 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: rho_new, s_hist
     727          626 :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: rho_hist
     728              : 
     729          626 :       NULLIFY (rho_hist)
     730          626 :       CALL timeset(routineN, handle)
     731          626 :       CALL cite_reference(Kolafa2004)
     732          626 :       CALL cite_reference(Kuhne2007)
     733              : 
     734          626 :       IF (rtp%linear_scaling) THEN
     735          182 :          CALL get_rtp(rtp=rtp, rho_new=rho_new)
     736              :       ELSE
     737          444 :          CALL get_rtp(rtp=rtp, mos_new=mos_new)
     738              :       END IF
     739              : 
     740          626 :       naspc = MIN(rtp%istep, aspc_order)
     741          626 :       IF (rtp%linear_scaling) THEN
     742          182 :          nmat = SIZE(rho_new)
     743          182 :          rho_hist => rtp%history%rho_history
     744          686 :          DO imat = 1, nmat
     745         1454 :             DO iaspc = 1, naspc
     746              :                alpha = (-1.0_dp)**(iaspc + 1)*REAL(iaspc, KIND=dp)* &
     747          768 :                        binomial(2*naspc, naspc - iaspc)/binomial(2*naspc - 2, naspc - 1)
     748          768 :                ihist = MOD(rtp%istep - iaspc, aspc_order) + 1
     749         1272 :                IF (iaspc == 1) THEN
     750          504 :                   CALL dbcsr_add(rho_new(imat)%matrix, rho_hist(imat, ihist)%matrix, zero, alpha)
     751              :                ELSE
     752          264 :                   CALL dbcsr_add(rho_new(imat)%matrix, rho_hist(imat, ihist)%matrix, one, alpha)
     753              :                END IF
     754              :             END DO
     755              :          END DO
     756              :       ELSE
     757          444 :          mo_hist => rtp%history%mo_history
     758          444 :          nmat = SIZE(mos_new)
     759         1544 :          DO imat = 1, nmat
     760         3968 :             DO iaspc = 1, naspc
     761              :                alpha = (-1.0_dp)**(iaspc + 1)*REAL(iaspc, KIND=dp)* &
     762         2424 :                        binomial(2*naspc, naspc - iaspc)/binomial(2*naspc - 2, naspc - 1)
     763         2424 :                ihist = MOD(rtp%istep - iaspc, aspc_order) + 1
     764         3524 :                IF (iaspc == 1) THEN
     765         1100 :                   CALL cp_fm_scale_and_add(zero, mos_new(imat), alpha, mo_hist(imat, ihist))
     766              :                ELSE
     767         1324 :                   CALL cp_fm_scale_and_add(one, mos_new(imat), alpha, mo_hist(imat, ihist))
     768              :                END IF
     769              :             END DO
     770              :          END DO
     771              : 
     772          444 :          mo_hist => rtp%history%mo_history
     773          444 :          s_hist => rtp%history%s_history
     774          994 :          DO i = 1, SIZE(mos_new)/2
     775          550 :             NULLIFY (matrix_struct, matrix_struct_new)
     776              : 
     777              :             CALL cp_fm_struct_double(matrix_struct, &
     778              :                                      mos_new(2*i)%matrix_struct, &
     779              :                                      mos_new(2*i)%matrix_struct%context, &
     780          550 :                                      .TRUE., .FALSE.)
     781              : 
     782          550 :             CALL cp_fm_create(fm_tmp, matrix_struct)
     783          550 :             CALL cp_fm_create(fm_tmp1, matrix_struct)
     784          550 :             CALL cp_fm_create(fm_tmp2, mos_new(2*i)%matrix_struct)
     785          550 :             CALL cp_cfm_create(cfm_tmp, mos_new(2*i)%matrix_struct)
     786          550 :             CALL cp_cfm_create(cfm_tmp1, mos_new(2*i)%matrix_struct)
     787              : 
     788          550 :             CALL cp_fm_get_info(fm_tmp, ncol_global=kdbl)
     789              : 
     790              :             CALL cp_fm_get_info(mos_new(2*i), &
     791              :                                 nrow_global=n, &
     792              :                                 ncol_global=k, &
     793          550 :                                 ncol_local=ncol_local)
     794              : 
     795              :             CALL cp_fm_struct_create(matrix_struct_new, &
     796              :                                      template_fmstruct=mos_new(2*i)%matrix_struct, &
     797              :                                      nrow_global=k, &
     798          550 :                                      ncol_global=k)
     799          550 :             CALL cp_cfm_create(csc, matrix_struct_new)
     800              : 
     801          550 :             CALL cp_fm_struct_release(matrix_struct_new)
     802          550 :             CALL cp_fm_struct_release(matrix_struct)
     803              : 
     804              :             ! first the most recent
     805              : 
     806              : ! reorthogonalize vectors
     807         2612 :             DO icol_local = 1, ncol_local
     808        22188 :                fm_tmp%local_data(:, icol_local) = mos_new(2*i - 1)%local_data(:, icol_local)
     809        22738 :                fm_tmp%local_data(:, icol_local + ncol_local) = mos_new(2*i)%local_data(:, icol_local)
     810              :             END DO
     811              : 
     812          550 :             CALL cp_dbcsr_sm_fm_multiply(matrix_s(1)%matrix, fm_tmp, fm_tmp1, kdbl)
     813              : 
     814         2612 :             DO icol_local = 1, ncol_local
     815              :                cfm_tmp%local_data(:, icol_local) = CMPLX(fm_tmp1%local_data(:, icol_local), &
     816        22188 :                                                          fm_tmp1%local_data(:, icol_local + ncol_local), dp)
     817              :                cfm_tmp1%local_data(:, icol_local) = CMPLX(mos_new(2*i - 1)%local_data(:, icol_local), &
     818        22738 :                                                           mos_new(2*i)%local_data(:, icol_local), dp)
     819              :             END DO
     820          550 :             CALL parallel_gemm('C', 'N', k, k, n, cone, cfm_tmp1, cfm_tmp, czero, csc)
     821          550 :             CALL cp_cfm_cholesky_decompose(csc)
     822          550 :             CALL cp_cfm_triangular_multiply(csc, cfm_tmp1, n_cols=k, side='R', invert_tr=.TRUE.)
     823         2612 :             DO icol_local = 1, ncol_local
     824        22188 :                mos_new(2*i - 1)%local_data(:, icol_local) = REAL(cfm_tmp1%local_data(:, icol_local), dp)
     825        22738 :                mos_new(2*i)%local_data(:, icol_local) = AIMAG(cfm_tmp1%local_data(:, icol_local))
     826              :             END DO
     827              : 
     828              : ! deallocate work matrices
     829          550 :             CALL cp_cfm_release(csc)
     830          550 :             CALL cp_fm_release(fm_tmp)
     831          550 :             CALL cp_fm_release(fm_tmp1)
     832          550 :             CALL cp_fm_release(fm_tmp2)
     833          550 :             CALL cp_cfm_release(cfm_tmp)
     834         2094 :             CALL cp_cfm_release(cfm_tmp1)
     835              :          END DO
     836              : 
     837              :       END IF
     838              : 
     839          626 :       CALL timestop(handle)
     840              : 
     841          626 :    END SUBROUTINE aspc_extrapolate
     842              : 
     843              : ! **************************************************************************************************
     844              : !> \brief ...
     845              : !> \param rtp ...
     846              : !> \param mos ...
     847              : !> \param rho ...
     848              : !> \param s_mat ...
     849              : !> \param ihist ...
     850              : ! **************************************************************************************************
     851          830 :    SUBROUTINE put_data_to_history(rtp, mos, rho, s_mat, ihist)
     852              :       TYPE(rt_prop_type), POINTER                        :: rtp
     853              :       TYPE(cp_fm_type), DIMENSION(:), POINTER            :: mos
     854              :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: rho
     855              :       TYPE(dbcsr_p_type), DIMENSION(:), OPTIONAL, &
     856              :          POINTER                                         :: s_mat
     857              :       INTEGER                                            :: ihist
     858              : 
     859              :       INTEGER                                            :: i
     860              : 
     861          830 :       IF (rtp%linear_scaling) THEN
     862         1032 :          DO i = 1, SIZE(rho)
     863         1032 :             CALL dbcsr_copy(rtp%history%rho_history(i, ihist)%matrix, rho(i)%matrix)
     864              :          END DO
     865              :       ELSE
     866         1950 :          DO i = 1, SIZE(mos)
     867         1950 :             CALL cp_fm_to_fm(mos(i), rtp%history%mo_history(i, ihist))
     868              :          END DO
     869          558 :          IF (PRESENT(s_mat)) THEN
     870          342 :             IF (ASSOCIATED(rtp%history%s_history(ihist)%matrix)) THEN ! the sparsity might be different
     871              :                ! (future struct:check)
     872          124 :                CALL dbcsr_deallocate_matrix(rtp%history%s_history(ihist)%matrix)
     873              :             END IF
     874          342 :             ALLOCATE (rtp%history%s_history(ihist)%matrix)
     875          342 :             CALL dbcsr_copy(rtp%history%s_history(ihist)%matrix, s_mat(1)%matrix)
     876              :          END IF
     877              :       END IF
     878              : 
     879          830 :    END SUBROUTINE put_data_to_history
     880              : 
     881              : ! **************************************************************************************************
     882              : !> \brief Computes Maximally localised Wannier functions and print properties according to
     883              : !>        FORCE_EVAL%DFT%LOCALIZE, adapted from qs_scf_post_gpw::scf_post_calculation_gpw
     884              : !> \param qs_env QuickStep environment
     885              : !> \param rtp Real time propagation environment
     886              : !> \par History 03/2020 created [LS]
     887              : !> \author Lukas Schreder
     888              : ! **************************************************************************************************
     889          352 :    SUBROUTINE rtp_localize(qs_env, rtp)
     890              : 
     891              :       TYPE(qs_environment_type), INTENT(IN), POINTER     :: qs_env
     892              :       TYPE(rt_prop_type), INTENT(IN), POINTER            :: rtp
     893              : 
     894              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'rtp_localize'
     895              : 
     896              :       INTEGER                                            :: handle, ispin, output_unit
     897          352 :       INTEGER, DIMENSION(:, :, :), POINTER               :: marked_states
     898              :       LOGICAL                                            :: do_homo, do_mo_cubes, do_wannier_cubes, &
     899              :                                                             p_loc
     900          352 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: mo_eigenvalues
     901          352 :       TYPE(cp_1d_r_p_type), DIMENSION(:), POINTER        :: occupied_evals
     902          352 :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:)        :: mo_localized, occupied_orbs
     903          352 :       TYPE(cp_fm_type), DIMENSION(:), POINTER            :: mo_coeff
     904              :       TYPE(cp_logger_type), POINTER                      :: logger
     905              :       TYPE(dft_control_type), POINTER                    :: dft_control
     906          352 :       TYPE(mo_set_type), DIMENSION(:), POINTER           :: mos
     907              :       TYPE(particle_list_type), POINTER                  :: particles
     908              :       TYPE(pw_c1d_gs_type)                               :: wf_g
     909              :       TYPE(pw_env_type), POINTER                         :: pw_env
     910              :       TYPE(pw_pool_type), POINTER                        :: auxbas_pw_pool
     911              :       TYPE(pw_r3d_rs_type)                               :: wf_r
     912              :       TYPE(qs_loc_env_type), POINTER                     :: qs_loc_env
     913              :       TYPE(section_vals_type), POINTER                   :: dft_section, input, loc_print_section, &
     914              :                                                             loc_section, print_key
     915              : 
     916          352 :       CALL timeset(routineN, handle)
     917              : 
     918              :       ! Localization of propagated orbitals requires MO coefficients
     919          352 :       IF (rtp%linear_scaling) THEN
     920          136 :          CALL timestop(handle)
     921          272 :          RETURN
     922              :       END IF
     923              : 
     924          216 :       CALL cite_reference(Schreder2021)
     925              : 
     926          216 :       NULLIFY (auxbas_pw_pool, dft_control, dft_section, input, loc_print_section, &
     927          216 :                loc_section, logger, marked_states, mo_coeff, mo_eigenvalues, mos, &
     928          216 :                occupied_evals, particles, print_key, pw_env, qs_loc_env)
     929              : 
     930          216 :       logger => cp_get_default_logger()
     931          216 :       output_unit = cp_logger_get_default_io_unit(logger)
     932              : 
     933          216 :       IF (output_unit > 0) THEN
     934          108 :          WRITE (unit=output_unit, fmt="(A)") "LOCALIZE| Localizing propagated orbitals"
     935              :       END IF
     936              : 
     937              :       ! get section properties
     938          216 :       CALL get_qs_env(qs_env, dft_control=dft_control, input=input, pw_env=pw_env)
     939              :       ! get propagated MO coeffs
     940          216 :       CALL get_rtp(rtp, mos_new=mo_coeff)
     941          216 :       dft_section => section_vals_get_subs_vals(input, "DFT")
     942          216 :       loc_section => section_vals_get_subs_vals(dft_section, "LOCALIZE")
     943          216 :       loc_print_section => section_vals_get_subs_vals(loc_section, "PRINT")
     944              : 
     945              :       ! what properties to print out
     946          216 :       print_key => section_vals_get_subs_vals(loc_print_section, "MOLECULAR_DIPOLES")
     947          216 :       p_loc = BTEST(cp_print_key_should_output(logger%iter_info, print_key), cp_p_file)
     948              : 
     949          216 :       print_key => section_vals_get_subs_vals(loc_print_section, "TOTAL_DIPOLE")
     950              :       p_loc = p_loc &
     951          216 :               .OR. BTEST(cp_print_key_should_output(logger%iter_info, print_key), cp_p_file)
     952          216 :       print_key => section_vals_get_subs_vals(loc_print_section, "WANNIER_CENTERS")
     953              :       p_loc = p_loc &
     954          216 :               .OR. BTEST(cp_print_key_should_output(logger%iter_info, print_key), cp_p_file)
     955          216 :       print_key => section_vals_get_subs_vals(loc_print_section, "WANNIER_SPREADS")
     956              :       p_loc = p_loc &
     957          216 :               .OR. BTEST(cp_print_key_should_output(logger%iter_info, print_key), cp_p_file)
     958          216 :       print_key => section_vals_get_subs_vals(loc_print_section, "WANNIER_CUBES")
     959              :       p_loc = p_loc &
     960          216 :               .OR. BTEST(cp_print_key_should_output(logger%iter_info, print_key), cp_p_file)
     961          216 :       print_key => section_vals_get_subs_vals(loc_print_section, "MOLECULAR_STATES")
     962              :       p_loc = p_loc &
     963          216 :               .OR. BTEST(cp_print_key_should_output(logger%iter_info, print_key), cp_p_file)
     964          216 :       print_key => section_vals_get_subs_vals(loc_print_section, "MOLECULAR_MOMENTS")
     965              :       p_loc = p_loc &
     966          216 :               .OR. BTEST(cp_print_key_should_output(logger%iter_info, print_key), cp_p_file)
     967          216 :       print_key => section_vals_get_subs_vals(loc_print_section, "LOCALIZED_MOMENTS")
     968              :       p_loc = p_loc &
     969          216 :               .OR. BTEST(cp_print_key_should_output(logger%iter_info, print_key), cp_p_file)
     970          216 :       print_key => section_vals_get_subs_vals(loc_print_section, "WANNIER_STATES")
     971              :       p_loc = p_loc &
     972          216 :               .OR. BTEST(cp_print_key_should_output(logger%iter_info, print_key), cp_p_file)
     973              : 
     974              :       do_wannier_cubes = BTEST(cp_print_key_should_output(logger%iter_info, loc_print_section, &
     975          216 :                                                           "WANNIER_CUBES"), cp_p_file)
     976              : 
     977          216 :       CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool)
     978          216 :       CALL auxbas_pw_pool%create_pw(wf_r)
     979          216 :       CALL auxbas_pw_pool%create_pw(wf_g)
     980              : 
     981          216 :       IF (p_loc) THEN
     982          122 :          ALLOCATE (occupied_evals(dft_control%nspins))
     983          166 :          ALLOCATE (occupied_orbs(SIZE(mo_coeff)))
     984          140 :          ALLOCATE (mo_localized(SIZE(mo_coeff)))
     985           26 :          CALL get_qs_env(qs_env, mos=mos)
     986           26 :          CALL get_rtp(rtp, mos_new=mo_coeff)
     987          114 :          DO ispin = 1, SIZE(mo_coeff)
     988           88 :             occupied_orbs(ispin) = mo_coeff(ispin)
     989           88 :             CALL cp_fm_create(mo_localized(ispin), mo_coeff(ispin)%matrix_struct)
     990          114 :             CALL cp_fm_to_fm(mo_coeff(ispin), mo_localized(ispin))
     991              :          END DO
     992              : 
     993           70 :          DO ispin = 1, dft_control%nspins
     994           44 :             CALL get_mo_set(mos(ispin), eigenvalues=mo_eigenvalues)
     995           70 :             occupied_evals(ispin)%array => mo_eigenvalues
     996              :          END DO
     997              : 
     998           26 :          do_homo = .TRUE.
     999          182 :          ALLOCATE (qs_loc_env)
    1000           26 :          CALL qs_loc_env_create(qs_loc_env)
    1001           26 :          CALL qs_loc_control_init(qs_loc_env, loc_section, do_homo=do_homo)
    1002           26 :          CALL qs_loc_init(qs_env, qs_loc_env, loc_section, mo_localized, do_homo, do_mo_cubes)
    1003              :          CALL get_localization_info(qs_env, qs_loc_env, loc_section, mo_localized, wf_r, wf_g, &
    1004           26 :                                     particles, occupied_orbs, occupied_evals, marked_states)
    1005           26 :          CALL loc_dipole(input, dft_control, qs_loc_env, logger, qs_env)
    1006              : 
    1007          114 :          DO ispin = 1, SIZE(mo_localized)
    1008          114 :             CALL cp_fm_release(mo_localized(ispin))
    1009              :          END DO
    1010           26 :          DEALLOCATE (mo_localized)
    1011           26 :          DEALLOCATE (occupied_orbs)
    1012           26 :          DEALLOCATE (occupied_evals)
    1013           26 :          CALL qs_loc_env_release(qs_loc_env)
    1014           26 :          DEALLOCATE (qs_loc_env)
    1015           52 :          IF (ASSOCIATED(marked_states)) THEN
    1016           18 :             DEALLOCATE (marked_states)
    1017              :          END IF
    1018              :       END IF
    1019              : 
    1020          216 :       CALL auxbas_pw_pool%give_back_pw(wf_r)
    1021          216 :       CALL auxbas_pw_pool%give_back_pw(wf_g)
    1022              : 
    1023          216 :       CALL timestop(handle)
    1024              : 
    1025          840 :    END SUBROUTINE rtp_localize
    1026              : 
    1027              : END MODULE rt_propagation_methods
        

Generated by: LCOV version 2.0-1