LCOV - code coverage report
Current view: top level - src - mao_methods.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:c24029e) Lines: 70.4 % 469 330
Test Date: 2026-07-04 06:36:57 Functions: 78.6 % 14 11

            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 Calculate MAO's and analyze wavefunctions
      10              : !> \par History
      11              : !>      03.2016 created [JGH]
      12              : !>      12.2016 split into four modules [JGH]
      13              : !> \author JGH
      14              : ! **************************************************************************************************
      15              : MODULE mao_methods
      16              :    USE atomic_kind_types,               ONLY: get_atomic_kind
      17              :    USE basis_set_container_types,       ONLY: add_basis_set_to_container
      18              :    USE basis_set_types,                 ONLY: create_primitive_basis_set,&
      19              :                                               get_gto_basis_set,&
      20              :                                               gto_basis_set_p_type,&
      21              :                                               gto_basis_set_type,&
      22              :                                               write_gto_basis_set
      23              :    USE cp_control_types,                ONLY: dft_control_type
      24              :    USE cp_dbcsr_api,                    ONLY: &
      25              :         dbcsr_copy, dbcsr_create, dbcsr_desymmetrize, dbcsr_distribution_type, dbcsr_get_block_p, &
      26              :         dbcsr_get_info, dbcsr_iterator_blocks_left, dbcsr_iterator_next_block, &
      27              :         dbcsr_iterator_start, dbcsr_iterator_stop, dbcsr_iterator_type, dbcsr_multiply, &
      28              :         dbcsr_p_type, dbcsr_release, dbcsr_set, dbcsr_type, dbcsr_type_no_symmetry, &
      29              :         dbcsr_type_symmetric
      30              :    USE cp_dbcsr_contrib,                ONLY: dbcsr_dot,&
      31              :                                               dbcsr_reserve_diag_blocks
      32              :    USE cp_dbcsr_cp2k_link,              ONLY: cp_dbcsr_alloc_block_from_nbl
      33              :    USE cp_dbcsr_operations,             ONLY: copy_dbcsr_to_fm,&
      34              :                                               cp_dbcsr_plus_fm_fm_t,&
      35              :                                               dbcsr_allocate_matrix_set
      36              :    USE cp_fm_diag,                      ONLY: cp_fm_geeig
      37              :    USE cp_fm_struct,                    ONLY: cp_fm_struct_create,&
      38              :                                               cp_fm_struct_release,&
      39              :                                               cp_fm_struct_type
      40              :    USE cp_fm_types,                     ONLY: cp_fm_create,&
      41              :                                               cp_fm_release,&
      42              :                                               cp_fm_type
      43              :    USE input_constants,                 ONLY: mao_basis_ext,&
      44              :                                               mao_basis_orb,&
      45              :                                               mao_basis_prim
      46              :    USE iterate_matrix,                  ONLY: invert_Hotelling
      47              :    USE kinds,                           ONLY: dp
      48              :    USE kpoint_methods,                  ONLY: rskp_transform
      49              :    USE kpoint_types,                    ONLY: get_kpoint_info,&
      50              :                                               kpoint_type
      51              :    USE mathlib,                         ONLY: invert_matrix
      52              :    USE message_passing,                 ONLY: mp_comm_type,&
      53              :                                               mp_para_env_type
      54              :    USE particle_types,                  ONLY: particle_type
      55              :    USE qs_environment_types,            ONLY: get_qs_env,&
      56              :                                               qs_environment_type
      57              :    USE qs_interactions,                 ONLY: init_interaction_radii_orb_basis
      58              :    USE qs_kind_types,                   ONLY: get_qs_kind,&
      59              :                                               qs_kind_type
      60              :    USE qs_neighbor_list_types,          ONLY: neighbor_list_set_p_type
      61              : #include "./base/base_uses.f90"
      62              : 
      63              :    IMPLICIT NONE
      64              :    PRIVATE
      65              : 
      66              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'mao_methods'
      67              : 
      68              :    TYPE mblocks
      69              :       INTEGER                                        :: n = -1, ma = -1
      70              :       REAL(KIND=dp), DIMENSION(:, :), POINTER        :: mat => NULL()
      71              :       REAL(KIND=dp), DIMENSION(:), POINTER           :: eig => NULL()
      72              :    END TYPE mblocks
      73              : 
      74              :    PUBLIC :: mao_initialization, mao_function, mao_function_gradient, mao_orthogonalization, &
      75              :              mao_project_gradient, mao_scalar_product, mao_build_q, mao_basis_analysis, &
      76              :              mao_reference_basis, calculate_p_gamma, mao_update_coef, mao_preconditioner
      77              : 
      78              : ! **************************************************************************************************
      79              : 
      80              : CONTAINS
      81              : 
      82              : ! **************************************************************************************************
      83              : !> \brief ...
      84              : !> \param mao_coef ...
      85              : !> \param pmat ...
      86              : !> \param smat ...
      87              : !> \param eps1 ...
      88              : !> \param iolevel ...
      89              : !> \param iw ...
      90              : ! **************************************************************************************************
      91           16 :    SUBROUTINE mao_initialization(mao_coef, pmat, smat, eps1, iolevel, iw)
      92              :       TYPE(dbcsr_type)                                   :: mao_coef, pmat, smat
      93              :       REAL(KIND=dp), INTENT(IN)                          :: eps1
      94              :       INTEGER, INTENT(IN)                                :: iolevel, iw
      95              : 
      96              :       INTEGER                                            :: i, iatom, info, jatom, lwork, m, n, nblk
      97           16 :       INTEGER, DIMENSION(:), POINTER                     :: col_blk_sizes, mao_blk, row_blk, &
      98           16 :                                                             row_blk_sizes
      99              :       LOGICAL                                            :: found
     100           16 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: w, work
     101           16 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: amat, bmat
     102           16 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: cblock, pblock, sblock
     103              :       TYPE(dbcsr_distribution_type)                      :: dbcsr_dist
     104              :       TYPE(dbcsr_iterator_type)                          :: dbcsr_iter
     105           16 :       TYPE(mblocks), ALLOCATABLE, DIMENSION(:)           :: mbl
     106              :       TYPE(mp_comm_type)                                 :: group
     107              : 
     108           16 :       CALL dbcsr_get_info(mao_coef, nblkrows_total=nblk)
     109          126 :       ALLOCATE (mbl(nblk))
     110           94 :       DO i = 1, nblk
     111           94 :          NULLIFY (mbl(i)%mat, mbl(i)%eig)
     112              :       END DO
     113              : 
     114           16 :       CALL dbcsr_iterator_start(dbcsr_iter, mao_coef)
     115           55 :       DO WHILE (dbcsr_iterator_blocks_left(dbcsr_iter))
     116           39 :          CALL dbcsr_iterator_next_block(dbcsr_iter, iatom, jatom, cblock)
     117           39 :          CPASSERT(iatom == jatom)
     118           39 :          m = SIZE(cblock, 2)
     119           39 :          NULLIFY (pblock, sblock)
     120           39 :          CALL dbcsr_get_block_p(matrix=pmat, row=iatom, col=jatom, block=pblock, found=found)
     121           39 :          CPASSERT(found)
     122           39 :          CALL dbcsr_get_block_p(matrix=smat, row=iatom, col=jatom, block=sblock, found=found)
     123           39 :          CPASSERT(found)
     124           39 :          n = SIZE(sblock, 1)
     125           39 :          lwork = MAX(n*n, 100)
     126          390 :          ALLOCATE (amat(n, n), bmat(n, n), w(n), work(lwork))
     127        20925 :          amat(1:n, 1:n) = pblock(1:n, 1:n)
     128        20925 :          bmat(1:n, 1:n) = sblock(1:n, 1:n)
     129           39 :          info = 0
     130           39 :          CALL dsygv(1, "V", "U", n, amat, n, bmat, n, w, work, lwork, info)
     131           39 :          CPASSERT(info == 0)
     132          234 :          ALLOCATE (mbl(iatom)%mat(n, n), mbl(iatom)%eig(n))
     133           39 :          mbl(iatom)%n = n
     134           39 :          mbl(iatom)%ma = m
     135          797 :          DO i = 1, n
     136          758 :             mbl(iatom)%eig(i) = w(n - i + 1)
     137        20925 :             mbl(iatom)%mat(1:n, i) = amat(1:n, n - i + 1)
     138              :          END DO
     139         2105 :          cblock(1:n, 1:m) = amat(1:n, n:n - m + 1:-1)
     140          172 :          DEALLOCATE (amat, bmat, w, work)
     141              :       END DO
     142           16 :       CALL dbcsr_iterator_stop(dbcsr_iter)
     143              : 
     144           16 :       IF (eps1 < 10.0_dp) THEN
     145            0 :          CALL dbcsr_get_info(mao_coef, row_blk_size=row_blk_sizes, group=group)
     146            0 :          ALLOCATE (row_blk(nblk), mao_blk(nblk))
     147            0 :          mao_blk = 0
     148            0 :          row_blk = row_blk_sizes
     149            0 :          DO iatom = 1, nblk
     150            0 :             IF (ASSOCIATED(mbl(iatom)%mat)) THEN
     151            0 :                n = mbl(iatom)%n
     152            0 :                m = 0
     153            0 :                DO i = 1, n
     154            0 :                   IF (mbl(iatom)%eig(i) < eps1) EXIT
     155            0 :                   m = i
     156              :                END DO
     157            0 :                m = MAX(m, mbl(iatom)%ma)
     158            0 :                mbl(iatom)%ma = m
     159            0 :                mao_blk(iatom) = m
     160              :             END IF
     161              :          END DO
     162            0 :          CALL group%sum(mao_blk)
     163            0 :          CALL dbcsr_get_info(mao_coef, distribution=dbcsr_dist)
     164            0 :          CALL dbcsr_release(mao_coef)
     165              :          CALL dbcsr_create(mao_coef, name="MAO_COEF", dist=dbcsr_dist, &
     166            0 :                            matrix_type=dbcsr_type_no_symmetry, row_blk_size=row_blk, col_blk_size=mao_blk)
     167            0 :          CALL dbcsr_reserve_diag_blocks(matrix=mao_coef)
     168            0 :          DEALLOCATE (mao_blk, row_blk)
     169              :          !
     170            0 :          CALL dbcsr_iterator_start(dbcsr_iter, mao_coef)
     171            0 :          DO WHILE (dbcsr_iterator_blocks_left(dbcsr_iter))
     172            0 :             CALL dbcsr_iterator_next_block(dbcsr_iter, iatom, jatom, cblock)
     173            0 :             CPASSERT(iatom == jatom)
     174            0 :             n = SIZE(cblock, 1)
     175            0 :             m = SIZE(cblock, 2)
     176            0 :             CPASSERT(n == mbl(iatom)%n .AND. m == mbl(iatom)%ma)
     177            0 :             cblock(1:n, 1:m) = mbl(iatom)%mat(1:n, 1:m)
     178              :          END DO
     179            0 :          CALL dbcsr_iterator_stop(dbcsr_iter)
     180              :          !
     181              :       END IF
     182              : 
     183           16 :       IF (iolevel > 2) THEN
     184              :          CALL dbcsr_get_info(mao_coef, col_blk_size=col_blk_sizes, &
     185           12 :                              row_blk_size=row_blk_sizes, group=group)
     186           66 :          DO iatom = 1, nblk
     187           54 :             n = row_blk_sizes(iatom)
     188           54 :             m = col_blk_sizes(iatom)
     189          162 :             ALLOCATE (w(n))
     190          978 :             w(1:n) = 0._dp
     191           54 :             IF (ASSOCIATED(mbl(iatom)%mat)) THEN
     192          489 :                w(1:n) = mbl(iatom)%eig(1:n)
     193              :             END IF
     194           54 :             CALL group%sum(w)
     195           54 :             IF (iw > 0) THEN
     196           27 :                WRITE (iw, '(A,i2,20F8.4)', ADVANCE="NO") " Spectrum/Gap  ", iatom, w(1:m)
     197           27 :                WRITE (iw, '(A,F8.4)') " || ", w(m + 1)
     198              :             END IF
     199           66 :             DEALLOCATE (w)
     200              :          END DO
     201              :       END IF
     202              : 
     203           16 :       CALL mao_orthogonalization(mao_coef, smat)
     204              : 
     205           94 :       DO i = 1, nblk
     206           78 :          IF (ASSOCIATED(mbl(i)%mat)) THEN
     207           39 :             DEALLOCATE (mbl(i)%mat)
     208              :          END IF
     209           94 :          IF (ASSOCIATED(mbl(i)%eig)) THEN
     210           39 :             DEALLOCATE (mbl(i)%eig)
     211              :          END IF
     212              :       END DO
     213           16 :       DEALLOCATE (mbl)
     214              : 
     215           48 :    END SUBROUTINE mao_initialization
     216              : 
     217              : ! **************************************************************************************************
     218              : !> \brief ...
     219              : !> \param mao_coef ...
     220              : !> \param fval ...
     221              : !> \param qmat ...
     222              : !> \param smat ...
     223              : !> \param binv ...
     224              : !> \param reuse ...
     225              : ! **************************************************************************************************
     226          804 :    SUBROUTINE mao_function(mao_coef, fval, qmat, smat, binv, reuse)
     227              :       TYPE(dbcsr_type)                                   :: mao_coef
     228              :       REAL(KIND=dp), INTENT(OUT)                         :: fval
     229              :       TYPE(dbcsr_type)                                   :: qmat, smat, binv
     230              :       LOGICAL, INTENT(IN)                                :: reuse
     231              : 
     232              :       REAL(KIND=dp)                                      :: convergence, threshold
     233              :       TYPE(dbcsr_type)                                   :: bmat, scmat, tmat
     234              : 
     235          402 :       threshold = 1.e-8_dp
     236          402 :       convergence = 1.e-6_dp
     237              :       ! temp matrices
     238          402 :       CALL dbcsr_create(scmat, template=mao_coef)
     239          402 :       CALL dbcsr_create(bmat, template=binv)
     240          402 :       CALL dbcsr_create(tmat, template=qmat)
     241              :       ! calculate B=C(T)*S*C matrix, S=(MAO,MAO) overlap
     242          402 :       CALL dbcsr_multiply("N", "N", 1.0_dp, smat, mao_coef, 0.0_dp, scmat)
     243          402 :       CALL dbcsr_multiply("T", "N", 1.0_dp, mao_coef, scmat, 0.0_dp, bmat)
     244              :       ! calculate inverse of B
     245              :       CALL invert_Hotelling(binv, bmat, threshold, use_inv_as_guess=reuse, &
     246          402 :                             norm_convergence=convergence, silent=.TRUE.)
     247              :       ! calculate Binv*C and T=C(T)*Binv*C
     248          402 :       CALL dbcsr_multiply("N", "N", 1.0_dp, mao_coef, binv, 0.0_dp, scmat)
     249          402 :       CALL dbcsr_multiply("N", "T", 1.0_dp, scmat, mao_coef, 0.0_dp, tmat)
     250              :       ! function = Tr(Q*T)
     251          402 :       CALL dbcsr_dot(qmat, tmat, fval)
     252              :       ! free temp matrices
     253          402 :       CALL dbcsr_release(scmat)
     254          402 :       CALL dbcsr_release(bmat)
     255          402 :       CALL dbcsr_release(tmat)
     256              : 
     257          402 :    END SUBROUTINE mao_function
     258              : 
     259              : ! **************************************************************************************************
     260              : !> \brief ...
     261              : !> \param mao_coef ...
     262              : !> \param fval ...
     263              : !> \param mao_grad ...
     264              : !> \param qmat ...
     265              : !> \param smat ...
     266              : !> \param binv ...
     267              : !> \param reuse ...
     268              : ! **************************************************************************************************
     269          416 :    SUBROUTINE mao_function_gradient(mao_coef, fval, mao_grad, qmat, smat, binv, reuse)
     270              :       TYPE(dbcsr_type)                                   :: mao_coef
     271              :       REAL(KIND=dp), INTENT(OUT)                         :: fval
     272              :       TYPE(dbcsr_type)                                   :: mao_grad, qmat, smat, binv
     273              :       LOGICAL, INTENT(IN)                                :: reuse
     274              : 
     275              :       REAL(KIND=dp)                                      :: convergence, threshold
     276              :       TYPE(dbcsr_type)                                   :: bmat, scmat, t2mat, tmat
     277              : 
     278          208 :       threshold = 1.e-8_dp
     279          208 :       convergence = 1.e-6_dp
     280              :       ! temp matrices
     281          208 :       CALL dbcsr_create(scmat, template=mao_coef)
     282          208 :       CALL dbcsr_create(bmat, template=binv)
     283          208 :       CALL dbcsr_create(tmat, template=qmat)
     284          208 :       CALL dbcsr_create(t2mat, template=scmat)
     285              :       ! calculate B=C(T)*S*C matrix, S=(MAO,MAO) overlap
     286          208 :       CALL dbcsr_multiply("N", "N", 1.0_dp, smat, mao_coef, 0.0_dp, scmat)
     287          208 :       CALL dbcsr_multiply("T", "N", 1.0_dp, mao_coef, scmat, 0.0_dp, bmat)
     288              :       ! calculate inverse of B
     289              :       CALL invert_Hotelling(binv, bmat, threshold, use_inv_as_guess=reuse, &
     290          208 :                             norm_convergence=convergence, silent=.TRUE.)
     291              :       ! calculate R=C*Binv and T=C*Binv*C(T)=R*C(T)
     292          208 :       CALL dbcsr_multiply("N", "N", 1.0_dp, mao_coef, binv, 0.0_dp, scmat)
     293          208 :       CALL dbcsr_multiply("N", "T", 1.0_dp, scmat, mao_coef, 0.0_dp, tmat)
     294              :       ! function = Tr(Q*T)
     295          208 :       CALL dbcsr_dot(qmat, tmat, fval)
     296              :       ! Gradient part 1: g = 2*Q*C*Binv = 2*Q*R
     297              :       CALL dbcsr_multiply("N", "N", 2.0_dp, qmat, scmat, 0.0_dp, mao_grad, &
     298          208 :                           retain_sparsity=.TRUE.)
     299              :       ! Gradient part 2: g = -2*S*T*X; X = Q*R
     300          208 :       CALL dbcsr_multiply("N", "N", 1.0_dp, qmat, scmat, 0.0_dp, t2mat)
     301          208 :       CALL dbcsr_multiply("N", "N", 1.0_dp, tmat, t2mat, 0.0_dp, scmat)
     302              :       CALL dbcsr_multiply("N", "N", -2.0_dp, smat, scmat, 1.0_dp, mao_grad, &
     303          208 :                           retain_sparsity=.TRUE.)
     304              :       ! free temp matrices
     305          208 :       CALL dbcsr_release(scmat)
     306          208 :       CALL dbcsr_release(bmat)
     307          208 :       CALL dbcsr_release(tmat)
     308          208 :       CALL dbcsr_release(t2mat)
     309              : 
     310              :       ! apply Lagrange multiplyer
     311          208 :       CALL mao_grad_lagrange(mao_coef, mao_grad, smat)
     312              : 
     313          208 :    END SUBROUTINE mao_function_gradient
     314              : 
     315              : ! **************************************************************************************************
     316              : !> \brief Preconditioner for MAO optimization (seems not to work, but left for further tests)
     317              : !> \param mao_coef ...
     318              : !> \param mao_grad ...
     319              : !> \param qmat ...
     320              : !> \param smat ...
     321              : ! **************************************************************************************************
     322            0 :    SUBROUTINE mao_preconditioner(mao_coef, mao_grad, qmat, smat)
     323              :       TYPE(dbcsr_type)                                   :: mao_coef, mao_grad, qmat, smat
     324              : 
     325              :       INTEGER                                            :: i, iatom, jatom, m, n
     326            0 :       INTEGER, DIMENSION(:), POINTER                     :: col_blk_sizes
     327              :       LOGICAL                                            :: found
     328              :       REAL(KIND=dp)                                      :: eval_error, q_shift
     329            0 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: qinv, qsmat
     330            0 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: bblock, gblock, qblock
     331              :       TYPE(dbcsr_distribution_type)                      :: dbcsr_dist
     332              :       TYPE(dbcsr_iterator_type)                          :: dbcsr_iter
     333              :       TYPE(dbcsr_type)                                   :: bmat, scmat
     334              : 
     335              :       ! temp matrices
     336            0 :       CALL dbcsr_create(scmat, template=mao_coef)
     337            0 :       CALL dbcsr_get_info(mao_coef, col_blk_size=col_blk_sizes, distribution=dbcsr_dist)
     338              :       CALL dbcsr_create(bmat, name="Binv", dist=dbcsr_dist, matrix_type=dbcsr_type_symmetric, &
     339            0 :                         row_blk_size=col_blk_sizes, col_blk_size=col_blk_sizes)
     340              :       ! calculate B=C(T)*S*C matrix, S=(MAO,MAO) overlap
     341            0 :       CALL dbcsr_multiply("N", "N", 1.0_dp, smat, mao_coef, 0.0_dp, scmat)
     342            0 :       CALL dbcsr_multiply("T", "N", 1.0_dp, mao_coef, scmat, 0.0_dp, bmat)
     343              : 
     344            0 :       q_shift = 0.001_dp
     345              : 
     346            0 :       CALL dbcsr_iterator_start(dbcsr_iter, mao_grad)
     347            0 :       DO WHILE (dbcsr_iterator_blocks_left(dbcsr_iter))
     348            0 :          CALL dbcsr_iterator_next_block(dbcsr_iter, iatom, jatom, gblock)
     349            0 :          CPASSERT(iatom == jatom)
     350            0 :          m = SIZE(gblock, 1)
     351            0 :          n = SIZE(gblock, 2)
     352            0 :          CALL dbcsr_get_block_p(matrix=bmat, row=iatom, col=jatom, block=bblock, found=found)
     353            0 :          CPASSERT(found)
     354            0 :          CALL dbcsr_get_block_p(matrix=qmat, row=iatom, col=jatom, block=qblock, found=found)
     355            0 :          CPASSERT(found)
     356            0 :          ALLOCATE (qinv(m, m), qsmat(m, m))
     357            0 :          qsmat(1:m, 1:m) = qblock(1:m, 1:m)
     358            0 :          DO i = 1, m
     359            0 :             qsmat(i, i) = qsmat(i, i) + q_shift
     360              :          END DO
     361            0 :          CALL invert_matrix(qsmat, qinv, eval_error)
     362              :          ! g = q * g * b
     363            0 :          gblock(1:m, 1:n) = MATMUL(qinv(1:m, 1:m), MATMUL(gblock(1:m, 1:n), bblock(1:n, 1:n)))
     364            0 :          DEALLOCATE (qinv, qsmat)
     365              :       END DO
     366            0 :       CALL dbcsr_iterator_stop(dbcsr_iter)
     367              : 
     368            0 :       CALL mao_project_gradient(mao_coef, mao_grad, smat)
     369              : 
     370              :       ! free temp matrices
     371            0 :       CALL dbcsr_release(scmat)
     372            0 :       CALL dbcsr_release(bmat)
     373              : 
     374            0 :    END SUBROUTINE mao_preconditioner
     375              : 
     376              : ! **************************************************************************************************
     377              : !> \brief ...
     378              : !> \param mao_coef ...
     379              : !> \param mao_grad ...
     380              : !> \param smat ...
     381              : ! **************************************************************************************************
     382          208 :    SUBROUTINE mao_grad_lagrange(mao_coef, mao_grad, smat)
     383              :       TYPE(dbcsr_type)                                   :: mao_coef, mao_grad, smat
     384              : 
     385              :       INTEGER                                            :: i, iatom, info, jatom, lwork, m, n
     386              :       LOGICAL                                            :: found
     387          208 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: w, work
     388          208 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: amat, bmat, lmat, rmat
     389          208 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: cblock, gblock, sblock
     390              :       TYPE(dbcsr_iterator_type)                          :: dbcsr_iter
     391              : 
     392          208 :       CALL dbcsr_iterator_start(dbcsr_iter, mao_coef)
     393          766 :       DO WHILE (dbcsr_iterator_blocks_left(dbcsr_iter))
     394          558 :          CALL dbcsr_iterator_next_block(dbcsr_iter, iatom, jatom, cblock)
     395          558 :          CPASSERT(iatom == jatom)
     396          558 :          m = SIZE(cblock, 2)
     397          558 :          n = SIZE(cblock, 1)
     398          558 :          NULLIFY (sblock)
     399          558 :          CALL dbcsr_get_block_p(matrix=smat, row=iatom, col=jatom, block=sblock, found=found)
     400          558 :          CPASSERT(found)
     401          558 :          lwork = MAX(n*n, 100)
     402         8928 :          ALLOCATE (amat(n, m), bmat(m, m), rmat(m, m), lmat(n, n), w(m), work(lwork))
     403      1160634 :          amat(1:n, 1:m) = MATMUL(sblock(1:n, 1:n), cblock(1:n, 1:m))
     404       122610 :          bmat(1:m, 1:m) = MATMUL(TRANSPOSE(amat(1:n, 1:m)), amat(1:n, 1:m))
     405          558 :          info = 0
     406          558 :          CALL dsyev("V", "U", m, bmat, m, w, work, lwork, info)
     407          558 :          CPASSERT(info == 0)
     408         1674 :          CPASSERT(ALL(w > 0.0_dp))
     409         1674 :          w = 1.0_dp/w
     410         1674 :          DO i = 1, m
     411         5022 :             rmat(1:m, i) = bmat(1:m, i)*w(i)
     412              :          END DO
     413        27342 :          bmat(1:m, 1:m) = MATMUL(rmat(1:m, 1:m), TRANSPOSE(bmat(1:m, 1:m)))
     414      2827626 :          lmat(1:n, 1:n) = MATMUL(MATMUL(amat(1:n, 1:m), bmat(1:m, 1:m)), TRANSPOSE(amat(1:n, 1:m)))
     415              :          !
     416          558 :          CALL dbcsr_get_block_p(matrix=mao_grad, row=iatom, col=iatom, block=gblock, found=found)
     417          558 :          CPASSERT(found)
     418      1161192 :          gblock(1:n, 1:m) = gblock(1:n, 1:m) - MATMUL(lmat(1:n, 1:n), gblock(1:n, 1:m))
     419         2232 :          DEALLOCATE (amat, bmat, rmat, lmat, w, work)
     420              :       END DO
     421          208 :       CALL dbcsr_iterator_stop(dbcsr_iter)
     422              : 
     423          416 :    END SUBROUTINE mao_grad_lagrange
     424              : 
     425              : ! **************************************************************************************************
     426              : !> \brief ...
     427              : !> \param mao_up ...
     428              : !> \param mao_coef ...
     429              : !> \param mao_grad ...
     430              : !> \param smat ...
     431              : !> \param alpha ...
     432              : ! **************************************************************************************************
     433          594 :    SUBROUTINE mao_update_coef(mao_up, mao_coef, mao_grad, smat, alpha)
     434              :       TYPE(dbcsr_type)                                   :: mao_up, mao_coef, mao_grad, smat
     435              :       REAL(KIND=dp)                                      :: alpha
     436              : 
     437              :       INTEGER                                            :: i, iatom, info, jatom, lwork, m, n
     438              :       LOGICAL                                            :: found
     439          594 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: w, work
     440          594 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: amat, bmat, r1mat, r2mat
     441          594 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: cblock, gblock, sblock, ublock
     442              :       TYPE(dbcsr_iterator_type)                          :: dbcsr_iter
     443              : 
     444          594 :       CALL dbcsr_copy(mao_up, mao_coef)
     445          594 :       CALL dbcsr_iterator_start(dbcsr_iter, mao_coef)
     446         2196 :       DO WHILE (dbcsr_iterator_blocks_left(dbcsr_iter))
     447         1602 :          CALL dbcsr_iterator_next_block(dbcsr_iter, iatom, jatom, cblock)
     448         1602 :          CPASSERT(iatom == jatom)
     449         1602 :          CALL dbcsr_get_block_p(matrix=mao_grad, row=iatom, col=iatom, block=gblock, found=found)
     450         1602 :          CPASSERT(found)
     451         1602 :          m = SIZE(cblock, 2)
     452         1602 :          n = SIZE(cblock, 1)
     453         1602 :          NULLIFY (sblock)
     454         1602 :          CALL dbcsr_get_block_p(matrix=smat, row=iatom, col=jatom, block=sblock, found=found)
     455         1602 :          CPASSERT(found)
     456         1602 :          CALL dbcsr_get_block_p(matrix=mao_up, row=iatom, col=iatom, block=ublock, found=found)
     457         1602 :          CPASSERT(found)
     458         1602 :          lwork = MAX(n*n, 100)
     459        24030 :          ALLOCATE (amat(n, m), bmat(m, m), r1mat(m, m), r2mat(m, m), w(m), work(lwork))
     460              :          !
     461        98862 :          amat(1:n, 1:m) = alpha*gblock(1:n, 1:m)
     462      7085412 :          bmat(1:m, 1:m) = MATMUL(TRANSPOSE(amat(1:n, 1:m)), MATMUL(sblock(1:n, 1:n), amat(1:n, 1:m)))
     463         1602 :          info = 0
     464         1602 :          CALL dsyev("V", "U", m, bmat, m, w, work, lwork, info)
     465         1602 :          CPASSERT(info == 0)
     466         4806 :          DO i = 1, m
     467         3204 :             IF (w(i) < 1.E-12_dp) THEN
     468           36 :                w(i) = 0.0_dp
     469              :             ELSE
     470         3168 :                w(i) = SQRT(w(i))
     471              :             END IF
     472        12816 :             r1mat(1:m, i) = bmat(1:m, i)*COS(w(i))
     473         4806 :             IF (w(i) < 1.E-6_dp) THEN
     474          180 :                r2mat(1:m, i) = bmat(1:m, i)*(1._dp - w(i)**2/6._dp)
     475              :             ELSE
     476        12636 :                r2mat(1:m, i) = bmat(1:m, i)*SIN(w(i))/w(i)
     477              :             END IF
     478              :          END DO
     479        75294 :          r1mat(1:m, 1:m) = MATMUL(r1mat(1:m, 1:m), TRANSPOSE(bmat(1:m, 1:m)))
     480        75294 :          r2mat(1:m, 1:m) = MATMUL(r2mat(1:m, 1:m), TRANSPOSE(bmat(1:m, 1:m)))
     481              :          !
     482         6408 :          ublock(1:n, 1:m) = MATMUL(cblock(1:n, 1:m), r1mat(1:m, 1:m)) + &
     483       777222 :                             MATMUL(amat(1:n, 1:m), r2mat(1:m, 1:m))
     484              :          !
     485         8010 :          DEALLOCATE (amat, bmat, r1mat, r2mat, w, work)
     486              :       END DO
     487          594 :       CALL dbcsr_iterator_stop(dbcsr_iter)
     488              : 
     489         1188 :    END SUBROUTINE mao_update_coef
     490              : 
     491              : ! **************************************************************************************************
     492              : !> \brief ...
     493              : !> \param mao_coef ...
     494              : !> \param smat ...
     495              : ! **************************************************************************************************
     496           16 :    SUBROUTINE mao_orthogonalization(mao_coef, smat)
     497              :       TYPE(dbcsr_type)                                   :: mao_coef, smat
     498              : 
     499              :       INTEGER                                            :: i, iatom, info, jatom, lwork, m, n
     500              :       LOGICAL                                            :: found
     501           16 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: w, work
     502           16 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: amat, bmat, rmat
     503           16 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: cblock, sblock
     504              :       TYPE(dbcsr_iterator_type)                          :: dbcsr_iter
     505              : 
     506           16 :       CALL dbcsr_iterator_start(dbcsr_iter, mao_coef)
     507           55 :       DO WHILE (dbcsr_iterator_blocks_left(dbcsr_iter))
     508           39 :          CALL dbcsr_iterator_next_block(dbcsr_iter, iatom, jatom, cblock)
     509           39 :          CPASSERT(iatom == jatom)
     510           39 :          m = SIZE(cblock, 2)
     511           39 :          n = SIZE(cblock, 1)
     512           39 :          NULLIFY (sblock)
     513           39 :          CALL dbcsr_get_block_p(matrix=smat, row=iatom, col=jatom, block=sblock, found=found)
     514           39 :          CPASSERT(found)
     515           39 :          lwork = MAX(n*n, 100)
     516          507 :          ALLOCATE (amat(n, m), bmat(m, m), rmat(m, m), w(m), work(lwork))
     517        66947 :          amat(1:n, 1:m) = MATMUL(sblock(1:n, 1:n), cblock(1:n, 1:m))
     518         7571 :          bmat(1:m, 1:m) = MATMUL(TRANSPOSE(cblock(1:n, 1:m)), amat(1:n, 1:m))
     519           39 :          info = 0
     520           39 :          CALL dsyev("V", "U", m, bmat, m, w, work, lwork, info)
     521           39 :          CPASSERT(info == 0)
     522          117 :          CPASSERT(ALL(w > 0.0_dp))
     523          117 :          w = 1.0_dp/SQRT(w)
     524          117 :          DO i = 1, m
     525          351 :             rmat(1:m, i) = bmat(1:m, i)*w(i)
     526              :          END DO
     527         1833 :          bmat(1:m, 1:m) = MATMUL(rmat(1:m, 1:m), TRANSPOSE(bmat(1:m, 1:m)))
     528        11391 :          cblock(1:n, 1:m) = MATMUL(cblock(1:n, 1:m), bmat(1:m, 1:m))
     529          117 :          DEALLOCATE (amat, bmat, rmat, w, work)
     530              :       END DO
     531           16 :       CALL dbcsr_iterator_stop(dbcsr_iter)
     532              : 
     533           32 :    END SUBROUTINE mao_orthogonalization
     534              : 
     535              : ! **************************************************************************************************
     536              : !> \brief ...
     537              : !> \param mao_coef ...
     538              : !> \param mao_grad ...
     539              : !> \param smat ...
     540              : ! **************************************************************************************************
     541            0 :    SUBROUTINE mao_project_gradient(mao_coef, mao_grad, smat)
     542              :       TYPE(dbcsr_type)                                   :: mao_coef, mao_grad, smat
     543              : 
     544              :       INTEGER                                            :: iatom, jatom, m, n
     545              :       LOGICAL                                            :: found
     546            0 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: amat
     547            0 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: cblock, gblock, sblock
     548              :       TYPE(dbcsr_iterator_type)                          :: dbcsr_iter
     549              : 
     550            0 :       CALL dbcsr_iterator_start(dbcsr_iter, mao_coef)
     551            0 :       DO WHILE (dbcsr_iterator_blocks_left(dbcsr_iter))
     552            0 :          CALL dbcsr_iterator_next_block(dbcsr_iter, iatom, jatom, cblock)
     553            0 :          CPASSERT(iatom == jatom)
     554            0 :          m = SIZE(cblock, 2)
     555            0 :          n = SIZE(cblock, 1)
     556            0 :          NULLIFY (sblock)
     557            0 :          CALL dbcsr_get_block_p(matrix=smat, row=iatom, col=jatom, block=sblock, found=found)
     558            0 :          CPASSERT(found)
     559            0 :          NULLIFY (gblock)
     560            0 :          CALL dbcsr_get_block_p(matrix=mao_grad, row=iatom, col=jatom, block=gblock, found=found)
     561            0 :          CPASSERT(found)
     562            0 :          ALLOCATE (amat(m, m))
     563            0 :          amat(1:m, 1:m) = MATMUL(TRANSPOSE(cblock(1:n, 1:m)), MATMUL(sblock(1:n, 1:n), gblock(1:n, 1:m)))
     564            0 :          gblock(1:n, 1:m) = gblock(1:n, 1:m) - MATMUL(cblock(1:n, 1:m), amat(1:m, 1:m))
     565            0 :          DEALLOCATE (amat)
     566              :       END DO
     567            0 :       CALL dbcsr_iterator_stop(dbcsr_iter)
     568              : 
     569            0 :    END SUBROUTINE mao_project_gradient
     570              : 
     571              : ! **************************************************************************************************
     572              : !> \brief ...
     573              : !> \param fmat1 ...
     574              : !> \param fmat2 ...
     575              : !> \return ...
     576              : ! **************************************************************************************************
     577          416 :    FUNCTION mao_scalar_product(fmat1, fmat2) RESULT(spro)
     578              :       TYPE(dbcsr_type)                                   :: fmat1, fmat2
     579              :       REAL(KIND=dp)                                      :: spro
     580              : 
     581              :       INTEGER                                            :: iatom, jatom, m, n
     582              :       LOGICAL                                            :: found
     583          208 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: ablock, bblock
     584              :       TYPE(dbcsr_iterator_type)                          :: dbcsr_iter
     585              :       TYPE(mp_comm_type)                                 :: group
     586              : 
     587          208 :       spro = 0.0_dp
     588              : 
     589          208 :       CALL dbcsr_iterator_start(dbcsr_iter, fmat1)
     590          766 :       DO WHILE (dbcsr_iterator_blocks_left(dbcsr_iter))
     591          558 :          CALL dbcsr_iterator_next_block(dbcsr_iter, iatom, jatom, ablock)
     592          558 :          CPASSERT(iatom == jatom)
     593          558 :          m = SIZE(ablock, 2)
     594          558 :          n = SIZE(ablock, 1)
     595          558 :          CALL dbcsr_get_block_p(matrix=fmat2, row=iatom, col=jatom, block=bblock, found=found)
     596          558 :          CPASSERT(found)
     597        34474 :          spro = spro + SUM(ablock(1:n, 1:m)*bblock(1:n, 1:m))
     598              :       END DO
     599          208 :       CALL dbcsr_iterator_stop(dbcsr_iter)
     600              : 
     601          208 :       CALL dbcsr_get_info(fmat1, group=group)
     602          208 :       CALL group%sum(spro)
     603              : 
     604          208 :    END FUNCTION mao_scalar_product
     605              : 
     606              : ! **************************************************************************************************
     607              : !> \brief Calculate the density matrix at the Gamma point
     608              : !> \param pmat ...
     609              : !> \param ksmat ...
     610              : !> \param smat ...
     611              : !> \param kpoints      Kpoint environment
     612              : !> \param nmos         Number of occupied orbitals
     613              : !> \param occ          Maximum occupation per orbital
     614              : !> \par History
     615              : !>      04.2016 created [JGH]
     616              : ! **************************************************************************************************
     617            0 :    SUBROUTINE calculate_p_gamma(pmat, ksmat, smat, kpoints, nmos, occ)
     618              : 
     619              :       TYPE(dbcsr_type)                                   :: pmat, ksmat, smat
     620              :       TYPE(kpoint_type), POINTER                         :: kpoints
     621              :       INTEGER, INTENT(IN)                                :: nmos
     622              :       REAL(KIND=dp), INTENT(IN)                          :: occ
     623              : 
     624              :       INTEGER                                            :: norb
     625              :       REAL(KIND=dp)                                      :: de
     626              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: eigenvalues
     627              :       TYPE(cp_fm_struct_type), POINTER                   :: matrix_struct
     628              :       TYPE(cp_fm_type)                                   :: fmksmat, fmsmat, fmvec, fmwork
     629              :       TYPE(dbcsr_type)                                   :: tempmat
     630              : 
     631              :       ! FM matrices
     632              : 
     633            0 :       CALL dbcsr_get_info(smat, nfullrows_total=norb)
     634              :       CALL cp_fm_struct_create(fmstruct=matrix_struct, context=kpoints%blacs_env_all, &
     635            0 :                                nrow_global=norb, ncol_global=norb)
     636            0 :       CALL cp_fm_create(fmksmat, matrix_struct)
     637            0 :       CALL cp_fm_create(fmsmat, matrix_struct)
     638            0 :       CALL cp_fm_create(fmvec, matrix_struct)
     639            0 :       CALL cp_fm_create(fmwork, matrix_struct)
     640            0 :       ALLOCATE (eigenvalues(norb))
     641              : 
     642              :       ! DBCSR matrix
     643            0 :       CALL dbcsr_create(tempmat, template=smat, matrix_type=dbcsr_type_no_symmetry)
     644              : 
     645              :       ! transfer to FM
     646            0 :       CALL dbcsr_desymmetrize(smat, tempmat)
     647            0 :       CALL copy_dbcsr_to_fm(tempmat, fmsmat)
     648            0 :       CALL dbcsr_desymmetrize(ksmat, tempmat)
     649            0 :       CALL copy_dbcsr_to_fm(tempmat, fmksmat)
     650              : 
     651              :       ! diagonalize
     652            0 :       CALL cp_fm_geeig(fmksmat, fmsmat, fmvec, eigenvalues, fmwork)
     653            0 :       de = eigenvalues(nmos + 1) - eigenvalues(nmos)
     654            0 :       IF (de < 0.001_dp) THEN
     655              :          CALL cp_warn(__LOCATION__, "MAO: No band gap at "// &
     656            0 :                       "Gamma point. MAO analysis not reliable.")
     657              :       END IF
     658              :       ! density matrix
     659            0 :       CALL cp_dbcsr_plus_fm_fm_t(sparse_matrix=pmat, matrix_v=fmvec, ncol=nmos, alpha=occ)
     660              : 
     661            0 :       DEALLOCATE (eigenvalues)
     662            0 :       CALL dbcsr_release(tempmat)
     663            0 :       CALL cp_fm_release(fmksmat)
     664            0 :       CALL cp_fm_release(fmsmat)
     665            0 :       CALL cp_fm_release(fmvec)
     666            0 :       CALL cp_fm_release(fmwork)
     667            0 :       CALL cp_fm_struct_release(matrix_struct)
     668              : 
     669            0 :    END SUBROUTINE calculate_p_gamma
     670              : 
     671              : ! **************************************************************************************************
     672              : !> \brief Define the MAO reference basis set
     673              : !> \param qs_env ...
     674              : !> \param mao_basis ...
     675              : !> \param mao_basis_set_list ...
     676              : !> \param orb_basis_set_list ...
     677              : !> \param iunit ...
     678              : !> \param print_basis ...
     679              : !> \par History
     680              : !>      07.2016 created [JGH]
     681              : ! **************************************************************************************************
     682           10 :    SUBROUTINE mao_reference_basis(qs_env, mao_basis, mao_basis_set_list, orb_basis_set_list, &
     683              :                                   iunit, print_basis)
     684              : 
     685              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     686              :       INTEGER, INTENT(IN)                                :: mao_basis
     687              :       TYPE(gto_basis_set_p_type), DIMENSION(:), POINTER  :: mao_basis_set_list, orb_basis_set_list
     688              :       INTEGER, INTENT(IN), OPTIONAL                      :: iunit
     689              :       LOGICAL, INTENT(IN), OPTIONAL                      :: print_basis
     690              : 
     691              :       INTEGER                                            :: ikind, nbas, nkind, unit_nr
     692              :       REAL(KIND=dp)                                      :: eps_pgf_orb
     693              :       TYPE(dft_control_type), POINTER                    :: dft_control
     694              :       TYPE(gto_basis_set_type), POINTER                  :: basis_set, pbasis
     695           10 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
     696              :       TYPE(qs_kind_type), POINTER                        :: qs_kind
     697              : 
     698              :       ! Reference basis set
     699            0 :       CPASSERT(.NOT. ASSOCIATED(mao_basis_set_list))
     700           10 :       CPASSERT(.NOT. ASSOCIATED(orb_basis_set_list))
     701              : 
     702              :       ! options
     703           10 :       IF (PRESENT(iunit)) THEN
     704           10 :          unit_nr = iunit
     705              :       ELSE
     706            0 :          unit_nr = -1
     707              :       END IF
     708              : 
     709           10 :       CALL get_qs_env(qs_env=qs_env, qs_kind_set=qs_kind_set)
     710           10 :       nkind = SIZE(qs_kind_set)
     711           80 :       ALLOCATE (mao_basis_set_list(nkind), orb_basis_set_list(nkind))
     712           30 :       DO ikind = 1, nkind
     713           20 :          NULLIFY (mao_basis_set_list(ikind)%gto_basis_set)
     714           30 :          NULLIFY (orb_basis_set_list(ikind)%gto_basis_set)
     715              :       END DO
     716              :       !
     717           30 :       DO ikind = 1, nkind
     718           20 :          qs_kind => qs_kind_set(ikind)
     719           20 :          CALL get_qs_kind(qs_kind=qs_kind, basis_set=basis_set, basis_type="ORB")
     720           30 :          IF (ASSOCIATED(basis_set)) orb_basis_set_list(ikind)%gto_basis_set => basis_set
     721              :       END DO
     722              :       !
     723           12 :       SELECT CASE (mao_basis)
     724              :       CASE (mao_basis_orb)
     725            6 :          DO ikind = 1, nkind
     726            4 :             qs_kind => qs_kind_set(ikind)
     727            4 :             CALL get_qs_kind(qs_kind=qs_kind, basis_set=basis_set, basis_type="ORB")
     728            6 :             IF (ASSOCIATED(basis_set)) mao_basis_set_list(ikind)%gto_basis_set => basis_set
     729              :          END DO
     730              :       CASE (mao_basis_prim)
     731            6 :          DO ikind = 1, nkind
     732            4 :             qs_kind => qs_kind_set(ikind)
     733            4 :             CALL get_qs_kind(qs_kind=qs_kind, basis_set=basis_set, basis_type="ORB")
     734            4 :             NULLIFY (pbasis)
     735            6 :             IF (ASSOCIATED(basis_set)) THEN
     736            4 :                CALL create_primitive_basis_set(basis_set, pbasis)
     737            4 :                CALL get_qs_env(qs_env, dft_control=dft_control)
     738            4 :                eps_pgf_orb = dft_control%qs_control%eps_pgf_orb
     739            4 :                CALL init_interaction_radii_orb_basis(pbasis, eps_pgf_orb)
     740            4 :                pbasis%kind_radius = basis_set%kind_radius
     741            4 :                mao_basis_set_list(ikind)%gto_basis_set => pbasis
     742            4 :                CALL add_basis_set_to_container(qs_kind%basis_sets, pbasis, "MAO")
     743              :             END IF
     744              :          END DO
     745              :       CASE (mao_basis_ext)
     746           18 :          DO ikind = 1, nkind
     747           12 :             qs_kind => qs_kind_set(ikind)
     748           12 :             CALL get_qs_kind(qs_kind=qs_kind, basis_set=basis_set, basis_type="MAO")
     749           18 :             IF (ASSOCIATED(basis_set)) THEN
     750           12 :                basis_set%kind_radius = orb_basis_set_list(ikind)%gto_basis_set%kind_radius
     751           12 :                mao_basis_set_list(ikind)%gto_basis_set => basis_set
     752              :             END IF
     753              :          END DO
     754              :       CASE DEFAULT
     755           10 :          CPABORT("Unknown option for MAO basis")
     756              :       END SELECT
     757           10 :       IF (unit_nr > 0) THEN
     758           15 :          DO ikind = 1, nkind
     759           15 :             IF (.NOT. ASSOCIATED(mao_basis_set_list(ikind)%gto_basis_set)) THEN
     760              :                WRITE (UNIT=unit_nr, FMT="(T2,A,I4)") &
     761            0 :                   "WARNING: No MAO basis set associated with Kind ", ikind
     762              :             ELSE
     763           10 :                nbas = mao_basis_set_list(ikind)%gto_basis_set%nsgf
     764              :                WRITE (UNIT=unit_nr, FMT="(T2,A,I4,T56,A,I10)") &
     765           10 :                   "MAO basis set Kind ", ikind, " Number of BSF:", nbas
     766              :             END IF
     767              :          END DO
     768              :       END IF
     769              : 
     770           10 :       IF (PRESENT(print_basis)) THEN
     771           10 :          IF (print_basis) THEN
     772            0 :             DO ikind = 1, nkind
     773            0 :                basis_set => mao_basis_set_list(ikind)%gto_basis_set
     774            0 :                IF (ASSOCIATED(basis_set)) CALL write_gto_basis_set(basis_set, unit_nr, "MAO REFERENCE BASIS")
     775              :             END DO
     776              :          END IF
     777              :       END IF
     778              : 
     779           10 :    END SUBROUTINE mao_reference_basis
     780              : 
     781              : ! **************************************************************************************************
     782              : !> \brief Analyze the MAO basis, projection on angular functions
     783              : !> \param mao_coef ...
     784              : !> \param matrix_smm ...
     785              : !> \param mao_basis_set_list ...
     786              : !> \param particle_set ...
     787              : !> \param qs_kind_set ...
     788              : !> \param unit_nr ...
     789              : !> \param para_env ...
     790              : !> \par History
     791              : !>      07.2016 created [JGH]
     792              : ! **************************************************************************************************
     793           10 :    SUBROUTINE mao_basis_analysis(mao_coef, matrix_smm, mao_basis_set_list, particle_set, &
     794              :                                  qs_kind_set, unit_nr, para_env)
     795              : 
     796              :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: mao_coef, matrix_smm
     797              :       TYPE(gto_basis_set_p_type), DIMENSION(:), POINTER  :: mao_basis_set_list
     798              :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     799              :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
     800              :       INTEGER, INTENT(IN)                                :: unit_nr
     801              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     802              : 
     803              :       CHARACTER(len=2)                                   :: element_symbol
     804              :       INTEGER                                            :: ia, iab, iatom, ikind, iset, ishell, &
     805              :                                                             ispin, l, lmax, lshell, m, ma, na, &
     806              :                                                             natom, nspin
     807              :       LOGICAL                                            :: found
     808           10 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: cmask, vec1, vec2
     809           10 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: weight
     810           10 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: block, cmao
     811              :       TYPE(gto_basis_set_type), POINTER                  :: basis_set
     812              : 
     813              :       ! Analyze the MAO basis
     814           10 :       IF (unit_nr > 0) THEN
     815            5 :          WRITE (unit_nr, "(/,A)") " Analyze angular momentum character of MAOs "
     816              :          WRITE (unit_nr, "(T7,A,T15,A,T20,A,T40,A,T50,A,T60,A,T70,A,T80,A)") &
     817            5 :             "ATOM", "Spin", "MAO", "S", "P", "D", "F", "G"
     818              :       END IF
     819           10 :       lmax = 4 ! analyze up to g-functions
     820           10 :       natom = SIZE(particle_set)
     821           10 :       nspin = SIZE(mao_coef)
     822           58 :       DO iatom = 1, natom
     823              :          CALL get_atomic_kind(atomic_kind=particle_set(iatom)%atomic_kind, &
     824           48 :                               element_symbol=element_symbol, kind_number=ikind)
     825           48 :          basis_set => mao_basis_set_list(ikind)%gto_basis_set
     826           48 :          CALL get_qs_kind(qs_kind_set(ikind), mao=na)
     827           48 :          CALL get_gto_basis_set(basis_set, nsgf=ma)
     828          336 :          ALLOCATE (cmask(ma), vec1(ma), vec2(ma), weight(0:lmax, na))
     829           48 :          weight = 0.0_dp
     830              :          CALL dbcsr_get_block_p(matrix=matrix_smm(1)%matrix, row=iatom, col=iatom, &
     831           48 :                                 block=block, found=found)
     832          102 :          DO ispin = 1, nspin
     833              :             CALL dbcsr_get_block_p(matrix=mao_coef(ispin)%matrix, row=iatom, col=iatom, &
     834           54 :                                    block=cmao, found=found)
     835           54 :             IF (found) THEN
     836          162 :                DO l = 0, lmax
     837          135 :                   cmask = 0.0_dp
     838          135 :                   iab = 0
     839          675 :                   DO iset = 1, basis_set%nset
     840         1635 :                      DO ishell = 1, basis_set%nshell(iset)
     841          960 :                         lshell = basis_set%l(ishell, iset)
     842         3810 :                         DO m = -lshell, lshell
     843         2310 :                            iab = iab + 1
     844         3270 :                            IF (l == lshell) cmask(iab) = 1.0_dp
     845              :                         END DO
     846              :                      END DO
     847              :                   END DO
     848          432 :                   DO ia = 1, na
     849         6450 :                      vec1(1:ma) = cmask*cmao(1:ma, ia)
     850       383430 :                      vec2(1:ma) = MATMUL(block, vec1)
     851         6585 :                      weight(l, ia) = SUM(vec1(1:ma)*vec2(1:ma))
     852              :                   END DO
     853              :                END DO
     854              :             END IF
     855           54 :             CALL para_env%sum(weight)
     856          156 :             IF (unit_nr > 0) THEN
     857           81 :                DO ia = 1, na
     858           81 :                   IF (ispin == 1 .AND. ia == 1) THEN
     859              :                      WRITE (unit_nr, "(i6,T9,A2,T17,i2,T20,i3,T31,5F10.4)") &
     860           24 :                         iatom, element_symbol, ispin, ia, weight(0:lmax, ia)
     861              :                   ELSE
     862           30 :                      WRITE (unit_nr, "(T17,i2,T20,i3,T31,5F10.4)") ispin, ia, weight(0:lmax, ia)
     863              :                   END IF
     864              :                END DO
     865              :             END IF
     866              :          END DO
     867          154 :          DEALLOCATE (cmask, weight, vec1, vec2)
     868              :       END DO
     869           20 :    END SUBROUTINE mao_basis_analysis
     870              : 
     871              : ! **************************************************************************************************
     872              : !> \brief Calculte the Q=APA(T) matrix, A=(MAO,ORB) overlap
     873              : !> \param matrix_q ...
     874              : !> \param matrix_p ...
     875              : !> \param matrix_s ...
     876              : !> \param matrix_smm ...
     877              : !> \param matrix_smo ...
     878              : !> \param smm_list ...
     879              : !> \param electra ...
     880              : !> \param eps_filter ...
     881              : !> \param nimages ...
     882              : !> \param kpoints ...
     883              : !> \param matrix_ks ...
     884              : !> \param sab_orb ...
     885              : !> \par History
     886              : !>      08.2016 created [JGH]
     887              : ! **************************************************************************************************
     888           14 :    SUBROUTINE mao_build_q(matrix_q, matrix_p, matrix_s, matrix_smm, matrix_smo, smm_list, &
     889              :                           electra, eps_filter, nimages, kpoints, matrix_ks, sab_orb)
     890              : 
     891              :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_q
     892              :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: matrix_p, matrix_s
     893              :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_smm, matrix_smo
     894              :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
     895              :          POINTER                                         :: smm_list
     896              :       REAL(KIND=dp), DIMENSION(2), INTENT(OUT)           :: electra
     897              :       REAL(KIND=dp), INTENT(IN)                          :: eps_filter
     898              :       INTEGER, INTENT(IN), OPTIONAL                      :: nimages
     899              :       TYPE(kpoint_type), OPTIONAL, POINTER               :: kpoints
     900              :       TYPE(dbcsr_p_type), DIMENSION(:, :), OPTIONAL, &
     901              :          POINTER                                         :: matrix_ks
     902              :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
     903              :          OPTIONAL, POINTER                               :: sab_orb
     904              : 
     905              :       INTEGER                                            :: im, ispin, nim, nocc, norb, nspin
     906           14 :       INTEGER, DIMENSION(:, :, :), POINTER               :: cell_to_index
     907              :       REAL(KIND=dp)                                      :: elex, xkp(3)
     908              :       TYPE(dbcsr_type)                                   :: ksmat, pmat, smat, tmat
     909              : 
     910           14 :       nim = 1
     911           14 :       IF (PRESENT(nimages)) nim = nimages
     912            0 :       IF (nim > 1) THEN
     913            0 :          CPASSERT(PRESENT(kpoints))
     914            0 :          CPASSERT(PRESENT(matrix_ks))
     915            0 :          CPASSERT(PRESENT(sab_orb))
     916              :       END IF
     917              : 
     918              :       ! Reference
     919           14 :       nspin = SIZE(matrix_p, 1)
     920           30 :       DO ispin = 1, nspin
     921           16 :          electra(ispin) = 0.0_dp
     922           46 :          DO im = 1, nim
     923           16 :             CALL dbcsr_dot(matrix_p(ispin, im)%matrix, matrix_s(1, im)%matrix, elex)
     924           32 :             electra(ispin) = electra(ispin) + elex
     925              :          END DO
     926              :       END DO
     927              : 
     928              :       ! Q matrix
     929           14 :       NULLIFY (matrix_q)
     930           14 :       CALL dbcsr_allocate_matrix_set(matrix_q, nspin)
     931           30 :       DO ispin = 1, nspin
     932           16 :          ALLOCATE (matrix_q(ispin)%matrix)
     933           16 :          CALL dbcsr_create(matrix_q(ispin)%matrix, template=matrix_smm(1)%matrix)
     934           30 :          CALL cp_dbcsr_alloc_block_from_nbl(matrix_q(ispin)%matrix, smm_list)
     935              :       END DO
     936              :       ! temp matrix
     937           14 :       CALL dbcsr_create(tmat, template=matrix_smo(1)%matrix, matrix_type=dbcsr_type_no_symmetry)
     938              :       ! Q=APA(T)
     939           30 :       DO ispin = 1, nspin
     940           30 :          IF (nim == 1) THEN
     941              :             CALL dbcsr_multiply("N", "N", 1.0_dp, matrix_smo(1)%matrix, matrix_p(ispin, 1)%matrix, &
     942           16 :                                 0.0_dp, tmat, filter_eps=eps_filter)
     943              :             CALL dbcsr_multiply("N", "T", 1.0_dp, tmat, matrix_smo(1)%matrix, &
     944           16 :                                 0.0_dp, matrix_q(ispin)%matrix, filter_eps=eps_filter)
     945              :          ELSE
     946              :             ! k-points
     947            0 :             CALL dbcsr_create(pmat, template=matrix_s(1, 1)%matrix)
     948            0 :             CALL dbcsr_create(smat, template=matrix_s(1, 1)%matrix)
     949            0 :             CALL dbcsr_create(ksmat, template=matrix_s(1, 1)%matrix)
     950            0 :             CALL cp_dbcsr_alloc_block_from_nbl(pmat, sab_orb)
     951            0 :             CALL cp_dbcsr_alloc_block_from_nbl(smat, sab_orb)
     952            0 :             CALL cp_dbcsr_alloc_block_from_nbl(ksmat, sab_orb)
     953            0 :             NULLIFY (cell_to_index)
     954            0 :             CALL get_kpoint_info(kpoint=kpoints, cell_to_index=cell_to_index)
     955              :             ! calculate density matrix at gamma point
     956            0 :             xkp = 0.0_dp
     957              :             ! transform KS and S matrices to the gamma point
     958            0 :             CALL dbcsr_set(ksmat, 0.0_dp)
     959              :             CALL rskp_transform(rmatrix=ksmat, rsmat=matrix_ks, ispin=ispin, &
     960            0 :                                 xkp=xkp, cell_to_index=cell_to_index, sab_nl=sab_orb)
     961            0 :             CALL dbcsr_set(smat, 0.0_dp)
     962              :             CALL rskp_transform(rmatrix=smat, rsmat=matrix_s, ispin=1, &
     963            0 :                                 xkp=xkp, cell_to_index=cell_to_index, sab_nl=sab_orb)
     964            0 :             norb = NINT(electra(ispin))
     965            0 :             nocc = MOD(2, nspin) + 1
     966            0 :             CALL calculate_p_gamma(pmat, ksmat, smat, kpoints, norb, REAL(nocc, KIND=dp))
     967              :             CALL dbcsr_multiply("N", "N", 1.0_dp, matrix_smo(1)%matrix, pmat, &
     968            0 :                                 0.0_dp, tmat, filter_eps=eps_filter)
     969              :             CALL dbcsr_multiply("N", "T", 1.0_dp, tmat, matrix_smo(1)%matrix, &
     970            0 :                                 0.0_dp, matrix_q(ispin)%matrix, filter_eps=eps_filter)
     971            0 :             CALL dbcsr_release(pmat)
     972            0 :             CALL dbcsr_release(smat)
     973            0 :             CALL dbcsr_release(ksmat)
     974              :          END IF
     975              :       END DO
     976              :       ! free temp matrix
     977           14 :       CALL dbcsr_release(tmat)
     978              : 
     979           14 :    END SUBROUTINE mao_build_q
     980              : 
     981         4320 : END MODULE mao_methods
        

Generated by: LCOV version 2.0-1