(git:ccc2433)
mao_optimizer.F
Go to the documentation of this file.
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 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 ! **************************************************************************************************
18  USE dbcsr_api, ONLY: &
19  dbcsr_add, dbcsr_copy, dbcsr_create, dbcsr_distribution_type, dbcsr_get_info, dbcsr_norm, &
20  dbcsr_norm_maxabsnorm, dbcsr_p_type, dbcsr_release, dbcsr_reserve_diag_blocks, dbcsr_type, &
21  dbcsr_type_symmetric
22  USE kinds, ONLY: dp
23  USE mao_methods, ONLY: mao_function,&
28 #include "./base/base_uses.f90"
29 
30  IMPLICIT NONE
31  PRIVATE
32 
33  CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'mao_optimizer'
34 
35  PUBLIC :: mao_optimize
36 
37 ! **************************************************************************************************
38 
39 CONTAINS
40 
41 ! **************************************************************************************************
42 !> \brief ...
43 !> \param mao_coef ...
44 !> \param matrix_q ...
45 !> \param matrix_smm ...
46 !> \param electra ...
47 !> \param max_iter ...
48 !> \param eps_grad ...
49 !> \param eps1 ...
50 !> \param iolevel ...
51 !> \param iw ...
52 ! **************************************************************************************************
53  SUBROUTINE mao_optimize(mao_coef, matrix_q, matrix_smm, electra, max_iter, eps_grad, eps1, &
54  iolevel, iw)
55  TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: mao_coef, matrix_q, matrix_smm
56  REAL(kind=dp), DIMENSION(:), INTENT(IN) :: electra
57  INTEGER, INTENT(IN) :: max_iter
58  REAL(kind=dp), INTENT(IN) :: eps_grad, eps1
59  INTEGER, INTENT(IN) :: iolevel, iw
60 
61  CHARACTER(len=*), PARAMETER :: routinen = 'mao_optimize'
62 
63  INTEGER :: handle, i, ispin, iter, nspin
64  INTEGER, DIMENSION(:), POINTER :: col_blk_sizes, mao_sizes_a, mao_sizes_b
65  LOGICAL :: spin_warning
66  REAL(kind=dp) :: a1, a2, alpha, an, beta, eps_fun, fa1, &
67  fa2, fnnew, fnold, fval, grad_norm
68  TYPE(dbcsr_distribution_type) :: dbcsr_dist
69  TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: mao_grad
70  TYPE(dbcsr_type) :: amat, binv, cgmat
71 
72  CALL timeset(routinen, handle)
73 
74  eps_fun = 10._dp*eps_grad
75 
76  nspin = SIZE(mao_coef, 1)
77 
78  IF (iw > 0) THEN
79  WRITE (iw, '(/,T2,A)') '!-----------------------------------------------------------------------------!'
80  WRITE (unit=iw, fmt="(T32,A)") "MAO BASIS GENERATION"
81  WRITE (iw, '(T2,A)') '!-----------------------------------------------------------------------------!'
82  END IF
83 
84  ! initialize MAO coeficients from diagonal blocks of the Q matrix
85  DO ispin = 1, nspin
86  CALL mao_initialization(mao_coef(ispin)%matrix, &
87  matrix_q(ispin)%matrix, matrix_smm(1)%matrix, eps1, iolevel, iw)
88  END DO
89  ! check for mao sizes
90  spin_warning = .false.
91  CALL dbcsr_get_info(mao_coef(1)%matrix, col_blk_size=mao_sizes_a, distribution=dbcsr_dist)
92  IF (nspin == 2) THEN
93  CALL dbcsr_get_info(mao_coef(2)%matrix, col_blk_size=mao_sizes_b, distribution=dbcsr_dist)
94  DO i = 1, SIZE(mao_sizes_a)
95  IF (mao_sizes_a(i) /= mao_sizes_b(i)) spin_warning = .true.
96  END DO
97  END IF
98  IF (iw > 0 .AND. spin_warning) THEN
99  WRITE (unit=iw, fmt="(/,A)") ">>>> WARNING: Different number of MAOs for different spins"
100  END IF
101  IF (iw > 0) THEN
102  DO ispin = 1, nspin
103  IF (ispin == 1) THEN
104  WRITE (unit=iw, fmt="(/,A,I2,T70,I11)") " MAO's for SPIN ", ispin, sum(mao_sizes_a)
105  WRITE (unit=iw, fmt="(20I4)") mao_sizes_a(:)
106  ELSE IF (ispin == 2) THEN
107  WRITE (unit=iw, fmt="(/,A,I2,T70,I11)") " MAO's for SPIN ", ispin, sum(mao_sizes_b)
108  WRITE (unit=iw, fmt="(20I4)") mao_sizes_b(:)
109  END IF
110  END DO
111  WRITE (unit=iw, fmt="(A)")
112  END IF
113 
114  IF (max_iter < 1) THEN
115  ! projection only
116  DO ispin = 1, nspin
117  CALL dbcsr_get_info(mao_coef(ispin)%matrix, col_blk_size=col_blk_sizes, distribution=dbcsr_dist)
118  CALL dbcsr_create(binv, name="Binv", dist=dbcsr_dist, matrix_type=dbcsr_type_symmetric, &
119  row_blk_size=col_blk_sizes, col_blk_size=col_blk_sizes, nze=0)
120  CALL mao_function(mao_coef(ispin)%matrix, fval, matrix_q(ispin)%matrix, &
121  matrix_smm(1)%matrix, binv, .false.)
122  IF (iw > 0) THEN
123  WRITE (unit=iw, fmt="(T2,A,T31,A,I2,T56,A,F12.8)") &
124  "MAO Projection", "Spin:", ispin, "Completeness:", fval/electra(ispin)
125  END IF
126  CALL dbcsr_release(binv)
127  END DO
128  IF (iw > 0) WRITE (unit=iw, fmt="(A)")
129  ELSE
130  ! optimize MAOs
131  NULLIFY (mao_grad)
132  CALL dbcsr_allocate_matrix_set(mao_grad, nspin)
133  DO ispin = 1, nspin
134  ALLOCATE (mao_grad(ispin)%matrix)
135  CALL dbcsr_create(matrix=mao_grad(ispin)%matrix, name="MAO_GRAD", template=mao_coef(1)%matrix)
136  CALL dbcsr_reserve_diag_blocks(matrix=mao_grad(ispin)%matrix)
137  END DO
138  CALL dbcsr_get_info(mao_coef(1)%matrix, col_blk_size=col_blk_sizes, distribution=dbcsr_dist)
139  CALL dbcsr_create(binv, name="Binv", dist=dbcsr_dist, matrix_type=dbcsr_type_symmetric, &
140  row_blk_size=col_blk_sizes, col_blk_size=col_blk_sizes, nze=0)
141  CALL dbcsr_create(cgmat, template=mao_grad(1)%matrix)
142  CALL dbcsr_create(amat, template=mao_coef(1)%matrix)
143  DO ispin = 1, nspin
144  alpha = 0.25_dp
145  beta = 0.0_dp
146  CALL mao_function_gradient(mao_coef(ispin)%matrix, fval, mao_grad(ispin)%matrix, &
147  matrix_q(ispin)%matrix, matrix_smm(1)%matrix, binv, .false.)
148  CALL dbcsr_copy(cgmat, mao_grad(ispin)%matrix)
149  CALL dbcsr_norm(mao_grad(ispin)%matrix, dbcsr_norm_maxabsnorm, norm_scalar=grad_norm)
150  fnold = mao_scalar_product(mao_grad(ispin)%matrix, mao_grad(ispin)%matrix)
151  IF (iw > 0) THEN
152  WRITE (unit=iw, fmt="(/,T2,A,T73,A,I2)") "MAO OPTIMIZATION", "Spin =", ispin
153  WRITE (unit=iw, fmt="(T2,A,T24,A,F11.8,T48,A,F11.8,T69,A,F6.3)") &
154  "Initialization", "fval =", fval/electra(ispin), "grad =", grad_norm, "step =", alpha
155  END IF
156  DO iter = 1, max_iter
157  IF (grad_norm < eps_grad) EXIT
158  IF ((1.0_dp - fval/electra(ispin)) < eps_fun) EXIT
159  CALL dbcsr_add(mao_coef(ispin)%matrix, cgmat, 1.0_dp, alpha)
160  CALL mao_orthogonalization(mao_coef(ispin)%matrix, matrix_smm(1)%matrix)
161  CALL mao_function_gradient(mao_coef(ispin)%matrix, fval, mao_grad(ispin)%matrix, &
162  matrix_q(ispin)%matrix, matrix_smm(1)%matrix, binv, .true.)
163  CALL dbcsr_norm(mao_grad(ispin)%matrix, dbcsr_norm_maxabsnorm, norm_scalar=grad_norm)
164  IF (iw > 0) THEN
165  WRITE (unit=iw, fmt="(T2,A,i8,T24,A,F11.8,T48,A,F11.8,T69,A,F6.3)") &
166  "iter=", iter, "fval =", fval/electra(ispin), "grad =", grad_norm, "step =", alpha
167  END IF
168  fnnew = mao_scalar_product(mao_grad(ispin)%matrix, mao_grad(ispin)%matrix)
169  beta = fnnew/fnold
170  CALL dbcsr_add(cgmat, mao_grad(ispin)%matrix, beta, 1.0_dp)
171  fnold = fnnew
172  ! line search, update alpha
173  CALL dbcsr_copy(amat, mao_coef(ispin)%matrix)
174  CALL dbcsr_add(amat, cgmat, 1.0_dp, 0.5_dp*alpha)
175  CALL mao_orthogonalization(amat, matrix_smm(1)%matrix)
176  CALL mao_function(amat, fa1, matrix_q(ispin)%matrix, matrix_smm(1)%matrix, binv, .true.)
177  CALL dbcsr_copy(amat, mao_coef(ispin)%matrix)
178  CALL dbcsr_add(amat, cgmat, 1.0_dp, alpha)
179  CALL mao_orthogonalization(amat, matrix_smm(1)%matrix)
180  CALL mao_function(amat, fa2, matrix_q(ispin)%matrix, matrix_smm(1)%matrix, binv, .true.)
181  a2 = (4._dp*fa1 - fa2 - 3._dp*fval)/alpha
182  a1 = (fa2 - fval - a2*alpha)/(alpha*alpha)
183  IF (abs(a1) > 1.e-14_dp) THEN
184  an = -a2/(2._dp*a1)
185  an = min(an, 2.0_dp*alpha)
186  ELSE
187  an = 2.0_dp*alpha
188  END IF
189  IF (an < 0.05_dp .OR. a1 > 0.0_dp) THEN
190  CALL dbcsr_copy(cgmat, mao_grad(ispin)%matrix)
191  alpha = 0.25_dp
192  ELSE
193  alpha = an
194  END IF
195  END DO
196  END DO
197  CALL dbcsr_release(binv)
198  CALL dbcsr_release(cgmat)
199  CALL dbcsr_release(amat)
200  IF (ASSOCIATED(mao_grad)) CALL dbcsr_deallocate_matrix_set(mao_grad)
201  END IF
202 
203  CALL timestop(handle)
204 
205  END SUBROUTINE mao_optimize
206 
207 END MODULE mao_optimizer
DBCSR operations in CP2K.
Defines the basic variable types.
Definition: kinds.F:23
integer, parameter, public dp
Definition: kinds.F:34
Calculate MAO's and analyze wavefunctions.
Definition: mao_methods.F:15
subroutine, public mao_function_gradient(mao_coef, fval, mao_grad, qmat, smat, binv, reuse)
...
Definition: mao_methods.F:273
subroutine, public mao_orthogonalization(mao_coef, smat)
...
Definition: mao_methods.F:323
subroutine, public mao_initialization(mao_coef, pmat, smat, eps1, iolevel, iw)
...
Definition: mao_methods.F:91
real(kind=dp) function, public mao_scalar_product(fmat1, fmat2)
...
Definition: mao_methods.F:404
subroutine, public mao_function(mao_coef, fval, qmat, smat, binv, reuse)
...
Definition: mao_methods.F:230
Calculate MAO's and analyze wavefunctions.
Definition: mao_optimizer.F:15
subroutine, public mao_optimize(mao_coef, matrix_q, matrix_smm, electra, max_iter, eps_grad, eps1, iolevel, iw)
...
Definition: mao_optimizer.F:55