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