LCOV - code coverage report
Current view: top level - src - pao_param_methods.F (source / functions) Hit Total Coverage
Test: CP2K Regtests (git:2fce0f8) Lines: 129 130 99.2 %
Date: 2024-12-21 06:28:57 Functions: 4 4 100.0 %

          Line data    Source code
       1             : !--------------------------------------------------------------------------------------------------!
       2             : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3             : !   Copyright 2000-2024 CP2K developers group <https://cp2k.org>                                   !
       4             : !                                                                                                  !
       5             : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6             : !--------------------------------------------------------------------------------------------------!
       7             : 
       8             : ! **************************************************************************************************
       9             : !> \brief Common routines for PAO parametrizations.
      10             : !> \author Ole Schuett
      11             : ! **************************************************************************************************
      12             : MODULE pao_param_methods
      13             :    USE cp_control_types,                ONLY: dft_control_type
      14             :    USE cp_dbcsr_api,                    ONLY: &
      15             :         dbcsr_add, dbcsr_complete_redistribute, dbcsr_create, dbcsr_get_block_p, dbcsr_get_info, &
      16             :         dbcsr_iterator_blocks_left, dbcsr_iterator_next_block, dbcsr_iterator_start, &
      17             :         dbcsr_iterator_stop, dbcsr_iterator_type, dbcsr_multiply, dbcsr_p_type, dbcsr_release, &
      18             :         dbcsr_reserve_diag_blocks, dbcsr_scale, dbcsr_type
      19             :    USE cp_log_handling,                 ONLY: cp_to_string
      20             :    USE dm_ls_scf_qs,                    ONLY: matrix_decluster
      21             :    USE dm_ls_scf_types,                 ONLY: ls_mstruct_type,&
      22             :                                               ls_scf_env_type
      23             :    USE kinds,                           ONLY: dp
      24             :    USE message_passing,                 ONLY: mp_comm_type
      25             :    USE pao_types,                       ONLY: pao_env_type
      26             :    USE qs_environment_types,            ONLY: get_qs_env,&
      27             :                                               qs_environment_type
      28             :    USE qs_rho_types,                    ONLY: qs_rho_get,&
      29             :                                               qs_rho_type
      30             : #include "./base/base_uses.f90"
      31             : 
      32             :    IMPLICIT NONE
      33             : 
      34             :    PRIVATE
      35             : 
      36             :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'pao_param_methods'
      37             : 
      38             :    PUBLIC :: pao_calc_grad_lnv_wrt_U, pao_calc_AB_from_U, pao_calc_grad_lnv_wrt_AB
      39             : 
      40             : CONTAINS
      41             : 
      42             : ! **************************************************************************************************
      43             : !> \brief Helper routine, calculates partial derivative dE/dU
      44             : !> \param qs_env ...
      45             : !> \param ls_scf_env ...
      46             : !> \param matrix_M_diag the derivate wrt U, matrix uses pao%diag_distribution
      47             : ! **************************************************************************************************
      48        2430 :    SUBROUTINE pao_calc_grad_lnv_wrt_U(qs_env, ls_scf_env, matrix_M_diag)
      49             :       TYPE(qs_environment_type), POINTER                 :: qs_env
      50             :       TYPE(ls_scf_env_type), TARGET                      :: ls_scf_env
      51             :       TYPE(dbcsr_type)                                   :: matrix_M_diag
      52             : 
      53             :       CHARACTER(len=*), PARAMETER :: routineN = 'pao_calc_grad_lnv_wrt_U'
      54             : 
      55             :       INTEGER                                            :: handle
      56             :       REAL(KIND=dp)                                      :: filter_eps
      57        2430 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_s
      58             :       TYPE(dbcsr_type)                                   :: matrix_M, matrix_Ma, matrix_Mb, matrix_NM
      59             :       TYPE(ls_mstruct_type), POINTER                     :: ls_mstruct
      60             :       TYPE(pao_env_type), POINTER                        :: pao
      61             : 
      62        2430 :       CALL timeset(routineN, handle)
      63             : 
      64        2430 :       ls_mstruct => ls_scf_env%ls_mstruct
      65        2430 :       pao => ls_scf_env%pao_env
      66        2430 :       filter_eps = ls_scf_env%eps_filter
      67        2430 :       CALL get_qs_env(qs_env, matrix_s=matrix_s)
      68             : 
      69        2430 :       CALL pao_calc_grad_lnv_wrt_AB(qs_env, ls_scf_env, matrix_Ma, matrix_Mb)
      70             : 
      71             :       ! Calculation uses distr. of matrix_s, afterwards we redistribute to pao%diag_distribution.
      72        2430 :       CALL dbcsr_create(matrix_M, template=matrix_s(1)%matrix, matrix_type="N")
      73        2430 :       CALL dbcsr_reserve_diag_blocks(matrix_M)
      74             : 
      75        2430 :       CALL dbcsr_create(matrix_NM, template=ls_mstruct%matrix_A, matrix_type="N")
      76             : 
      77             :       CALL dbcsr_multiply("N", "N", 1.0_dp, pao%matrix_N_inv, matrix_Ma, &
      78        2430 :                           1.0_dp, matrix_NM, filter_eps=filter_eps)
      79             : 
      80             :       CALL dbcsr_multiply("N", "N", 1.0_dp, pao%matrix_N, matrix_Mb, &
      81        2430 :                           1.0_dp, matrix_NM, filter_eps=filter_eps)
      82             : 
      83             :       CALL dbcsr_multiply("N", "T", 1.0_dp, matrix_NM, pao%matrix_Y, &
      84        2430 :                           1.0_dp, matrix_M, filter_eps=filter_eps)
      85             : 
      86             :       !---------------------------------------------------------------------------
      87             :       ! redistribute using pao%diag_distribution
      88             :       CALL dbcsr_create(matrix_M_diag, &
      89             :                         name="PAO matrix_M", &
      90             :                         matrix_type="N", &
      91             :                         dist=pao%diag_distribution, &
      92        2430 :                         template=matrix_s(1)%matrix)
      93        2430 :       CALL dbcsr_reserve_diag_blocks(matrix_M_diag)
      94        2430 :       CALL dbcsr_complete_redistribute(matrix_M, matrix_M_diag)
      95             : 
      96             :       !---------------------------------------------------------------------------
      97             :       ! cleanup:
      98        2430 :       CALL dbcsr_release(matrix_M)
      99        2430 :       CALL dbcsr_release(matrix_Ma)
     100        2430 :       CALL dbcsr_release(matrix_Mb)
     101        2430 :       CALL dbcsr_release(matrix_NM)
     102             : 
     103        2430 :       CALL timestop(handle)
     104        2430 :    END SUBROUTINE pao_calc_grad_lnv_wrt_U
     105             : 
     106             : ! **************************************************************************************************
     107             : !> \brief Takes current matrix_X and calculates the matrices A and B.
     108             : !> \param pao ...
     109             : !> \param qs_env ...
     110             : !> \param ls_scf_env ...
     111             : !> \param matrix_U_diag ...
     112             : ! **************************************************************************************************
     113       13070 :    SUBROUTINE pao_calc_AB_from_U(pao, qs_env, ls_scf_env, matrix_U_diag)
     114             :       TYPE(pao_env_type), POINTER                        :: pao
     115             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     116             :       TYPE(ls_scf_env_type), TARGET                      :: ls_scf_env
     117             :       TYPE(dbcsr_type)                                   :: matrix_U_diag
     118             : 
     119             :       CHARACTER(len=*), PARAMETER :: routineN = 'pao_calc_AB_from_U'
     120             : 
     121             :       INTEGER                                            :: acol, arow, handle, iatom
     122             :       LOGICAL                                            :: found
     123       13070 :       REAL(dp), DIMENSION(:, :), POINTER                 :: block_A, block_B, block_N, block_N_inv, &
     124       13070 :                                                             block_U, block_Y
     125             :       TYPE(dbcsr_iterator_type)                          :: iter
     126       13070 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_s
     127             :       TYPE(dbcsr_type)                                   :: matrix_U
     128             :       TYPE(ls_mstruct_type), POINTER                     :: ls_mstruct
     129             : 
     130       13070 :       CALL timeset(routineN, handle)
     131       13070 :       CALL get_qs_env(qs_env, matrix_s=matrix_s)
     132       13070 :       ls_mstruct => ls_scf_env%ls_mstruct
     133             : 
     134             :       ! --------------------------------------------------------------------------------------------
     135             :       ! sanity check matrix U
     136       13070 :       CALL pao_assert_unitary(pao, matrix_U_diag)
     137             : 
     138             :       ! --------------------------------------------------------------------------------------------
     139             :       ! redistribute matrix_U_diag from diag_distribution to distribution of matrix_s
     140       13070 :       CALL get_qs_env(qs_env, matrix_s=matrix_s)
     141       13070 :       CALL dbcsr_create(matrix_U, matrix_type="N", template=matrix_s(1)%matrix)
     142       13070 :       CALL dbcsr_reserve_diag_blocks(matrix_U)
     143       13070 :       CALL dbcsr_complete_redistribute(matrix_U_diag, matrix_U)
     144             : 
     145             :       ! --------------------------------------------------------------------------------------------
     146             :       ! calculate matrix A and B from matrix U
     147             :       ! Multiplying diagonal matrices is a local operation.
     148             :       ! To take advantage of this we're using an iterator instead of calling dbcsr_multiply().
     149             : !$OMP PARALLEL DEFAULT(NONE) SHARED(pao,ls_mstruct,matrix_U) &
     150       13070 : !$OMP PRIVATE(iter,arow,acol,iatom,block_U,block_Y,block_A,block_B,block_N,block_N_inv,found)
     151             :       CALL dbcsr_iterator_start(iter, matrix_U)
     152             :       DO WHILE (dbcsr_iterator_blocks_left(iter))
     153             :          CALL dbcsr_iterator_next_block(iter, arow, acol, block_U)
     154             :          iatom = arow; CPASSERT(arow == acol)
     155             : 
     156             :          CALL dbcsr_get_block_p(matrix=pao%matrix_Y, row=iatom, col=iatom, block=block_Y, found=found)
     157             :          CPASSERT(ASSOCIATED(block_Y))
     158             : 
     159             :          CALL dbcsr_get_block_p(matrix=ls_mstruct%matrix_A, row=iatom, col=iatom, block=block_A, found=found)
     160             :          CALL dbcsr_get_block_p(matrix=pao%matrix_N_inv, row=iatom, col=iatom, block=block_N_inv, found=found)
     161             :          CPASSERT(ASSOCIATED(block_A) .AND. ASSOCIATED(block_N_inv))
     162             : 
     163             :          CALL dbcsr_get_block_p(matrix=ls_mstruct%matrix_B, row=iatom, col=iatom, block=block_B, found=found)
     164             :          CALL dbcsr_get_block_p(matrix=pao%matrix_N, row=iatom, col=iatom, block=block_N, found=found)
     165             :          CPASSERT(ASSOCIATED(block_B) .AND. ASSOCIATED(block_N))
     166             : 
     167             :          block_A = MATMUL(MATMUL(block_N_inv, block_U), block_Y)
     168             :          block_B = MATMUL(MATMUL(block_N, block_U), block_Y)
     169             : 
     170             :       END DO
     171             :       CALL dbcsr_iterator_stop(iter)
     172             : !$OMP END PARALLEL
     173             : 
     174       13070 :       CALL dbcsr_release(matrix_U)
     175             : 
     176       13070 :       CALL timestop(handle)
     177       13070 :    END SUBROUTINE pao_calc_AB_from_U
     178             : 
     179             : ! **************************************************************************************************
     180             : !> \brief Debugging routine, check unitaryness of U
     181             : !> \param pao ...
     182             : !> \param matrix_U ...
     183             : ! **************************************************************************************************
     184       18002 :    SUBROUTINE pao_assert_unitary(pao, matrix_U)
     185             :       TYPE(pao_env_type), POINTER                        :: pao
     186             :       TYPE(dbcsr_type)                                   :: matrix_U
     187             : 
     188             :       CHARACTER(len=*), PARAMETER :: routineN = 'pao_assert_unitary'
     189             : 
     190             :       INTEGER                                            :: acol, arow, group_handle, handle, i, &
     191             :                                                             iatom, M, N
     192       13070 :       INTEGER, DIMENSION(:), POINTER                     :: blk_sizes_pao, blk_sizes_pri
     193             :       REAL(dp)                                           :: delta_max
     194       13070 :       REAL(dp), DIMENSION(:, :), POINTER                 :: block_test, tmp1, tmp2
     195             :       TYPE(dbcsr_iterator_type)                          :: iter
     196             :       TYPE(mp_comm_type)                                 :: group
     197             : 
     198       10604 :       IF (pao%check_unitary_tol < 0.0_dp) RETURN ! no checking
     199             : 
     200        2466 :       CALL timeset(routineN, handle)
     201        2466 :       delta_max = 0.0_dp
     202             : 
     203        2466 :       CALL dbcsr_get_info(pao%matrix_Y, row_blk_size=blk_sizes_pri, col_blk_size=blk_sizes_pao)
     204             : 
     205             : !$OMP PARALLEL DEFAULT(NONE) SHARED(pao,matrix_U,blk_sizes_pri,blk_sizes_pao,delta_max) &
     206        2466 : !$OMP PRIVATE(iter,arow,acol,iatom,N,M,block_test,tmp1,tmp2)
     207             :       CALL dbcsr_iterator_start(iter, matrix_U)
     208             :       DO WHILE (dbcsr_iterator_blocks_left(iter))
     209             :          CALL dbcsr_iterator_next_block(iter, arow, acol, block_test)
     210             :          iatom = arow; CPASSERT(arow == acol)
     211             :          N = blk_sizes_pri(iatom) ! size of primary basis
     212             :          M = blk_sizes_pao(iatom) ! size of pao basis
     213             : 
     214             :          ! we only need the upper left "PAO-corner" to be unitary
     215             :          ALLOCATE (tmp1(N, M), tmp2(M, M))
     216             :          tmp1 = block_test(:, 1:M)
     217             :          tmp2 = MATMUL(TRANSPOSE(tmp1), tmp1)
     218             :          DO i = 1, M
     219             :             tmp2(i, i) = tmp2(i, i) - 1.0_dp
     220             :          END DO
     221             : 
     222             : !$OMP ATOMIC
     223             :          delta_max = MAX(delta_max, MAXVAL(ABS(tmp2)))
     224             : 
     225             :          DEALLOCATE (tmp1, tmp2)
     226             :       END DO
     227             :       CALL dbcsr_iterator_stop(iter)
     228             : !$OMP END PARALLEL
     229             : 
     230        2466 :       CALL dbcsr_get_info(matrix_U, group=group_handle)
     231        2466 :       CALL group%set_handle(group_handle)
     232             : 
     233        2466 :       CALL group%max(delta_max)
     234        2466 :       IF (pao%iw > 0) WRITE (pao%iw, *) 'PAO| checked unitaryness, max delta:', delta_max
     235        2466 :       IF (delta_max > pao%check_unitary_tol) &
     236           0 :          CPABORT("Found bad unitaryness:"//cp_to_string(delta_max))
     237             : 
     238        2466 :       CALL timestop(handle)
     239       13070 :    END SUBROUTINE pao_assert_unitary
     240             : 
     241             : ! **************************************************************************************************
     242             : !> \brief Helper routine, calculates partial derivative dE/dA and dE/dB.
     243             : !>        As energy functional serves the definition by LNV (Li, Nunes, Vanderbilt).
     244             : !> \param qs_env ...
     245             : !> \param ls_scf_env ...
     246             : !> \param matrix_Ma the derivate wrt A, matrix uses s_matrix-distribution.
     247             : !> \param matrix_Mb the derivate wrt B, matrix uses s_matrix-distribution.
     248             : ! **************************************************************************************************
     249        2662 :    SUBROUTINE pao_calc_grad_lnv_wrt_AB(qs_env, ls_scf_env, matrix_Ma, matrix_Mb)
     250             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     251             :       TYPE(ls_scf_env_type), TARGET                      :: ls_scf_env
     252             :       TYPE(dbcsr_type)                                   :: matrix_Ma, matrix_Mb
     253             : 
     254             :       CHARACTER(len=*), PARAMETER :: routineN = 'pao_calc_grad_lnv_wrt_AB'
     255             : 
     256             :       INTEGER                                            :: handle, nspin
     257        2662 :       INTEGER, DIMENSION(:), POINTER                     :: pao_blk_sizes
     258             :       REAL(KIND=dp)                                      :: filter_eps
     259        2662 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_ks, matrix_s, rho_ao
     260             :       TYPE(dbcsr_type) :: matrix_HB, matrix_HPS, matrix_M, matrix_M1, matrix_M1_dc, matrix_M2, &
     261             :          matrix_M2_dc, matrix_M3, matrix_M3_dc, matrix_PA, matrix_PH, matrix_PHP, matrix_PSP, &
     262             :          matrix_SB, matrix_SP
     263             :       TYPE(dft_control_type), POINTER                    :: dft_control
     264             :       TYPE(ls_mstruct_type), POINTER                     :: ls_mstruct
     265             :       TYPE(pao_env_type), POINTER                        :: pao
     266             :       TYPE(qs_rho_type), POINTER                         :: rho
     267             : 
     268        2662 :       CALL timeset(routineN, handle)
     269             : 
     270        2662 :       ls_mstruct => ls_scf_env%ls_mstruct
     271        2662 :       pao => ls_scf_env%pao_env
     272             : 
     273             :       CALL get_qs_env(qs_env, &
     274             :                       rho=rho, &
     275             :                       matrix_ks=matrix_ks, &
     276             :                       matrix_s=matrix_s, &
     277        2662 :                       dft_control=dft_control)
     278        2662 :       CALL qs_rho_get(rho, rho_ao=rho_ao)
     279        2662 :       nspin = dft_control%nspins
     280        2662 :       filter_eps = ls_scf_env%eps_filter
     281             : 
     282        2662 :       CALL dbcsr_get_info(ls_mstruct%matrix_A, col_blk_size=pao_blk_sizes)
     283             : 
     284        2662 :       IF (nspin /= 1) CPABORT("open shell not yet implemented")
     285             :       !TODO: handle openshell case properly
     286             : 
     287             :       ! Notation according to equation (4.6) on page 50 from:
     288             :       ! https://dx.doi.org/10.3929%2Fethz-a-010819495
     289             : 
     290             :       !---------------------------------------------------------------------------
     291             :       ! calculate need products in pao basis
     292        2662 :       CALL dbcsr_create(matrix_PH, template=ls_scf_env%matrix_s, matrix_type="N")
     293             :       CALL dbcsr_multiply("N", "N", 1.0_dp, ls_scf_env%matrix_p(1), ls_scf_env%matrix_ks(1), &
     294        2662 :                           0.0_dp, matrix_PH, filter_eps=filter_eps)
     295             : 
     296        2662 :       CALL dbcsr_create(matrix_PHP, template=ls_scf_env%matrix_s, matrix_type="N")
     297             :       CALL dbcsr_multiply("N", "N", 1.0_dp, matrix_PH, ls_scf_env%matrix_p(1), &
     298        2662 :                           0.0_dp, matrix_PHP, filter_eps=filter_eps)
     299             : 
     300        2662 :       CALL dbcsr_create(matrix_SP, template=ls_scf_env%matrix_s, matrix_type="N")
     301             :       CALL dbcsr_multiply("N", "N", 1.0_dp, ls_scf_env%matrix_s, ls_scf_env%matrix_p(1), &
     302        2662 :                           0.0_dp, matrix_SP, filter_eps=filter_eps)
     303             : 
     304        2662 :       IF (nspin == 1) CALL dbcsr_scale(matrix_SP, 0.5_dp)
     305             : 
     306        2662 :       CALL dbcsr_create(matrix_HPS, template=ls_scf_env%matrix_s, matrix_type="N")
     307             :       CALL dbcsr_multiply("N", "T", 1.0_dp, ls_scf_env%matrix_ks(1), matrix_SP, &
     308        2662 :                           0.0_dp, matrix_HPS, filter_eps=filter_eps)
     309             : 
     310        2662 :       CALL dbcsr_create(matrix_PSP, template=ls_scf_env%matrix_s, matrix_type="N")
     311             :       CALL dbcsr_multiply("N", "N", 1.0_dp, ls_scf_env%matrix_p(1), matrix_SP, &
     312        2662 :                           0.0_dp, matrix_PSP, filter_eps=filter_eps)
     313             : 
     314             :       !---------------------------------------------------------------------------
     315             :       ! M1 = dE_lnv / dP_pao
     316        2662 :       CALL dbcsr_create(matrix_M1, template=ls_scf_env%matrix_s, matrix_type="N")
     317             : 
     318             :       CALL dbcsr_multiply("N", "T", 3.0_dp, ls_scf_env%matrix_ks(1), matrix_SP, &
     319        2662 :                           1.0_dp, matrix_M1, filter_eps=filter_eps)
     320             : 
     321             :       CALL dbcsr_multiply("N", "N", 3.0_dp, matrix_SP, ls_scf_env%matrix_ks(1), &
     322        2662 :                           1.0_dp, matrix_M1, filter_eps=filter_eps)
     323             : 
     324             :       CALL dbcsr_multiply("N", "T", -2.0_dp, matrix_HPS, matrix_SP, &
     325        2662 :                           1.0_dp, matrix_M1, filter_eps=filter_eps)
     326             : 
     327             :       CALL dbcsr_multiply("N", "N", -2.0_dp, matrix_SP, matrix_HPS, &
     328        2662 :                           1.0_dp, matrix_M1, filter_eps=filter_eps)
     329             : 
     330             :       CALL dbcsr_multiply("N", "T", -2.0_dp, matrix_SP, matrix_HPS, &
     331        2662 :                           1.0_dp, matrix_M1, filter_eps=filter_eps)
     332             : 
     333             :       ! reverse possible molecular clustering
     334             :       CALL dbcsr_create(matrix_M1_dc, &
     335             :                         template=matrix_s(1)%matrix, &
     336             :                         row_blk_size=pao_blk_sizes, &
     337        2662 :                         col_blk_size=pao_blk_sizes)
     338        2662 :       CALL matrix_decluster(matrix_M1_dc, matrix_M1, ls_mstruct)
     339             : 
     340             :       !---------------------------------------------------------------------------
     341             :       ! M2 = dE_lnv / dH
     342        2662 :       CALL dbcsr_create(matrix_M2, template=ls_scf_env%matrix_s, matrix_type="N")
     343             : 
     344        2662 :       CALL dbcsr_add(matrix_M2, matrix_PSP, 1.0_dp, 3.0_dp)
     345             : 
     346             :       CALL dbcsr_multiply("N", "N", -2.0_dp, matrix_PSP, matrix_SP, &
     347        2662 :                           1.0_dp, matrix_M2, filter_eps=filter_eps)
     348             : 
     349             :       ! reverse possible molecular clustering
     350             :       CALL dbcsr_create(matrix_M2_dc, &
     351             :                         template=matrix_s(1)%matrix, &
     352             :                         row_blk_size=pao_blk_sizes, &
     353        2662 :                         col_blk_size=pao_blk_sizes)
     354        2662 :       CALL matrix_decluster(matrix_M2_dc, matrix_M2, ls_mstruct)
     355             : 
     356             :       !---------------------------------------------------------------------------
     357             :       ! M3 = dE_lnv / dS
     358        2662 :       CALL dbcsr_create(matrix_M3, template=ls_scf_env%matrix_s, matrix_type="N")
     359             : 
     360        2662 :       CALL dbcsr_add(matrix_M3, matrix_PHP, 1.0_dp, 3.0_dp)
     361             : 
     362             :       CALL dbcsr_multiply("N", "N", -2.0_dp, matrix_PHP, matrix_SP, &
     363        2662 :                           1.0_dp, matrix_M3, filter_eps=filter_eps)
     364             : 
     365             :       CALL dbcsr_multiply("N", "T", -2.0_dp, matrix_PSP, matrix_PH, &
     366        2662 :                           1.0_dp, matrix_M3, filter_eps=filter_eps)
     367             : 
     368             :       ! reverse possible molecular clustering
     369             :       CALL dbcsr_create(matrix_M3_dc, &
     370             :                         template=matrix_s(1)%matrix, &
     371             :                         row_blk_size=pao_blk_sizes, &
     372        2662 :                         col_blk_size=pao_blk_sizes)
     373        2662 :       CALL matrix_decluster(matrix_M3_dc, matrix_M3, ls_mstruct)
     374             : 
     375             :       !---------------------------------------------------------------------------
     376             :       ! assemble Ma and Mb
     377             :       ! matrix_Ma = dE_lnv / dA = P * A * M1
     378             :       ! matrix_Mb = dE_lnv / dB = H * B * M2  +  S * B * M3
     379        2662 :       CALL dbcsr_create(matrix_Ma, template=ls_mstruct%matrix_A, matrix_type="N")
     380        2662 :       CALL dbcsr_reserve_diag_blocks(matrix_Ma)
     381        2662 :       CALL dbcsr_create(matrix_Mb, template=ls_mstruct%matrix_B, matrix_type="N")
     382        2662 :       CALL dbcsr_reserve_diag_blocks(matrix_Mb)
     383             : 
     384             :       !---------------------------------------------------------------------------
     385             :       ! combine M1 with matrices from primary basis
     386        2662 :       CALL dbcsr_create(matrix_PA, template=ls_mstruct%matrix_A, matrix_type="N")
     387             :       CALL dbcsr_multiply("N", "N", 1.0_dp, rho_ao(1)%matrix, ls_mstruct%matrix_A, &
     388        2662 :                           0.0_dp, matrix_PA, filter_eps=filter_eps)
     389             : 
     390             :       ! matrix_Ma = P * A * M1
     391             :       CALL dbcsr_multiply("N", "N", 1.0_dp, matrix_PA, matrix_M1_dc, &
     392        2662 :                           0.0_dp, matrix_Ma, filter_eps=filter_eps)
     393             : 
     394             :       !---------------------------------------------------------------------------
     395             :       ! combine M2 with matrices from primary basis
     396        2662 :       CALL dbcsr_create(matrix_HB, template=ls_mstruct%matrix_B, matrix_type="N")
     397             :       CALL dbcsr_multiply("N", "N", 1.0_dp, matrix_ks(1)%matrix, ls_mstruct%matrix_B, &
     398        2662 :                           0.0_dp, matrix_HB, filter_eps=filter_eps)
     399             : 
     400             :       ! matrix_Mb = H * B * M2
     401             :       CALL dbcsr_multiply("N", "N", 1.0_dp, matrix_HB, matrix_M2_dc, &
     402        2662 :                           0.0_dp, matrix_Mb, filter_eps=filter_eps)
     403             : 
     404             :       !---------------------------------------------------------------------------
     405             :       ! combine M3 with matrices from primary basis
     406        2662 :       CALL dbcsr_create(matrix_SB, template=ls_mstruct%matrix_B, matrix_type="N")
     407             :       CALL dbcsr_multiply("N", "N", 1.0_dp, matrix_s(1)%matrix, ls_mstruct%matrix_B, &
     408        2662 :                           0.0_dp, matrix_SB, filter_eps=filter_eps)
     409             : 
     410        2662 :       IF (nspin == 1) CALL dbcsr_scale(matrix_SB, 0.5_dp)
     411             : 
     412             :       ! matrix_Mb += S * B * M3
     413             :       CALL dbcsr_multiply("N", "N", 1.0_dp, matrix_SB, matrix_M3_dc, &
     414        2662 :                           1.0_dp, matrix_Mb, filter_eps=filter_eps)
     415             : 
     416        2662 :       IF (nspin == 1) CALL dbcsr_scale(matrix_Ma, 2.0_dp)
     417        2662 :       IF (nspin == 1) CALL dbcsr_scale(matrix_Mb, 2.0_dp)
     418             : 
     419             :       !---------------------------------------------------------------------------
     420             :       ! cleanup: TODO release matrices as early as possible
     421        2662 :       CALL dbcsr_release(matrix_PH)
     422        2662 :       CALL dbcsr_release(matrix_PHP)
     423        2662 :       CALL dbcsr_release(matrix_SP)
     424        2662 :       CALL dbcsr_release(matrix_HPS)
     425        2662 :       CALL dbcsr_release(matrix_PSP)
     426        2662 :       CALL dbcsr_release(matrix_M)
     427        2662 :       CALL dbcsr_release(matrix_M1)
     428        2662 :       CALL dbcsr_release(matrix_M2)
     429        2662 :       CALL dbcsr_release(matrix_M3)
     430        2662 :       CALL dbcsr_release(matrix_M1_dc)
     431        2662 :       CALL dbcsr_release(matrix_M2_dc)
     432        2662 :       CALL dbcsr_release(matrix_M3_dc)
     433        2662 :       CALL dbcsr_release(matrix_PA)
     434        2662 :       CALL dbcsr_release(matrix_HB)
     435        2662 :       CALL dbcsr_release(matrix_SB)
     436             : 
     437        2662 :       CALL timestop(handle)
     438        2662 :    END SUBROUTINE pao_calc_grad_lnv_wrt_AB
     439             : 
     440             : END MODULE pao_param_methods

Generated by: LCOV version 1.15