LCOV - code coverage report
Current view: top level - src - cp_dbcsr_diag.F (source / functions) Hit Total Coverage
Test: CP2K Regtests (git:4c33f95) Lines: 68 95 71.6 %
Date: 2025-01-30 06:53:08 Functions: 3 4 75.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   Interface to (sca)lapack for the Cholesky based procedures
      10             : !> \author  VW
      11             : !> \date    2009-11-09
      12             : !> \version 0.8
      13             : !>
      14             : !> <b>Modification history:</b>
      15             : !> - Created 2009-11-09
      16             : ! **************************************************************************************************
      17             : MODULE cp_dbcsr_diag
      18             : 
      19             :    USE cp_blacs_env,                    ONLY: cp_blacs_env_type
      20             :    USE cp_cfm_diag,                     ONLY: cp_cfm_heevd
      21             :    USE cp_cfm_types,                    ONLY: cp_cfm_create,&
      22             :                                               cp_cfm_release,&
      23             :                                               cp_cfm_to_fm,&
      24             :                                               cp_cfm_type,&
      25             :                                               cp_fm_to_cfm
      26             :    USE cp_dbcsr_api,                    ONLY: dbcsr_get_info,&
      27             :                                               dbcsr_type
      28             :    USE cp_dbcsr_operations,             ONLY: copy_dbcsr_to_fm,&
      29             :                                               copy_fm_to_dbcsr
      30             :    USE cp_fm_diag,                      ONLY: choose_eigv_solver,&
      31             :                                               cp_fm_power,&
      32             :                                               cp_fm_syevx
      33             :    USE cp_fm_struct,                    ONLY: cp_fm_struct_create,&
      34             :                                               cp_fm_struct_release,&
      35             :                                               cp_fm_struct_type
      36             :    USE cp_fm_types,                     ONLY: cp_fm_create,&
      37             :                                               cp_fm_release,&
      38             :                                               cp_fm_type
      39             :    USE kinds,                           ONLY: dp
      40             :    USE message_passing,                 ONLY: mp_para_env_type
      41             : #include "base/base_uses.f90"
      42             : 
      43             :    IMPLICIT NONE
      44             : 
      45             :    PRIVATE
      46             : 
      47             :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'cp_dbcsr_diag'
      48             : 
      49             :    ! Public subroutines
      50             : 
      51             :    PUBLIC :: cp_dbcsr_syevd, &
      52             :              cp_dbcsr_syevx, &
      53             :              cp_dbcsr_heevd, &
      54             :              cp_dbcsr_power
      55             : 
      56             : CONTAINS
      57             : 
      58             : ! **************************************************************************************************
      59             : !> \brief ...
      60             : !> \param matrix ...
      61             : !> \param eigenvectors ...
      62             : !> \param eigenvalues ...
      63             : !> \param para_env ...
      64             : !> \param blacs_env ...
      65             : ! **************************************************************************************************
      66       45167 :    SUBROUTINE cp_dbcsr_syevd(matrix, eigenvectors, eigenvalues, para_env, blacs_env)
      67             : 
      68             :       ! Computes all eigenvalues and vectors of a real symmetric matrix
      69             :       ! should be quite a bit faster than syevx for that case
      70             :       ! especially in parallel with tightly clustered evals
      71             :       ! needs more workspace in the worst case, but much better distributed
      72             : 
      73             :       TYPE(dbcsr_type)                                   :: matrix, eigenvectors
      74             :       REAL(KIND=dp), DIMENSION(:), INTENT(OUT)           :: eigenvalues
      75             :       TYPE(mp_para_env_type), POINTER                    :: para_env
      76             :       TYPE(cp_blacs_env_type), POINTER                   :: blacs_env
      77             : 
      78             :       CHARACTER(len=*), PARAMETER                        :: routineN = 'cp_dbcsr_syevd'
      79             : 
      80             :       INTEGER                                            :: handle, nfullrows_total
      81             :       TYPE(cp_fm_struct_type), POINTER                   :: fm_struct
      82             :       TYPE(cp_fm_type)                                   :: fm_eigenvectors, fm_matrix
      83             : 
      84       45167 :       CALL timeset(routineN, handle)
      85             : 
      86       45167 :       NULLIFY (fm_struct)
      87       45167 :       CALL dbcsr_get_info(matrix, nfullrows_total=nfullrows_total)
      88             : 
      89             :       CALL cp_fm_struct_create(fm_struct, context=blacs_env, nrow_global=nfullrows_total, &
      90       45167 :                                ncol_global=nfullrows_total, para_env=para_env)
      91       45167 :       CALL cp_fm_create(fm_matrix, fm_struct, name="fm_matrix")
      92       45167 :       CALL cp_fm_create(fm_eigenvectors, fm_struct, name="fm_eigenvectors")
      93       45167 :       CALL cp_fm_struct_release(fm_struct)
      94             : 
      95       45167 :       CALL copy_dbcsr_to_fm(matrix, fm_matrix)
      96             : 
      97       45167 :       CALL choose_eigv_solver(fm_matrix, fm_eigenvectors, eigenvalues)
      98             : 
      99       45167 :       CALL copy_fm_to_dbcsr(fm_eigenvectors, eigenvectors)
     100             : 
     101       45167 :       CALL cp_fm_release(fm_matrix)
     102       45167 :       CALL cp_fm_release(fm_eigenvectors)
     103             : 
     104       45167 :       CALL timestop(handle)
     105             : 
     106       45167 :    END SUBROUTINE cp_dbcsr_syevd
     107             : 
     108             : ! **************************************************************************************************
     109             : !> \brief   compute eigenvalues and optionally eigenvectors of a real symmetric matrix using scalapack.
     110             : !>          If eigenvectors are required this routine will replicate a full matrix on each CPU...
     111             : !>          if more than a handful of vectors are needed, use cp_dbcsr_syevd instead
     112             : !> \param matrix ...
     113             : !> \param eigenvectors ...
     114             : !> \param eigenvalues ...
     115             : !> \param neig ...
     116             : !> \param work_syevx ...
     117             : !> \param para_env ...
     118             : !> \param blacs_env ...
     119             : !> \par     matrix is supposed to be in upper triangular form, and overwritten by this routine
     120             : !>          neig   is the number of vectors needed (default all)
     121             : !>          work_syevx evec calculation only, is the fraction of the working buffer allowed (1.0 use full buffer)
     122             : !>                     reducing this saves time, but might cause the routine to fail
     123             : ! **************************************************************************************************
     124           0 :    SUBROUTINE cp_dbcsr_syevx(matrix, eigenvectors, eigenvalues, neig, work_syevx, &
     125             :                              para_env, blacs_env)
     126             : 
     127             :       ! Diagonalise the symmetric n by n matrix using the LAPACK library.
     128             : 
     129             :       TYPE(dbcsr_type), POINTER                          :: matrix
     130             :       TYPE(dbcsr_type), OPTIONAL, POINTER                :: eigenvectors
     131             :       REAL(KIND=dp), DIMENSION(:), INTENT(OUT)           :: eigenvalues
     132             :       INTEGER, INTENT(IN), OPTIONAL                      :: neig
     133             :       REAL(KIND=dp), INTENT(IN), OPTIONAL                :: work_syevx
     134             :       TYPE(mp_para_env_type), POINTER                    :: para_env
     135             :       TYPE(cp_blacs_env_type), POINTER                   :: blacs_env
     136             : 
     137             :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'cp_dbcsr_syevx'
     138             : 
     139             :       INTEGER                                            :: handle, n, neig_local
     140             :       TYPE(cp_fm_struct_type), POINTER                   :: fm_struct
     141             :       TYPE(cp_fm_type)                                   :: fm_eigenvectors, fm_matrix
     142             : 
     143           0 :       CALL timeset(routineN, handle)
     144             : 
     145             :       ! by default all
     146           0 :       CALL dbcsr_get_info(matrix, nfullrows_total=n)
     147           0 :       neig_local = n
     148           0 :       IF (PRESENT(neig)) neig_local = neig
     149           0 :       IF (neig_local == 0) RETURN
     150             : 
     151           0 :       NULLIFY (fm_struct)
     152             :       CALL cp_fm_struct_create(fm_struct, context=blacs_env, nrow_global=n, &
     153           0 :                                ncol_global=n, para_env=para_env)
     154           0 :       CALL cp_fm_create(fm_matrix, fm_struct, name="fm_matrix")
     155             : 
     156           0 :       CALL copy_dbcsr_to_fm(matrix, fm_matrix)
     157             : 
     158           0 :       IF (PRESENT(eigenvectors)) THEN
     159           0 :          CALL cp_fm_create(fm_eigenvectors, fm_struct, name="fm_eigenvectors")
     160           0 :          CALL cp_fm_syevx(fm_matrix, fm_eigenvectors, eigenvalues, neig, work_syevx)
     161           0 :          CALL copy_fm_to_dbcsr(fm_eigenvectors, eigenvectors)
     162           0 :          CALL cp_fm_release(fm_eigenvectors)
     163             :       ELSE
     164           0 :          CALL cp_fm_syevx(fm_matrix, eigenvalues=eigenvalues, neig=neig, work_syevx=work_syevx)
     165             :       END IF
     166             : 
     167           0 :       CALL cp_fm_struct_release(fm_struct)
     168           0 :       CALL cp_fm_release(fm_matrix)
     169             : 
     170           0 :       CALL timestop(handle)
     171             : 
     172           0 :    END SUBROUTINE cp_dbcsr_syevx
     173             : 
     174             : ! **************************************************************************************************
     175             : !> \brief ...
     176             : !> \param matrix_re ...
     177             : !> \param matrix_im ...
     178             : !> \param eigenvectors_re ...
     179             : !> \param eigenvectors_im ...
     180             : !> \param eigenvalues ...
     181             : !> \param para_env ...
     182             : !> \param blacs_env ...
     183             : ! **************************************************************************************************
     184       10152 :    SUBROUTINE cp_dbcsr_heevd(matrix_re, matrix_im, eigenvectors_re, eigenvectors_im, &
     185        2538 :                              eigenvalues, para_env, blacs_env)
     186             : 
     187             :       TYPE(dbcsr_type), OPTIONAL                         :: matrix_re, matrix_im, eigenvectors_re, &
     188             :                                                             eigenvectors_im
     189             :       REAL(KIND=dp), DIMENSION(:), INTENT(OUT)           :: eigenvalues
     190             :       TYPE(mp_para_env_type), POINTER                    :: para_env
     191             :       TYPE(cp_blacs_env_type), POINTER                   :: blacs_env
     192             : 
     193             :       CHARACTER(len=*), PARAMETER                        :: routineN = 'cp_dbcsr_heevd'
     194             : 
     195             :       INTEGER                                            :: handle, nfullrows_total
     196             :       TYPE(cp_cfm_type)                                  :: cfm_eigenvectors, cfm_matrix
     197             :       TYPE(cp_fm_struct_type), POINTER                   :: fm_struct
     198             :       TYPE(cp_fm_type)                                   :: fm_eigenvectors_im, fm_eigenvectors_re, &
     199             :                                                             fm_matrix_im, fm_matrix_re
     200             : 
     201        2538 :       CALL timeset(routineN, handle)
     202             : 
     203             :       ! Create full matrix structure.
     204        2538 :       NULLIFY (fm_struct)
     205        2538 :       IF (PRESENT(matrix_re)) THEN
     206           0 :          CALL dbcsr_get_info(matrix_re, nfullrows_total=nfullrows_total)
     207        2538 :       ELSE IF (PRESENT(matrix_im)) THEN
     208        2538 :          CALL dbcsr_get_info(matrix_im, nfullrows_total=nfullrows_total)
     209             :       ELSE
     210           0 :          CPABORT("Neither matrix_re nor matrix_im are present.")
     211             :       END IF
     212             :       CALL cp_fm_struct_create(fm_struct, context=blacs_env, nrow_global=nfullrows_total, &
     213        2538 :                                ncol_global=nfullrows_total, para_env=para_env)
     214             : 
     215             :       ! Create full real matrices.
     216        2538 :       IF (PRESENT(matrix_re)) THEN
     217           0 :          CALL cp_fm_create(fm_matrix_re, fm_struct, name="fm_matrix_re")
     218           0 :          CALL copy_dbcsr_to_fm(matrix_re, fm_matrix_re)
     219             :       END IF
     220        2538 :       IF (PRESENT(matrix_im)) THEN
     221        2538 :          CALL cp_fm_create(fm_matrix_im, fm_struct, name="fm_matrix_im")
     222        2538 :          CALL copy_dbcsr_to_fm(matrix_im, fm_matrix_im)
     223             :       END IF
     224             : 
     225             :       ! Combine the two real matrices into a complex matrix.
     226        2538 :       CALL cp_cfm_create(cfm_matrix, fm_struct, name="cfm_matrix")
     227        2538 :       IF (PRESENT(matrix_re) .AND. PRESENT(matrix_im)) THEN
     228           0 :          CALL cp_fm_to_cfm(msourcer=fm_matrix_re, msourcei=fm_matrix_im, mtarget=cfm_matrix)
     229        2538 :       ELSE IF (PRESENT(matrix_re) .AND. .NOT. PRESENT(matrix_im)) THEN
     230           0 :          CALL cp_fm_to_cfm(msourcer=fm_matrix_re, mtarget=cfm_matrix)
     231        2538 :       ELSE IF (.NOT. PRESENT(matrix_re) .AND. PRESENT(matrix_im)) THEN
     232        2538 :          CALL cp_fm_to_cfm(msourcei=fm_matrix_im, mtarget=cfm_matrix)
     233             :       ELSE
     234           0 :          CPABORT("Neither matrix_re nor matrix_im are present.")
     235             :       END IF
     236        2538 :       IF (PRESENT(matrix_re)) CALL cp_fm_release(fm_matrix_re)
     237        2538 :       IF (PRESENT(matrix_im)) CALL cp_fm_release(fm_matrix_im)
     238             : 
     239             :       ! Diagnonalize the full complex matrix.
     240        2538 :       CALL cp_cfm_create(cfm_eigenvectors, fm_struct, name="cfm_eigenvectors")
     241        2538 :       CALL cp_cfm_heevd(cfm_matrix, cfm_eigenvectors, eigenvalues)
     242        2538 :       CALL cp_cfm_release(cfm_matrix)
     243             : 
     244             :       ! Copy the complex eigenvectors back into two real DBCSR matrices.
     245        2538 :       IF (PRESENT(eigenvectors_re)) THEN
     246        2538 :          CALL cp_fm_create(fm_eigenvectors_re, fm_struct, name="fm_eigenvectors_re")
     247        2538 :          CALL cp_cfm_to_fm(msource=cfm_eigenvectors, mtargetr=fm_eigenvectors_re)
     248        2538 :          CALL copy_fm_to_dbcsr(fm_eigenvectors_re, eigenvectors_re)
     249        2538 :          CALL cp_fm_release(fm_eigenvectors_re)
     250             :       END IF
     251        2538 :       IF (PRESENT(eigenvectors_im)) THEN
     252        2538 :          CALL cp_fm_create(fm_eigenvectors_im, fm_struct, name="fm_eigenvectors_im")
     253        2538 :          CALL cp_cfm_to_fm(msource=cfm_eigenvectors, mtargeti=fm_eigenvectors_im)
     254        2538 :          CALL copy_fm_to_dbcsr(fm_eigenvectors_im, eigenvectors_im)
     255        2538 :          CALL cp_fm_release(fm_eigenvectors_im)
     256             :       END IF
     257             : 
     258             :       ! Clean up.
     259        2538 :       CALL cp_cfm_release(cfm_eigenvectors)
     260        2538 :       CALL cp_fm_struct_release(fm_struct)
     261             : 
     262        2538 :       CALL timestop(handle)
     263             : 
     264        2538 :    END SUBROUTINE cp_dbcsr_heevd
     265             : 
     266             : ! **************************************************************************************************
     267             : !> \brief ...
     268             : !> \param matrix ...
     269             : !> \param exponent ...
     270             : !> \param threshold ...
     271             : !> \param n_dependent ...
     272             : !> \param para_env ...
     273             : !> \param blacs_env ...
     274             : !> \param verbose ...
     275             : !> \param eigenvectors ...
     276             : !> \param eigenvalues ...
     277             : ! **************************************************************************************************
     278         410 :    SUBROUTINE cp_dbcsr_power(matrix, exponent, threshold, n_dependent, para_env, blacs_env, verbose, eigenvectors, eigenvalues)
     279             :       TYPE(dbcsr_type), INTENT(INOUT)                    :: matrix
     280             :       REAL(dp), INTENT(IN)                               :: exponent, threshold
     281             :       INTEGER, INTENT(OUT)                               :: n_dependent
     282             :       TYPE(mp_para_env_type), POINTER                    :: para_env
     283             :       TYPE(cp_blacs_env_type), POINTER                   :: blacs_env
     284             :       LOGICAL, INTENT(IN), OPTIONAL                      :: verbose
     285             :       TYPE(dbcsr_type), INTENT(INOUT), OPTIONAL          :: eigenvectors
     286             :       REAL(KIND=dp), DIMENSION(2), INTENT(OUT), OPTIONAL :: eigenvalues
     287             : 
     288             :       CHARACTER(len=*), PARAMETER                        :: routineN = 'cp_dbcsr_power'
     289             : 
     290             :       INTEGER                                            :: handle, nfullrows_total
     291             :       REAL(KIND=dp), DIMENSION(2)                        :: eigenvalues_prv
     292             :       TYPE(cp_fm_struct_type), POINTER                   :: fm_struct
     293             :       TYPE(cp_fm_type)                                   :: fm_eigenvectors, fm_matrix
     294             : 
     295          82 :       CALL timeset(routineN, handle)
     296             : 
     297          82 :       NULLIFY (fm_struct)
     298          82 :       CALL dbcsr_get_info(matrix, nfullrows_total=nfullrows_total)
     299             : 
     300             :       CALL cp_fm_struct_create(fm_struct, context=blacs_env, nrow_global=nfullrows_total, &
     301          82 :                                ncol_global=nfullrows_total, para_env=para_env)
     302          82 :       CALL cp_fm_create(fm_matrix, fm_struct, name="fm_matrix")
     303          82 :       CALL cp_fm_create(fm_eigenvectors, fm_struct, name="fm_eigenvectors")
     304          82 :       CALL cp_fm_struct_release(fm_struct)
     305             : 
     306          82 :       CALL copy_dbcsr_to_fm(matrix, fm_matrix)
     307             : 
     308          82 :       CALL cp_fm_power(fm_matrix, fm_eigenvectors, exponent, threshold, n_dependent, verbose, eigenvalues_prv)
     309             : 
     310          82 :       CALL copy_fm_to_dbcsr(fm_matrix, matrix)
     311          82 :       CALL cp_fm_release(fm_matrix)
     312             : 
     313          82 :       IF (PRESENT(eigenvalues)) eigenvalues(:) = eigenvalues_prv
     314          82 :       IF (PRESENT(eigenvectors)) CALL copy_fm_to_dbcsr(fm_eigenvectors, eigenvectors)
     315             : 
     316          82 :       CALL cp_fm_release(fm_eigenvectors)
     317             : 
     318          82 :       CALL timestop(handle)
     319             : 
     320          82 :    END SUBROUTINE
     321             : 
     322             : END MODULE cp_dbcsr_diag

Generated by: LCOV version 1.15