LCOV - code coverage report
Current view: top level - src - preconditioner_apply.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:24d69ee) Lines: 78.1 % 187 146
Test Date: 2026-09-03 07:32:15 Functions: 81.8 % 11 9

            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 computes preconditioners, and implements methods to apply them
      10              : !>      currently used in qs_ot
      11              : !> \par History
      12              : !>      - [UB] 2009-05-13 Adding stable approximate inverse (full and sparse)
      13              : !> \author Joost VandeVondele (09.2002)
      14              : ! **************************************************************************************************
      15              : MODULE preconditioner_apply
      16              :    USE cp_cfm_basic_linalg,             ONLY: cp_cfm_gemm
      17              :    USE cp_cfm_types,                    ONLY: cp_cfm_create,&
      18              :                                               cp_cfm_get_info,&
      19              :                                               cp_cfm_release,&
      20              :                                               cp_cfm_to_fm,&
      21              :                                               cp_cfm_type,&
      22              :                                               cp_fm_to_cfm
      23              :    USE cp_dbcsr_api,                    ONLY: &
      24              :         dbcsr_add, dbcsr_copy, dbcsr_get_info, dbcsr_iterator_blocks_left, &
      25              :         dbcsr_iterator_next_block, dbcsr_iterator_start, dbcsr_iterator_stop, dbcsr_iterator_type, &
      26              :         dbcsr_multiply, dbcsr_release, dbcsr_set, dbcsr_type
      27              :    USE cp_dbcsr_operations,             ONLY: copy_dbcsr_to_fm,&
      28              :                                               copy_fm_to_dbcsr
      29              :    USE cp_fm_basic_linalg,              ONLY: cp_fm_scale,&
      30              :                                               cp_fm_scale_and_add
      31              :    USE cp_fm_cholesky,                  ONLY: cp_fm_cholesky_restore
      32              :    USE cp_fm_types,                     ONLY: cp_fm_create,&
      33              :                                               cp_fm_get_info,&
      34              :                                               cp_fm_release,&
      35              :                                               cp_fm_to_fm,&
      36              :                                               cp_fm_type
      37              :    USE input_constants,                 ONLY: &
      38              :         ot_precond_full_all, ot_precond_full_kinetic, ot_precond_full_single, &
      39              :         ot_precond_full_single_inverse, ot_precond_s_inverse, ot_precond_solver_chebyshev, &
      40              :         ot_precond_solver_direct, ot_precond_solver_inv_chol, ot_precond_solver_update
      41              :    USE kinds,                           ONLY: dp
      42              :    USE mathconstants,                   ONLY: z_one,&
      43              :                                               z_zero
      44              :    USE parallel_gemm_api,               ONLY: parallel_gemm
      45              :    USE preconditioner_types,            ONLY: preconditioner_type
      46              : #include "./base/base_uses.f90"
      47              : 
      48              :    IMPLICIT NONE
      49              :    PRIVATE
      50              : 
      51              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'preconditioner_apply'
      52              : 
      53              :    PUBLIC :: apply_preconditioner_cfm_complex, apply_preconditioner_dbcsr_complex, &
      54              :              apply_preconditioner_fm, apply_preconditioner_dbcsr
      55              : 
      56              : CONTAINS
      57              : 
      58              : ! **************************************************************************************************
      59              : !> \brief applies a previously created preconditioner to a full matrix
      60              : !> \param preconditioner_env ...
      61              : !> \param matrix_in ...
      62              : !> \param matrix_out ...
      63              : ! **************************************************************************************************
      64        50362 :    SUBROUTINE apply_preconditioner_fm(preconditioner_env, matrix_in, matrix_out)
      65              : 
      66              :       TYPE(preconditioner_type)                          :: preconditioner_env
      67              :       TYPE(cp_fm_type), INTENT(IN)                       :: matrix_in, matrix_out
      68              : 
      69              :       CHARACTER(len=*), PARAMETER :: routineN = 'apply_preconditioner_fm'
      70              : 
      71              :       INTEGER                                            :: handle
      72              : 
      73        50362 :       CALL timeset(routineN, handle)
      74              : 
      75        50362 :       SELECT CASE (preconditioner_env%in_use)
      76              :       CASE (0)
      77            0 :          CPABORT("No preconditioner in use")
      78              :       CASE (ot_precond_full_single)
      79         1320 :          CALL apply_full_single(preconditioner_env, matrix_in, matrix_out)
      80              :       CASE (ot_precond_full_all)
      81        28380 :          CALL apply_full_all(preconditioner_env, matrix_in, matrix_out)
      82              :       CASE (ot_precond_full_kinetic, ot_precond_full_single_inverse, ot_precond_s_inverse)
      83        41324 :          SELECT CASE (preconditioner_env%solver)
      84              :          CASE (ot_precond_solver_inv_chol, ot_precond_solver_update)
      85        20662 :             CALL apply_full_single(preconditioner_env, matrix_in, matrix_out)
      86              :          CASE (ot_precond_solver_direct)
      87            0 :             CALL apply_full_direct(preconditioner_env, matrix_in, matrix_out)
      88              :          CASE (ot_precond_solver_chebyshev)
      89            0 :             CALL apply_chebyshev_fm(preconditioner_env, matrix_in, matrix_out)
      90              :          CASE DEFAULT
      91        20662 :             CPABORT("Solver not implemented")
      92              :          END SELECT
      93              :       CASE DEFAULT
      94        50362 :          CPABORT("Unknown preconditioner")
      95              :       END SELECT
      96              : 
      97        50362 :       CALL timestop(handle)
      98              : 
      99        50362 :    END SUBROUTINE apply_preconditioner_fm
     100              : 
     101              : ! **************************************************************************************************
     102              : !> \brief ...
     103              : !> \param preconditioner_env ...
     104              : !> \param matrix_in ...
     105              : !> \param matrix_out ...
     106              : ! **************************************************************************************************
     107        76441 :    SUBROUTINE apply_preconditioner_dbcsr(preconditioner_env, matrix_in, matrix_out)
     108              : 
     109              :       TYPE(preconditioner_type)                          :: preconditioner_env
     110              :       TYPE(dbcsr_type)                                   :: matrix_in, matrix_out
     111              : 
     112              :       CHARACTER(len=*), PARAMETER :: routineN = 'apply_preconditioner_dbcsr'
     113              : 
     114              :       INTEGER                                            :: handle
     115              : 
     116        76441 :       CALL timeset(routineN, handle)
     117              : 
     118        76441 :       SELECT CASE (preconditioner_env%in_use)
     119              :       CASE (0)
     120            0 :          CPABORT("No preconditioner in use")
     121              :       CASE (ot_precond_full_single)
     122          202 :          CALL apply_single(preconditioner_env, matrix_in, matrix_out)
     123              :       CASE (ot_precond_full_all)
     124        23636 :          CALL apply_all(preconditioner_env, matrix_in, matrix_out)
     125              :       CASE (ot_precond_full_kinetic, ot_precond_full_single_inverse, ot_precond_s_inverse)
     126       105168 :          SELECT CASE (preconditioner_env%solver)
     127              :          CASE (ot_precond_solver_inv_chol, ot_precond_solver_update)
     128        52565 :             CALL apply_single(preconditioner_env, matrix_in, matrix_out)
     129              :          CASE (ot_precond_solver_direct)
     130            0 :             CPABORT("Apply_full_direct not supported with ot")
     131              :             !CALL apply_full_direct(preconditioner_env, matrix_in, matrix_out)
     132              :          CASE (ot_precond_solver_chebyshev)
     133           38 :             CALL apply_chebyshev_dbcsr(preconditioner_env, matrix_in, matrix_out)
     134              :          CASE DEFAULT
     135        52603 :             CPABORT("Wrong solver")
     136              :          END SELECT
     137              :       CASE DEFAULT
     138        76441 :          CPABORT("Wrong preconditioner")
     139              :       END SELECT
     140              : 
     141        76441 :       CALL timestop(handle)
     142              : 
     143        76441 :    END SUBROUTINE apply_preconditioner_dbcsr
     144              : 
     145              : ! **************************************************************************************************
     146              : !> \brief Apply a complex k-point orbital preconditioner.
     147              : !> \param preconditioner_env complex preconditioner storage
     148              : !> \param matrix_in complex input channel
     149              : !> \param matrix_out complex output channel
     150              : ! **************************************************************************************************
     151        57864 :    SUBROUTINE apply_preconditioner_cfm_complex(preconditioner_env, matrix_in, matrix_out)
     152              : 
     153              :       TYPE(preconditioner_type)                          :: preconditioner_env
     154              :       TYPE(cp_cfm_type), INTENT(IN)                      :: matrix_in, matrix_out
     155              : 
     156              :       CHARACTER(len=*), PARAMETER :: routineN = 'apply_preconditioner_cfm_complex'
     157              : 
     158              :       COMPLEX(KIND=dp), CONTIGUOUS, DIMENSION(:, :), &
     159        19288 :          POINTER                                         :: local_data
     160              :       INTEGER                                            :: handle, i, j, k, n, ncol_local, npre, &
     161              :                                                             nrow_local
     162        19288 :       INTEGER, DIMENSION(:), POINTER                     :: col_indices, row_indices
     163              :       REAL(KIND=dp)                                      :: scale
     164              :       TYPE(cp_cfm_type)                                  :: matrix_spectral
     165              : 
     166        19288 :       CALL timeset(routineN, handle)
     167              : 
     168        19288 :       SELECT CASE (preconditioner_env%in_use)
     169              :       CASE (ot_precond_full_all, ot_precond_full_single, ot_precond_full_single_inverse, &
     170              :             ot_precond_full_kinetic, ot_precond_s_inverse)
     171              :       CASE DEFAULT
     172        19288 :          CPABORT("Unsupported complex K-point OT preconditioner")
     173              :       END SELECT
     174        19288 :       CPASSERT(ASSOCIATED(preconditioner_env%complex_fm))
     175        19288 :       CALL cp_cfm_get_info(matrix_in, nrow_global=n, ncol_global=k)
     176        19288 :       CALL cp_cfm_get_info(preconditioner_env%complex_fm, nrow_global=npre)
     177        19288 :       CPASSERT(n == npre)
     178              : 
     179        19288 :       IF (preconditioner_env%in_use == ot_precond_full_all) THEN
     180        15321 :          CPASSERT(ASSOCIATED(preconditioner_env%full_evals))
     181        15321 :          CPASSERT(ASSOCIATED(preconditioner_env%occ_evals))
     182        15321 :          CPASSERT(n == SIZE(preconditioner_env%full_evals))
     183        15321 :          CPASSERT(k == SIZE(preconditioner_env%occ_evals))
     184              :          CALL cp_cfm_create(matrix_spectral, matrix_in%matrix_struct, &
     185        15321 :                             name='complex FULL_ALL spectral input')
     186              :          CALL cp_cfm_gemm('C', 'N', n, k, n, z_one, preconditioner_env%complex_fm, &
     187        15321 :                           matrix_in, z_zero, matrix_spectral)
     188              :          CALL cp_cfm_get_info(matrix_spectral, nrow_local=nrow_local, ncol_local=ncol_local, &
     189        15321 :                               row_indices=row_indices, col_indices=col_indices, local_data=local_data)
     190       276066 :          DO j = 1, ncol_local
     191      7408673 :             DO i = 1, nrow_local
     192              :                scale = 1.0_dp/MAX(preconditioner_env%energy_gap, &
     193              :                                   preconditioner_env%full_evals(row_indices(i)) - &
     194      7132607 :                                   preconditioner_env%occ_evals(col_indices(j)))
     195      7393352 :                local_data(i, j) = scale*local_data(i, j)
     196              :             END DO
     197              :          END DO
     198              :          CALL cp_cfm_gemm('N', 'N', n, k, n, z_one, preconditioner_env%complex_fm, &
     199        15321 :                           matrix_spectral, z_zero, matrix_out)
     200        15321 :          CALL cp_cfm_release(matrix_spectral)
     201              :       ELSE
     202              :          CALL cp_cfm_gemm('N', 'N', n, k, n, z_one, preconditioner_env%complex_fm, &
     203         3967 :                           matrix_in, z_zero, matrix_out)
     204              :       END IF
     205              : 
     206        19288 :       CALL timestop(handle)
     207              : 
     208        19288 :    END SUBROUTINE apply_preconditioner_cfm_complex
     209              : 
     210              : ! **************************************************************************************************
     211              : !> \brief Apply a complex orbital preconditioner to paired real/imaginary DBCSR matrices.
     212              : !> \param preconditioner_env complex k-point preconditioner
     213              : !> \param matrix_in_re real input channel
     214              : !> \param matrix_in_im imaginary input channel
     215              : !> \param matrix_out_re real output channel
     216              : !> \param matrix_out_im imaginary output channel
     217              : ! **************************************************************************************************
     218        29096 :    SUBROUTINE apply_preconditioner_dbcsr_complex(preconditioner_env, matrix_in_re, matrix_in_im, &
     219              :                                                  matrix_out_re, matrix_out_im)
     220              : 
     221              :       TYPE(preconditioner_type)                          :: preconditioner_env
     222              :       TYPE(dbcsr_type)                                   :: matrix_in_re, matrix_in_im, &
     223              :                                                             matrix_out_re, matrix_out_im
     224              : 
     225              :       CHARACTER(len=*), PARAMETER :: routineN = 'apply_preconditioner_dbcsr_complex'
     226              : 
     227              :       INTEGER                                            :: handle, k, n
     228              :       TYPE(cp_cfm_type)                                  :: matrix_in, matrix_out
     229              :       TYPE(cp_fm_type)                                   :: matrix_in_im_fm, matrix_in_re_fm, &
     230              :                                                             matrix_out_im_fm, matrix_out_re_fm
     231              : 
     232         3637 :       CALL timeset(routineN, handle)
     233              : 
     234         3637 :       CALL dbcsr_get_info(matrix_in_re, nfullrows_total=n, nfullcols_total=k)
     235         3637 :       CPASSERT(ASSOCIATED(preconditioner_env%complex_fm))
     236              : 
     237              :       CALL cp_fm_create(matrix_in_re_fm, preconditioner_env%complex_fm%matrix_struct, &
     238         3637 :                         nrow=n, ncol=k, name='complex preconditioner input real')
     239              :       CALL cp_fm_create(matrix_in_im_fm, preconditioner_env%complex_fm%matrix_struct, &
     240         3637 :                         nrow=n, ncol=k, name='complex preconditioner input imaginary')
     241              :       CALL cp_fm_create(matrix_out_re_fm, preconditioner_env%complex_fm%matrix_struct, &
     242         3637 :                         nrow=n, ncol=k, name='complex preconditioner output real')
     243              :       CALL cp_fm_create(matrix_out_im_fm, preconditioner_env%complex_fm%matrix_struct, &
     244         3637 :                         nrow=n, ncol=k, name='complex preconditioner output imaginary')
     245         3637 :       CALL copy_dbcsr_to_fm(matrix_in_re, matrix_in_re_fm)
     246         3637 :       CALL copy_dbcsr_to_fm(matrix_in_im, matrix_in_im_fm)
     247              : 
     248              :       CALL cp_cfm_create(matrix_in, matrix_in_re_fm%matrix_struct, &
     249         3637 :                          name='complex preconditioner input')
     250              :       CALL cp_cfm_create(matrix_out, matrix_in_re_fm%matrix_struct, &
     251         3637 :                          name='complex preconditioner output')
     252         3637 :       CALL cp_fm_to_cfm(matrix_in_re_fm, matrix_in_im_fm, matrix_in)
     253         3637 :       CALL apply_preconditioner_cfm_complex(preconditioner_env, matrix_in, matrix_out)
     254         3637 :       CALL cp_cfm_to_fm(matrix_out, matrix_out_re_fm, matrix_out_im_fm)
     255         3637 :       CALL dbcsr_set(matrix_out_re, 0.0_dp)
     256         3637 :       CALL dbcsr_set(matrix_out_im, 0.0_dp)
     257         3637 :       CALL copy_fm_to_dbcsr(matrix_out_re_fm, matrix_out_re)
     258         3637 :       CALL copy_fm_to_dbcsr(matrix_out_im_fm, matrix_out_im)
     259              : 
     260         3637 :       CALL cp_cfm_release(matrix_out)
     261         3637 :       CALL cp_cfm_release(matrix_in)
     262         3637 :       CALL cp_fm_release(matrix_out_im_fm)
     263         3637 :       CALL cp_fm_release(matrix_out_re_fm)
     264         3637 :       CALL cp_fm_release(matrix_in_im_fm)
     265         3637 :       CALL cp_fm_release(matrix_in_re_fm)
     266              : 
     267         3637 :       CALL timestop(handle)
     268              : 
     269         3637 :    END SUBROUTINE apply_preconditioner_dbcsr_complex
     270              : 
     271              : ! **************************************************************************************************
     272              : !> \brief apply to full matrix, complete inversion has already been done
     273              : !> \param preconditioner_env ...
     274              : !> \param matrix_in ...
     275              : !> \param matrix_out ...
     276              : ! **************************************************************************************************
     277        43964 :    SUBROUTINE apply_full_single(preconditioner_env, matrix_in, matrix_out)
     278              : 
     279              :       TYPE(preconditioner_type)                          :: preconditioner_env
     280              :       TYPE(cp_fm_type), INTENT(IN)                       :: matrix_in, matrix_out
     281              : 
     282              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'apply_full_single'
     283              : 
     284              :       INTEGER                                            :: handle, k, n
     285              : 
     286        21982 :       CALL timeset(routineN, handle)
     287              : 
     288        21982 :       CALL cp_fm_get_info(matrix_in, nrow_global=n, ncol_global=k)
     289              :       CALL parallel_gemm('N', 'N', n, k, n, 1.0_dp, preconditioner_env%fm, &
     290        21982 :                          matrix_in, 0.0_dp, matrix_out)
     291        21982 :       CALL timestop(handle)
     292              : 
     293        21982 :    END SUBROUTINE apply_full_single
     294              : 
     295              : ! **************************************************************************************************
     296              : !> \brief apply to dbcsr matrix, complete inversion has already been done
     297              : !> \param preconditioner_env ...
     298              : !> \param matrix_in ...
     299              : !> \param matrix_out ...
     300              : ! **************************************************************************************************
     301        52767 :    SUBROUTINE apply_single(preconditioner_env, matrix_in, matrix_out)
     302              : 
     303              :       TYPE(preconditioner_type)                          :: preconditioner_env
     304              :       TYPE(dbcsr_type)                                   :: matrix_in, matrix_out
     305              : 
     306              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'apply_single'
     307              : 
     308              :       INTEGER                                            :: handle
     309              : 
     310        52767 :       CALL timeset(routineN, handle)
     311              : 
     312        52767 :       IF (.NOT. ASSOCIATED(preconditioner_env%dbcsr_matrix)) THEN
     313            0 :          CPABORT("NOT ASSOCIATED preconditioner_env%dbcsr_matrix")
     314              :       END IF
     315              :       CALL dbcsr_multiply('N', 'N', 1.0_dp, preconditioner_env%dbcsr_matrix, matrix_in, &
     316        52767 :                           0.0_dp, matrix_out)
     317              : 
     318        52767 :       CALL timestop(handle)
     319              : 
     320        52767 :    END SUBROUTINE apply_single
     321              : 
     322              : ! **************************************************************************************************
     323              : !> \brief preconditioner contains the factorization, application done by
     324              : !>        solving the linear system
     325              : !> \param preconditioner_env ...
     326              : !> \param matrix_in ...
     327              : !> \param matrix_out ...
     328              : ! **************************************************************************************************
     329            0 :    SUBROUTINE apply_full_direct(preconditioner_env, matrix_in, matrix_out)
     330              : 
     331              :       TYPE(preconditioner_type)                          :: preconditioner_env
     332              :       TYPE(cp_fm_type), INTENT(IN)                       :: matrix_in, matrix_out
     333              : 
     334              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'apply_full_direct'
     335              : 
     336              :       INTEGER                                            :: handle, k, n
     337              :       TYPE(cp_fm_type)                                   :: work
     338              : 
     339            0 :       CALL timeset(routineN, handle)
     340              : 
     341            0 :       CALL cp_fm_get_info(matrix_in, nrow_global=n, ncol_global=k)
     342            0 :       CALL cp_fm_create(work, matrix_in%matrix_struct, name="apply_full_single")
     343              :       CALL cp_fm_cholesky_restore(matrix_in, k, preconditioner_env%fm, work,&
     344            0 :            &                      "SOLVE", transa="T")
     345              :       CALL cp_fm_cholesky_restore(work, k, preconditioner_env%fm, matrix_out,&
     346            0 :            &                      "SOLVE", transa="N")
     347            0 :       CALL cp_fm_release(work)
     348              : 
     349            0 :       CALL timestop(handle)
     350              : 
     351            0 :    END SUBROUTINE apply_full_direct
     352              : 
     353              : ! **************************************************************************************************
     354              : !> \brief Apply a Chebyshev approximation to the inverse of the stored dense SPD operator.
     355              : !> \param preconditioner_env ...
     356              : !> \param matrix_in ...
     357              : !> \param matrix_out ...
     358              : ! **************************************************************************************************
     359            0 :    SUBROUTINE apply_chebyshev_fm(preconditioner_env, matrix_in, matrix_out)
     360              : 
     361              :       TYPE(preconditioner_type)                          :: preconditioner_env
     362              :       TYPE(cp_fm_type), INTENT(IN)                       :: matrix_in, matrix_out
     363              : 
     364              :       INTEGER                                            :: degree, iteration, k, n
     365              :       REAL(KIND=dp)                                      :: delta, rho, rho_previous, sigma, theta
     366              :       TYPE(cp_fm_type)                                   :: direction, residual
     367              : 
     368            0 :       CPASSERT(ASSOCIATED(preconditioner_env%fm))
     369            0 :       degree = preconditioner_env%polynomial_degree
     370            0 :       CPASSERT(degree >= 1)
     371            0 :       theta = 0.5_dp*(preconditioner_env%polynomial_max + preconditioner_env%polynomial_min)
     372            0 :       delta = 0.5_dp*(preconditioner_env%polynomial_max - preconditioner_env%polynomial_min)
     373            0 :       sigma = theta/delta
     374            0 :       rho_previous = 1.0_dp/sigma
     375            0 :       CALL cp_fm_get_info(matrix_in, nrow_global=n, ncol_global=k)
     376            0 :       CALL cp_fm_create(direction, matrix_in%matrix_struct, name='Chebyshev direction')
     377            0 :       CALL cp_fm_create(residual, matrix_in%matrix_struct, name='Chebyshev residual')
     378            0 :       CALL cp_fm_to_fm(matrix_in, direction)
     379            0 :       CALL cp_fm_scale(1.0_dp/theta, direction)
     380            0 :       CALL cp_fm_to_fm(direction, matrix_out)
     381            0 :       DO iteration = 2, degree
     382            0 :          CALL cp_fm_to_fm(matrix_in, residual)
     383              :          CALL parallel_gemm('N', 'N', n, k, n, -1.0_dp, preconditioner_env%fm, &
     384            0 :                             matrix_out, 1.0_dp, residual)
     385            0 :          rho = 1.0_dp/(2.0_dp*sigma - rho_previous)
     386            0 :          CALL cp_fm_scale(rho*rho_previous, direction)
     387            0 :          CALL cp_fm_scale_and_add(1.0_dp, direction, 2.0_dp*rho/delta, residual)
     388            0 :          CALL cp_fm_scale_and_add(1.0_dp, matrix_out, 1.0_dp, direction)
     389            0 :          rho_previous = rho
     390              :       END DO
     391            0 :       CALL cp_fm_release(residual)
     392            0 :       CALL cp_fm_release(direction)
     393              : 
     394            0 :    END SUBROUTINE apply_chebyshev_fm
     395              : 
     396              : ! **************************************************************************************************
     397              : !> \brief Apply a Chebyshev approximation to the inverse of the stored sparse SPD operator.
     398              : !> \param preconditioner_env ...
     399              : !> \param matrix_in ...
     400              : !> \param matrix_out ...
     401              : ! **************************************************************************************************
     402           38 :    SUBROUTINE apply_chebyshev_dbcsr(preconditioner_env, matrix_in, matrix_out)
     403              : 
     404              :       TYPE(preconditioner_type)                          :: preconditioner_env
     405              :       TYPE(dbcsr_type)                                   :: matrix_in, matrix_out
     406              : 
     407              :       INTEGER                                            :: degree, iteration
     408              :       REAL(KIND=dp)                                      :: delta, rho, rho_previous, sigma, theta
     409              :       TYPE(dbcsr_type)                                   :: direction, residual
     410              : 
     411            0 :       CPASSERT(ASSOCIATED(preconditioner_env%dbcsr_matrix))
     412           38 :       degree = preconditioner_env%polynomial_degree
     413           38 :       CPASSERT(degree >= 1)
     414           38 :       theta = 0.5_dp*(preconditioner_env%polynomial_max + preconditioner_env%polynomial_min)
     415           38 :       delta = 0.5_dp*(preconditioner_env%polynomial_max - preconditioner_env%polynomial_min)
     416           38 :       sigma = theta/delta
     417           38 :       rho_previous = 1.0_dp/sigma
     418           38 :       CALL dbcsr_copy(direction, matrix_in, name='Chebyshev direction')
     419           38 :       CALL dbcsr_copy(residual, matrix_in, name='Chebyshev residual')
     420           38 :       CALL dbcsr_set(matrix_out, 0.0_dp)
     421           38 :       CALL dbcsr_add(matrix_out, direction, 1.0_dp, 1.0_dp/theta)
     422           38 :       CALL dbcsr_set(direction, 0.0_dp)
     423           38 :       CALL dbcsr_add(direction, matrix_in, 1.0_dp, 1.0_dp/theta)
     424          304 :       DO iteration = 2, degree
     425          266 :          CALL dbcsr_set(residual, 0.0_dp)
     426          266 :          CALL dbcsr_add(residual, matrix_in, 1.0_dp, 1.0_dp)
     427              :          CALL dbcsr_multiply('N', 'N', -1.0_dp, preconditioner_env%dbcsr_matrix, &
     428          266 :                              matrix_out, 1.0_dp, residual)
     429          266 :          rho = 1.0_dp/(2.0_dp*sigma - rho_previous)
     430          266 :          CALL dbcsr_add(direction, residual, rho*rho_previous, 2.0_dp*rho/delta)
     431          266 :          CALL dbcsr_add(matrix_out, direction, 1.0_dp, 1.0_dp)
     432          304 :          rho_previous = rho
     433              :       END DO
     434           38 :       CALL dbcsr_release(residual)
     435           38 :       CALL dbcsr_release(direction)
     436              : 
     437           38 :    END SUBROUTINE apply_chebyshev_dbcsr
     438              : 
     439              : ! **************************************************************************************************
     440              : !> \brief full all to a full matrix
     441              : !> \param preconditioner_env ...
     442              : !> \param matrix_in ...
     443              : !> \param matrix_out ...
     444              : ! **************************************************************************************************
     445       113520 :    SUBROUTINE apply_full_all(preconditioner_env, matrix_in, matrix_out)
     446              : 
     447              :       TYPE(preconditioner_type)                          :: preconditioner_env
     448              :       TYPE(cp_fm_type), INTENT(IN)                       :: matrix_in, matrix_out
     449              : 
     450              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'apply_full_all'
     451              : 
     452              :       INTEGER                                            :: handle, i, j, k, n, ncol_local, &
     453              :                                                             nrow_local
     454        28380 :       INTEGER, DIMENSION(:), POINTER                     :: col_indices, row_indices
     455              :       REAL(KIND=dp)                                      :: dum
     456              :       REAL(KIND=dp), CONTIGUOUS, DIMENSION(:, :), &
     457        28380 :          POINTER                                         :: local_data
     458              :       TYPE(cp_fm_type)                                   :: matrix_tmp
     459              : 
     460        28380 :       CALL timeset(routineN, handle)
     461              : 
     462        28380 :       CALL cp_fm_get_info(matrix_in, nrow_global=n, ncol_global=k)
     463              : 
     464        28380 :       CALL cp_fm_create(matrix_tmp, matrix_in%matrix_struct, name="apply_full_all")
     465              :       CALL cp_fm_get_info(matrix_tmp, nrow_local=nrow_local, ncol_local=ncol_local, &
     466        28380 :                           row_indices=row_indices, col_indices=col_indices, local_data=local_data)
     467              : 
     468              :       !
     469              :       CALL parallel_gemm('T', 'N', n, k, n, 1.0_dp, preconditioner_env%fm, &
     470        28380 :                          matrix_in, 0.0_dp, matrix_tmp)
     471              : 
     472              :       ! do the right scaling
     473       224454 :       DO j = 1, ncol_local
     474      2822205 :       DO i = 1, nrow_local
     475              :          dum = 1.0_dp/MAX(preconditioner_env%energy_gap, &
     476      2597751 :                           preconditioner_env%full_evals(row_indices(i)) - preconditioner_env%occ_evals(col_indices(j)))
     477      2793825 :          local_data(i, j) = local_data(i, j)*dum
     478              :       END DO
     479              :       END DO
     480              : 
     481              :       ! mult back
     482              :       CALL parallel_gemm('N', 'N', n, k, n, 1.0_dp, preconditioner_env%fm, &
     483        28380 :                          matrix_tmp, 0.0_dp, matrix_out)
     484              : 
     485        28380 :       CALL cp_fm_release(matrix_tmp)
     486              : 
     487        28380 :       CALL timestop(handle)
     488              : 
     489        28380 :    END SUBROUTINE apply_full_all
     490              : 
     491              : ! **************************************************************************************************
     492              : !> \brief full all to a dbcsr matrix
     493              : !> \param preconditioner_env ...
     494              : !> \param matrix_in ...
     495              : !> \param matrix_out ...
     496              : ! **************************************************************************************************
     497        47272 :    SUBROUTINE apply_all(preconditioner_env, matrix_in, matrix_out)
     498              : 
     499              :       TYPE(preconditioner_type)                          :: preconditioner_env
     500              :       TYPE(dbcsr_type)                                   :: matrix_in, matrix_out
     501              : 
     502              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'apply_all'
     503              : 
     504              :       INTEGER                                            :: col, col_offset, col_size, handle, i, j, &
     505              :                                                             row, row_offset, row_size
     506              :       REAL(KIND=dp)                                      :: dum
     507        23636 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: DATA
     508              :       TYPE(dbcsr_iterator_type)                          :: iter
     509              :       TYPE(dbcsr_type)                                   :: matrix_tmp
     510              : 
     511        23636 :       CALL timeset(routineN, handle)
     512              : 
     513        23636 :       CALL dbcsr_copy(matrix_tmp, matrix_in, name="apply_full_all")
     514              :       CALL dbcsr_multiply('T', 'N', 1.0_dp, preconditioner_env%dbcsr_matrix, &
     515        23636 :                           matrix_in, 0.0_dp, matrix_tmp)
     516              :       ! do the right scaling
     517        23636 :       CALL dbcsr_iterator_start(iter, matrix_tmp)
     518        66616 :       DO WHILE (dbcsr_iterator_blocks_left(iter))
     519              :          CALL dbcsr_iterator_next_block(iter, row, col, DATA, &
     520              :                                         row_size=row_size, col_size=col_size, &
     521        42980 :                                         row_offset=row_offset, col_offset=col_offset)
     522       423944 :          DO j = 1, col_size
     523      3228737 :          DO i = 1, row_size
     524              :             dum = 1.0_dp/MAX(preconditioner_env%energy_gap, &
     525              :                              preconditioner_env%full_evals(row_offset + i - 1) &
     526      2828429 :                              - preconditioner_env%occ_evals(col_offset + j - 1))
     527      3185757 :             DATA(i, j) = DATA(i, j)*dum
     528              :          END DO
     529              :          END DO
     530              :       END DO
     531        23636 :       CALL dbcsr_iterator_stop(iter)
     532              : 
     533              :       ! mult back
     534              :       CALL dbcsr_multiply('N', 'N', 1.0_dp, preconditioner_env%dbcsr_matrix, &
     535        23636 :                           matrix_tmp, 0.0_dp, matrix_out)
     536        23636 :       CALL dbcsr_release(matrix_tmp)
     537        23636 :       CALL timestop(handle)
     538              : 
     539        23636 :    END SUBROUTINE apply_all
     540              : 
     541              : END MODULE preconditioner_apply
        

Generated by: LCOV version 2.0-1