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 orbital transformations
10 : !> \par History
11 : !> Added Taylor expansion based computation of the matrix functions (01.2004)
12 : !> added additional rotation variables for non-equivalent occupied orbs (08.2004)
13 : !> \author Joost VandeVondele (06.2002)
14 : ! **************************************************************************************************
15 : MODULE qs_ot
16 : USE arnoldi_api, ONLY: arnoldi_extremal
17 : USE cp_dbcsr_api, ONLY: &
18 : dbcsr_add, dbcsr_add_on_diag, dbcsr_copy, dbcsr_distribution_type, dbcsr_filter, &
19 : dbcsr_frobenius_norm, dbcsr_gershgorin_norm, dbcsr_get_block_p, dbcsr_get_info, &
20 : dbcsr_get_occupation, dbcsr_hadamard_product, dbcsr_init_p, dbcsr_iterator_blocks_left, &
21 : dbcsr_iterator_next_block, dbcsr_iterator_start, dbcsr_iterator_stop, dbcsr_iterator_type, &
22 : dbcsr_multiply, dbcsr_release, dbcsr_release_p, dbcsr_scale, dbcsr_scale_by_vector, &
23 : dbcsr_set, dbcsr_transposed, dbcsr_type
24 : USE cp_dbcsr_cholesky, ONLY: cp_dbcsr_cholesky_decompose,&
25 : cp_dbcsr_cholesky_invert,&
26 : cp_dbcsr_cholesky_restore
27 : USE cp_dbcsr_diag, ONLY: cp_dbcsr_heevd,&
28 : cp_dbcsr_syevd
29 : USE kinds, ONLY: dp
30 : USE message_passing, ONLY: mp_comm_type
31 : USE preconditioner, ONLY: apply_preconditioner
32 : USE preconditioner_types, ONLY: preconditioner_type
33 : USE qs_ot_types, ONLY: qs_ot_type
34 : #include "./base/base_uses.f90"
35 :
36 : IMPLICIT NONE
37 : PRIVATE
38 :
39 : PUBLIC :: qs_ot_get_p
40 : PUBLIC :: qs_ot_get_orbitals
41 : PUBLIC :: qs_ot_get_derivative
42 : PUBLIC :: qs_ot_get_orbitals_ref
43 : PUBLIC :: qs_ot_get_derivative_ref
44 : PUBLIC :: qs_ot_new_preconditioner
45 : PRIVATE :: qs_ot_p2m_diag
46 : PRIVATE :: qs_ot_sinc
47 : PRIVATE :: qs_ot_ref_poly
48 : PRIVATE :: qs_ot_ref_chol
49 : PRIVATE :: qs_ot_ref_lwdn
50 : PRIVATE :: qs_ot_ref_decide
51 : PRIVATE :: qs_ot_ref_update
52 : PRIVATE :: qs_ot_refine
53 : PRIVATE :: qs_ot_on_the_fly_localize
54 :
55 : CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'qs_ot'
56 :
57 : CONTAINS
58 :
59 : ! gets ready to use the preconditioner/ or renew the preconditioner
60 : ! only keeps a pointer to the preconditioner.
61 : ! If you change the preconditioner, you have to call this routine
62 : ! you remain responsible of proper deallocate of your preconditioner
63 : ! (or you can reuse it on the next step of the computation)
64 : ! **************************************************************************************************
65 : !> \brief ...
66 : !> \param qs_ot_env ...
67 : !> \param preconditioner ...
68 : ! **************************************************************************************************
69 7393 : SUBROUTINE qs_ot_new_preconditioner(qs_ot_env, preconditioner)
70 : TYPE(qs_ot_type) :: qs_ot_env
71 : TYPE(preconditioner_type), POINTER :: preconditioner
72 :
73 : INTEGER :: ncoef
74 :
75 7393 : qs_ot_env%preconditioner => preconditioner
76 7393 : qs_ot_env%os_valid = .FALSE.
77 7393 : IF (.NOT. ASSOCIATED(qs_ot_env%matrix_psc0)) THEN
78 7393 : CALL dbcsr_init_p(qs_ot_env%matrix_psc0)
79 7393 : CALL dbcsr_copy(qs_ot_env%matrix_psc0, qs_ot_env%matrix_sc0, 'matrix_psc0')
80 : END IF
81 :
82 7393 : IF (.NOT. qs_ot_env%use_dx) THEN
83 4147 : qs_ot_env%use_dx = .TRUE.
84 4147 : CALL dbcsr_init_p(qs_ot_env%matrix_dx)
85 4147 : CALL dbcsr_copy(qs_ot_env%matrix_dx, qs_ot_env%matrix_gx, 'matrix_dx')
86 4147 : IF (qs_ot_env%settings%do_rotation) THEN
87 30 : CALL dbcsr_init_p(qs_ot_env%rot_mat_dx)
88 30 : CALL dbcsr_copy(qs_ot_env%rot_mat_dx, qs_ot_env%rot_mat_gx, 'rot_mat_dx')
89 : END IF
90 4147 : IF (qs_ot_env%settings%do_ener) THEN
91 0 : ncoef = SIZE(qs_ot_env%ener_gx)
92 0 : ALLOCATE (qs_ot_env%ener_dx(ncoef))
93 0 : qs_ot_env%ener_dx = 0.0_dp
94 : END IF
95 : END IF
96 :
97 7393 : END SUBROUTINE qs_ot_new_preconditioner
98 :
99 : ! **************************************************************************************************
100 : !> \brief ...
101 : !> \param qs_ot_env ...
102 : !> \param C_NEW ...
103 : !> \param SC ...
104 : !> \param G_OLD ...
105 : !> \param D ...
106 : ! **************************************************************************************************
107 240 : SUBROUTINE qs_ot_on_the_fly_localize(qs_ot_env, C_NEW, SC, G_OLD, D)
108 : !
109 : TYPE(qs_ot_type) :: qs_ot_env
110 : TYPE(dbcsr_type), POINTER :: C_NEW, SC, G_OLD, D
111 :
112 : CHARACTER(len=*), PARAMETER :: routineN = 'qs_ot_on_the_fly_localize'
113 : INTEGER, PARAMETER :: taylor_order = 50
114 : REAL(KIND=dp), PARAMETER :: alpha = 0.1_dp, f2_eps = 0.01_dp
115 :
116 : INTEGER :: blk, col, col_size, group_handle, &
117 : handle, i, k, n, p, row, row_size
118 48 : REAL(dp), DIMENSION(:, :), POINTER :: DATA
119 : REAL(KIND=dp) :: expfactor, f2, norm_fro, norm_gct, tmp
120 : TYPE(dbcsr_distribution_type) :: dist
121 : TYPE(dbcsr_iterator_type) :: iter
122 : TYPE(dbcsr_type), POINTER :: C, Gp1, Gp2, GU, U
123 : TYPE(mp_comm_type) :: group
124 :
125 48 : CALL timeset(routineN, handle)
126 : !
127 : !
128 48 : CALL dbcsr_get_info(C_NEW, nfullrows_total=n, nfullcols_total=k)
129 : !
130 : ! C = C*expm(-G)
131 48 : GU => qs_ot_env%buf1_k_k_nosym ! a buffer
132 48 : U => qs_ot_env%buf2_k_k_nosym ! a buffer
133 48 : Gp1 => qs_ot_env%buf3_k_k_nosym ! a buffer
134 48 : Gp2 => qs_ot_env%buf4_k_k_nosym ! a buffer
135 48 : C => qs_ot_env%buf1_n_k ! a buffer
136 : !
137 : ! compute the derivative of the norm
138 : !-------------------------------------------------------------------
139 : ! (x^2+eps)^1/2
140 48 : f2 = 0.0_dp
141 48 : CALL dbcsr_copy(C, C_NEW)
142 48 : CALL dbcsr_iterator_start(iter, C)
143 104 : DO WHILE (dbcsr_iterator_blocks_left(iter))
144 : CALL dbcsr_iterator_next_block(iter, row, col, DATA, blk, &
145 56 : row_size=row_size, col_size=col_size)
146 392 : DO p = 1, col_size ! p
147 3576 : DO i = 1, row_size ! i
148 3232 : tmp = SQRT(DATA(i, p)**2 + f2_eps)
149 3232 : f2 = f2 + tmp
150 3520 : DATA(i, p) = DATA(i, p)/tmp
151 : END DO
152 : END DO
153 : END DO
154 48 : CALL dbcsr_iterator_stop(iter)
155 48 : CALL dbcsr_get_info(C, group=group_handle)
156 48 : CALL group%set_handle(group_handle)
157 48 : CALL group%sum(f2)
158 : !
159 : !
160 48 : CALL dbcsr_multiply('T', 'N', 1.0_dp, C, C_NEW, 0.0_dp, GU)
161 : !
162 : ! antisymetrize
163 48 : CALL dbcsr_get_info(GU, distribution=dist)
164 : CALL dbcsr_transposed(U, GU, shallow_data_copy=.FALSE., &
165 : use_distribution=dist, &
166 48 : transpose_distribution=.FALSE.)
167 48 : CALL dbcsr_add(GU, U, alpha_scalar=-0.5_dp, beta_scalar=0.5_dp)
168 : !-------------------------------------------------------------------
169 : !
170 48 : norm_fro = dbcsr_frobenius_norm(GU)
171 48 : norm_gct = dbcsr_gershgorin_norm(GU)
172 : !write(*,*) 'qs_ot_localize: ||P-I||_f=',norm_fro,' ||P-I||_GCT=',norm_gct
173 : !
174 : !kscale = CEILING(LOG(MIN(norm_fro,norm_gct))/LOG(2.0_dp))
175 : !scale = LOG(MIN(norm_fro,norm_gct))/LOG(2.0_dp)
176 : !write(*,*) 'qs_ot_localize: scale=',scale,' kscale=',kscale
177 : !
178 : ! rescale for steepest descent
179 48 : CALL dbcsr_scale(GU, -alpha)
180 : !
181 : ! compute unitary transform
182 : ! zeroth and first order
183 48 : expfactor = 1.0_dp
184 48 : CALL dbcsr_copy(U, GU)
185 48 : CALL dbcsr_scale(U, expfactor)
186 48 : CALL dbcsr_add_on_diag(U, 1.0_dp)
187 : ! other orders
188 48 : CALL dbcsr_copy(Gp1, GU)
189 296 : DO i = 2, taylor_order
190 : ! new power of G
191 296 : CALL dbcsr_multiply('N', 'N', 1.0_dp, GU, Gp1, 0.0_dp, Gp2)
192 296 : CALL dbcsr_copy(Gp1, Gp2)
193 : ! add to the taylor expansion so far
194 296 : expfactor = expfactor/REAL(i, KIND=dp)
195 296 : CALL dbcsr_add(U, Gp1, alpha_scalar=1.0_dp, beta_scalar=expfactor)
196 296 : norm_fro = dbcsr_frobenius_norm(Gp1)
197 : !write(*,*) 'Taylor expansion i=',i,' norm(X^i)/i!=',norm_fro*expfactor
198 296 : IF (norm_fro*expfactor .LT. 1.0E-10_dp) EXIT
199 : END DO
200 : !
201 : ! rotate MOs
202 48 : CALL dbcsr_multiply('N', 'N', 1.0_dp, C_NEW, U, 0.0_dp, C)
203 48 : CALL dbcsr_copy(C_NEW, C)
204 : !
205 : ! rotate SC
206 48 : CALL dbcsr_multiply('N', 'N', 1.0_dp, SC, U, 0.0_dp, C)
207 48 : CALL dbcsr_copy(SC, C)
208 : !
209 : ! rotate D_i
210 48 : CALL dbcsr_multiply('N', 'N', 1.0_dp, D, U, 0.0_dp, C)
211 48 : CALL dbcsr_copy(D, C)
212 : !
213 : ! rotate G_i-1
214 48 : IF (ASSOCIATED(G_OLD)) THEN
215 48 : CALL dbcsr_multiply('N', 'N', 1.0_dp, G_OLD, U, 0.0_dp, C)
216 48 : CALL dbcsr_copy(G_OLD, C)
217 : END IF
218 : !
219 48 : CALL timestop(handle)
220 48 : END SUBROUTINE qs_ot_on_the_fly_localize
221 :
222 : ! **************************************************************************************************
223 : !> \brief ...
224 : !> \param qs_ot_env ...
225 : !> \param C_OLD ...
226 : !> \param C_TMP ...
227 : !> \param C_NEW ...
228 : !> \param P ...
229 : !> \param SC ...
230 : !> \param update ...
231 : ! **************************************************************************************************
232 1456 : SUBROUTINE qs_ot_ref_chol(qs_ot_env, C_OLD, C_TMP, C_NEW, P, SC, update)
233 : !
234 : TYPE(qs_ot_type) :: qs_ot_env
235 : TYPE(dbcsr_type) :: C_OLD, C_TMP, C_NEW, P, SC
236 : LOGICAL, INTENT(IN) :: update
237 :
238 : CHARACTER(len=*), PARAMETER :: routineN = 'qs_ot_ref_chol'
239 :
240 : INTEGER :: handle, k, n
241 :
242 728 : CALL timeset(routineN, handle)
243 : !
244 728 : CALL dbcsr_get_info(C_NEW, nfullrows_total=n, nfullcols_total=k)
245 : !
246 : ! P = U'*U
247 728 : CALL cp_dbcsr_cholesky_decompose(P, k, qs_ot_env%para_env, qs_ot_env%blacs_env)
248 : !
249 : ! C_NEW = C_OLD*inv(U)
250 : CALL cp_dbcsr_cholesky_restore(C_OLD, k, P, C_NEW, op="SOLVE", pos="RIGHT", &
251 728 : transa="N", para_env=qs_ot_env%para_env, blacs_env=qs_ot_env%blacs_env)
252 : !
253 : ! Update SC if needed
254 728 : IF (update) THEN
255 : CALL cp_dbcsr_cholesky_restore(SC, k, P, C_TMP, op="SOLVE", pos="RIGHT", &
256 408 : transa="N", para_env=qs_ot_env%para_env, blacs_env=qs_ot_env%blacs_env)
257 408 : CALL dbcsr_copy(SC, C_TMP)
258 : END IF
259 : !
260 728 : CALL timestop(handle)
261 728 : END SUBROUTINE qs_ot_ref_chol
262 :
263 : ! **************************************************************************************************
264 : !> \brief ...
265 : !> \param qs_ot_env ...
266 : !> \param C_OLD ...
267 : !> \param C_TMP ...
268 : !> \param C_NEW ...
269 : !> \param P ...
270 : !> \param SC ...
271 : !> \param update ...
272 : ! **************************************************************************************************
273 240 : SUBROUTINE qs_ot_ref_lwdn(qs_ot_env, C_OLD, C_TMP, C_NEW, P, SC, update)
274 : !
275 : TYPE(qs_ot_type) :: qs_ot_env
276 : TYPE(dbcsr_type) :: C_OLD, C_TMP, C_NEW, P, SC
277 : LOGICAL, INTENT(IN) :: update
278 :
279 : CHARACTER(len=*), PARAMETER :: routineN = 'qs_ot_ref_lwdn'
280 :
281 : INTEGER :: handle, i, k, n
282 240 : REAL(dp), ALLOCATABLE, DIMENSION(:) :: eig, fun
283 : TYPE(dbcsr_type), POINTER :: V, W
284 :
285 240 : CALL timeset(routineN, handle)
286 : !
287 240 : CALL dbcsr_get_info(C_NEW, nfullrows_total=n, nfullcols_total=k)
288 : !
289 240 : V => qs_ot_env%buf1_k_k_nosym ! a buffer
290 240 : W => qs_ot_env%buf2_k_k_nosym ! a buffer
291 960 : ALLOCATE (eig(k), fun(k))
292 : !
293 240 : CALL cp_dbcsr_syevd(P, V, eig, qs_ot_env%para_env, qs_ot_env%blacs_env)
294 : !
295 : ! compute the P^(-1/2)
296 1408 : DO i = 1, k
297 1168 : IF (eig(i) .LE. 0.0_dp) &
298 0 : CPABORT("P not positive definite")
299 1408 : IF (eig(i) .LT. 1.0E-8_dp) THEN
300 0 : fun(i) = 0.0_dp
301 : ELSE
302 1168 : fun(i) = 1.0_dp/SQRT(eig(i))
303 : END IF
304 : END DO
305 240 : CALL dbcsr_copy(W, V)
306 240 : CALL dbcsr_scale_by_vector(V, alpha=fun, side='right')
307 240 : CALL dbcsr_multiply('N', 'T', 1.0_dp, W, V, 0.0_dp, P)
308 : !
309 : ! Update C
310 240 : CALL dbcsr_multiply('N', 'N', 1.0_dp, C_OLD, P, 0.0_dp, C_NEW)
311 : !
312 : ! Update SC if needed
313 240 : IF (update) THEN
314 188 : CALL dbcsr_multiply('N', 'N', 1.0_dp, SC, P, 0.0_dp, C_TMP)
315 188 : CALL dbcsr_copy(SC, C_TMP)
316 : END IF
317 : !
318 240 : DEALLOCATE (eig, fun)
319 : !
320 240 : CALL timestop(handle)
321 480 : END SUBROUTINE qs_ot_ref_lwdn
322 :
323 : ! **************************************************************************************************
324 : !> \brief ...
325 : !> \param qs_ot_env ...
326 : !> \param C_OLD ...
327 : !> \param C_TMP ...
328 : !> \param C_NEW ...
329 : !> \param P ...
330 : !> \param SC ...
331 : !> \param norm_in ...
332 : !> \param update ...
333 : ! **************************************************************************************************
334 6808 : SUBROUTINE qs_ot_ref_poly(qs_ot_env, C_OLD, C_TMP, C_NEW, P, SC, norm_in, update)
335 : !
336 : TYPE(qs_ot_type) :: qs_ot_env
337 : TYPE(dbcsr_type), POINTER :: C_OLD, C_TMP, C_NEW, P
338 : TYPE(dbcsr_type) :: SC
339 : REAL(dp), INTENT(IN) :: norm_in
340 : LOGICAL, INTENT(IN) :: update
341 :
342 : CHARACTER(len=*), PARAMETER :: routineN = 'qs_ot_ref_poly'
343 :
344 : INTEGER :: handle, irefine, k, n
345 : LOGICAL :: quick_exit
346 : REAL(dp) :: norm, norm_fro, norm_gct, occ_in, &
347 : occ_out, rescale
348 : TYPE(dbcsr_type), POINTER :: BUF1, BUF2, BUF_NOSYM, FT, FY
349 :
350 3404 : CALL timeset(routineN, handle)
351 : !
352 3404 : CALL dbcsr_get_info(C_NEW, nfullrows_total=n, nfullcols_total=k)
353 : !
354 3404 : BUF_NOSYM => qs_ot_env%buf1_k_k_nosym ! a buffer
355 3404 : BUF1 => qs_ot_env%buf1_k_k_sym ! a buffer
356 3404 : BUF2 => qs_ot_env%buf2_k_k_sym ! a buffer
357 3404 : FY => qs_ot_env%buf3_k_k_sym ! a buffer
358 3404 : FT => qs_ot_env%buf4_k_k_sym ! a buffer
359 : !
360 : ! initialize the norm (already computed in qs_ot_get_orbitals_ref)
361 3404 : norm = norm_in
362 : !
363 : ! can we do a quick exit?
364 3404 : quick_exit = .FALSE.
365 3404 : IF (norm .LT. qs_ot_env%settings%eps_irac_quick_exit) quick_exit = .TRUE.
366 : !
367 : ! lets refine
368 3404 : rescale = 1.0_dp
369 3692 : DO irefine = 1, qs_ot_env%settings%max_irac
370 : !
371 : ! rescaling
372 3692 : IF (norm .GT. 1.0_dp) THEN
373 12 : CALL dbcsr_scale(P, 1.0_dp/norm)
374 12 : rescale = rescale/SQRT(norm)
375 : END IF
376 : !
377 : ! get the refinement polynomial
378 : CALL qs_ot_refine(P, FY, BUF1, BUF2, qs_ot_env%settings%irac_degree, &
379 3692 : qs_ot_env%settings%eps_irac_filter_matrix)
380 : !
381 : ! collect the transformation
382 3692 : IF (irefine .EQ. 1) THEN
383 3404 : CALL dbcsr_copy(FT, FY, name='FT')
384 : ELSE
385 288 : CALL dbcsr_multiply('N', 'N', 1.0_dp, FT, FY, 0.0_dp, BUF1)
386 288 : IF (qs_ot_env%settings%eps_irac_filter_matrix .GT. 0.0_dp) THEN
387 4 : occ_in = dbcsr_get_occupation(buf1)
388 4 : CALL dbcsr_filter(buf1, qs_ot_env%settings%eps_irac_filter_matrix)
389 4 : occ_out = dbcsr_get_occupation(buf1)
390 : END IF
391 288 : CALL dbcsr_copy(FT, BUF1, name='FT')
392 : END IF
393 : !
394 : ! quick exit if possible
395 3692 : IF (quick_exit) THEN
396 : EXIT
397 : END IF
398 : !
399 : ! P = FY^T * P * FY
400 1460 : CALL dbcsr_multiply('N', 'N', 1.0_dp, P, FY, 0.0_dp, BUF_NOSYM)
401 1460 : IF (qs_ot_env%settings%eps_irac_filter_matrix .GT. 0.0_dp) THEN
402 8 : occ_in = dbcsr_get_occupation(buf_nosym)
403 8 : CALL dbcsr_filter(buf_nosym, qs_ot_env%settings%eps_irac_filter_matrix)
404 8 : occ_out = dbcsr_get_occupation(buf_nosym)
405 : END IF
406 1460 : CALL dbcsr_multiply('N', 'N', 1.0_dp, FY, BUF_NOSYM, 0.0_dp, P)
407 1460 : IF (qs_ot_env%settings%eps_irac_filter_matrix .GT. 0.0_dp) THEN
408 8 : occ_in = dbcsr_get_occupation(p)
409 8 : CALL dbcsr_filter(p, qs_ot_env%settings%eps_irac_filter_matrix)
410 8 : occ_out = dbcsr_get_occupation(p)
411 : END IF
412 : !
413 : ! check ||P-1||_gct
414 1460 : CALL dbcsr_add_on_diag(P, -1.0_dp)
415 1460 : norm_fro = dbcsr_frobenius_norm(P)
416 1460 : norm_gct = dbcsr_gershgorin_norm(P)
417 1460 : CALL dbcsr_add_on_diag(P, 1.0_dp)
418 1460 : norm = MIN(norm_gct, norm_fro)
419 : !
420 : ! printing
421 : !
422 : ! blows up
423 1460 : IF (norm > 1.0E10_dp) THEN
424 : CALL cp_abort(__LOCATION__, &
425 : "Refinement blows up! "// &
426 : "We need you to improve the code, please post your input on "// &
427 0 : "the forum https://www.cp2k.org/")
428 : END IF
429 : !
430 : ! can we do a quick exit next step?
431 1460 : IF (norm .LT. qs_ot_env%settings%eps_irac_quick_exit) quick_exit = .TRUE.
432 : !
433 : ! are we done?
434 3692 : IF (norm .LT. qs_ot_env%settings%eps_irac) EXIT
435 : !
436 : END DO
437 : !
438 : ! C_NEW = C_NEW * FT * rescale
439 3404 : CALL dbcsr_multiply('N', 'N', rescale, C_OLD, FT, 0.0_dp, C_NEW)
440 3404 : IF (qs_ot_env%settings%eps_irac_filter_matrix .GT. 0.0_dp) THEN
441 4 : occ_in = dbcsr_get_occupation(c_new)
442 4 : CALL dbcsr_filter(c_new, qs_ot_env%settings%eps_irac_filter_matrix)
443 4 : occ_out = dbcsr_get_occupation(c_new)
444 : END IF
445 : !
446 : ! update SC = SC * FY * rescale
447 3404 : IF (update) THEN
448 1356 : CALL dbcsr_multiply('N', 'N', rescale, SC, FT, 0.0_dp, C_TMP)
449 1356 : IF (qs_ot_env%settings%eps_irac_filter_matrix .GT. 0.0_dp) THEN
450 4 : occ_in = dbcsr_get_occupation(c_tmp)
451 4 : CALL dbcsr_filter(c_tmp, qs_ot_env%settings%eps_irac_filter_matrix)
452 4 : occ_out = dbcsr_get_occupation(c_tmp)
453 : END IF
454 1356 : CALL dbcsr_copy(SC, C_TMP)
455 : END IF
456 : !
457 3404 : CALL timestop(handle)
458 3404 : END SUBROUTINE qs_ot_ref_poly
459 :
460 : ! **************************************************************************************************
461 : !> \brief ...
462 : !> \param qs_ot_env1 ...
463 : !> \return ...
464 : ! **************************************************************************************************
465 4372 : FUNCTION qs_ot_ref_update(qs_ot_env1) RESULT(update)
466 : !
467 : TYPE(qs_ot_type) :: qs_ot_env1
468 : LOGICAL :: update
469 :
470 4372 : update = .FALSE.
471 3940 : SELECT CASE (qs_ot_env1%settings%ot_method)
472 : CASE ("CG")
473 3940 : SELECT CASE (qs_ot_env1%settings%line_search_method)
474 : CASE ("2PNT")
475 3940 : IF (qs_ot_env1%line_search_count .EQ. 2) update = .TRUE.
476 : CASE DEFAULT
477 3940 : CPABORT("NYI")
478 : END SELECT
479 : CASE ("DIIS")
480 0 : update = .TRUE.
481 : CASE DEFAULT
482 4372 : CPABORT("NYI")
483 : END SELECT
484 4372 : END FUNCTION qs_ot_ref_update
485 :
486 : ! **************************************************************************************************
487 : !> \brief ...
488 : !> \param qs_ot_env1 ...
489 : !> \param norm_in ...
490 : !> \param ortho_irac ...
491 : ! **************************************************************************************************
492 4372 : SUBROUTINE qs_ot_ref_decide(qs_ot_env1, norm_in, ortho_irac)
493 : !
494 : TYPE(qs_ot_type) :: qs_ot_env1
495 : REAL(dp), INTENT(IN) :: norm_in
496 : CHARACTER(LEN=*), INTENT(INOUT) :: ortho_irac
497 :
498 4372 : ortho_irac = qs_ot_env1%settings%ortho_irac
499 4372 : IF (norm_in .LT. qs_ot_env1%settings%eps_irac_switch) ortho_irac = "POLY"
500 4372 : END SUBROUTINE qs_ot_ref_decide
501 :
502 : ! **************************************************************************************************
503 : !> \brief ...
504 : !> \param matrix_c ...
505 : !> \param matrix_s ...
506 : !> \param matrix_x ...
507 : !> \param matrix_sx ...
508 : !> \param matrix_gx_old ...
509 : !> \param matrix_dx ...
510 : !> \param qs_ot_env ...
511 : !> \param qs_ot_env1 ...
512 : ! **************************************************************************************************
513 8744 : SUBROUTINE qs_ot_get_orbitals_ref(matrix_c, matrix_s, matrix_x, matrix_sx, &
514 : matrix_gx_old, matrix_dx, qs_ot_env, qs_ot_env1)
515 : !
516 : TYPE(dbcsr_type), POINTER :: matrix_c, matrix_s, matrix_x, matrix_sx, &
517 : matrix_gx_old, matrix_dx
518 : TYPE(qs_ot_type) :: qs_ot_env, qs_ot_env1
519 :
520 : CHARACTER(len=*), PARAMETER :: routineN = 'qs_ot_get_orbitals_ref'
521 :
522 : CHARACTER(LEN=4) :: ortho_irac
523 : INTEGER :: handle, k, n
524 : LOGICAL :: on_the_fly_loc, update
525 : REAL(dp) :: norm, norm_fro, norm_gct, occ_in, occ_out
526 : TYPE(dbcsr_type), POINTER :: C_NEW, C_OLD, C_TMP, D, G_OLD, P, S, SC
527 :
528 4372 : CALL timeset(routineN, handle)
529 :
530 4372 : CALL dbcsr_get_info(matrix_c, nfullrows_total=n, nfullcols_total=k)
531 : !
532 4372 : C_NEW => matrix_c
533 4372 : C_OLD => matrix_x ! need to be carefully updated for the gradient !
534 4372 : SC => matrix_sx ! need to be carefully updated for the gradient !
535 4372 : G_OLD => matrix_gx_old ! need to be carefully updated for localization !
536 4372 : D => matrix_dx ! need to be carefully updated for localization !
537 4372 : S => matrix_s
538 :
539 4372 : P => qs_ot_env%p_k_k_sym ! a buffer
540 4372 : C_TMP => qs_ot_env%buf1_n_k ! a buffer
541 : !
542 : ! do we need to update C_OLD and SC?
543 4372 : update = qs_ot_ref_update(qs_ot_env1)
544 : !
545 : ! do we want to on the fly localize?
546 : ! for the moment this is set from the input,
547 : ! later we might want to localize every n-step or
548 : ! when the sparsity increases...
549 4372 : on_the_fly_loc = qs_ot_env1%settings%on_the_fly_loc
550 : !
551 : ! compute SC = S*C
552 4372 : IF (ASSOCIATED(S)) THEN
553 4372 : CALL dbcsr_multiply('N', 'N', 1.0_dp, S, C_OLD, 0.0_dp, SC)
554 4372 : IF (qs_ot_env1%settings%eps_irac_filter_matrix .GT. 0.0_dp) THEN
555 4 : occ_in = dbcsr_get_occupation(sc)
556 4 : CALL dbcsr_filter(sc, qs_ot_env1%settings%eps_irac_filter_matrix)
557 4 : occ_out = dbcsr_get_occupation(sc)
558 : END IF
559 : ELSE
560 0 : CALL dbcsr_copy(SC, C_OLD)
561 : END IF
562 : !
563 : ! compute P = C'*SC
564 4372 : CALL dbcsr_multiply('T', 'N', 1.0_dp, C_OLD, SC, 0.0_dp, P)
565 4372 : IF (qs_ot_env1%settings%eps_irac_filter_matrix .GT. 0.0_dp) THEN
566 4 : occ_in = dbcsr_get_occupation(p)
567 4 : CALL dbcsr_filter(p, qs_ot_env1%settings%eps_irac_filter_matrix)
568 4 : occ_out = dbcsr_get_occupation(p)
569 : END IF
570 : !
571 : ! check ||P-1||_f and ||P-1||_gct
572 4372 : CALL dbcsr_add_on_diag(P, -1.0_dp)
573 4372 : norm_fro = dbcsr_frobenius_norm(P)
574 4372 : norm_gct = dbcsr_gershgorin_norm(P)
575 4372 : CALL dbcsr_add_on_diag(P, 1.0_dp)
576 4372 : norm = MIN(norm_gct, norm_fro)
577 4372 : CALL qs_ot_ref_decide(qs_ot_env1, norm, ortho_irac)
578 : !
579 : ! select the orthogonality method
580 728 : SELECT CASE (ortho_irac)
581 : CASE ("CHOL")
582 728 : CALL qs_ot_ref_chol(qs_ot_env, C_OLD, C_TMP, C_NEW, P, SC, update)
583 : CASE ("LWDN")
584 240 : CALL qs_ot_ref_lwdn(qs_ot_env, C_OLD, C_TMP, C_NEW, P, SC, update)
585 : CASE ("POLY")
586 3404 : CALL qs_ot_ref_poly(qs_ot_env, C_OLD, C_TMP, C_NEW, P, SC, norm, update)
587 : CASE DEFAULT
588 4372 : CPABORT("Wrong argument")
589 : END SELECT
590 : !
591 : ! We update the C_i+1 and localization
592 4372 : IF (update) THEN
593 1952 : IF (on_the_fly_loc) THEN
594 48 : CALL qs_ot_on_the_fly_localize(qs_ot_env, C_NEW, SC, G_OLD, D)
595 : END IF
596 1952 : CALL dbcsr_copy(C_OLD, C_NEW)
597 : END IF
598 : !
599 4372 : CALL timestop(handle)
600 4372 : END SUBROUTINE qs_ot_get_orbitals_ref
601 :
602 : ! **************************************************************************************************
603 : !> \brief ...
604 : !> \param P ...
605 : !> \param FY ...
606 : !> \param P2 ...
607 : !> \param T ...
608 : !> \param irac_degree ...
609 : !> \param eps_irac_filter_matrix ...
610 : ! **************************************************************************************************
611 7384 : SUBROUTINE qs_ot_refine(P, FY, P2, T, irac_degree, eps_irac_filter_matrix)
612 : !----------------------------------------------------------------------
613 : ! refinement polynomial of degree 2,3 and 4 (PRB 70, 193102 (2004))
614 : !----------------------------------------------------------------------
615 :
616 : TYPE(dbcsr_type), INTENT(inout) :: P, FY, P2, T
617 : INTEGER, INTENT(in) :: irac_degree
618 : REAL(dp), INTENT(in) :: eps_irac_filter_matrix
619 :
620 : CHARACTER(len=*), PARAMETER :: routineN = 'qs_ot_refine'
621 :
622 : INTEGER :: handle, k
623 : REAL(dp) :: occ_in, occ_out, r
624 :
625 3692 : CALL timeset(routineN, handle)
626 :
627 3692 : CALL dbcsr_get_info(P, nfullcols_total=k)
628 3692 : SELECT CASE (irac_degree)
629 : CASE (2)
630 : ! C_out = C_in * ( 15/8 * I - 10/8 * P + 3/8 * P^2)
631 0 : r = 3.0_dp/8.0_dp
632 0 : CALL dbcsr_multiply('N', 'N', r, P, P, 0.0_dp, FY)
633 0 : IF (eps_irac_filter_matrix .GT. 0.0_dp) THEN
634 0 : occ_in = dbcsr_get_occupation(fy)
635 0 : CALL dbcsr_filter(fy, eps_irac_filter_matrix)
636 0 : occ_out = dbcsr_get_occupation(fy)
637 : END IF
638 0 : r = -10.0_dp/8.0_dp
639 0 : CALL dbcsr_add(FY, P, alpha_scalar=1.0_dp, beta_scalar=r)
640 0 : r = 15.0_dp/8.0_dp
641 0 : CALL dbcsr_add_on_diag(FY, alpha_scalar=r)
642 : CASE (3)
643 : ! C_out = C_in * ( 35/16 * I - 35/16 * P + 21/16 * P^2 - 5/16 P^3)
644 0 : CALL dbcsr_multiply('N', 'N', 1.0_dp, P, P, 0.0_dp, P2)
645 0 : IF (eps_irac_filter_matrix .GT. 0.0_dp) THEN
646 0 : occ_in = dbcsr_get_occupation(p2)
647 0 : CALL dbcsr_filter(p2, eps_irac_filter_matrix)
648 0 : occ_out = dbcsr_get_occupation(p2)
649 : END IF
650 0 : r = -5.0_dp/16.0_dp
651 0 : CALL dbcsr_multiply('N', 'N', r, P2, P, 0.0_dp, FY)
652 0 : IF (eps_irac_filter_matrix .GT. 0.0_dp) THEN
653 0 : occ_in = dbcsr_get_occupation(fy)
654 0 : CALL dbcsr_filter(fy, eps_irac_filter_matrix)
655 0 : occ_out = dbcsr_get_occupation(fy)
656 : END IF
657 0 : r = 21.0_dp/16.0_dp
658 0 : CALL dbcsr_add(FY, P2, alpha_scalar=1.0_dp, beta_scalar=r)
659 0 : r = -35.0_dp/16.0_dp
660 0 : CALL dbcsr_add(FY, P, alpha_scalar=1.0_dp, beta_scalar=r)
661 0 : r = 35.0_dp/16.0_dp
662 0 : CALL dbcsr_add_on_diag(FY, alpha_scalar=r)
663 : CASE (4)
664 : ! C_out = C_in * ( 315/128 * I - 420/128 * P + 378/128 * P^2 - 180/128 P^3 + 35/128 P^4 )
665 : ! = C_in * ( 315/128 * I - 420/128 * P + 378/128 * P^2 + ( - 180/128 * P + 35/128 * P^2 ) * P^2 )
666 3692 : CALL dbcsr_multiply('N', 'N', 1.0_dp, P, P, 0.0_dp, P2) ! P^2
667 3692 : IF (eps_irac_filter_matrix .GT. 0.0_dp) THEN
668 8 : occ_in = dbcsr_get_occupation(p2)
669 8 : CALL dbcsr_filter(p2, eps_irac_filter_matrix)
670 8 : occ_out = dbcsr_get_occupation(p2)
671 : END IF
672 3692 : r = -180.0_dp/128.0_dp
673 3692 : CALL dbcsr_add(T, P, alpha_scalar=0.0_dp, beta_scalar=r) ! T=-180/128*P
674 3692 : r = 35.0_dp/128.0_dp
675 3692 : CALL dbcsr_add(T, P2, alpha_scalar=1.0_dp, beta_scalar=r) ! T=T+35/128*P^2
676 3692 : CALL dbcsr_multiply('N', 'N', 1.0_dp, T, P2, 0.0_dp, FY) ! Y=T*P^2
677 3692 : IF (eps_irac_filter_matrix .GT. 0.0_dp) THEN
678 8 : occ_in = dbcsr_get_occupation(fy)
679 8 : CALL dbcsr_filter(fy, eps_irac_filter_matrix)
680 8 : occ_out = dbcsr_get_occupation(fy)
681 : END IF
682 3692 : r = 378.0_dp/128.0_dp
683 3692 : CALL dbcsr_add(FY, P2, alpha_scalar=1.0_dp, beta_scalar=r) ! Y=Y+378/128*P^2
684 3692 : r = -420.0_dp/128.0_dp
685 3692 : CALL dbcsr_add(FY, P, alpha_scalar=1.0_dp, beta_scalar=r) ! Y=Y-420/128*P
686 3692 : r = 315.0_dp/128.0_dp
687 3692 : CALL dbcsr_add_on_diag(FY, alpha_scalar=r) ! Y=Y+315/128*I
688 : CASE DEFAULT
689 3692 : CPABORT("This irac_order NYI")
690 : END SELECT
691 3692 : CALL timestop(handle)
692 3692 : END SUBROUTINE qs_ot_refine
693 :
694 : ! **************************************************************************************************
695 : !> \brief ...
696 : !> \param matrix_hc ...
697 : !> \param matrix_x ...
698 : !> \param matrix_sx ...
699 : !> \param matrix_gx ...
700 : !> \param qs_ot_env ...
701 : ! **************************************************************************************************
702 5704 : SUBROUTINE qs_ot_get_derivative_ref(matrix_hc, matrix_x, matrix_sx, matrix_gx, &
703 : qs_ot_env)
704 : TYPE(dbcsr_type), POINTER :: matrix_hc, matrix_x, matrix_sx, matrix_gx
705 : TYPE(qs_ot_type) :: qs_ot_env
706 :
707 : CHARACTER(len=*), PARAMETER :: routineN = 'qs_ot_get_derivative_ref'
708 :
709 : INTEGER :: handle, k, n
710 : REAL(dp) :: occ_in, occ_out
711 : TYPE(dbcsr_type), POINTER :: C, CHC, G, G_dp, HC, SC
712 :
713 2852 : CALL timeset(routineN, handle)
714 :
715 2852 : CALL dbcsr_get_info(matrix_x, nfullrows_total=n, nfullcols_total=k)
716 : !
717 2852 : C => matrix_x ! NBsf*NOcc
718 2852 : SC => matrix_sx ! NBsf*NOcc need to be up2date
719 2852 : HC => matrix_hc ! NBsf*NOcc
720 2852 : G => matrix_gx ! NBsf*NOcc
721 2852 : CHC => qs_ot_env%buf1_k_k_sym ! buffer
722 2852 : G_dp => qs_ot_env%buf1_n_k_dp ! buffer dp
723 :
724 : ! C'*(H*C)
725 2852 : CALL dbcsr_multiply('T', 'N', 1.0_dp, C, HC, 0.0_dp, CHC)
726 2852 : IF (qs_ot_env%settings%eps_irac_filter_matrix .GT. 0.0_dp) THEN
727 4 : occ_in = dbcsr_get_occupation(chc)
728 4 : CALL dbcsr_filter(chc, qs_ot_env%settings%eps_irac_filter_matrix)
729 4 : occ_out = dbcsr_get_occupation(chc)
730 : END IF
731 : ! (S*C)*(C'*H*C)
732 2852 : CALL dbcsr_multiply('N', 'N', 1.0_dp, SC, CHC, 0.0_dp, G)
733 2852 : IF (qs_ot_env%settings%eps_irac_filter_matrix .GT. 0.0_dp) THEN
734 4 : occ_in = dbcsr_get_occupation(g)
735 4 : CALL dbcsr_filter(g, qs_ot_env%settings%eps_irac_filter_matrix)
736 4 : occ_out = dbcsr_get_occupation(g)
737 : END IF
738 : ! G = 2*(1-S*C*C')*H*C
739 2852 : CALL dbcsr_add(G, HC, alpha_scalar=-1.0_dp, beta_scalar=1.0_dp)
740 : !
741 2852 : CALL timestop(handle)
742 2852 : END SUBROUTINE qs_ot_get_derivative_ref
743 :
744 : ! computes p=x*S*x and the matrix functionals related matrices
745 : ! **************************************************************************************************
746 : !> \brief ...
747 : !> \param matrix_x ...
748 : !> \param matrix_sx ...
749 : !> \param qs_ot_env ...
750 : ! **************************************************************************************************
751 269115 : SUBROUTINE qs_ot_get_p(matrix_x, matrix_sx, qs_ot_env)
752 :
753 : TYPE(dbcsr_type), POINTER :: matrix_x, matrix_sx
754 : TYPE(qs_ot_type) :: qs_ot_env
755 :
756 : CHARACTER(len=*), PARAMETER :: routineN = 'qs_ot_get_p'
757 : REAL(KIND=dp), PARAMETER :: rone = 1.0_dp, rzero = 0.0_dp
758 :
759 : INTEGER :: handle, k, max_iter, n
760 : LOGICAL :: converged
761 : REAL(KIND=dp) :: max_ev, min_ev, threshold
762 :
763 89705 : CALL timeset(routineN, handle)
764 :
765 89705 : CALL dbcsr_get_info(matrix_x, nfullrows_total=n, nfullcols_total=k)
766 :
767 : ! get the overlap
768 : CALL dbcsr_multiply('T', 'N', rone, matrix_x, matrix_sx, rzero, &
769 89705 : qs_ot_env%matrix_p)
770 :
771 : ! get an upper bound for the largest eigenvalue
772 : ! try using lancos first and fall back to gershgorin norm if it fails
773 89705 : max_iter = 30; threshold = 1.0E-03_dp
774 89705 : CALL arnoldi_extremal(qs_ot_env%matrix_p, max_ev, min_ev, converged, threshold, max_iter)
775 89705 : qs_ot_env%largest_eval_upper_bound = MAX(max_ev, ABS(min_ev))
776 :
777 89705 : IF (.NOT. converged) qs_ot_env%largest_eval_upper_bound = dbcsr_gershgorin_norm(qs_ot_env%matrix_p)
778 89705 : CALL decide_strategy(qs_ot_env)
779 89705 : IF (qs_ot_env%do_taylor) THEN
780 49980 : CALL qs_ot_p2m_taylor(qs_ot_env)
781 : ELSE
782 39725 : CALL qs_ot_p2m_diag(qs_ot_env)
783 : END IF
784 :
785 89705 : IF (qs_ot_env%settings%do_rotation) THEN
786 2590 : CALL qs_ot_generate_rotation(qs_ot_env)
787 : END IF
788 :
789 89705 : CALL timestop(handle)
790 :
791 89705 : END SUBROUTINE qs_ot_get_p
792 :
793 : ! **************************************************************************************************
794 : !> \brief computes the rotation matrix rot_mat_u that is associated to a given
795 : !> rot_mat_x using rot_mat_u=exp(rot_mat_x)
796 : !> \param qs_ot_env a valid qs_ot_env
797 : !> \par History
798 : !> 08.2004 created [Joost VandeVondele]
799 : ! **************************************************************************************************
800 2590 : SUBROUTINE qs_ot_generate_rotation(qs_ot_env)
801 :
802 : TYPE(qs_ot_type) :: qs_ot_env
803 :
804 : CHARACTER(len=*), PARAMETER :: routineN = 'qs_ot_generate_rotation'
805 : COMPLEX(KIND=dp), PARAMETER :: cone = (1.0_dp, 0.0_dp), &
806 : czero = (0.0_dp, 0.0_dp)
807 :
808 2590 : COMPLEX(KIND=dp), ALLOCATABLE, DIMENSION(:) :: evals_exp
809 2590 : COMPLEX(KIND=dp), DIMENSION(:), POINTER :: data_z
810 : INTEGER :: blk, col, handle, k, row
811 : LOGICAL :: found
812 2590 : REAL(KIND=dp), DIMENSION(:), POINTER :: data_d
813 : TYPE(dbcsr_iterator_type) :: iter
814 : TYPE(dbcsr_type) :: cmat_u, cmat_x
815 :
816 2590 : CALL timeset(routineN, handle)
817 :
818 2590 : CALL dbcsr_get_info(qs_ot_env%rot_mat_x, nfullrows_total=k)
819 :
820 2590 : IF (k /= 0) THEN
821 2538 : CALL dbcsr_copy(cmat_x, qs_ot_env%rot_mat_evec, name='cmat_x')
822 2538 : CALL dbcsr_copy(cmat_u, qs_ot_env%rot_mat_evec, name='cmat_u')
823 7614 : ALLOCATE (evals_exp(k))
824 :
825 : ! rot_mat_u = exp(rot_mat_x)
826 : ! i rot_mat_x is hermitian, so go over the complex variables for diag
827 : !vwCALL cp_cfm_get_info(cmat_x,local_data=local_data_c)
828 : !vwCALL cp_fm_get_info(qs_ot_env%rot_mat_x,local_data=local_data_r)
829 : !vwlocal_data_c=CMPLX(0.0_dp,local_data_r,KIND=dp)
830 2538 : CALL dbcsr_iterator_start(iter, cmat_x)
831 3698 : DO WHILE (dbcsr_iterator_blocks_left(iter))
832 1160 : CALL dbcsr_iterator_next_block(iter, row, col, data_z, blk)
833 1160 : CALL dbcsr_get_block_p(qs_ot_env%rot_mat_x, row, col, data_d, found)
834 3698 : IF (.NOT. found) THEN
835 0 : WRITE (*, *) routineN//' .NOT.found'
836 : !stop
837 : ELSE
838 25960 : data_z = CMPLX(0.0_dp, data_d, KIND=dp)
839 : END IF
840 : END DO
841 2538 : CALL dbcsr_iterator_stop(iter)
842 :
843 : CALL cp_dbcsr_heevd(cmat_x, qs_ot_env%rot_mat_evec, qs_ot_env%rot_mat_evals, &
844 2538 : qs_ot_env%para_env, qs_ot_env%blacs_env)
845 12830 : evals_exp(:) = EXP((0.0_dp, -1.0_dp)*qs_ot_env%rot_mat_evals(:))
846 2538 : CALL dbcsr_copy(cmat_x, qs_ot_env%rot_mat_evec)
847 2538 : CALL dbcsr_scale_by_vector(cmat_x, alpha=evals_exp, side='right')
848 2538 : CALL dbcsr_multiply('N', 'C', cone, cmat_x, qs_ot_env%rot_mat_evec, czero, cmat_u)
849 2538 : CALL dbcsr_copy(qs_ot_env%rot_mat_u, cmat_u, keep_imaginary=.FALSE.)
850 2538 : CALL dbcsr_release(cmat_x)
851 2538 : CALL dbcsr_release(cmat_u)
852 5076 : DEALLOCATE (evals_exp)
853 : END IF
854 :
855 2590 : CALL timestop(handle)
856 :
857 5180 : END SUBROUTINE qs_ot_generate_rotation
858 :
859 : ! **************************************************************************************************
860 : !> \brief computes the derivative fields with respect to rot_mat_x
861 : !> \param qs_ot_env valid qs_ot_env. In particular qs_ot_generate_rotation has to be called before
862 : !> and the rot_mat_dedu matrix has to be up to date
863 : !> \par History
864 : !> 08.2004 created [ Joost VandeVondele ]
865 : ! **************************************************************************************************
866 2768 : SUBROUTINE qs_ot_rot_mat_derivative(qs_ot_env)
867 : TYPE(qs_ot_type) :: qs_ot_env
868 :
869 : CHARACTER(len=*), PARAMETER :: routineN = 'qs_ot_rot_mat_derivative'
870 :
871 : COMPLEX(KIND=dp), PARAMETER :: cone = (1.0_dp, 0.0_dp), &
872 : czero = (0.0_dp, 0.0_dp)
873 :
874 : INTEGER :: handle, i, j, k
875 : REAL(KIND=dp) :: e1, e2
876 1384 : REAL(KIND=dp), DIMENSION(:, :), POINTER :: data_d
877 : TYPE(dbcsr_type) :: cmat_buf1, cmat_buf2
878 : TYPE(dbcsr_iterator_type) :: iter
879 1384 : COMPLEX(dp), DIMENSION(:, :), POINTER :: data_z
880 : INTEGER::row, col, blk, row_offset, col_offset, row_size, col_size
881 : LOGICAL::found
882 : TYPE(dbcsr_distribution_type) :: dist
883 :
884 1384 : CALL timeset(routineN, handle)
885 :
886 1384 : CALL dbcsr_get_info(qs_ot_env%rot_mat_u, nfullrows_total=k)
887 1384 : IF (k /= 0) THEN
888 1358 : CALL dbcsr_copy(qs_ot_env%matrix_buf1, qs_ot_env%rot_mat_dedu)
889 : ! now we get to the derivative wrt the antisymmetric matrix rot_mat_x
890 1358 : CALL dbcsr_copy(cmat_buf1, qs_ot_env%rot_mat_evec, "cmat_buf1")
891 1358 : CALL dbcsr_copy(cmat_buf2, qs_ot_env%rot_mat_evec, "cmat_buf2")
892 :
893 : ! init cmat_buf1
894 : !CALL cp_fm_get_info(qs_ot_env%matrix_buf1,matrix_struct=fm_struct, local_data=local_data_r)
895 : !CALL cp_cfm_get_info(cmat_buf1, nrow_local=nrow_local, ncol_local=ncol_local, &
896 : ! row_indices=row_indices, col_indices=col_indices, &
897 : ! local_data=local_data_c)
898 : !local_data_c=local_data_r
899 :
900 1358 : CALL dbcsr_iterator_start(iter, cmat_buf1)
901 2037 : DO WHILE (dbcsr_iterator_blocks_left(iter))
902 679 : CALL dbcsr_iterator_next_block(iter, row, col, data_z, blk)
903 679 : CALL dbcsr_get_block_p(qs_ot_env%matrix_buf1, row, col, data_d, found)
904 21459 : data_z = data_d
905 : END DO
906 1358 : CALL dbcsr_iterator_stop(iter)
907 :
908 : CALL dbcsr_multiply('T', 'N', cone, cmat_buf1, qs_ot_env%rot_mat_evec, &
909 1358 : czero, cmat_buf2)
910 : CALL dbcsr_multiply('C', 'N', cone, qs_ot_env%rot_mat_evec, cmat_buf2, &
911 1358 : czero, cmat_buf1)
912 :
913 1358 : CALL dbcsr_iterator_start(iter, cmat_buf1)
914 2037 : DO WHILE (dbcsr_iterator_blocks_left(iter))
915 : CALL dbcsr_iterator_next_block(iter, row, col, data_z, blk, &
916 : row_size=row_size, col_size=col_size, &
917 679 : row_offset=row_offset, col_offset=col_offset)
918 4965 : DO j = 1, col_size
919 20101 : DO i = 1, row_size
920 16494 : e1 = qs_ot_env%rot_mat_evals(row_offset + i - 1)
921 16494 : e2 = qs_ot_env%rot_mat_evals(col_offset + j - 1)
922 19422 : data_z(i, j) = data_z(i, j)*cint(e1, e2)
923 : END DO
924 : END DO
925 : END DO
926 1358 : CALL dbcsr_iterator_stop(iter)
927 :
928 : CALL dbcsr_multiply('N', 'N', cone, qs_ot_env%rot_mat_evec, cmat_buf1, &
929 1358 : czero, cmat_buf2)
930 : CALL dbcsr_multiply('N', 'C', cone, cmat_buf2, qs_ot_env%rot_mat_evec, &
931 1358 : czero, cmat_buf1)
932 :
933 1358 : CALL dbcsr_copy(qs_ot_env%matrix_buf1, cmat_buf1)
934 :
935 1358 : CALL dbcsr_get_info(qs_ot_env%matrix_buf3, distribution=dist)
936 : CALL dbcsr_transposed(qs_ot_env%matrix_buf2, qs_ot_env%matrix_buf1, &
937 : shallow_data_copy=.FALSE., use_distribution=dist, &
938 1358 : transpose_distribution=.FALSE.)
939 : CALL dbcsr_add(qs_ot_env%matrix_buf1, qs_ot_env%matrix_buf2, &
940 1358 : alpha_scalar=-1.0_dp, beta_scalar=+1.0_dp)
941 1358 : CALL dbcsr_copy(qs_ot_env%rot_mat_gx, qs_ot_env%matrix_buf1)
942 1358 : CALL dbcsr_release(cmat_buf1)
943 1358 : CALL dbcsr_release(cmat_buf2)
944 : END IF
945 2768 : CALL timestop(handle)
946 : CONTAINS
947 : ! **************************************************************************************************
948 : !> \brief ...
949 : !> \param e1 ...
950 : !> \param e2 ...
951 : !> \return ...
952 : ! **************************************************************************************************
953 16494 : FUNCTION cint(e1, e2)
954 : REAL(KIND=dp) :: e1, e2
955 : COMPLEX(KIND=dp) :: cint
956 :
957 : COMPLEX(KIND=dp) :: l1, l2, x
958 : INTEGER :: I
959 :
960 16494 : l1 = (0.0_dp, -1.0_dp)*e1
961 16494 : l2 = (0.0_dp, -1.0_dp)*e2
962 16494 : IF (ABS(l1 - l2) .GT. 0.5_dp) THEN
963 886 : cint = (EXP(l1) - EXP(l2))/(l1 - l2)
964 : ELSE
965 : x = 1.0_dp
966 : cint = 0.0_dp
967 265336 : DO I = 1, 16
968 249728 : cint = cint + x
969 265336 : x = x*(l1 - l2)/REAL(I + 1, KIND=dp)
970 : END DO
971 15608 : cint = cint*EXP(l2)
972 : END IF
973 16494 : END FUNCTION cint
974 : END SUBROUTINE qs_ot_rot_mat_derivative
975 :
976 : !
977 : ! decide strategy
978 : ! tries to decide if the taylor expansion of cos(sqrt(xsx)) converges rapidly enough
979 : ! to make a taylor expansion of the functions cos(sqrt(xsx)) and sin(sqrt(xsx))/sqrt(xsx)
980 : ! and their derivatives faster than their computation based on diagonalization
981 : ! since xsx can be very small, especially during dynamics, only a few terms might indeed be needed
982 : ! we find the necessary order N to have largest_eval_upper_bound**(N+1)/(2(N+1))! < eps_taylor
983 : !
984 : ! **************************************************************************************************
985 : !> \brief ...
986 : !> \param qs_ot_env ...
987 : ! **************************************************************************************************
988 89705 : SUBROUTINE decide_strategy(qs_ot_env)
989 : TYPE(qs_ot_type) :: qs_ot_env
990 :
991 : INTEGER :: N
992 : REAL(KIND=dp) :: num_error
993 :
994 89705 : qs_ot_env%do_taylor = .FALSE.
995 89705 : N = 0
996 89705 : num_error = qs_ot_env%largest_eval_upper_bound/(2.0_dp)
997 379185 : DO WHILE (num_error > qs_ot_env%settings%eps_taylor .AND. N <= qs_ot_env%settings%max_taylor)
998 289480 : N = N + 1
999 324563 : num_error = num_error*qs_ot_env%largest_eval_upper_bound/REAL((2*N + 1)*(2*N + 2), KIND=dp)
1000 : END DO
1001 89705 : qs_ot_env%taylor_order = N
1002 89705 : IF (qs_ot_env%taylor_order <= qs_ot_env%settings%max_taylor) THEN
1003 49980 : qs_ot_env%do_taylor = .TRUE.
1004 : END IF
1005 :
1006 89705 : END SUBROUTINE decide_strategy
1007 :
1008 : ! c=(c0*cos(p^0.5)+x*sin(p^0.5)*p^(-0.5)) x rot_mat_u
1009 : ! this assumes that x is already ortho to S*C0, and that p is x*S*x
1010 : ! rot_mat_u is an optional rotation matrix
1011 : ! **************************************************************************************************
1012 : !> \brief ...
1013 : !> \param matrix_c ...
1014 : !> \param matrix_x ...
1015 : !> \param qs_ot_env ...
1016 : ! **************************************************************************************************
1017 165888 : SUBROUTINE qs_ot_get_orbitals(matrix_c, matrix_x, qs_ot_env)
1018 :
1019 : TYPE(dbcsr_type), POINTER :: matrix_c, matrix_x
1020 : TYPE(qs_ot_type) :: qs_ot_env
1021 :
1022 : CHARACTER(len=*), PARAMETER :: routineN = 'qs_ot_get_orbitals'
1023 : REAL(KIND=dp), PARAMETER :: rone = 1.0_dp, rzero = 0.0_dp
1024 :
1025 : INTEGER :: handle, k, n
1026 : TYPE(dbcsr_type), POINTER :: matrix_kk
1027 :
1028 82944 : CALL timeset(routineN, handle)
1029 :
1030 82944 : CALL dbcsr_get_info(matrix_x, nfullrows_total=n, nfullcols_total=k)
1031 :
1032 : ! rotate the multiplying matrices cosp and sinp instead of the result,
1033 : ! this should be cheaper for large basis sets
1034 82944 : IF (qs_ot_env%settings%do_rotation) THEN
1035 2368 : matrix_kk => qs_ot_env%matrix_buf1
1036 : CALL dbcsr_multiply('N', 'N', rone, qs_ot_env%matrix_cosp, &
1037 2368 : qs_ot_env%rot_mat_u, rzero, matrix_kk)
1038 : ELSE
1039 80576 : matrix_kk => qs_ot_env%matrix_cosp
1040 : END IF
1041 :
1042 : CALL dbcsr_multiply('N', 'N', rone, qs_ot_env%matrix_c0, matrix_kk, &
1043 82944 : rzero, matrix_c)
1044 :
1045 82944 : IF (qs_ot_env%settings%do_rotation) THEN
1046 2368 : matrix_kk => qs_ot_env%matrix_buf1
1047 : CALL dbcsr_multiply('N', 'N', rone, qs_ot_env%matrix_sinp, &
1048 2368 : qs_ot_env%rot_mat_u, rzero, matrix_kk)
1049 : ELSE
1050 80576 : matrix_kk => qs_ot_env%matrix_sinp
1051 : END IF
1052 : CALL dbcsr_multiply('N', 'N', rone, matrix_x, matrix_kk, &
1053 82944 : rone, matrix_c)
1054 :
1055 82944 : CALL timestop(handle)
1056 :
1057 82944 : END SUBROUTINE qs_ot_get_orbitals
1058 :
1059 : ! **************************************************************************************************
1060 : ! this routines computes dE/dx=dx, with dx ortho to sc0
1061 : ! needs dE/dC=hc,C0,X,SX,p
1062 : ! if preconditioned it will not be the derivative, but the lagrangian multiplier
1063 : ! is changed so that P*dE/dx is the right derivative (i.e. in the allowed subspace)
1064 : ! **************************************************************************************************
1065 : !> \brief ...
1066 : !> \param matrix_hc ...
1067 : !> \param matrix_x ...
1068 : !> \param matrix_sx ...
1069 : !> \param matrix_gx ...
1070 : !> \param qs_ot_env ...
1071 : ! **************************************************************************************************
1072 190116 : SUBROUTINE qs_ot_get_derivative(matrix_hc, matrix_x, matrix_sx, matrix_gx, &
1073 : qs_ot_env)
1074 : TYPE(dbcsr_type), POINTER :: matrix_hc, matrix_x, matrix_sx, matrix_gx
1075 : TYPE(qs_ot_type) :: qs_ot_env
1076 :
1077 : CHARACTER(len=*), PARAMETER :: routineN = 'qs_ot_get_derivative'
1078 : REAL(KIND=dp), PARAMETER :: rone = 1.0_dp, rzero = 0.0_dp
1079 :
1080 : INTEGER :: handle, k, n, ortho_k
1081 : TYPE(dbcsr_type), POINTER :: matrix_hc_local, matrix_target
1082 :
1083 63372 : CALL timeset(routineN, handle)
1084 :
1085 63372 : NULLIFY (matrix_hc_local)
1086 :
1087 63372 : CALL dbcsr_get_info(matrix_x, nfullrows_total=n, nfullcols_total=k)
1088 :
1089 : ! could in principle be taken inside qs_ot_get_derivative_* for increased efficiency
1090 : ! create a local rotated version of matrix_hc leaving matrix_hc untouched (needed
1091 : ! for lagrangian multipliers)
1092 63372 : IF (qs_ot_env%settings%do_rotation) THEN
1093 1384 : CALL dbcsr_copy(matrix_gx, matrix_hc) ! use gx as temporary
1094 1384 : CALL dbcsr_init_p(matrix_hc_local)
1095 1384 : CALL dbcsr_copy(matrix_hc_local, matrix_hc, name='matrix_hc_local')
1096 1384 : CALL dbcsr_set(matrix_hc_local, 0.0_dp)
1097 1384 : CALL dbcsr_multiply('N', 'T', rone, matrix_gx, qs_ot_env%rot_mat_u, rzero, matrix_hc_local)
1098 : ELSE
1099 61988 : matrix_hc_local => matrix_hc
1100 : END IF
1101 :
1102 63372 : IF (qs_ot_env%do_taylor) THEN
1103 36234 : CALL qs_ot_get_derivative_taylor(matrix_hc_local, matrix_x, matrix_sx, matrix_gx, qs_ot_env)
1104 : ELSE
1105 27138 : CALL qs_ot_get_derivative_diag(matrix_hc_local, matrix_x, matrix_sx, matrix_gx, qs_ot_env)
1106 : END IF
1107 :
1108 : ! and make it orthogonal
1109 63372 : CALL dbcsr_get_info(qs_ot_env%matrix_sc0, nfullcols_total=ortho_k)
1110 :
1111 63372 : IF (ASSOCIATED(qs_ot_env%preconditioner)) THEN
1112 51898 : matrix_target => qs_ot_env%matrix_psc0
1113 : ELSE
1114 11474 : matrix_target => qs_ot_env%matrix_sc0
1115 : END IF
1116 : ! first make the matrix os if not yet valid
1117 63372 : IF (.NOT. qs_ot_env%os_valid) THEN
1118 : ! this assumes that the preconditioner is a single matrix
1119 : ! that maps sc0 onto psc0
1120 :
1121 7415 : IF (ASSOCIATED(qs_ot_env%preconditioner)) THEN
1122 : CALL apply_preconditioner(qs_ot_env%preconditioner, qs_ot_env%matrix_sc0, &
1123 6317 : qs_ot_env%matrix_psc0)
1124 : END IF
1125 : CALL dbcsr_multiply('T', 'N', rone, &
1126 : qs_ot_env%matrix_sc0, matrix_target, &
1127 7415 : rzero, qs_ot_env%matrix_os)
1128 : CALL cp_dbcsr_cholesky_decompose(qs_ot_env%matrix_os, &
1129 7415 : para_env=qs_ot_env%para_env, blacs_env=qs_ot_env%blacs_env)
1130 : CALL cp_dbcsr_cholesky_invert(qs_ot_env%matrix_os, &
1131 : para_env=qs_ot_env%para_env, blacs_env=qs_ot_env%blacs_env, &
1132 7415 : upper_to_full=.TRUE.)
1133 7415 : qs_ot_env%os_valid = .TRUE.
1134 : END IF
1135 : CALL dbcsr_multiply('T', 'N', rone, matrix_target, matrix_gx, &
1136 63372 : rzero, qs_ot_env%matrix_buf1_ortho)
1137 : CALL dbcsr_multiply('N', 'N', rone, qs_ot_env%matrix_os, &
1138 63372 : qs_ot_env%matrix_buf1_ortho, rzero, qs_ot_env%matrix_buf2_ortho)
1139 : CALL dbcsr_multiply('N', 'N', -rone, qs_ot_env%matrix_sc0, &
1140 63372 : qs_ot_env%matrix_buf2_ortho, rone, matrix_gx)
1141 : ! also treat the rot_mat gradient here
1142 63372 : IF (qs_ot_env%settings%do_rotation) THEN
1143 1384 : CALL qs_ot_rot_mat_derivative(qs_ot_env)
1144 : END IF
1145 :
1146 63372 : IF (qs_ot_env%settings%do_rotation) THEN
1147 1384 : CALL dbcsr_release_p(matrix_hc_local)
1148 : END IF
1149 :
1150 63372 : CALL timestop(handle)
1151 :
1152 63372 : END SUBROUTINE qs_ot_get_derivative
1153 :
1154 : ! **************************************************************************************************
1155 : !> \brief ...
1156 : !> \param matrix_hc ...
1157 : !> \param matrix_x ...
1158 : !> \param matrix_sx ...
1159 : !> \param matrix_gx ...
1160 : !> \param qs_ot_env ...
1161 : ! **************************************************************************************************
1162 81414 : SUBROUTINE qs_ot_get_derivative_diag(matrix_hc, matrix_x, matrix_sx, matrix_gx, &
1163 : qs_ot_env)
1164 :
1165 : TYPE(dbcsr_type), POINTER :: matrix_hc, matrix_x, matrix_sx, matrix_gx
1166 : TYPE(qs_ot_type) :: qs_ot_env
1167 :
1168 : CHARACTER(len=*), PARAMETER :: routineN = 'qs_ot_get_derivative_diag'
1169 : REAL(KIND=dp), PARAMETER :: rone = 1.0_dp, rzero = 0.0_dp
1170 :
1171 : INTEGER :: handle, k, n
1172 : TYPE(dbcsr_distribution_type) :: dist
1173 :
1174 27138 : CALL timeset(routineN, handle)
1175 :
1176 27138 : CALL dbcsr_get_info(matrix_x, nfullrows_total=n, nfullcols_total=k)
1177 :
1178 : ! go for the derivative now
1179 : ! this de/dc*(dX/dx)*sinp
1180 27138 : CALL dbcsr_multiply('N', 'N', rone, matrix_hc, qs_ot_env%matrix_sinp, rzero, matrix_gx)
1181 : ! overlap hc*x
1182 27138 : CALL dbcsr_multiply('T', 'N', rone, matrix_hc, matrix_x, rzero, qs_ot_env%matrix_buf2)
1183 : ! get it in the basis of the eigenvectors
1184 : CALL dbcsr_multiply('N', 'N', rone, qs_ot_env%matrix_buf2, qs_ot_env%matrix_r, &
1185 27138 : rzero, qs_ot_env%matrix_buf1)
1186 : CALL dbcsr_multiply('T', 'N', rone, qs_ot_env%matrix_r, qs_ot_env%matrix_buf1, &
1187 27138 : rzero, qs_ot_env%matrix_buf2)
1188 :
1189 : ! get the schur product of O_uv*B_uv
1190 : CALL dbcsr_hadamard_product(qs_ot_env%matrix_buf2, qs_ot_env%matrix_sinp_b, &
1191 27138 : qs_ot_env%matrix_buf3)
1192 :
1193 : ! overlap hc*c0
1194 : CALL dbcsr_multiply('T', 'N', rone, matrix_hc, qs_ot_env%matrix_c0, rzero, &
1195 27138 : qs_ot_env%matrix_buf2)
1196 : ! get it in the basis of the eigenvectors
1197 : CALL dbcsr_multiply('N', 'N', rone, qs_ot_env%matrix_buf2, qs_ot_env%matrix_r, &
1198 27138 : rzero, qs_ot_env%matrix_buf1)
1199 : CALL dbcsr_multiply('T', 'N', rone, qs_ot_env%matrix_r, qs_ot_env%matrix_buf1, &
1200 27138 : rzero, qs_ot_env%matrix_buf2)
1201 :
1202 : CALL dbcsr_hadamard_product(qs_ot_env%matrix_buf2, qs_ot_env%matrix_cosp_b, &
1203 27138 : qs_ot_env%matrix_buf4)
1204 :
1205 : ! add the two bs and compute b+b^T
1206 : CALL dbcsr_add(qs_ot_env%matrix_buf3, qs_ot_env%matrix_buf4, &
1207 27138 : alpha_scalar=rone, beta_scalar=rone)
1208 :
1209 : ! get the b in the eigenvector basis
1210 : CALL dbcsr_multiply('N', 'T', rone, qs_ot_env%matrix_buf3, qs_ot_env%matrix_r, &
1211 27138 : rzero, qs_ot_env%matrix_buf1)
1212 : CALL dbcsr_multiply('N', 'N', rone, qs_ot_env%matrix_r, qs_ot_env%matrix_buf1, &
1213 27138 : rzero, qs_ot_env%matrix_buf3)
1214 27138 : CALL dbcsr_get_info(qs_ot_env%matrix_buf3, distribution=dist)
1215 : CALL dbcsr_transposed(qs_ot_env%matrix_buf1, qs_ot_env%matrix_buf3, &
1216 : shallow_data_copy=.FALSE., use_distribution=dist, &
1217 27138 : transpose_distribution=.FALSE.)
1218 : CALL dbcsr_add(qs_ot_env%matrix_buf3, qs_ot_env%matrix_buf1, &
1219 27138 : alpha_scalar=rone, beta_scalar=rone)
1220 :
1221 : ! and add to the derivative
1222 : CALL dbcsr_multiply('N', 'N', rone, matrix_sx, qs_ot_env%matrix_buf3, &
1223 27138 : rone, matrix_gx)
1224 27138 : CALL timestop(handle)
1225 :
1226 27138 : END SUBROUTINE qs_ot_get_derivative_diag
1227 :
1228 : ! compute the derivative of the taylor expansion below
1229 : ! **************************************************************************************************
1230 : !> \brief ...
1231 : !> \param matrix_hc ...
1232 : !> \param matrix_x ...
1233 : !> \param matrix_sx ...
1234 : !> \param matrix_gx ...
1235 : !> \param qs_ot_env ...
1236 : ! **************************************************************************************************
1237 129642 : SUBROUTINE qs_ot_get_derivative_taylor(matrix_hc, matrix_x, matrix_sx, matrix_gx, &
1238 : qs_ot_env)
1239 :
1240 : TYPE(dbcsr_type), POINTER :: matrix_hc, matrix_x, matrix_sx, matrix_gx
1241 : TYPE(qs_ot_type) :: qs_ot_env
1242 :
1243 : CHARACTER(len=*), PARAMETER :: routineN = 'qs_ot_get_derivative_taylor'
1244 : REAL(KIND=dp), PARAMETER :: rone = 1.0_dp, rzero = 0.0_dp
1245 :
1246 : INTEGER :: handle, i, k, n
1247 : REAL(KIND=dp) :: cosfactor, sinfactor
1248 : TYPE(dbcsr_distribution_type) :: dist
1249 : TYPE(dbcsr_type), POINTER :: matrix_left, matrix_right
1250 :
1251 36234 : CALL timeset(routineN, handle)
1252 :
1253 36234 : CALL dbcsr_get_info(matrix_x, nfullrows_total=n, nfullcols_total=k)
1254 :
1255 : ! go for the derivative now
1256 : ! this de/dc*(dX/dx)*sinp i.e. zeroth order
1257 36234 : CALL dbcsr_multiply('N', 'N', rone, matrix_hc, qs_ot_env%matrix_sinp, rzero, matrix_gx)
1258 :
1259 36234 : IF (qs_ot_env%taylor_order .LE. 0) THEN
1260 7647 : CALL timestop(handle)
1261 7647 : RETURN
1262 : END IF
1263 :
1264 : ! we store the matrix that will multiply sx in matrix_r
1265 28587 : CALL dbcsr_set(qs_ot_env%matrix_r, rzero)
1266 :
1267 : ! just better names for matrix_cosp_b and matrix_sinp_b (they are buffer space here)
1268 28587 : matrix_left => qs_ot_env%matrix_cosp_b
1269 28587 : matrix_right => qs_ot_env%matrix_sinp_b
1270 :
1271 : ! overlap hc*x and add its transpose to matrix_left
1272 28587 : CALL dbcsr_multiply('T', 'N', rone, matrix_hc, matrix_x, rzero, matrix_left)
1273 28587 : CALL dbcsr_get_info(matrix_left, distribution=dist)
1274 : CALL dbcsr_transposed(qs_ot_env%matrix_buf1, matrix_left, &
1275 : shallow_data_copy=.FALSE., use_distribution=dist, &
1276 28587 : transpose_distribution=.FALSE.)
1277 : CALL dbcsr_add(matrix_left, qs_ot_env%matrix_buf1, &
1278 28587 : alpha_scalar=1.0_dp, beta_scalar=1.0_dp)
1279 28587 : CALL dbcsr_copy(matrix_right, matrix_left)
1280 :
1281 : ! first order
1282 28587 : sinfactor = -1.0_dp/(2.0_dp*3.0_dp)
1283 : CALL dbcsr_add(qs_ot_env%matrix_r, matrix_left, &
1284 28587 : alpha_scalar=1.0_dp, beta_scalar=sinfactor)
1285 :
1286 : ! M
1287 : ! OM+MO
1288 : ! OOM+OMO+MOO
1289 : ! ...
1290 61447 : DO i = 2, qs_ot_env%taylor_order
1291 32860 : sinfactor = sinfactor*(-1.0_dp)/REAL(2*i*(2*i + 1), KIND=dp)
1292 32860 : CALL dbcsr_multiply('N', 'N', rone, qs_ot_env%matrix_p, matrix_left, rzero, qs_ot_env%matrix_buf1)
1293 32860 : CALL dbcsr_multiply('N', 'N', rone, matrix_right, qs_ot_env%matrix_p, rzero, matrix_left)
1294 32860 : CALL dbcsr_copy(matrix_right, matrix_left)
1295 : CALL dbcsr_add(matrix_left, qs_ot_env%matrix_buf1, &
1296 32860 : 1.0_dp, 1.0_dp)
1297 : CALL dbcsr_add(qs_ot_env%matrix_r, matrix_left, &
1298 61447 : alpha_scalar=1.0_dp, beta_scalar=sinfactor)
1299 : END DO
1300 :
1301 : ! overlap hc*c0 and add its transpose to matrix_left
1302 28587 : CALL dbcsr_multiply('T', 'N', rone, matrix_hc, qs_ot_env%matrix_c0, rzero, matrix_left)
1303 28587 : CALL dbcsr_get_info(matrix_left, distribution=dist)
1304 : CALL dbcsr_transposed(qs_ot_env%matrix_buf1, matrix_left, &
1305 : shallow_data_copy=.FALSE., use_distribution=dist, &
1306 28587 : transpose_distribution=.FALSE.)
1307 28587 : CALL dbcsr_add(matrix_left, qs_ot_env%matrix_buf1, 1.0_dp, 1.0_dp)
1308 28587 : CALL dbcsr_copy(matrix_right, matrix_left)
1309 :
1310 : ! first order
1311 28587 : cosfactor = -1.0_dp/(1.0_dp*2.0_dp)
1312 : CALL dbcsr_add(qs_ot_env%matrix_r, matrix_left, &
1313 28587 : alpha_scalar=1.0_dp, beta_scalar=cosfactor)
1314 :
1315 : ! M
1316 : ! OM+MO
1317 : ! OOM+OMO+MOO
1318 : ! ...
1319 61447 : DO i = 2, qs_ot_env%taylor_order
1320 32860 : cosfactor = cosfactor*(-1.0_dp)/REAL(2*i*(2*i - 1), KIND=dp)
1321 32860 : CALL dbcsr_multiply('N', 'N', rone, qs_ot_env%matrix_p, matrix_left, rzero, qs_ot_env%matrix_buf1)
1322 32860 : CALL dbcsr_multiply('N', 'N', rone, matrix_right, qs_ot_env%matrix_p, rzero, matrix_left)
1323 32860 : CALL dbcsr_copy(matrix_right, matrix_left)
1324 32860 : CALL dbcsr_add(matrix_left, qs_ot_env%matrix_buf1, 1.0_dp, 1.0_dp)
1325 : CALL dbcsr_add(qs_ot_env%matrix_r, matrix_left, &
1326 61447 : alpha_scalar=1.0_dp, beta_scalar=cosfactor)
1327 : END DO
1328 :
1329 : ! and add to the derivative
1330 28587 : CALL dbcsr_multiply('N', 'N', rone, matrix_sx, qs_ot_env%matrix_r, rone, matrix_gx)
1331 :
1332 28587 : CALL timestop(handle)
1333 :
1334 36234 : END SUBROUTINE qs_ot_get_derivative_taylor
1335 :
1336 : ! computes a taylor expansion.
1337 : ! **************************************************************************************************
1338 : !> \brief ...
1339 : !> \param qs_ot_env ...
1340 : ! **************************************************************************************************
1341 81958 : SUBROUTINE qs_ot_p2m_taylor(qs_ot_env)
1342 : TYPE(qs_ot_type) :: qs_ot_env
1343 :
1344 : CHARACTER(len=*), PARAMETER :: routineN = 'qs_ot_p2m_taylor'
1345 : REAL(KIND=dp), PARAMETER :: rone = 1.0_dp, rzero = 0.0_dp
1346 :
1347 : INTEGER :: handle, i, k
1348 : REAL(KIND=dp) :: cosfactor, sinfactor
1349 :
1350 49980 : CALL timeset(routineN, handle)
1351 :
1352 : ! zeroth order
1353 49980 : CALL dbcsr_set(qs_ot_env%matrix_cosp, rzero)
1354 49980 : CALL dbcsr_set(qs_ot_env%matrix_sinp, rzero)
1355 49980 : CALL dbcsr_add_on_diag(qs_ot_env%matrix_cosp, rone)
1356 49980 : CALL dbcsr_add_on_diag(qs_ot_env%matrix_sinp, rone)
1357 :
1358 49980 : IF (qs_ot_env%taylor_order .LE. 0) THEN
1359 8229 : CALL timestop(handle)
1360 18002 : RETURN
1361 : END IF
1362 :
1363 : ! first order
1364 41751 : cosfactor = -1.0_dp/(1.0_dp*2.0_dp)
1365 41751 : sinfactor = -1.0_dp/(2.0_dp*3.0_dp)
1366 41751 : CALL dbcsr_add(qs_ot_env%matrix_cosp, qs_ot_env%matrix_p, alpha_scalar=1.0_dp, beta_scalar=cosfactor)
1367 41751 : CALL dbcsr_add(qs_ot_env%matrix_sinp, qs_ot_env%matrix_p, alpha_scalar=1.0_dp, beta_scalar=sinfactor)
1368 41751 : IF (qs_ot_env%taylor_order .LE. 1) THEN
1369 9773 : CALL timestop(handle)
1370 9773 : RETURN
1371 : END IF
1372 :
1373 : ! other orders
1374 31978 : CALL dbcsr_get_info(qs_ot_env%matrix_p, nfullrows_total=k)
1375 31978 : CALL dbcsr_copy(qs_ot_env%matrix_r, qs_ot_env%matrix_p)
1376 :
1377 81082 : DO i = 2, qs_ot_env%taylor_order
1378 : ! new power of p
1379 : CALL dbcsr_multiply('N', 'N', rone, qs_ot_env%matrix_p, qs_ot_env%matrix_r, &
1380 49104 : rzero, qs_ot_env%matrix_buf1)
1381 49104 : CALL dbcsr_copy(qs_ot_env%matrix_r, qs_ot_env%matrix_buf1)
1382 : ! add to the taylor expansion so far
1383 49104 : cosfactor = cosfactor*(-1.0_dp)/REAL(2*i*(2*i - 1), KIND=dp)
1384 49104 : sinfactor = sinfactor*(-1.0_dp)/REAL(2*i*(2*i + 1), KIND=dp)
1385 : CALL dbcsr_add(qs_ot_env%matrix_cosp, qs_ot_env%matrix_r, &
1386 49104 : alpha_scalar=1.0_dp, beta_scalar=cosfactor)
1387 : CALL dbcsr_add(qs_ot_env%matrix_sinp, qs_ot_env%matrix_r, &
1388 81082 : alpha_scalar=1.0_dp, beta_scalar=sinfactor)
1389 : END DO
1390 :
1391 31978 : CALL timestop(handle)
1392 :
1393 : END SUBROUTINE qs_ot_p2m_taylor
1394 :
1395 : ! given p, computes - eigenstuff (matrix_r,evals)
1396 : ! - cos(p^0.5),p^(-0.5)*sin(p^0.5)
1397 : ! - the real b matrices, needed for the derivatives of these guys
1398 : ! cosp_b_ij=(1/(2pii) * int(cos(z^1/2)/((z-eval(i))*(z-eval(j))))
1399 : ! sinp_b_ij=(1/(2pii) * int(z^(-1/2)*sin(z^1/2)/((z-eval(i))*(z-eval(j))))
1400 : ! **************************************************************************************************
1401 : !> \brief ...
1402 : !> \param qs_ot_env ...
1403 : ! **************************************************************************************************
1404 158900 : SUBROUTINE qs_ot_p2m_diag(qs_ot_env)
1405 :
1406 : TYPE(qs_ot_type) :: qs_ot_env
1407 :
1408 : CHARACTER(len=*), PARAMETER :: routineN = 'qs_ot_p2m_diag'
1409 : REAL(KIND=dp), PARAMETER :: rone = 1.0_dp, rzero = 0.0_dp
1410 :
1411 : INTEGER :: blk, col, col_offset, col_size, handle, &
1412 : i, j, k, row, row_offset, row_size
1413 39725 : REAL(dp), DIMENSION(:, :), POINTER :: DATA
1414 : REAL(KIND=dp) :: a, b
1415 : TYPE(dbcsr_iterator_type) :: iter
1416 :
1417 39725 : CALL timeset(routineN, handle)
1418 :
1419 39725 : CALL dbcsr_get_info(qs_ot_env%matrix_p, nfullrows_total=k)
1420 39725 : CALL dbcsr_copy(qs_ot_env%matrix_buf1, qs_ot_env%matrix_p)
1421 : CALL cp_dbcsr_syevd(qs_ot_env%matrix_buf1, qs_ot_env%matrix_r, qs_ot_env%evals, &
1422 39725 : qs_ot_env%para_env, qs_ot_env%blacs_env)
1423 442639 : DO i = 1, k
1424 442639 : qs_ot_env%evals(i) = MAX(0.0_dp, qs_ot_env%evals(i))
1425 : END DO
1426 :
1427 39725 : !$OMP PARALLEL DO DEFAULT(NONE) PRIVATE(i) SHARED(k,qs_ot_env)
1428 : DO i = 1, k
1429 : qs_ot_env%dum(i) = COS(SQRT(qs_ot_env%evals(i)))
1430 : END DO
1431 39725 : CALL dbcsr_copy(qs_ot_env%matrix_buf1, qs_ot_env%matrix_r)
1432 39725 : CALL dbcsr_scale_by_vector(qs_ot_env%matrix_buf1, alpha=qs_ot_env%dum, side='right')
1433 : CALL dbcsr_multiply('N', 'T', rone, qs_ot_env%matrix_r, qs_ot_env%matrix_buf1, &
1434 39725 : rzero, qs_ot_env%matrix_cosp)
1435 :
1436 39725 : !$OMP PARALLEL DO DEFAULT(NONE) PRIVATE(i) SHARED(k,qs_ot_env)
1437 : DO i = 1, k
1438 : qs_ot_env%dum(i) = qs_ot_sinc(SQRT(qs_ot_env%evals(i)))
1439 : END DO
1440 39725 : CALL dbcsr_copy(qs_ot_env%matrix_buf1, qs_ot_env%matrix_r)
1441 39725 : CALL dbcsr_scale_by_vector(qs_ot_env%matrix_buf1, alpha=qs_ot_env%dum, side='right')
1442 : CALL dbcsr_multiply('N', 'T', rone, qs_ot_env%matrix_r, qs_ot_env%matrix_buf1, &
1443 39725 : rzero, qs_ot_env%matrix_sinp)
1444 :
1445 39725 : CALL dbcsr_copy(qs_ot_env%matrix_cosp_b, qs_ot_env%matrix_cosp)
1446 39725 : CALL dbcsr_iterator_start(iter, qs_ot_env%matrix_cosp_b)
1447 69687 : DO WHILE (dbcsr_iterator_blocks_left(iter))
1448 : CALL dbcsr_iterator_next_block(iter, row, col, DATA, &
1449 : block_number=blk, row_size=row_size, col_size=col_size, &
1450 29962 : row_offset=row_offset, col_offset=col_offset)
1451 478695 : DO j = 1, col_size
1452 9633853 : DO i = 1, row_size
1453 : a = (SQRT(qs_ot_env%evals(row_offset + i - 1)) &
1454 9194883 : - SQRT(qs_ot_env%evals(col_offset + j - 1)))/2.0_dp
1455 : b = (SQRT(qs_ot_env%evals(row_offset + i - 1)) &
1456 9194883 : + SQRT(qs_ot_env%evals(col_offset + j - 1)))/2.0_dp
1457 9603891 : DATA(i, j) = -0.5_dp*qs_ot_sinc(a)*qs_ot_sinc(b)
1458 : END DO
1459 : END DO
1460 : END DO
1461 39725 : CALL dbcsr_iterator_stop(iter)
1462 :
1463 39725 : CALL dbcsr_copy(qs_ot_env%matrix_sinp_b, qs_ot_env%matrix_sinp)
1464 39725 : CALL dbcsr_iterator_start(iter, qs_ot_env%matrix_sinp_b)
1465 69687 : DO WHILE (dbcsr_iterator_blocks_left(iter))
1466 : CALL dbcsr_iterator_next_block(iter, row, col, DATA, &
1467 : block_number=blk, row_size=row_size, col_size=col_size, &
1468 29962 : row_offset=row_offset, col_offset=col_offset)
1469 478695 : DO j = 1, col_size
1470 9633853 : DO i = 1, row_size
1471 9194883 : a = SQRT(qs_ot_env%evals(row_offset + i - 1))
1472 9194883 : b = SQRT(qs_ot_env%evals(col_offset + j - 1))
1473 9603891 : DATA(i, j) = qs_ot_sincf(a, b)
1474 : END DO
1475 : END DO
1476 : END DO
1477 39725 : CALL dbcsr_iterator_stop(iter)
1478 :
1479 39725 : CALL timestop(handle)
1480 :
1481 39725 : END SUBROUTINE qs_ot_p2m_diag
1482 :
1483 : ! computes sin(x)/x for all values of the argument
1484 : ! **************************************************************************************************
1485 : !> \brief ...
1486 : !> \param x ...
1487 : !> \return ...
1488 : ! **************************************************************************************************
1489 25238402 : FUNCTION qs_ot_sinc(x)
1490 :
1491 : REAL(KIND=dp), INTENT(IN) :: x
1492 : REAL(KIND=dp) :: qs_ot_sinc
1493 :
1494 : REAL(KIND=dp), PARAMETER :: q1 = 1.0_dp, q2 = -q1/(2.0_dp*3.0_dp), q3 = -q2/(4.0_dp*5.0_dp), &
1495 : q4 = -q3/(6.0_dp*7.0_dp), q5 = -q4/(8.0_dp*9.0_dp), q6 = -q5/(10.0_dp*11.0_dp), &
1496 : q7 = -q6/(12.0_dp*13.0_dp), q8 = -q7/(14.0_dp*15.0_dp), q9 = -q8/(16.0_dp*17.0_dp), &
1497 : q10 = -q9/(18.0_dp*19.0_dp)
1498 :
1499 : REAL(KIND=dp) :: y
1500 :
1501 25238402 : IF (ABS(x) > 0.5_dp) THEN
1502 7252181 : qs_ot_sinc = SIN(x)/x
1503 : ELSE
1504 17986221 : y = x*x
1505 17986221 : qs_ot_sinc = q1 + y*(q2 + y*(q3 + y*(q4 + y*(q5 + y*(q6 + y*(q7 + y*(q8 + y*(q9 + y*(q10)))))))))
1506 : END IF
1507 25238402 : END FUNCTION qs_ot_sinc
1508 : ! computes (1/(x^2-y^2))*(sinc(x)-sinc(y)) for all positive values of the arguments
1509 : ! **************************************************************************************************
1510 : !> \brief ...
1511 : !> \param xa ...
1512 : !> \param ya ...
1513 : !> \return ...
1514 : ! **************************************************************************************************
1515 9194883 : FUNCTION qs_ot_sincf(xa, ya)
1516 :
1517 : REAL(KIND=dp), INTENT(IN) :: xa, ya
1518 : REAL(KIND=dp) :: qs_ot_sincf
1519 :
1520 : INTEGER :: i
1521 : REAL(KIND=dp) :: a, b, rs, sf, x, xs, y, ybx, ybxs
1522 :
1523 : ! this is currently a limit of the routine, could be removed rather easily
1524 :
1525 9194883 : IF (xa .LT. 0) CPABORT("x is negative")
1526 9194883 : IF (ya .LT. 0) CPABORT("y is negative")
1527 :
1528 9194883 : IF (xa .LT. ya) THEN
1529 4429453 : x = ya
1530 4429453 : y = xa
1531 : ELSE
1532 4765430 : x = xa
1533 4765430 : y = ya
1534 : END IF
1535 :
1536 9194883 : IF (x .LT. 0.5_dp) THEN ! use series, keeping in mind that x,y,x+y,x-y can all be zero
1537 :
1538 5972022 : qs_ot_sincf = 0.0_dp
1539 5972022 : IF (x .GT. 0.0_dp) THEN
1540 5823504 : ybx = y/x
1541 : ELSE ! should be irrelevant !?
1542 : ybx = 0.0_dp
1543 : END IF
1544 :
1545 5972022 : sf = -1.0_dp/((1.0_dp + ybx)*6.0_dp)
1546 5972022 : rs = 1.0_dp
1547 5972022 : ybxs = ybx
1548 5972022 : xs = 1.0_dp
1549 :
1550 65692242 : DO i = 1, 10
1551 59720220 : qs_ot_sincf = qs_ot_sincf + sf*rs*xs*(1.0_dp + ybxs)
1552 59720220 : sf = -sf/(REAL((2*i + 2), dp)*REAL((2*i + 3), dp))
1553 59720220 : rs = rs + ybxs
1554 59720220 : ybxs = ybxs*ybx
1555 65692242 : xs = xs*x*x
1556 : END DO
1557 :
1558 : ELSE ! no series expansion
1559 3222861 : IF (x - y .GT. 0.1_dp) THEN ! safe to use the normal form
1560 2978554 : qs_ot_sincf = (qs_ot_sinc(x) - qs_ot_sinc(y))/((x + y)*(x - y))
1561 : ELSE
1562 244307 : a = (x + y)/2.0_dp
1563 244307 : b = (x - y)/2.0_dp ! might be close to zero
1564 : ! y (=(a-b)) can not be close to zero since it is close to x>0.5
1565 244307 : qs_ot_sincf = (qs_ot_sinc(b)*COS(a) - qs_ot_sinc(a)*COS(b))/(2*x*y)
1566 : END IF
1567 : END IF
1568 :
1569 9194883 : END FUNCTION qs_ot_sincf
1570 :
1571 : END MODULE qs_ot
|