LCOV - code coverage report
Current view: top level - src - ls_matrix_exp.F (source / functions) Hit Total Coverage
Test: CP2K Regtests (git:3130539) Lines: 202 209 96.7 %
Date: 2025-05-14 06:57:18 Functions: 5 5 100.0 %

          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 for calculating a complex matrix exponential with dbcsr matrices.
      10             : !>        Based on the code in matrix_exp.F from Florian Schiffmann
      11             : !> \author Samuel Andermatt (02.14)
      12             : ! **************************************************************************************************
      13             : MODULE ls_matrix_exp
      14             : 
      15             :    USE cp_dbcsr_api,                    ONLY: &
      16             :         dbcsr_add, dbcsr_copy, dbcsr_create, dbcsr_deallocate_matrix, dbcsr_filter, &
      17             :         dbcsr_multiply, dbcsr_p_type, dbcsr_release, dbcsr_scale, dbcsr_set, dbcsr_transposed, &
      18             :         dbcsr_type
      19             :    USE cp_dbcsr_contrib,                ONLY: dbcsr_add_on_diag,&
      20             :                                               dbcsr_frobenius_norm
      21             :    USE cp_log_handling,                 ONLY: cp_logger_get_default_io_unit
      22             :    USE kinds,                           ONLY: dp
      23             : #include "./base/base_uses.f90"
      24             : 
      25             :    IMPLICIT NONE
      26             : 
      27             :    PRIVATE
      28             : 
      29             :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'ls_matrix_exp'
      30             : 
      31             :    PUBLIC :: taylor_only_imaginary_dbcsr, &
      32             :              taylor_full_complex_dbcsr, &
      33             :              cp_complex_dbcsr_gemm_3, &
      34             :              bch_expansion_imaginary_propagator, &
      35             :              bch_expansion_complex_propagator
      36             : 
      37             : CONTAINS
      38             : 
      39             : ! **************************************************************************************************
      40             : !> \brief Convenience function. Computes the matrix multiplications needed
      41             : !>        for the multiplication of complex sparse matrices.
      42             : !>        C = beta * C + alpha * ( A  ** transa ) * ( B ** transb )
      43             : !> \param transa : 'N' -> normal   'T' -> transpose
      44             : !>      alpha,beta :: can be 0.0_dp and 1.0_dp
      45             : !> \param transb ...
      46             : !> \param alpha ...
      47             : !> \param A_re m x k matrix ( ! for transa = 'N'), real part
      48             : !> \param A_im m x k matrix ( ! for transa = 'N'), imaginary part
      49             : !> \param B_re k x n matrix ( ! for transb = 'N'), real part
      50             : !> \param B_im k x n matrix ( ! for transb = 'N'), imaginary part
      51             : !> \param beta ...
      52             : !> \param C_re m x n matrix, real part
      53             : !> \param C_im m x n matrix, imaginary part
      54             : !> \param filter_eps ...
      55             : !> \author Samuel Andermatt
      56             : !> \note
      57             : !>      C should have no overlap with A, B
      58             : !>      This subroutine uses three real matrix multiplications instead of two complex
      59             : !>      This reduces the amount of flops and memory bandwidth by 25%, but for memory bandwidth
      60             : !>      true complex algebra is still superior (one third less bandwidth needed)
      61             : !>      limited cases matrix multiplications
      62             : ! **************************************************************************************************
      63        6852 :    SUBROUTINE cp_complex_dbcsr_gemm_3(transa, transb, alpha, A_re, A_im, &
      64             :                                       B_re, B_im, beta, C_re, C_im, filter_eps)
      65             :       CHARACTER(LEN=1), INTENT(IN)                       :: transa, transb
      66             :       REAL(KIND=dp), INTENT(IN)                          :: alpha
      67             :       TYPE(dbcsr_type), INTENT(IN)                       :: A_re, A_im, B_re, B_im
      68             :       REAL(KIND=dp), INTENT(IN)                          :: beta
      69             :       TYPE(dbcsr_type), INTENT(INOUT)                    :: C_re, C_im
      70             :       REAL(KIND=dp), INTENT(IN), OPTIONAL                :: filter_eps
      71             : 
      72             :       CHARACTER(len=*), PARAMETER :: routineN = 'cp_complex_dbcsr_gemm_3'
      73             :       REAL(KIND=dp), PARAMETER                           :: one = 1.0_dp, zero = 0.0_dp
      74             : 
      75             :       CHARACTER(LEN=1)                                   :: transa2, transb2
      76             :       INTEGER                                            :: handle
      77             :       REAL(KIND=dp)                                      :: alpha2, alpha3, alpha4
      78             :       TYPE(dbcsr_type), POINTER                          :: a_plus_b, ac, bd, c_plus_d
      79             : 
      80        6852 :       CALL timeset(routineN, handle)
      81             :       !A complex matrix matrix multiplication can be done with only three multiplications
      82             :       !(a+ib)*(c+id)=ac-bd+i((a+b)*(c+d) - ac - bd)
      83             :       !A_re=a, A_im=b, B_re=c, B_im=d
      84             : 
      85        6852 :       alpha2 = -alpha
      86        6852 :       alpha3 = alpha
      87        6852 :       alpha4 = alpha
      88             : 
      89        6852 :       IF (transa == "C") THEN
      90           0 :          alpha2 = -alpha2
      91           0 :          alpha3 = -alpha3
      92           0 :          transa2 = "T"
      93             :       ELSE
      94        6852 :          transa2 = transa
      95             :       END IF
      96        6852 :       IF (transb == "C") THEN
      97        1068 :          alpha2 = -alpha2
      98        1068 :          alpha4 = -alpha4
      99        1068 :          transb2 = "T"
     100             :       ELSE
     101        5784 :          transb2 = transb
     102             :       END IF
     103             : 
     104             :       !create the work matrices
     105             :       NULLIFY (ac)
     106        6852 :       ALLOCATE (ac)
     107        6852 :       CALL dbcsr_create(ac, template=A_re, matrix_type="N")
     108             :       NULLIFY (bd)
     109        6852 :       ALLOCATE (bd)
     110        6852 :       CALL dbcsr_create(bd, template=A_re, matrix_type="N")
     111             :       NULLIFY (a_plus_b)
     112        6852 :       ALLOCATE (a_plus_b)
     113        6852 :       CALL dbcsr_create(a_plus_b, template=A_re, matrix_type="N")
     114             :       NULLIFY (c_plus_d)
     115        6852 :       ALLOCATE (c_plus_d)
     116        6852 :       CALL dbcsr_create(c_plus_d, template=A_re, matrix_type="N")
     117             : 
     118             :       !Do the neccesarry multiplications
     119        6852 :       CALL dbcsr_multiply(transa2, transb2, alpha, A_re, B_re, zero, ac, filter_eps=filter_eps)
     120        6852 :       CALL dbcsr_multiply(transa2, transb2, alpha2, A_im, B_im, zero, bd, filter_eps=filter_eps)
     121             : 
     122        6852 :       CALL dbcsr_add(a_plus_b, A_re, zero, alpha)
     123        6852 :       CALL dbcsr_add(a_plus_b, A_im, one, alpha3)
     124        6852 :       CALL dbcsr_add(c_plus_d, B_re, zero, alpha)
     125        6852 :       CALL dbcsr_add(c_plus_d, B_im, one, alpha4)
     126             : 
     127             :       !this can already be written into C_im
     128             :       !now both matrixes have been scaled which means we currently multiplied by alpha squared
     129        6852 :       CALL dbcsr_multiply(transa2, transb2, one/alpha, a_plus_b, c_plus_d, beta, C_im, filter_eps=filter_eps)
     130             : 
     131             :       !now add up all the terms into the result
     132        6852 :       CALL dbcsr_add(C_re, ac, beta, one)
     133             :       !the minus sign was already taken care of at the definition of alpha2
     134        6852 :       CALL dbcsr_add(C_re, bd, one, one)
     135        6852 :       CALL dbcsr_filter(C_re, filter_eps)
     136             : 
     137        6852 :       CALL dbcsr_add(C_im, ac, one, -one)
     138             :       !the minus sign was already taken care of at the definition of alpha2
     139        6852 :       CALL dbcsr_add(C_im, bd, one, one)
     140        6852 :       CALL dbcsr_filter(C_im, filter_eps)
     141             : 
     142             :       !Deallocate the work matrices
     143        6852 :       CALL dbcsr_deallocate_matrix(ac)
     144        6852 :       CALL dbcsr_deallocate_matrix(bd)
     145        6852 :       CALL dbcsr_deallocate_matrix(a_plus_b)
     146        6852 :       CALL dbcsr_deallocate_matrix(c_plus_d)
     147             : 
     148        6852 :       CALL timestop(handle)
     149             : 
     150        6852 :    END SUBROUTINE cp_complex_dbcsr_gemm_3
     151             : 
     152             : ! **************************************************************************************************
     153             : !> \brief specialized subroutine for purely imaginary matrix exponentials
     154             : !> \param exp_H ...
     155             : !> \param im_matrix ...
     156             : !> \param nsquare ...
     157             : !> \param ntaylor ...
     158             : !> \param filter_eps ...
     159             : !> \author Samuel Andermatt (02.2014)
     160             : ! **************************************************************************************************
     161         704 :    SUBROUTINE taylor_only_imaginary_dbcsr(exp_H, im_matrix, nsquare, ntaylor, filter_eps)
     162             : 
     163             :       TYPE(dbcsr_p_type), DIMENSION(2)                   :: exp_H
     164             :       TYPE(dbcsr_type), POINTER                          :: im_matrix
     165             :       INTEGER, INTENT(in)                                :: nsquare, ntaylor
     166             :       REAL(KIND=dp), INTENT(in)                          :: filter_eps
     167             : 
     168             :       CHARACTER(len=*), PARAMETER :: routineN = 'taylor_only_imaginary_dbcsr'
     169             :       REAL(KIND=dp), PARAMETER                           :: one = 1.0_dp, zero = 0.0_dp
     170             : 
     171             :       INTEGER                                            :: handle, i, nloop
     172             :       REAL(KIND=dp)                                      :: square_fac, Tfac, tmp
     173             :       TYPE(dbcsr_type), POINTER                          :: T1, T2, Tres_im, Tres_re
     174             : 
     175         704 :       CALL timeset(routineN, handle)
     176             : 
     177             :       !The divider that comes from the scaling and squaring procedure
     178         704 :       square_fac = 1.0_dp/(2.0_dp**REAL(nsquare, dp))
     179             : 
     180             :       !Allocate work matrices
     181             :       NULLIFY (T1)
     182         704 :       ALLOCATE (T1)
     183         704 :       CALL dbcsr_create(T1, template=im_matrix, matrix_type="N")
     184             :       NULLIFY (T2)
     185         704 :       ALLOCATE (T2)
     186         704 :       CALL dbcsr_create(T2, template=im_matrix, matrix_type="N")
     187             :       NULLIFY (Tres_re)
     188         704 :       ALLOCATE (Tres_re)
     189         704 :       CALL dbcsr_create(Tres_re, template=im_matrix, matrix_type="N")
     190             :       NULLIFY (Tres_im)
     191         704 :       ALLOCATE (Tres_im)
     192         704 :       CALL dbcsr_create(Tres_im, template=im_matrix, matrix_type="N")
     193             : 
     194             :       !Create the unit matrices
     195         704 :       CALL dbcsr_set(T1, zero)
     196         704 :       CALL dbcsr_add_on_diag(T1, one)
     197         704 :       CALL dbcsr_set(Tres_re, zero)
     198         704 :       CALL dbcsr_add_on_diag(Tres_re, one)
     199         704 :       CALL dbcsr_set(Tres_im, zero)
     200             : 
     201         704 :       nloop = CEILING(REAL(ntaylor, dp)/2.0_dp)
     202             :       !the inverse of the prefactor in the taylor series
     203         704 :       tmp = 1.0_dp
     204        3488 :       DO i = 1, nloop
     205        2784 :          CALL dbcsr_scale(T1, 1.0_dp/(REAL(i, dp)*2.0_dp - 1.0_dp))
     206        2784 :          CALL dbcsr_filter(T1, filter_eps)
     207             :          CALL dbcsr_multiply("N", "N", square_fac, im_matrix, T1, zero, &
     208        2784 :                              T2, filter_eps=filter_eps)
     209        2784 :          Tfac = one
     210        2784 :          IF (MOD(i, 2) == 0) Tfac = -Tfac
     211        2784 :          CALL dbcsr_add(Tres_im, T2, one, Tfac)
     212        2784 :          CALL dbcsr_scale(T2, 1.0_dp/(REAL(i, dp)*2.0_dp))
     213        2784 :          CALL dbcsr_filter(T2, filter_eps)
     214             :          CALL dbcsr_multiply("N", "N", square_fac, im_matrix, T2, zero, &
     215        2784 :                              T1, filter_eps=filter_eps)
     216        2784 :          Tfac = one
     217        2784 :          IF (MOD(i, 2) == 1) Tfac = -Tfac
     218        3488 :          CALL dbcsr_add(Tres_re, T1, one, Tfac)
     219             :       END DO
     220             : 
     221             :       !Square the matrices, due to the scaling and squaring procedure
     222         704 :       IF (nsquare .GT. 0) THEN
     223           0 :          DO i = 1, nsquare
     224             :             CALL cp_complex_dbcsr_gemm_3("N", "N", one, Tres_re, Tres_im, &
     225             :                                          Tres_re, Tres_im, zero, exp_H(1)%matrix, exp_H(2)%matrix, &
     226           0 :                                          filter_eps=filter_eps)
     227           0 :             CALL dbcsr_copy(Tres_re, exp_H(1)%matrix)
     228           0 :             CALL dbcsr_copy(Tres_im, exp_H(2)%matrix)
     229             :          END DO
     230             :       ELSE
     231         704 :          CALL dbcsr_copy(exp_H(1)%matrix, Tres_re)
     232         704 :          CALL dbcsr_copy(exp_H(2)%matrix, Tres_im)
     233             :       END IF
     234         704 :       CALL dbcsr_deallocate_matrix(T1)
     235         704 :       CALL dbcsr_deallocate_matrix(T2)
     236         704 :       CALL dbcsr_deallocate_matrix(Tres_re)
     237         704 :       CALL dbcsr_deallocate_matrix(Tres_im)
     238             : 
     239         704 :       CALL timestop(handle)
     240             : 
     241         704 :    END SUBROUTINE taylor_only_imaginary_dbcsr
     242             : 
     243             : ! **************************************************************************************************
     244             : !> \brief subroutine for general complex matrix exponentials
     245             : !>        on input a separate dbcsr_type for real and complex part
     246             : !>        on output a size 2 dbcsr_p_type, first element is the real part of
     247             : !>        the exponential second the imaginary
     248             : !> \param exp_H ...
     249             : !> \param re_part ...
     250             : !> \param im_part ...
     251             : !> \param nsquare ...
     252             : !> \param ntaylor ...
     253             : !> \param filter_eps ...
     254             : !> \author Samuel Andermatt (02.2014)
     255             : ! **************************************************************************************************
     256         264 :    SUBROUTINE taylor_full_complex_dbcsr(exp_H, re_part, im_part, nsquare, ntaylor, filter_eps)
     257             :       TYPE(dbcsr_p_type), DIMENSION(2)                   :: exp_H
     258             :       TYPE(dbcsr_type), POINTER                          :: re_part, im_part
     259             :       INTEGER, INTENT(in)                                :: nsquare, ntaylor
     260             :       REAL(KIND=dp), INTENT(in)                          :: filter_eps
     261             : 
     262             :       CHARACTER(len=*), PARAMETER :: routineN = 'taylor_full_complex_dbcsr'
     263             : 
     264             :       INTEGER                                            :: handle, i
     265             :       REAL(KIND=dp)                                      :: square_fac
     266             :       TYPE(dbcsr_type)                                   :: T1_im, T1_re, T2_im, T2_re
     267             :       TYPE(dbcsr_type), POINTER                          :: Tres_im, Tres_re
     268             : 
     269         264 :       CALL timeset(routineN, handle)
     270             : 
     271             :       ! convenient aliases for result matrices
     272         264 :       Tres_re => exp_H(1)%matrix
     273         264 :       Tres_im => exp_H(2)%matrix
     274             : 
     275             :       ! The divider that comes from the scaling and squaring procedure
     276         264 :       square_fac = 1.0_dp/REAL(2**nsquare, dp)
     277             : 
     278             :       ! Allocate work matrices
     279         264 :       CALL dbcsr_create(T1_re, template=re_part, matrix_type="N")
     280         264 :       CALL dbcsr_create(T1_im, template=re_part, matrix_type="N")
     281         264 :       CALL dbcsr_create(T2_re, template=re_part, matrix_type="N")
     282         264 :       CALL dbcsr_create(T2_im, template=re_part, matrix_type="N")
     283             : 
     284             :       ! T1 = identity
     285         264 :       CALL dbcsr_set(T1_re, 0.0_dp)
     286         264 :       CALL dbcsr_set(T1_im, 0.0_dp)
     287         264 :       CALL dbcsr_add_on_diag(T1_re, 1.0_dp)
     288             : 
     289             :       ! Tres = identity
     290         264 :       CALL dbcsr_set(Tres_re, 0.0_dp)
     291         264 :       CALL dbcsr_set(Tres_im, 0.0_dp)
     292         264 :       CALL dbcsr_add_on_diag(Tres_re, 1.0_dp)
     293             : 
     294        2522 :       DO i = 1, ntaylor
     295             :          ! T1 = T1 / i
     296        2258 :          CALL dbcsr_scale(T1_re, 1.0_dp/REAL(i, dp))
     297        2258 :          CALL dbcsr_scale(T1_im, 1.0_dp/REAL(i, dp))
     298        2258 :          CALL dbcsr_filter(T1_re, filter_eps)
     299        2258 :          CALL dbcsr_filter(T1_im, filter_eps)
     300             : 
     301             :          ! T2 = square_fac * T1 * input
     302             :          CALL cp_complex_dbcsr_gemm_3("N", "N", alpha=square_fac, beta=0.0_dp, &
     303             :                                       A_re=T1_re, A_im=T1_im, &
     304             :                                       B_re=re_part, B_im=im_part, &
     305        2258 :                                       C_re=T2_re, C_im=T2_im, filter_eps=filter_eps)
     306             : 
     307             :          ! Tres = Tres + T2
     308        2258 :          CALL dbcsr_add(Tres_re, T2_re, 1.0_dp, 1.0_dp)
     309        2258 :          CALL dbcsr_add(Tres_im, T2_im, 1.0_dp, 1.0_dp)
     310             : 
     311             :          ! T1 = T2
     312        2258 :          CALL dbcsr_copy(T1_re, T2_re)
     313        2522 :          CALL dbcsr_copy(T1_im, T2_im)
     314             :       END DO
     315             : 
     316         264 :       IF (nsquare .GT. 0) THEN
     317         970 :          DO i = 1, nsquare
     318             :             ! T2 = Tres * Tres
     319             :             CALL cp_complex_dbcsr_gemm_3("N", "N", alpha=1.0_dp, beta=0.0_dp, &
     320             :                                          A_re=Tres_re, A_im=Tres_im, &
     321             :                                          B_re=Tres_re, B_im=Tres_im, &
     322         758 :                                          C_re=T2_re, C_im=T2_im, filter_eps=filter_eps)
     323             : 
     324             :             ! Tres = T2
     325         758 :             CALL dbcsr_copy(Tres_re, T2_re)
     326         970 :             CALL dbcsr_copy(Tres_im, T2_im)
     327             :          END DO
     328             :       END IF
     329             : 
     330         264 :       CALL dbcsr_release(T1_re)
     331         264 :       CALL dbcsr_release(T1_im)
     332         264 :       CALL dbcsr_release(T2_re)
     333         264 :       CALL dbcsr_release(T2_im)
     334             : 
     335         264 :       CALL timestop(handle)
     336             : 
     337         264 :    END SUBROUTINE taylor_full_complex_dbcsr
     338             : 
     339             : ! **************************************************************************************************
     340             : !> \brief  The Baker-Campbell-Hausdorff expansion for a purely imaginary exponent (e.g. rtp)
     341             : !>         Works for a non unitary propagator, because the density matrix is hermitian
     342             : !> \param propagator The exponent of the matrix exponential
     343             : !> \param density_re Real part of the density matrix
     344             : !> \param density_im Imaginary part of the density matrix
     345             : !> \param filter_eps The filtering threshold for all matrices
     346             : !> \param filter_eps_small ...
     347             : !> \param eps_exp The accuracy of the exponential
     348             : !> \author Samuel Andermatt (02.2014)
     349             : ! **************************************************************************************************
     350         112 :    SUBROUTINE bch_expansion_imaginary_propagator(propagator, density_re, density_im, filter_eps, filter_eps_small, eps_exp)
     351             :       TYPE(dbcsr_type), POINTER                          :: propagator, density_re, density_im
     352             :       REAL(KIND=dp), INTENT(in)                          :: filter_eps, filter_eps_small, eps_exp
     353             : 
     354             :       CHARACTER(len=*), PARAMETER :: routineN = 'bch_expansion_imaginary_propagator'
     355             :       REAL(KIND=dp), PARAMETER                           :: one = 1.0_dp, zero = 0.0_dp
     356             : 
     357             :       INTEGER                                            :: handle, i, unit_nr
     358             :       LOGICAL                                            :: convergence
     359             :       REAL(KIND=dp)                                      :: alpha, max_alpha, prefac
     360             :       TYPE(dbcsr_type), POINTER                          :: comm, comm2, tmp, tmp2
     361             : 
     362         112 :       CALL timeset(routineN, handle)
     363             : 
     364         112 :       unit_nr = cp_logger_get_default_io_unit()
     365             : 
     366             :       NULLIFY (tmp)
     367         112 :       ALLOCATE (tmp)
     368         112 :       CALL dbcsr_create(tmp, template=propagator)
     369             :       NULLIFY (tmp2)
     370         112 :       ALLOCATE (tmp2)
     371         112 :       CALL dbcsr_create(tmp2, template=propagator)
     372             :       NULLIFY (comm)
     373         112 :       ALLOCATE (comm)
     374         112 :       CALL dbcsr_create(comm, template=propagator)
     375             :       NULLIFY (comm2)
     376         112 :       ALLOCATE (comm2)
     377         112 :       CALL dbcsr_create(comm2, template=propagator)
     378             : 
     379         112 :       CALL dbcsr_copy(tmp, density_re)
     380         112 :       CALL dbcsr_copy(tmp2, density_im)
     381             : 
     382         112 :       convergence = .FALSE.
     383         494 :       DO i = 1, 20
     384         494 :          prefac = one/i
     385             :          CALL dbcsr_multiply("N", "N", -prefac, propagator, tmp2, zero, comm, &
     386         494 :                              filter_eps=filter_eps_small)
     387             :          CALL dbcsr_multiply("N", "N", prefac, propagator, tmp, zero, comm2, &
     388         494 :                              filter_eps=filter_eps_small)
     389         494 :          CALL dbcsr_transposed(tmp, comm)
     390         494 :          CALL dbcsr_transposed(tmp2, comm2)
     391         494 :          CALL dbcsr_add(comm, tmp, one, one)
     392         494 :          CALL dbcsr_add(comm2, tmp2, one, -one)
     393         494 :          CALL dbcsr_add(density_re, comm, one, one)
     394         494 :          CALL dbcsr_add(density_im, comm2, one, one)
     395         494 :          CALL dbcsr_copy(tmp, comm)
     396         494 :          CALL dbcsr_copy(tmp2, comm2)
     397             :          !check for convergence
     398         494 :          max_alpha = zero
     399         494 :          alpha = dbcsr_frobenius_norm(comm)
     400         494 :          IF (alpha > max_alpha) max_alpha = alpha
     401         494 :          alpha = dbcsr_frobenius_norm(comm2)
     402         494 :          IF (alpha > max_alpha) max_alpha = alpha
     403         494 :          IF (max_alpha < eps_exp) convergence = .TRUE.
     404         382 :          IF (convergence) THEN
     405         112 :             IF (unit_nr > 0) WRITE (UNIT=unit_nr, FMT="((T3,A,I2,A))") &
     406          56 :                "BCH converged after ", i, " steps"
     407             :             EXIT
     408             :          END IF
     409             :       END DO
     410             : 
     411         112 :       CALL dbcsr_filter(density_re, filter_eps)
     412         112 :       CALL dbcsr_filter(density_im, filter_eps)
     413             : 
     414         112 :       CPWARN_IF(.NOT. convergence, "BCH method did not converge")
     415             : 
     416         112 :       CALL dbcsr_deallocate_matrix(tmp)
     417         112 :       CALL dbcsr_deallocate_matrix(tmp2)
     418         112 :       CALL dbcsr_deallocate_matrix(comm)
     419         112 :       CALL dbcsr_deallocate_matrix(comm2)
     420             : 
     421         112 :       CALL timestop(handle)
     422             : 
     423         112 :    END SUBROUTINE bch_expansion_imaginary_propagator
     424             : 
     425             : ! **************************************************************************************************
     426             : !> \brief  The Baker-Campbell-Hausdorff expansion for a complex exponent (e.g. rtp)
     427             : !>         Works for a non unitary propagator, because the density matrix is hermitian
     428             : !> \param propagator_re Real part of the exponent
     429             : !> \param propagator_im Imaginary part of the exponent
     430             : !> \param density_re Real part of the density matrix
     431             : !> \param density_im Imaginary part of the density matrix
     432             : !> \param filter_eps The filtering threshold for all matrices
     433             : !> \param filter_eps_small ...
     434             : !> \param eps_exp The accuracy of the exponential
     435             : !> \author Samuel Andermatt (02.2014)
     436             : ! **************************************************************************************************
     437         124 :    SUBROUTINE bch_expansion_complex_propagator(propagator_re, propagator_im, density_re, density_im, &
     438             :                                                filter_eps, filter_eps_small, eps_exp)
     439             :       TYPE(dbcsr_type), POINTER                          :: propagator_re, propagator_im, &
     440             :                                                             density_re, density_im
     441             :       REAL(KIND=dp), INTENT(in)                          :: filter_eps, filter_eps_small, eps_exp
     442             : 
     443             :       CHARACTER(len=*), PARAMETER :: routineN = 'bch_expansion_complex_propagator'
     444             :       REAL(KIND=dp), PARAMETER                           :: one = 1.0_dp, zero = 0.0_dp
     445             : 
     446             :       INTEGER                                            :: handle, i, unit_nr
     447             :       LOGICAL                                            :: convergence
     448             :       REAL(KIND=dp)                                      :: alpha, max_alpha, prefac
     449             :       TYPE(dbcsr_type), POINTER                          :: comm, comm2, tmp, tmp2
     450             : 
     451         124 :       CALL timeset(routineN, handle)
     452             : 
     453         124 :       unit_nr = cp_logger_get_default_io_unit()
     454             : 
     455             :       NULLIFY (tmp)
     456         124 :       ALLOCATE (tmp)
     457         124 :       CALL dbcsr_create(tmp, template=propagator_re)
     458             :       NULLIFY (tmp2)
     459         124 :       ALLOCATE (tmp2)
     460         124 :       CALL dbcsr_create(tmp2, template=propagator_re)
     461             :       NULLIFY (comm)
     462         124 :       ALLOCATE (comm)
     463         124 :       CALL dbcsr_create(comm, template=propagator_re)
     464             :       NULLIFY (comm2)
     465         124 :       ALLOCATE (comm2)
     466         124 :       CALL dbcsr_create(comm2, template=propagator_re)
     467             : 
     468         124 :       CALL dbcsr_copy(tmp, density_re)
     469         124 :       CALL dbcsr_copy(tmp2, density_im)
     470             : 
     471         124 :       convergence = .FALSE.
     472             : 
     473        1152 :       DO i = 1, 20
     474        1152 :          prefac = one/i
     475             :          CALL cp_complex_dbcsr_gemm_3("N", "N", prefac, propagator_re, propagator_im, &
     476        1152 :                                       tmp, tmp2, zero, comm, comm2, filter_eps=filter_eps_small)
     477        1152 :          CALL dbcsr_transposed(tmp, comm)
     478        1152 :          CALL dbcsr_transposed(tmp2, comm2)
     479        1152 :          CALL dbcsr_add(comm, tmp, one, one)
     480        1152 :          CALL dbcsr_add(comm2, tmp2, one, -one)
     481        1152 :          CALL dbcsr_add(density_re, comm, one, one)
     482        1152 :          CALL dbcsr_add(density_im, comm2, one, one)
     483        1152 :          CALL dbcsr_copy(tmp, comm)
     484        1152 :          CALL dbcsr_copy(tmp2, comm2)
     485             :          !check for convergence
     486        1152 :          max_alpha = zero
     487        1152 :          alpha = dbcsr_frobenius_norm(comm)
     488        1152 :          IF (alpha > max_alpha) max_alpha = alpha
     489        1152 :          alpha = dbcsr_frobenius_norm(comm2)
     490        1152 :          IF (alpha > max_alpha) max_alpha = alpha
     491        1152 :          IF (max_alpha < eps_exp) convergence = .TRUE.
     492        1028 :          IF (convergence) THEN
     493         124 :             IF (unit_nr > 0) WRITE (UNIT=unit_nr, FMT="((T3,A,I2,A))") &
     494          62 :                "BCH converged after ", i, " steps"
     495             :             EXIT
     496             :          END IF
     497             :       END DO
     498             : 
     499         124 :       CALL dbcsr_filter(density_re, filter_eps)
     500         124 :       CALL dbcsr_filter(density_im, filter_eps)
     501             : 
     502         124 :       CPWARN_IF(.NOT. convergence, "BCH method did not converge")
     503             : 
     504         124 :       CALL dbcsr_deallocate_matrix(tmp)
     505         124 :       CALL dbcsr_deallocate_matrix(tmp2)
     506         124 :       CALL dbcsr_deallocate_matrix(comm)
     507         124 :       CALL dbcsr_deallocate_matrix(comm2)
     508             : 
     509         124 :       CALL timestop(handle)
     510             : 
     511         124 :    END SUBROUTINE bch_expansion_complex_propagator
     512             : 
     513             : END MODULE ls_matrix_exp

Generated by: LCOV version 1.15