(git:374b731)
Loading...
Searching...
No Matches
ct_methods.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 Cayley transformation methods
10!> \par History
11!> 2011.06 created [Rustam Z Khaliullin]
12!> \author Rustam Z Khaliullin
13! **************************************************************************************************
21 USE ct_types, ONLY: ct_step_env_type
22 USE dbcsr_api, ONLY: &
23 dbcsr_add, dbcsr_add_on_diag, dbcsr_copy, dbcsr_create, dbcsr_desymmetrize, &
24 dbcsr_distribution_get, dbcsr_distribution_type, dbcsr_dot, dbcsr_filter, dbcsr_finalize, &
25 dbcsr_frobenius_norm, dbcsr_func_inverse, dbcsr_function_of_elements, dbcsr_get_diag, &
26 dbcsr_get_info, dbcsr_get_stored_coordinates, dbcsr_hadamard_product, &
27 dbcsr_iterator_blocks_left, dbcsr_iterator_next_block, dbcsr_iterator_start, &
28 dbcsr_iterator_stop, dbcsr_iterator_type, dbcsr_multiply, dbcsr_nblkcols_total, &
29 dbcsr_nblkrows_total, dbcsr_norm, dbcsr_norm_maxabsnorm, dbcsr_release, &
30 dbcsr_reserve_block2d, dbcsr_scale, dbcsr_set, dbcsr_set_diag, dbcsr_transposed, &
31 dbcsr_type, dbcsr_type_no_symmetry, dbcsr_work_create
32 USE input_constants, ONLY: &
36 USE kinds, ONLY: dp
37 USE machine, ONLY: m_walltime
38#include "./base/base_uses.f90"
39
40 IMPLICIT NONE
41
42 PRIVATE
43
44 CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'ct_methods'
45
46 ! Public subroutines
48
49CONTAINS
50
51! **************************************************************************************************
52!> \brief Performs Cayley transformation
53!> \param cts_env ...
54!> \par History
55!> 2011.06 created [Rustam Z Khaliullin]
56!> \author Rustam Z Khaliullin
57! **************************************************************************************************
58 SUBROUTINE ct_step_execute(cts_env)
59
60 TYPE(ct_step_env_type) :: cts_env
61
62 CHARACTER(len=*), PARAMETER :: routinen = 'ct_step_execute'
63
64 INTEGER :: handle, n, preconditioner_type, unit_nr
65 REAL(kind=dp) :: gap_estimate, safety_margin
66 REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: evals
67 TYPE(cp_logger_type), POINTER :: logger
68 TYPE(dbcsr_type) :: matrix_pp, matrix_pq, matrix_qp, &
69 matrix_qp_save, matrix_qq, oo1, &
70 oo1_sqrt, oo1_sqrt_inv, t_corr, tmp1, &
71 u_pp, u_qq
72
73!TYPE(dbcsr_type) :: rst_x1, rst_x2
74!REAL(KIND=dp) :: ener_tmp
75!TYPE(dbcsr_iterator_type) :: iter
76!INTEGER :: iblock_row,iblock_col,&
77! iblock_row_size,iblock_col_size
78!REAL(KIND=dp), DIMENSION(:,:), POINTER :: data_p
79
80 CALL timeset(routinen, handle)
81
82 logger => cp_get_default_logger()
83 IF (logger%para_env%is_source()) THEN
84 unit_nr = cp_logger_get_default_unit_nr(logger, local=.true.)
85 ELSE
86 unit_nr = -1
87 END IF
88
89 ! check if all input is in place and flags are consistent
90 IF (cts_env%update_q .AND. (.NOT. cts_env%update_p)) THEN
91 cpabort("q-update is possible only with p-update")
92 END IF
93
94 IF (cts_env%tensor_type .EQ. tensor_up_down) THEN
95 cpabort("riccati is not implemented for biorthogonal basis")
96 END IF
97
98 IF (.NOT. ASSOCIATED(cts_env%matrix_ks)) THEN
99 cpabort("KS matrix is not associated")
100 END IF
101
102 IF (cts_env%use_virt_orbs .AND. (.NOT. cts_env%use_occ_orbs)) THEN
103 cpabort("virtual orbs can be used only with occupied orbs")
104 END IF
105
106 IF (cts_env%use_occ_orbs) THEN
107 IF (.NOT. ASSOCIATED(cts_env%matrix_t)) THEN
108 cpabort("T matrix is not associated")
109 END IF
110 IF (.NOT. ASSOCIATED(cts_env%matrix_qp_template)) THEN
111 cpabort("QP template is not associated")
112 END IF
113 IF (.NOT. ASSOCIATED(cts_env%matrix_pq_template)) THEN
114 cpabort("PQ template is not associated")
115 END IF
116 END IF
117
118 IF (cts_env%use_virt_orbs) THEN
119 IF (.NOT. ASSOCIATED(cts_env%matrix_v)) THEN
120 cpabort("V matrix is not associated")
121 END IF
122 ELSE
123 IF (.NOT. ASSOCIATED(cts_env%matrix_p)) THEN
124 cpabort("P matrix is not associated")
125 END IF
126 END IF
127
128 IF (cts_env%tensor_type .NE. tensor_up_down .AND. &
129 cts_env%tensor_type .NE. tensor_orthogonal) THEN
130 cpabort("illegal tensor flag")
131 END IF
132
133 ! start real calculations
134 IF (cts_env%use_occ_orbs) THEN
135
136 ! create matrices for various ks blocks
137 CALL dbcsr_create(matrix_pp, &
138 template=cts_env%p_index_up, &
139 matrix_type=dbcsr_type_no_symmetry)
140 CALL dbcsr_create(matrix_qp, &
141 template=cts_env%matrix_qp_template, &
142 matrix_type=dbcsr_type_no_symmetry)
143 CALL dbcsr_create(matrix_qq, &
144 template=cts_env%q_index_up, &
145 matrix_type=dbcsr_type_no_symmetry)
146 CALL dbcsr_create(matrix_pq, &
147 template=cts_env%matrix_pq_template, &
148 matrix_type=dbcsr_type_no_symmetry)
149
150 ! create the residue matrix
151 CALL dbcsr_create(cts_env%matrix_res, &
152 template=cts_env%matrix_qp_template)
153
154 CALL assemble_ks_qp_blocks(cts_env%matrix_ks, &
155 cts_env%matrix_p, &
156 cts_env%matrix_t, &
157 cts_env%matrix_v, &
158 cts_env%q_index_down, &
159 cts_env%p_index_up, &
160 cts_env%q_index_up, &
161 matrix_pp, &
162 matrix_qq, &
163 matrix_qp, &
164 matrix_pq, &
165 cts_env%tensor_type, &
166 cts_env%use_virt_orbs, &
167 cts_env%eps_filter)
168
169 ! create a matrix of single-excitation amplitudes
170 CALL dbcsr_create(cts_env%matrix_x, &
171 template=cts_env%matrix_qp_template)
172 IF (ASSOCIATED(cts_env%matrix_x_guess)) THEN
173 CALL dbcsr_copy(cts_env%matrix_x, &
174 cts_env%matrix_x_guess)
175 IF (cts_env%tensor_type .EQ. tensor_orthogonal) THEN
176 ! bring x from contravariant-covariant representation
177 ! to the orthogonal/cholesky representation
178 ! use res as temporary storage
179 CALL dbcsr_multiply("N", "N", 1.0_dp, cts_env%q_index_down, &
180 cts_env%matrix_x, 0.0_dp, cts_env%matrix_res, &
181 filter_eps=cts_env%eps_filter)
182 CALL dbcsr_multiply("N", "N", 1.0_dp, cts_env%matrix_res, &
183 cts_env%p_index_up, 0.0_dp, &
184 cts_env%matrix_x, &
185 filter_eps=cts_env%eps_filter)
186 END IF
187 ELSE
188 ! set amplitudes to zero
189 CALL dbcsr_set(cts_env%matrix_x, 0.0_dp)
190 END IF
191
192 !SELECT CASE (cts_env%preconditioner_type)
193 !CASE (prec_eigenvector_blocks,prec_eigenvector_full)
194 preconditioner_type = 1
195 safety_margin = 2.0_dp
196 gap_estimate = 0.0001_dp
197 SELECT CASE (preconditioner_type)
198 CASE (1, 2)
199!RZK-warning diagonalization works only with orthogonal tensor!!!
200 ! find a better basis by diagonalizing diagonal blocks
201 ! first pp
202 CALL dbcsr_create(u_pp, template=matrix_pp, &
203 matrix_type=dbcsr_type_no_symmetry)
204 !IF (cts_env%preconditioner_type.eq.prec_eigenvector_full) THEN
205 IF (.true.) THEN
206 CALL dbcsr_get_info(matrix_pp, nfullrows_total=n)
207 ALLOCATE (evals(n))
208 CALL cp_dbcsr_syevd(matrix_pp, u_pp, evals, &
209 cts_env%para_env, cts_env%blacs_env)
210 DEALLOCATE (evals)
211 ELSE
212 CALL diagonalize_diagonal_blocks(matrix_pp, u_pp)
213 END IF
214 ! and now qq
215 CALL dbcsr_create(u_qq, template=matrix_qq, &
216 matrix_type=dbcsr_type_no_symmetry)
217 !IF (cts_env%preconditioner_type.eq.prec_eigenvector_full) THEN
218 IF (.true.) THEN
219 CALL dbcsr_get_info(matrix_qq, nfullrows_total=n)
220 ALLOCATE (evals(n))
221 CALL cp_dbcsr_syevd(matrix_qq, u_qq, evals, &
222 cts_env%para_env, cts_env%blacs_env)
223 DEALLOCATE (evals)
224 ELSE
225 CALL diagonalize_diagonal_blocks(matrix_qq, u_qq)
226 END IF
227
228 ! apply the transformation to all matrices
229 CALL matrix_forward_transform(matrix_pp, u_pp, u_pp, &
230 cts_env%eps_filter)
231 CALL matrix_forward_transform(matrix_qq, u_qq, u_qq, &
232 cts_env%eps_filter)
233 CALL matrix_forward_transform(matrix_qp, u_qq, u_pp, &
234 cts_env%eps_filter)
235 CALL matrix_forward_transform(matrix_pq, u_pp, u_qq, &
236 cts_env%eps_filter)
237 CALL matrix_forward_transform(cts_env%matrix_x, u_qq, u_pp, &
238 cts_env%eps_filter)
239
240 IF (cts_env%max_iter .GE. 0) THEN
241
242 CALL solve_riccati_equation( &
243 pp=matrix_pp, &
244 qq=matrix_qq, &
245 qp=matrix_qp, &
246 pq=matrix_pq, &
247 x=cts_env%matrix_x, &
248 res=cts_env%matrix_res, &
249 neglect_quadratic_term=cts_env%neglect_quadratic_term, &
250 conjugator=cts_env%conjugator, &
251 max_iter=cts_env%max_iter, &
252 eps_convergence=cts_env%eps_convergence, &
253 eps_filter=cts_env%eps_filter, &
254 converged=cts_env%converged)
255
256 IF (cts_env%converged) THEN
257 !IF (unit_nr>0) THEN
258 ! WRITE(unit_nr,*)
259 ! WRITE(unit_nr,'(T6,A)') &
260 ! "RICCATI equations solved"
261 ! CALL m_flush(unit_nr)
262 !ENDIF
263 ELSE
264 cpabort("RICCATI: CG algorithm has NOT converged")
265 END IF
266
267 END IF
268
269 IF (cts_env%calculate_energy_corr) THEN
270
271 CALL dbcsr_dot(matrix_qp, cts_env%matrix_x, cts_env%energy_correction)
272
273 END IF
274
275 CALL dbcsr_release(matrix_pp)
276 CALL dbcsr_release(matrix_qp)
277 CALL dbcsr_release(matrix_qq)
278 CALL dbcsr_release(matrix_pq)
279
280 ! back-transform to the original basis
281 CALL matrix_backward_transform(cts_env%matrix_x, u_qq, &
282 u_pp, cts_env%eps_filter)
283
284 CALL dbcsr_release(u_qq)
285 CALL dbcsr_release(u_pp)
286
287 !CASE (prec_cholesky_inverse)
288 CASE (3)
289
290! RZK-warning implemented only for orthogonal tensors!!!
291! generalization to up_down should be easy
292 CALL dbcsr_create(u_pp, template=matrix_pp, &
293 matrix_type=dbcsr_type_no_symmetry)
294 CALL dbcsr_copy(u_pp, matrix_pp)
295 CALL dbcsr_scale(u_pp, -1.0_dp)
296 CALL dbcsr_add_on_diag(u_pp, &
297 abs(safety_margin*gap_estimate))
298 CALL cp_dbcsr_cholesky_decompose(u_pp, &
299 para_env=cts_env%para_env, &
300 blacs_env=cts_env%blacs_env)
301 CALL cp_dbcsr_cholesky_invert(u_pp, &
302 para_env=cts_env%para_env, &
303 blacs_env=cts_env%blacs_env, &
304 upper_to_full=.true.)
305 !CALL dbcsr_scale(u_pp,-1.0_dp)
306
307 CALL dbcsr_create(u_qq, template=matrix_qq, &
308 matrix_type=dbcsr_type_no_symmetry)
309 CALL dbcsr_copy(u_qq, matrix_qq)
310 CALL dbcsr_add_on_diag(u_qq, &
311 abs(safety_margin*gap_estimate))
312 CALL cp_dbcsr_cholesky_decompose(u_qq, &
313 para_env=cts_env%para_env, &
314 blacs_env=cts_env%blacs_env)
315 CALL cp_dbcsr_cholesky_invert(u_qq, &
316 para_env=cts_env%para_env, &
317 blacs_env=cts_env%blacs_env, &
318 upper_to_full=.true.)
319
320 ! transform all riccati matrices (left-right preconditioner)
321 CALL dbcsr_create(tmp1, template=matrix_qq, &
322 matrix_type=dbcsr_type_no_symmetry)
323 CALL dbcsr_multiply("N", "N", 1.0_dp, u_qq, &
324 matrix_qq, 0.0_dp, tmp1, &
325 filter_eps=cts_env%eps_filter)
326 CALL dbcsr_copy(matrix_qq, tmp1)
327 CALL dbcsr_release(tmp1)
328
329 CALL dbcsr_create(tmp1, template=matrix_pp, &
330 matrix_type=dbcsr_type_no_symmetry)
331 CALL dbcsr_multiply("N", "N", 1.0_dp, matrix_pp, &
332 u_pp, 0.0_dp, tmp1, &
333 filter_eps=cts_env%eps_filter)
334 CALL dbcsr_copy(matrix_pp, tmp1)
335 CALL dbcsr_release(tmp1)
336
337 CALL dbcsr_create(matrix_qp_save, template=matrix_qp, &
338 matrix_type=dbcsr_type_no_symmetry)
339 CALL dbcsr_copy(matrix_qp_save, matrix_qp)
340
341 CALL dbcsr_create(tmp1, template=matrix_qp, &
342 matrix_type=dbcsr_type_no_symmetry)
343 CALL dbcsr_multiply("N", "N", 1.0_dp, matrix_qp, &
344 u_pp, 0.0_dp, tmp1, &
345 filter_eps=cts_env%eps_filter)
346 CALL dbcsr_multiply("N", "N", 1.0_dp, u_qq, tmp1, &
347 0.0_dp, matrix_qp, &
348 filter_eps=cts_env%eps_filter)
349 CALL dbcsr_release(tmp1)
350!CALL dbcsr_print(matrix_qq)
351!CALL dbcsr_print(matrix_qp)
352!CALL dbcsr_print(matrix_pp)
353
354 IF (cts_env%max_iter .GE. 0) THEN
355
356 CALL solve_riccati_equation( &
357 pp=matrix_pp, &
358 qq=matrix_qq, &
359 qp=matrix_qp, &
360 pq=matrix_pq, &
361 oo=u_pp, &
362 vv=u_qq, &
363 x=cts_env%matrix_x, &
364 res=cts_env%matrix_res, &
365 neglect_quadratic_term=cts_env%neglect_quadratic_term, &
366 conjugator=cts_env%conjugator, &
367 max_iter=cts_env%max_iter, &
368 eps_convergence=cts_env%eps_convergence, &
369 eps_filter=cts_env%eps_filter, &
370 converged=cts_env%converged)
371
372 IF (cts_env%converged) THEN
373 !IF (unit_nr>0) THEN
374 ! WRITE(unit_nr,*)
375 ! WRITE(unit_nr,'(T6,A)') &
376 ! "RICCATI equations solved"
377 ! CALL m_flush(unit_nr)
378 !ENDIF
379 ELSE
380 cpabort("RICCATI: CG algorithm has NOT converged")
381 END IF
382
383 END IF
384
385 IF (cts_env%calculate_energy_corr) THEN
386
387 CALL dbcsr_dot(matrix_qp_save, cts_env%matrix_x, cts_env%energy_correction)
388
389 END IF
390 CALL dbcsr_release(matrix_qp_save)
391
392 CALL dbcsr_release(matrix_pp)
393 CALL dbcsr_release(matrix_qp)
394 CALL dbcsr_release(matrix_qq)
395 CALL dbcsr_release(matrix_pq)
396
397 CALL dbcsr_release(u_qq)
398 CALL dbcsr_release(u_pp)
399
400 CASE DEFAULT
401 cpabort("illegal preconditioner type")
402 END SELECT ! preconditioner type
403
404 IF (cts_env%update_p) THEN
405
406 IF (cts_env%tensor_type .EQ. tensor_up_down) THEN
407 cpabort("orbital update is NYI for this tensor type")
408 END IF
409
410 ! transform occupied orbitals
411 ! in a way that preserves the overlap metric
412 CALL dbcsr_create(oo1, &
413 template=cts_env%p_index_up, &
414 matrix_type=dbcsr_type_no_symmetry)
415 CALL dbcsr_create(oo1_sqrt_inv, &
416 template=oo1)
417 CALL dbcsr_create(oo1_sqrt, &
418 template=oo1)
419
420 ! Compute (1+tr(X).X)^(-1/2)_up_down
421 CALL dbcsr_multiply("T", "N", 1.0_dp, cts_env%matrix_x, &
422 cts_env%matrix_x, 0.0_dp, oo1, &
423 filter_eps=cts_env%eps_filter)
424 CALL dbcsr_add_on_diag(oo1, 1.0_dp)
425 CALL matrix_sqrt_newton_schulz(oo1_sqrt, &
426 oo1_sqrt_inv, &
427 oo1, &
428 !if cholesky is used then sqrt
429 !guess cannot be provided
430 !matrix_sqrt_inv_guess=cts_env%p_index_up,&
431 !matrix_sqrt_guess=cts_env%p_index_down,&
432 threshold=cts_env%eps_filter, &
433 order=cts_env%order_lanczos, &
434 eps_lanczos=cts_env%eps_lancsoz, &
435 max_iter_lanczos=cts_env%max_iter_lanczos)
436 CALL dbcsr_multiply("N", "N", 1.0_dp, cts_env%p_index_up, &
437 oo1_sqrt_inv, 0.0_dp, oo1, &
438 filter_eps=cts_env%eps_filter)
439 CALL dbcsr_multiply("N", "N", 1.0_dp, oo1, &
440 cts_env%p_index_down, 0.0_dp, oo1_sqrt, &
441 filter_eps=cts_env%eps_filter)
442 CALL dbcsr_release(oo1)
443 CALL dbcsr_release(oo1_sqrt_inv)
444
445 ! bring x to contravariant-covariant representation now
446 CALL dbcsr_create(matrix_qp, &
447 template=cts_env%matrix_qp_template, &
448 matrix_type=dbcsr_type_no_symmetry)
449 CALL dbcsr_multiply("N", "N", 1.0_dp, cts_env%q_index_up, &
450 cts_env%matrix_x, 0.0_dp, matrix_qp, &
451 filter_eps=cts_env%eps_filter)
452 CALL dbcsr_multiply("N", "N", 1.0_dp, matrix_qp, &
453 cts_env%p_index_down, 0.0_dp, &
454 cts_env%matrix_x, &
455 filter_eps=cts_env%eps_filter)
456 CALL dbcsr_release(matrix_qp)
457
458 ! update T=T+X or T=T+V.X (whichever is appropriate)
459 CALL dbcsr_create(t_corr, template=cts_env%matrix_t)
460 IF (cts_env%use_virt_orbs) THEN
461 CALL dbcsr_multiply("N", "N", 1.0_dp, cts_env%matrix_v, &
462 cts_env%matrix_x, 0.0_dp, t_corr, &
463 filter_eps=cts_env%eps_filter)
464 CALL dbcsr_add(cts_env%matrix_t, t_corr, &
465 1.0_dp, 1.0_dp)
466 ELSE
467 CALL dbcsr_add(cts_env%matrix_t, cts_env%matrix_x, &
468 1.0_dp, 1.0_dp)
469 END IF
470 ! adjust T so the metric is preserved: T=(T+X).(1+tr(X).X)^(-1/2)
471 CALL dbcsr_multiply("N", "N", 1.0_dp, cts_env%matrix_t, oo1_sqrt, &
472 0.0_dp, t_corr, filter_eps=cts_env%eps_filter)
473 CALL dbcsr_copy(cts_env%matrix_t, t_corr)
474
475 CALL dbcsr_release(t_corr)
476 CALL dbcsr_release(oo1_sqrt)
477
478 ELSE ! do not update p
479
480 IF (cts_env%tensor_type .EQ. tensor_orthogonal) THEN
481 ! bring x to contravariant-covariant representation
482 CALL dbcsr_create(matrix_qp, &
483 template=cts_env%matrix_qp_template, &
484 matrix_type=dbcsr_type_no_symmetry)
485 CALL dbcsr_multiply("N", "N", 1.0_dp, cts_env%q_index_up, &
486 cts_env%matrix_x, 0.0_dp, matrix_qp, &
487 filter_eps=cts_env%eps_filter)
488 CALL dbcsr_multiply("N", "N", 1.0_dp, matrix_qp, &
489 cts_env%p_index_down, 0.0_dp, &
490 cts_env%matrix_x, &
491 filter_eps=cts_env%eps_filter)
492 CALL dbcsr_release(matrix_qp)
493 END IF
494
495 END IF
496
497 ELSE
498 cpabort("illegal occ option")
499 END IF
500
501 CALL timestop(handle)
502
503 END SUBROUTINE ct_step_execute
504
505! **************************************************************************************************
506!> \brief computes oo, ov, vo, and vv blocks of the ks matrix
507!> \param ks ...
508!> \param p ...
509!> \param t ...
510!> \param v ...
511!> \param q_index_down ...
512!> \param p_index_up ...
513!> \param q_index_up ...
514!> \param pp ...
515!> \param qq ...
516!> \param qp ...
517!> \param pq ...
518!> \param tensor_type ...
519!> \param use_virt_orbs ...
520!> \param eps_filter ...
521!> \par History
522!> 2011.06 created [Rustam Z Khaliullin]
523!> \author Rustam Z Khaliullin
524! **************************************************************************************************
525 SUBROUTINE assemble_ks_qp_blocks(ks, p, t, v, q_index_down, &
526 p_index_up, q_index_up, pp, qq, qp, pq, tensor_type, use_virt_orbs, eps_filter)
527
528 TYPE(dbcsr_type), INTENT(IN) :: ks, p, t, v, q_index_down, p_index_up, &
529 q_index_up
530 TYPE(dbcsr_type), INTENT(OUT) :: pp, qq, qp, pq
531 INTEGER, INTENT(IN) :: tensor_type
532 LOGICAL, INTENT(IN) :: use_virt_orbs
533 REAL(kind=dp), INTENT(IN) :: eps_filter
534
535 CHARACTER(len=*), PARAMETER :: routinen = 'assemble_ks_qp_blocks'
536
537 INTEGER :: handle
538 LOGICAL :: library_fixed
539 TYPE(dbcsr_type) :: kst, ksv, no, on, oo, q_index_up_nosym, &
540 sp, spf, t_or, v_or
541
542 CALL timeset(routinen, handle)
543
544 IF (use_virt_orbs) THEN
545
546 ! orthogonalize the orbitals
547 CALL dbcsr_create(t_or, template=t)
548 CALL dbcsr_create(v_or, template=v)
549 CALL dbcsr_multiply("N", "N", 1.0_dp, t, p_index_up, &
550 0.0_dp, t_or, filter_eps=eps_filter)
551 CALL dbcsr_multiply("N", "N", 1.0_dp, v, q_index_up, &
552 0.0_dp, v_or, filter_eps=eps_filter)
553
554 ! KS.T
555 CALL dbcsr_create(kst, template=t)
556 CALL dbcsr_multiply("N", "N", 1.0_dp, ks, t_or, &
557 0.0_dp, kst, filter_eps=eps_filter)
558 ! pp=tr(T)*KS.T
559 CALL dbcsr_multiply("T", "N", 1.0_dp, t_or, kst, &
560 0.0_dp, pp, filter_eps=eps_filter)
561 ! qp=tr(V)*KS.T
562 CALL dbcsr_multiply("T", "N", 1.0_dp, v_or, kst, &
563 0.0_dp, qp, filter_eps=eps_filter)
564 CALL dbcsr_release(kst)
565
566 ! KS.V
567 CALL dbcsr_create(ksv, template=v)
568 CALL dbcsr_multiply("N", "N", 1.0_dp, ks, v_or, &
569 0.0_dp, ksv, filter_eps=eps_filter)
570 ! tr(T)*KS.V
571 CALL dbcsr_multiply("T", "N", 1.0_dp, t_or, ksv, &
572 0.0_dp, pq, filter_eps=eps_filter)
573 ! tr(V)*KS.V
574 CALL dbcsr_multiply("T", "N", 1.0_dp, v_or, ksv, &
575 0.0_dp, qq, filter_eps=eps_filter)
576 CALL dbcsr_release(ksv)
577
578 CALL dbcsr_release(t_or)
579 CALL dbcsr_release(v_or)
580
581 ELSE ! no virtuals, use projected AOs
582
583! THIS PROCEDURE HAS NOT BEEN UPDATED FOR CHOLESKY p/q_index_up/down
584 CALL dbcsr_create(sp, template=q_index_down, &
585 matrix_type=dbcsr_type_no_symmetry)
586 CALL dbcsr_create(spf, template=q_index_down, &
587 matrix_type=dbcsr_type_no_symmetry)
588
589 ! qp=KS*T
590 CALL dbcsr_multiply("N", "N", 1.0_dp, ks, t, 0.0_dp, qp, &
591 filter_eps=eps_filter)
592 ! pp=tr(T)*KS.T
593 CALL dbcsr_multiply("T", "N", 1.0_dp, t, qp, 0.0_dp, pp, &
594 filter_eps=eps_filter)
595 ! sp=-S_*P
596 CALL dbcsr_multiply("N", "N", -1.0_dp, q_index_down, p, 0.0_dp, sp, &
597 filter_eps=eps_filter)
598
599 ! sp=1/S^-S_.P
600 SELECT CASE (tensor_type)
601 CASE (tensor_up_down)
602 CALL dbcsr_add_on_diag(sp, 1.0_dp)
603 CASE (tensor_orthogonal)
604 CALL dbcsr_create(q_index_up_nosym, template=q_index_up, &
605 matrix_type=dbcsr_type_no_symmetry)
606 CALL dbcsr_desymmetrize(q_index_up, q_index_up_nosym)
607 CALL dbcsr_add(sp, q_index_up_nosym, 1.0_dp, 1.0_dp)
608 CALL dbcsr_release(q_index_up_nosym)
609 END SELECT
610
611 ! spf=(1/S^-S_.P)*KS
612 CALL dbcsr_multiply("N", "N", 1.0_dp, sp, ks, 0.0_dp, spf, &
613 filter_eps=eps_filter)
614
615 ! qp=spf*T
616 CALL dbcsr_multiply("N", "N", 1.0_dp, spf, t, 0.0_dp, qp, &
617 filter_eps=eps_filter)
618
619 SELECT CASE (tensor_type)
620 CASE (tensor_up_down)
621 ! pq=tr(qp)
622 CALL dbcsr_transposed(pq, qp, transpose_distribution=.false.)
623 CASE (tensor_orthogonal)
624 ! pq=sig^.tr(qp)
625 CALL dbcsr_multiply("N", "T", 1.0_dp, p_index_up, qp, 0.0_dp, pq, &
626 filter_eps=eps_filter)
627 library_fixed = .false.
628 IF (library_fixed) THEN
629 CALL dbcsr_transposed(qp, pq, transpose_distribution=.false.)
630 ELSE
631 CALL dbcsr_create(no, template=qp, &
632 matrix_type=dbcsr_type_no_symmetry)
633 CALL dbcsr_multiply("N", "N", 1.0_dp, qp, p_index_up, 0.0_dp, no, &
634 filter_eps=eps_filter)
635 CALL dbcsr_copy(qp, no)
636 CALL dbcsr_release(no)
637 END IF
638 END SELECT
639
640 ! qq=spf*tr(sp)
641 CALL dbcsr_multiply("N", "T", 1.0_dp, spf, sp, 0.0_dp, qq, &
642 filter_eps=eps_filter)
643
644 SELECT CASE (tensor_type)
645 CASE (tensor_up_down)
646
647 CALL dbcsr_create(oo, template=pp, &
648 matrix_type=dbcsr_type_no_symmetry)
649 CALL dbcsr_create(no, template=qp, &
650 matrix_type=dbcsr_type_no_symmetry)
651
652 ! first index up
653 CALL dbcsr_multiply("N", "N", 1.0_dp, q_index_up, qq, 0.0_dp, spf, &
654 filter_eps=eps_filter)
655 CALL dbcsr_copy(qq, spf)
656 CALL dbcsr_multiply("N", "N", 1.0_dp, q_index_up, qp, 0.0_dp, no, &
657 filter_eps=eps_filter)
658 CALL dbcsr_copy(qp, no)
659 CALL dbcsr_multiply("N", "N", 1.0_dp, p_index_up, pp, 0.0_dp, oo, &
660 filter_eps=eps_filter)
661 CALL dbcsr_copy(pp, oo)
662 CALL dbcsr_multiply("N", "N", 1.0_dp, p_index_up, pq, 0.0_dp, on, &
663 filter_eps=eps_filter)
664 CALL dbcsr_copy(pq, on)
665
666 CALL dbcsr_release(no)
667 CALL dbcsr_release(oo)
668
669 CASE (tensor_orthogonal)
670
671 CALL dbcsr_create(oo, template=pp, &
672 matrix_type=dbcsr_type_no_symmetry)
673
674 ! both indeces up in the pp block
675 CALL dbcsr_multiply("N", "N", 1.0_dp, p_index_up, pp, 0.0_dp, oo, &
676 filter_eps=eps_filter)
677 CALL dbcsr_multiply("N", "N", 1.0_dp, oo, p_index_up, 0.0_dp, pp, &
678 filter_eps=eps_filter)
679
680 CALL dbcsr_release(oo)
681
682 END SELECT
683
684 CALL dbcsr_release(sp)
685 CALL dbcsr_release(spf)
686
687 END IF
688
689 CALL timestop(handle)
690
691 END SUBROUTINE assemble_ks_qp_blocks
692
693! **************************************************************************************************
694!> \brief Solves the generalized Riccati or Sylvester eqation
695!> using the preconditioned conjugate gradient algorithm
696!> qp + qq.x.oo - vv.x.pp - vv.x.pq.x.oo = 0 [oo and vv are optional]
697!> qp + qq.x - x.pp - x.pq.x = 0
698!> \param pp ...
699!> \param qq ...
700!> \param qp ...
701!> \param pq ...
702!> \param oo ...
703!> \param vv ...
704!> \param x ...
705!> \param res ...
706!> \param neglect_quadratic_term ...
707!> \param conjugator ...
708!> \param max_iter ...
709!> \param eps_convergence ...
710!> \param eps_filter ...
711!> \param converged ...
712!> \par History
713!> 2011.06 created [Rustam Z Khaliullin]
714!> 2011.11 generalized [Rustam Z Khaliullin]
715!> \author Rustam Z Khaliullin
716! **************************************************************************************************
717 RECURSIVE SUBROUTINE solve_riccati_equation(pp, qq, qp, pq, oo, vv, x, res, &
718 neglect_quadratic_term, &
719 conjugator, max_iter, eps_convergence, eps_filter, &
720 converged)
721
722 TYPE(dbcsr_type), INTENT(IN) :: pp, qq
723 TYPE(dbcsr_type), INTENT(INOUT) :: qp
724 TYPE(dbcsr_type), INTENT(IN) :: pq
725 TYPE(dbcsr_type), INTENT(IN), OPTIONAL :: oo, vv
726 TYPE(dbcsr_type), INTENT(INOUT) :: x
727 TYPE(dbcsr_type), INTENT(OUT) :: res
728 LOGICAL, INTENT(IN) :: neglect_quadratic_term
729 INTEGER, INTENT(IN) :: conjugator, max_iter
730 REAL(kind=dp), INTENT(IN) :: eps_convergence, eps_filter
731 LOGICAL, INTENT(OUT) :: converged
732
733 CHARACTER(len=*), PARAMETER :: routinen = 'solve_riccati_equation'
734
735 INTEGER :: handle, istep, iteration, nsteps, &
736 unit_nr, update_prec_freq
737 LOGICAL :: prepare_to_exit, present_oo, present_vv, &
738 quadratic_term, restart_conjugator
739 REAL(kind=dp) :: best_norm, best_step_size, beta, c0, c1, &
740 c2, c3, denom, kappa, numer, &
741 obj_function, t1, t2, tau
742 REAL(kind=dp), DIMENSION(3) :: step_size
743 TYPE(cp_logger_type), POINTER :: logger
744 TYPE(dbcsr_type) :: aux1, aux2, grad, m, n, oo1, oo2, prec, &
745 res_trial, step, step_oo, vv_step
746
747!TYPE(dbcsr_type) :: qqqq, pppp, zero_pq, zero_qp
748
749 CALL timeset(routinen, handle)
750
751 logger => cp_get_default_logger()
752 IF (logger%para_env%is_source()) THEN
753 unit_nr = cp_logger_get_default_unit_nr(logger, local=.true.)
754 ELSE
755 unit_nr = -1
756 END IF
757
758 t1 = m_walltime()
759
760!IF (level.gt.5) THEN
761! CPErrorMessage(cp_failure_level,routineP,"recursion level is too high")
762! CPPrecondition(.FALSE.,cp_failure_level,routineP,failure)
763!ENDIF
764!IF (unit_nr>0) THEN
765! WRITE(unit_nr,*) &
766! "========== LEVEL ",level,"=========="
767!ENDIF
768!CALL dbcsr_print(qq)
769!CALL dbcsr_print(pp)
770!CALL dbcsr_print(qp)
771!!CALL dbcsr_print(pq)
772!IF (unit_nr>0) THEN
773! WRITE(unit_nr,*) &
774! "====== END LEVEL ",level,"=========="
775!ENDIF
776
777 quadratic_term = .NOT. neglect_quadratic_term
778 present_oo = PRESENT(oo)
779 present_vv = PRESENT(vv)
780
781 ! create aux1 matrix and init
782 CALL dbcsr_create(aux1, template=pp)
783 CALL dbcsr_copy(aux1, pp)
784 CALL dbcsr_scale(aux1, -1.0_dp)
785
786 ! create aux2 matrix and init
787 CALL dbcsr_create(aux2, template=qq)
788 CALL dbcsr_copy(aux2, qq)
789
790 ! create the gradient matrix and init
791 CALL dbcsr_create(grad, template=x)
792 CALL dbcsr_set(grad, 0.0_dp)
793
794 ! create a preconditioner
795 ! RZK-warning how to apply it to up_down tensor?
796 CALL dbcsr_create(prec, template=x)
797 !CALL create_preconditioner(prec,aux1,aux2,qp,res,tensor_type,eps_filter)
798 !CALL dbcsr_set(prec,1.0_dp)
799
800 ! create the step matrix and init
801 CALL dbcsr_create(step, template=x)
802 !CALL dbcsr_hadamard_product(prec,grad,step)
803 !CALL dbcsr_scale(step,-1.0_dp)
804
805 CALL dbcsr_create(n, template=x)
806 CALL dbcsr_create(m, template=x)
807 CALL dbcsr_create(oo1, template=pp)
808 CALL dbcsr_create(oo2, template=pp)
809 CALL dbcsr_create(res_trial, template=res)
810 CALL dbcsr_create(vv_step, template=res)
811 CALL dbcsr_create(step_oo, template=res)
812
813 ! start conjugate gradient iterations
814 iteration = 0
815 converged = .false.
816 prepare_to_exit = .false.
817 beta = 0.0_dp
818 best_step_size = 0.0_dp
819 best_norm = 1.0e+100_dp
820 !ecorr=0.0_dp
821 !change_ecorr=0.0_dp
822 restart_conjugator = .false.
823 update_prec_freq = 20
824 DO
825
826 ! (re)-compute the residuals
827 IF (iteration .EQ. 0) THEN
828 CALL dbcsr_copy(res, qp)
829 IF (present_oo) THEN
830 CALL dbcsr_multiply("N", "N", +1.0_dp, qq, x, 0.0_dp, res_trial, &
831 filter_eps=eps_filter)
832 CALL dbcsr_multiply("N", "N", +1.0_dp, res_trial, oo, 1.0_dp, res, &
833 filter_eps=eps_filter)
834 ELSE
835 CALL dbcsr_multiply("N", "N", +1.0_dp, qq, x, 1.0_dp, res, &
836 filter_eps=eps_filter)
837 END IF
838 IF (present_vv) THEN
839 CALL dbcsr_multiply("N", "N", -1.0_dp, x, pp, 0.0_dp, res_trial, &
840 filter_eps=eps_filter)
841 CALL dbcsr_multiply("N", "N", +1.0_dp, vv, res_trial, 1.0_dp, res, &
842 filter_eps=eps_filter)
843 ELSE
844 CALL dbcsr_multiply("N", "N", -1.0_dp, x, pp, 1.0_dp, res, &
845 filter_eps=eps_filter)
846 END IF
847 IF (quadratic_term) THEN
848 IF (present_oo) THEN
849 CALL dbcsr_multiply("N", "N", +1.0_dp, pq, x, 0.0_dp, oo1, &
850 filter_eps=eps_filter)
851 CALL dbcsr_multiply("N", "N", +1.0_dp, oo1, oo, 0.0_dp, oo2, &
852 filter_eps=eps_filter)
853 ELSE
854 CALL dbcsr_multiply("N", "N", +1.0_dp, pq, x, 0.0_dp, oo2, &
855 filter_eps=eps_filter)
856 END IF
857 IF (present_vv) THEN
858 CALL dbcsr_multiply("N", "N", -1.0_dp, x, oo2, 0.0_dp, res_trial, &
859 filter_eps=eps_filter)
860 CALL dbcsr_multiply("N", "N", +1.0_dp, vv, res_trial, 1.0_dp, res, &
861 filter_eps=eps_filter)
862 ELSE
863 CALL dbcsr_multiply("N", "N", -1.0_dp, x, oo2, 1.0_dp, res, &
864 filter_eps=eps_filter)
865 END IF
866 END IF
867 CALL dbcsr_norm(res, dbcsr_norm_maxabsnorm, norm_scalar=best_norm)
868 ELSE
869 CALL dbcsr_add(res, m, 1.0_dp, best_step_size)
870 CALL dbcsr_add(res, n, 1.0_dp, -best_step_size*best_step_size)
871 CALL dbcsr_filter(res, eps_filter)
872 END IF
873
874 ! check convergence and other exit criteria
875 converged = (best_norm .LT. eps_convergence)
876 IF (converged .OR. (iteration .GE. max_iter)) THEN
877 prepare_to_exit = .true.
878 END IF
879
880 IF (.NOT. prepare_to_exit) THEN
881
882 ! update aux1=-pp-pq.x.oo and aux2=qq-vv.x.pq
883 IF (quadratic_term) THEN
884 IF (iteration .EQ. 0) THEN
885 IF (present_oo) THEN
886 CALL dbcsr_multiply("N", "N", -1.0_dp, pq, x, 0.0_dp, oo1, &
887 filter_eps=eps_filter)
888 CALL dbcsr_multiply("N", "N", +1.0_dp, oo1, oo, 1.0_dp, aux1, &
889 filter_eps=eps_filter)
890 ELSE
891 CALL dbcsr_multiply("N", "N", -1.0_dp, pq, x, 1.0_dp, aux1, &
892 filter_eps=eps_filter)
893 END IF
894 IF (present_vv) THEN
895 CALL dbcsr_multiply("N", "N", -1.0_dp, vv, x, 0.0_dp, res_trial, &
896 filter_eps=eps_filter)
897 CALL dbcsr_multiply("N", "N", +1.0_dp, res_trial, pq, 1.0_dp, aux2, &
898 filter_eps=eps_filter)
899 ELSE
900 CALL dbcsr_multiply("N", "N", -1.0_dp, x, pq, 1.0_dp, aux2, &
901 filter_eps=eps_filter)
902 END IF
903 ELSE
904 IF (present_oo) THEN
905 CALL dbcsr_multiply("N", "N", -best_step_size, pq, step_oo, 1.0_dp, aux1, &
906 filter_eps=eps_filter)
907 ELSE
908 CALL dbcsr_multiply("N", "N", -best_step_size, pq, step, 1.0_dp, aux1, &
909 filter_eps=eps_filter)
910 END IF
911 IF (present_vv) THEN
912 CALL dbcsr_multiply("N", "N", -best_step_size, vv_step, pq, 1.0_dp, aux2, &
913 filter_eps=eps_filter)
914 ELSE
915 CALL dbcsr_multiply("N", "N", -best_step_size, step, pq, 1.0_dp, aux2, &
916 filter_eps=eps_filter)
917 END IF
918 END IF
919 END IF
920
921 ! recompute the gradient, do not update it yet
922 ! use m matrix as a temporary storage
923 ! grad=t(vv).res.t(aux1)+t(aux2).res.t(oo)
924 IF (present_vv) THEN
925 CALL dbcsr_multiply("N", "T", 1.0_dp, res, aux1, 0.0_dp, res_trial, &
926 filter_eps=eps_filter)
927 CALL dbcsr_multiply("T", "N", 1.0_dp, vv, res_trial, 0.0_dp, m, &
928 filter_eps=eps_filter)
929 ELSE
930 CALL dbcsr_multiply("N", "T", 1.0_dp, res, aux1, 0.0_dp, m, &
931 filter_eps=eps_filter)
932 END IF
933 IF (present_oo) THEN
934 CALL dbcsr_multiply("T", "N", 1.0_dp, aux1, res, 0.0_dp, res_trial, &
935 filter_eps=eps_filter)
936 CALL dbcsr_multiply("N", "T", 1.0_dp, res_trial, oo, 1.0_dp, m, &
937 filter_eps=eps_filter)
938 ELSE
939 CALL dbcsr_multiply("T", "N", 1.0_dp, aux2, res, 1.0_dp, m, &
940 filter_eps=eps_filter)
941 END IF
942
943 ! compute preconditioner
944 !IF (iteration.eq.0.OR.(mod(iteration,update_prec_freq).eq.0)) THEN
945 IF (iteration .EQ. 0) THEN
946 CALL create_preconditioner(prec, aux1, aux2, eps_filter)
947 !restart_conjugator=.TRUE.
948!CALL dbcsr_set(prec,1.0_dp)
949!CALL dbcsr_print(prec)
950 END IF
951
952 ! compute the conjugation coefficient - beta
953 IF ((iteration .EQ. 0) .OR. restart_conjugator) THEN
954 beta = 0.0_dp
955 ELSE
956 restart_conjugator = .false.
957 SELECT CASE (conjugator)
959 CALL dbcsr_add(grad, m, -1.0_dp, 1.0_dp)
960 CALL dbcsr_hadamard_product(prec, grad, n)
961 CALL dbcsr_dot(n, m, numer)
962 CALL dbcsr_dot(grad, step, denom)
963 beta = numer/denom
964 CASE (cg_fletcher_reeves)
965 CALL dbcsr_hadamard_product(prec, grad, n)
966 CALL dbcsr_dot(grad, n, denom)
967 CALL dbcsr_hadamard_product(prec, m, n)
968 CALL dbcsr_dot(m, n, numer)
969 beta = numer/denom
970 CASE (cg_polak_ribiere)
971 CALL dbcsr_hadamard_product(prec, grad, n)
972 CALL dbcsr_dot(grad, n, denom)
973 CALL dbcsr_add(grad, m, -1.0_dp, 1.0_dp)
974 CALL dbcsr_hadamard_product(prec, grad, n)
975 CALL dbcsr_dot(n, m, numer)
976 beta = numer/denom
977 CASE (cg_fletcher)
978 CALL dbcsr_hadamard_product(prec, m, n)
979 CALL dbcsr_dot(m, n, numer)
980 CALL dbcsr_dot(grad, step, denom)
981 beta = -1.0_dp*numer/denom
982 CASE (cg_liu_storey)
983 CALL dbcsr_dot(grad, step, denom)
984 CALL dbcsr_add(grad, m, -1.0_dp, 1.0_dp)
985 CALL dbcsr_hadamard_product(prec, grad, n)
986 CALL dbcsr_dot(n, m, numer)
987 beta = -1.0_dp*numer/denom
988 CASE (cg_dai_yuan)
989 CALL dbcsr_hadamard_product(prec, m, n)
990 CALL dbcsr_dot(m, n, numer)
991 CALL dbcsr_add(grad, m, -1.0_dp, 1.0_dp)
992 CALL dbcsr_dot(grad, step, denom)
993 beta = numer/denom
994 CASE (cg_hager_zhang)
995 CALL dbcsr_add(grad, m, -1.0_dp, 1.0_dp)
996 CALL dbcsr_dot(grad, step, denom)
997 CALL dbcsr_hadamard_product(prec, grad, n)
998 CALL dbcsr_dot(n, grad, numer)
999 kappa = 2.0_dp*numer/denom
1000 CALL dbcsr_dot(n, m, numer)
1001 tau = numer/denom
1002 CALL dbcsr_dot(step, m, numer)
1003 beta = tau - kappa*numer/denom
1004 CASE (cg_zero)
1005 beta = 0.0_dp
1006 CASE DEFAULT
1007 cpabort("illegal conjugator")
1008 END SELECT
1009 END IF ! iteration.eq.0
1010
1011 ! move the current gradient to its storage
1012 CALL dbcsr_copy(grad, m)
1013
1014 ! precondition new gradient (use m as tmp storage)
1015 CALL dbcsr_hadamard_product(prec, grad, m)
1016 CALL dbcsr_filter(m, eps_filter)
1017
1018 ! recompute the step direction
1019 CALL dbcsr_add(step, m, beta, -1.0_dp)
1020 CALL dbcsr_filter(step, eps_filter)
1021
1022!! ALTERNATIVE METHOD TO OBTAIN THE STEP FROM THE GRADIENT
1023!CALL dbcsr_init(qqqq)
1024!CALL dbcsr_create(qqqq,template=qq)
1025!CALL dbcsr_init(pppp)
1026!CALL dbcsr_create(pppp,template=pp)
1027!CALL dbcsr_init(zero_pq)
1028!CALL dbcsr_create(zero_pq,template=pq)
1029!CALL dbcsr_init(zero_qp)
1030!CALL dbcsr_create(zero_qp,template=qp)
1031!CALL dbcsr_multiply("T","N",1.0_dp,aux2,aux2,0.0_dp,qqqq,&
1032! filter_eps=eps_filter)
1033!CALL dbcsr_multiply("N","T",-1.0_dp,aux1,aux1,0.0_dp,pppp,&
1034! filter_eps=eps_filter)
1035!CALL dbcsr_set(zero_qp,0.0_dp)
1036!CALL dbcsr_set(zero_pq,0.0_dp)
1037!CALL solve_riccati_equation(pppp,qqqq,grad,zero_pq,zero_qp,zero_qp,&
1038! .TRUE.,tensor_type,&
1039! conjugator,max_iter,eps_convergence,eps_filter,&
1040! converged,level+1)
1041!CALL dbcsr_release(qqqq)
1042!CALL dbcsr_release(pppp)
1043!CALL dbcsr_release(zero_qp)
1044!CALL dbcsr_release(zero_pq)
1045
1046 ! calculate the optimal step size
1047 ! m=step.aux1+aux2.step
1048 IF (present_vv) THEN
1049 CALL dbcsr_multiply("N", "N", 1.0_dp, vv, step, 0.0_dp, vv_step, &
1050 filter_eps=eps_filter)
1051 CALL dbcsr_multiply("N", "N", 1.0_dp, vv_step, aux1, 0.0_dp, m, &
1052 filter_eps=eps_filter)
1053 ELSE
1054 CALL dbcsr_multiply("N", "N", 1.0_dp, step, aux1, 0.0_dp, m, &
1055 filter_eps=eps_filter)
1056 END IF
1057 IF (present_oo) THEN
1058 CALL dbcsr_multiply("N", "N", 1.0_dp, step, oo, 0.0_dp, step_oo, &
1059 filter_eps=eps_filter)
1060 CALL dbcsr_multiply("N", "N", 1.0_dp, aux2, step_oo, 1.0_dp, m, &
1061 filter_eps=eps_filter)
1062 ELSE
1063 CALL dbcsr_multiply("N", "N", 1.0_dp, aux2, step, 1.0_dp, m, &
1064 filter_eps=eps_filter)
1065 END IF
1066
1067 IF (quadratic_term) THEN
1068 ! n=step.pq.step
1069 IF (present_oo) THEN
1070 CALL dbcsr_multiply("N", "N", 1.0_dp, pq, step, 0.0_dp, oo1, &
1071 filter_eps=eps_filter)
1072 CALL dbcsr_multiply("N", "N", 1.0_dp, oo1, oo, 0.0_dp, oo2, &
1073 filter_eps=eps_filter)
1074 ELSE
1075 CALL dbcsr_multiply("N", "N", 1.0_dp, pq, step, 0.0_dp, oo2, &
1076 filter_eps=eps_filter)
1077 END IF
1078 IF (present_vv) THEN
1079 CALL dbcsr_multiply("N", "N", 1.0_dp, step, oo2, 0.0_dp, res_trial, &
1080 filter_eps=eps_filter)
1081 CALL dbcsr_multiply("N", "N", 1.0_dp, vv, res_trial, 0.0_dp, n, &
1082 filter_eps=eps_filter)
1083 ELSE
1084 CALL dbcsr_multiply("N", "N", 1.0_dp, step, oo2, 0.0_dp, n, &
1085 filter_eps=eps_filter)
1086 END IF
1087
1088 ELSE
1089 CALL dbcsr_set(n, 0.0_dp)
1090 END IF
1091
1092 ! calculate coefficients of the cubic eq for alpha - step size
1093 c0 = 2.0_dp*(dbcsr_frobenius_norm(n))**2
1094
1095 CALL dbcsr_dot(m, n, c1)
1096 c1 = -3.0_dp*c1
1097
1098 CALL dbcsr_dot(res, n, c2)
1099 c2 = -2.0_dp*c2 + (dbcsr_frobenius_norm(m))**2
1100
1101 CALL dbcsr_dot(res, m, c3)
1102
1103 ! find step size
1104 CALL analytic_line_search(c0, c1, c2, c3, step_size, nsteps)
1105
1106 IF (nsteps .EQ. 0) THEN
1107 cpabort("no step sizes!")
1108 END IF
1109 ! if we have several possible step sizes
1110 ! choose one with the lowest objective function
1111 best_norm = 1.0e+100_dp
1112 best_step_size = 0.0_dp
1113 DO istep = 1, nsteps
1114 ! recompute the residues
1115 CALL dbcsr_copy(res_trial, res)
1116 CALL dbcsr_add(res_trial, m, 1.0_dp, step_size(istep))
1117 CALL dbcsr_add(res_trial, n, 1.0_dp, -step_size(istep)*step_size(istep))
1118 CALL dbcsr_filter(res_trial, eps_filter)
1119 ! RZK-warning objective function might be different in the case of
1120 ! tensor_up_down
1121 !obj_function=0.5_dp*(dbcsr_frobenius_norm(res_trial))**2
1122 CALL dbcsr_norm(res_trial, dbcsr_norm_maxabsnorm, norm_scalar=obj_function)
1123 IF (obj_function .LT. best_norm) THEN
1124 best_norm = obj_function
1125 best_step_size = step_size(istep)
1126 END IF
1127 END DO
1128
1129 END IF
1130
1131 ! update X along the line
1132 CALL dbcsr_add(x, step, 1.0_dp, best_step_size)
1133 CALL dbcsr_filter(x, eps_filter)
1134
1135 ! evaluate current energy correction
1136 !change_ecorr=ecorr
1137 !CALL dbcsr_dot(qp,x,ecorr,"T","N")
1138 !change_ecorr=ecorr-change_ecorr
1139
1140 ! check convergence and other exit criteria
1141 converged = (best_norm .LT. eps_convergence)
1142 IF (converged .OR. (iteration .GE. max_iter)) THEN
1143 prepare_to_exit = .true.
1144 END IF
1145
1146 t2 = m_walltime()
1147
1148 IF (unit_nr > 0) THEN
1149 WRITE (unit_nr, '(T6,A,1X,I4,1X,E12.3,F8.3)') &
1150 "RICCATI iter ", iteration, best_norm, t2 - t1
1151 !WRITE(unit_nr,'(T6,A,1X,I4,1X,F15.9,F15.9,E12.3,F8.3)') &
1152 ! "RICCATI iter ",iteration,ecorr,change_ecorr,best_norm,t2-t1
1153 END IF
1154
1155 t1 = m_walltime()
1156
1157 iteration = iteration + 1
1158
1159 IF (prepare_to_exit) EXIT
1160
1161 END DO
1162
1163 CALL dbcsr_release(aux1)
1164 CALL dbcsr_release(aux2)
1165 CALL dbcsr_release(grad)
1166 CALL dbcsr_release(step)
1167 CALL dbcsr_release(n)
1168 CALL dbcsr_release(m)
1169 CALL dbcsr_release(oo1)
1170 CALL dbcsr_release(oo2)
1171 CALL dbcsr_release(res_trial)
1172 CALL dbcsr_release(vv_step)
1173 CALL dbcsr_release(step_oo)
1174
1175 CALL timestop(handle)
1176
1177 END SUBROUTINE solve_riccati_equation
1178
1179! **************************************************************************************************
1180!> \brief Computes a preconditioner from diagonal elements of ~f_oo, ~f_vv
1181!> The preconditioner is approximately equal to
1182!> prec_ai ~ (e_a - e_i)^(-2)
1183!> However, the real expression is more complex
1184!> \param prec ...
1185!> \param pp ...
1186!> \param qq ...
1187!> \param eps_filter ...
1188!> \par History
1189!> 2011.07 created [Rustam Z Khaliullin]
1190!> \author Rustam Z Khaliullin
1191! **************************************************************************************************
1192 SUBROUTINE create_preconditioner(prec, pp, qq, eps_filter)
1193
1194 TYPE(dbcsr_type), INTENT(OUT) :: prec
1195 TYPE(dbcsr_type), INTENT(IN) :: pp, qq
1196 REAL(kind=dp), INTENT(IN) :: eps_filter
1197
1198 CHARACTER(len=*), PARAMETER :: routinen = 'create_preconditioner'
1199
1200 INTEGER :: col, handle, hold, iblock_col, &
1201 iblock_row, mynode, nblkcols_tot, &
1202 nblkrows_tot, p_nrows, q_nrows, row
1203 LOGICAL :: tr
1204 REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: p_diagonal, q_diagonal
1205 REAL(kind=dp), DIMENSION(:, :), POINTER :: p_new_block
1206 TYPE(dbcsr_distribution_type) :: dist
1207 TYPE(dbcsr_type) :: pp_diag, qq_diag, t1, t2, tmp
1208
1209!LOGICAL, INTENT(IN) :: use_virt_orbs
1210
1211 CALL timeset(routinen, handle)
1212
1213! ! copy diagonal elements
1214! CALL dbcsr_get_info(pp,nfullrows_total=nrows)
1215! CALL dbcsr_init(pp_diag)
1216! CALL dbcsr_create(pp_diag,template=pp)
1217! ALLOCATE(diagonal(nrows))
1218! CALL dbcsr_get_diag(pp,diagonal)
1219! CALL dbcsr_add_on_diag(pp_diag,1.0_dp)
1220! CALL dbcsr_set_diag(pp_diag,diagonal)
1221! DEALLOCATE(diagonal)
1222!
1223 ! initialize a matrix to 1.0
1224 CALL dbcsr_create(tmp, template=prec)
1225 ! use an ugly hack to set all elements of tmp to 1
1226 ! because dbcsr_set does not do it (despite its name)
1227 !CALL dbcsr_set(tmp,1.0_dp)
1228 CALL dbcsr_get_info(tmp, distribution=dist)
1229 CALL dbcsr_distribution_get(dist, mynode=mynode)
1230 CALL dbcsr_work_create(tmp, work_mutable=.true.)
1231 nblkrows_tot = dbcsr_nblkrows_total(tmp)
1232 nblkcols_tot = dbcsr_nblkcols_total(tmp)
1233 DO row = 1, nblkrows_tot
1234 DO col = 1, nblkcols_tot
1235 tr = .false.
1236 iblock_row = row
1237 iblock_col = col
1238 CALL dbcsr_get_stored_coordinates(tmp, iblock_row, iblock_col, hold)
1239 IF (hold .EQ. mynode) THEN
1240 NULLIFY (p_new_block)
1241 CALL dbcsr_reserve_block2d(tmp, iblock_row, iblock_col, p_new_block)
1242 cpassert(ASSOCIATED(p_new_block))
1243 p_new_block(:, :) = 1.0_dp
1244 END IF ! mynode
1245 END DO
1246 END DO
1247 CALL dbcsr_finalize(tmp)
1248
1249 ! copy diagonal elements of pp into cols of a matrix
1250 CALL dbcsr_get_info(pp, nfullrows_total=p_nrows)
1251 CALL dbcsr_create(pp_diag, template=pp)
1252 ALLOCATE (p_diagonal(p_nrows))
1253 CALL dbcsr_get_diag(pp, p_diagonal)
1254 CALL dbcsr_add_on_diag(pp_diag, 1.0_dp)
1255 CALL dbcsr_set_diag(pp_diag, p_diagonal)
1256 ! RZK-warning is it possible to use dbcsr_scale_by_vector?
1257 ! or even insert elements directly in the prev cycles
1258 CALL dbcsr_create(t2, template=prec)
1259 CALL dbcsr_multiply("N", "N", 1.0_dp, tmp, pp_diag, &
1260 0.0_dp, t2, filter_eps=eps_filter)
1261
1262 ! copy diagonal elements qq into rows of a matrix
1263 CALL dbcsr_get_info(qq, nfullrows_total=q_nrows)
1264 CALL dbcsr_create(qq_diag, template=qq)
1265 ALLOCATE (q_diagonal(q_nrows))
1266 CALL dbcsr_get_diag(qq, q_diagonal)
1267 CALL dbcsr_add_on_diag(qq_diag, 1.0_dp)
1268 CALL dbcsr_set_diag(qq_diag, q_diagonal)
1269 CALL dbcsr_set(tmp, 1.0_dp)
1270 CALL dbcsr_create(t1, template=prec)
1271 CALL dbcsr_multiply("N", "N", 1.0_dp, qq_diag, tmp, &
1272 0.0_dp, t1, filter_eps=eps_filter)
1273
1274 CALL dbcsr_hadamard_product(t1, t2, prec)
1275 CALL dbcsr_release(t1)
1276 CALL dbcsr_scale(prec, 2.0_dp)
1277
1278 ! Get the diagonal of tr(qq).qq
1279 CALL dbcsr_multiply("T", "N", 1.0_dp, qq, qq, &
1280 0.0_dp, qq_diag, retain_sparsity=.true., &
1281 filter_eps=eps_filter)
1282 CALL dbcsr_get_diag(qq_diag, q_diagonal)
1283 CALL dbcsr_set(qq_diag, 0.0_dp)
1284 CALL dbcsr_add_on_diag(qq_diag, 1.0_dp)
1285 CALL dbcsr_set_diag(qq_diag, q_diagonal)
1286 DEALLOCATE (q_diagonal)
1287 CALL dbcsr_set(tmp, 1.0_dp)
1288 CALL dbcsr_multiply("N", "N", 1.0_dp, qq_diag, tmp, &
1289 0.0_dp, t2, filter_eps=eps_filter)
1290 CALL dbcsr_release(qq_diag)
1291 CALL dbcsr_add(prec, t2, 1.0_dp, 1.0_dp)
1292
1293 ! Get the diagonal of pp.tr(pp)
1294 CALL dbcsr_multiply("N", "T", 1.0_dp, pp, pp, &
1295 0.0_dp, pp_diag, retain_sparsity=.true., &
1296 filter_eps=eps_filter)
1297 CALL dbcsr_get_diag(pp_diag, p_diagonal)
1298 CALL dbcsr_set(pp_diag, 0.0_dp)
1299 CALL dbcsr_add_on_diag(pp_diag, 1.0_dp)
1300 CALL dbcsr_set_diag(pp_diag, p_diagonal)
1301 DEALLOCATE (p_diagonal)
1302 CALL dbcsr_set(tmp, 1.0_dp)
1303 CALL dbcsr_multiply("N", "N", 1.0_dp, tmp, pp_diag, &
1304 0.0_dp, t2, filter_eps=eps_filter)
1305 CALL dbcsr_release(tmp)
1306 CALL dbcsr_release(pp_diag)
1307 CALL dbcsr_add(prec, t2, 1.0_dp, 1.0_dp)
1308
1309 ! now add the residual component
1310 !CALL dbcsr_hadamard_product(res,qp,t2)
1311 !CALL dbcsr_add(prec,t2,1.0_dp,-2.0_dp)
1312 CALL dbcsr_release(t2)
1313 CALL dbcsr_function_of_elements(prec, func=dbcsr_func_inverse)
1314 CALL dbcsr_filter(prec, eps_filter)
1315
1316 CALL timestop(handle)
1317
1318 END SUBROUTINE create_preconditioner
1319
1320! **************************************************************************************************
1321!> \brief Finds real roots of a cubic equation
1322!> > a*x**3 + b*x**2 + c*x + d = 0
1323!> and returns only those roots for which the derivative is positive
1324!>
1325!> Step 0: Check the true order of the equation. Cubic, quadratic, linear?
1326!> Step 1: Calculate p and q
1327!> p = ( 3*c/a - (b/a)**2 ) / 3
1328!> q = ( 2*(b/a)**3 - 9*b*c/a/a + 27*d/a ) / 27
1329!> Step 2: Calculate discriminant D
1330!> D = (p/3)**3 + (q/2)**2
1331!> Step 3: Depending on the sign of D, we follow different strategy.
1332!> If D<0, three distinct real roots.
1333!> If D=0, three real roots of which at least two are equal.
1334!> If D>0, one real and two complex roots.
1335!> Step 3a: For D>0 and D=0,
1336!> Calculate u and v
1337!> u = cubic_root(-q/2 + sqrt(D))
1338!> v = cubic_root(-q/2 - sqrt(D))
1339!> Find the three transformed roots
1340!> y1 = u + v
1341!> y2 = -(u+v)/2 + i (u-v)*sqrt(3)/2
1342!> y3 = -(u+v)/2 - i (u-v)*sqrt(3)/2
1343!> Step 3b Alternately, for D<0, a trigonometric formulation is more convenient
1344!> y1 = 2 * sqrt(|p|/3) * cos(phi/3)
1345!> y2 = -2 * sqrt(|p|/3) * cos((phi+pi)/3)
1346!> y3 = -2 * sqrt(|p|/3) * cos((phi-pi)/3)
1347!> where phi = acos(-q/2/sqrt(|p|**3/27))
1348!> pi = 3.141592654...
1349!> Step 4 Find the real roots
1350!> x = y - b/a/3
1351!> Step 5 Check the derivative and return only those real roots
1352!> for which the derivative is positive
1353!>
1354!> \param a ...
1355!> \param b ...
1356!> \param c ...
1357!> \param d ...
1358!> \param minima ...
1359!> \param nmins ...
1360!> \par History
1361!> 2011.06 created [Rustam Z Khaliullin]
1362!> \author Rustam Z Khaliullin
1363! **************************************************************************************************
1364 SUBROUTINE analytic_line_search(a, b, c, d, minima, nmins)
1365
1366 REAL(kind=dp), INTENT(IN) :: a, b, c, d
1367 REAL(kind=dp), DIMENSION(3), INTENT(OUT) :: minima
1368 INTEGER, INTENT(OUT) :: nmins
1369
1370 INTEGER :: i, nroots
1371 REAL(kind=dp) :: dd, der, p, phi, pi, q, temp1, temp2, u, &
1372 v, y1, y2, y2i, y2r, y3
1373 REAL(kind=dp), DIMENSION(3) :: x
1374
1375! CALL timeset(routineN,handle)
1376
1377 pi = acos(-1.0_dp)
1378
1379 ! Step 0: Check coefficients and find the true order of the eq
1380 IF (a .EQ. 0.0_dp) THEN
1381 IF (b .EQ. 0.0_dp) THEN
1382 IF (c .EQ. 0.0_dp) THEN
1383 ! Non-equation, no valid solutions
1384 nroots = 0
1385 ELSE
1386 ! Linear equation with one root.
1387 nroots = 1
1388 x(1) = -d/c
1389 END IF
1390 ELSE
1391 ! Quadratic equation with max two roots.
1392 dd = c*c - 4.0_dp*b*d
1393 IF (dd .GT. 0.0_dp) THEN
1394 nroots = 2
1395 x(1) = (-c + sqrt(dd))/2.0_dp/b
1396 x(2) = (-c - sqrt(dd))/2.0_dp/b
1397 ELSE IF (dd .LT. 0.0_dp) THEN
1398 nroots = 0
1399 ELSE
1400 nroots = 1
1401 x(1) = -c/2.0_dp/b
1402 END IF
1403 END IF
1404 ELSE
1405 ! Cubic equation with max three roots
1406 ! Calculate p and q
1407 p = c/a - b*b/a/a/3.0_dp
1408 q = (2.0_dp*b*b*b/a/a/a - 9.0_dp*b*c/a/a + 27.0_dp*d/a)/27.0_dp
1409
1410 ! Calculate DD
1411 dd = p*p*p/27.0_dp + q*q/4.0_dp
1412
1413 IF (dd .LT. 0.0_dp) THEN
1414 ! three real unequal roots -- use the trigonometric formulation
1415 phi = acos(-q/2.0_dp/sqrt(abs(p*p*p)/27.0_dp))
1416 temp1 = 2.0_dp*sqrt(abs(p)/3.0_dp)
1417 y1 = temp1*cos(phi/3.0_dp)
1418 y2 = -temp1*cos((phi + pi)/3.0_dp)
1419 y3 = -temp1*cos((phi - pi)/3.0_dp)
1420 ELSE
1421 ! 1 real & 2 conjugate complex roots OR 3 real roots (some are equal)
1422 temp1 = -q/2.0_dp + sqrt(dd)
1423 temp2 = -q/2.0_dp - sqrt(dd)
1424 u = abs(temp1)**(1.0_dp/3.0_dp)
1425 v = abs(temp2)**(1.0_dp/3.0_dp)
1426 IF (temp1 .LT. 0.0_dp) u = -u
1427 IF (temp2 .LT. 0.0_dp) v = -v
1428 y1 = u + v
1429 y2r = -(u + v)/2.0_dp
1430 y2i = (u - v)*sqrt(3.0_dp)/2.0_dp
1431 END IF
1432
1433 ! Final transformation
1434 temp1 = b/a/3.0_dp
1435 y1 = y1 - temp1
1436 y2 = y2 - temp1
1437 y3 = y3 - temp1
1438 y2r = y2r - temp1
1439
1440 ! Assign answers
1441 IF (dd .LT. 0.0_dp) THEN
1442 nroots = 3
1443 x(1) = y1
1444 x(2) = y2
1445 x(3) = y3
1446 ELSE IF (dd .EQ. 0.0_dp) THEN
1447 nroots = 2
1448 x(1) = y1
1449 x(2) = y2r
1450 !x(3) = cmplx(y2r, 0.)
1451 ELSE
1452 nroots = 1
1453 x(1) = y1
1454 !x(2) = cmplx(y2r, y2i)
1455 !x(3) = cmplx(y2r,-y2i)
1456 END IF
1457
1458 END IF
1459
1460!write(*,'(i2,a)') nroots, ' real root(s)'
1461 nmins = 0
1462 DO i = 1, nroots
1463 ! maximum or minimum? use the derivative
1464 ! 3*a*x**2+2*b*x+c
1465 der = 3.0_dp*a*x(i)*x(i) + 2.0_dp*b*x(i) + c
1466 IF (der .GT. 0.0_dp) THEN
1467 nmins = nmins + 1
1468 minima(nmins) = x(i)
1469!write(*,'(a,i2,a,f10.5)') 'Minimum ', i, ', value: ', x(i)
1470 END IF
1471 END DO
1472
1473! CALL timestop(handle)
1474
1475 END SUBROUTINE analytic_line_search
1476
1477! **************************************************************************************************
1478!> \brief Diagonalizes diagonal blocks of a symmetric dbcsr matrix
1479!> and returs its eigenvectors
1480!> \param matrix ...
1481!> \param c ...
1482!> \param e ...
1483!> \par History
1484!> 2011.07 created [Rustam Z Khaliullin]
1485!> \author Rustam Z Khaliullin
1486! **************************************************************************************************
1487 SUBROUTINE diagonalize_diagonal_blocks(matrix, c, e)
1488
1489 TYPE(dbcsr_type), INTENT(IN) :: matrix
1490 TYPE(dbcsr_type), INTENT(OUT) :: c
1491 TYPE(dbcsr_type), INTENT(OUT), OPTIONAL :: e
1492
1493 CHARACTER(len=*), PARAMETER :: routinen = 'diagonalize_diagonal_blocks'
1494
1495 INTEGER :: handle, iblock_col, iblock_row, &
1496 iblock_size, info, lwork, orbital
1497 LOGICAL :: block_needed, do_eigenvalues
1498 REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: eigenvalues, work
1499 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :) :: data_copy
1500 REAL(kind=dp), DIMENSION(:, :), POINTER :: data_p, p_new_block
1501 TYPE(dbcsr_iterator_type) :: iter
1502
1503 CALL timeset(routinen, handle)
1504
1505 IF (PRESENT(e)) THEN
1506 do_eigenvalues = .true.
1507 ELSE
1508 do_eigenvalues = .false.
1509 END IF
1510
1511 ! create a matrix for eigenvectors
1512 CALL dbcsr_work_create(c, work_mutable=.true.)
1513 IF (do_eigenvalues) &
1514 CALL dbcsr_work_create(e, work_mutable=.true.)
1515
1516 CALL dbcsr_iterator_start(iter, matrix)
1517
1518 DO WHILE (dbcsr_iterator_blocks_left(iter))
1519
1520 CALL dbcsr_iterator_next_block(iter, iblock_row, iblock_col, data_p, row_size=iblock_size)
1521
1522 block_needed = .false.
1523 IF (iblock_row == iblock_col) block_needed = .true.
1524
1525 IF (block_needed) THEN
1526
1527 ! Prepare data
1528 ALLOCATE (eigenvalues(iblock_size))
1529 ALLOCATE (data_copy(iblock_size, iblock_size))
1530 data_copy(:, :) = data_p(:, :)
1531
1532 ! Query the optimal workspace for dsyev
1533 lwork = -1
1534 ALLOCATE (work(max(1, lwork)))
1535 CALL dsyev('V', 'L', iblock_size, data_copy, iblock_size, eigenvalues, work, lwork, info)
1536 lwork = int(work(1))
1537 DEALLOCATE (work)
1538
1539 ! Allocate the workspace and solve the eigenproblem
1540 ALLOCATE (work(max(1, lwork)))
1541 CALL dsyev('V', 'L', iblock_size, data_copy, iblock_size, eigenvalues, work, lwork, info)
1542 IF (info .NE. 0) THEN
1543 cpabort("DSYEV failed")
1544 END IF
1545
1546 ! copy eigenvectors into a cp_dbcsr matrix
1547 NULLIFY (p_new_block)
1548 CALL dbcsr_reserve_block2d(c, iblock_row, iblock_col, p_new_block)
1549 cpassert(ASSOCIATED(p_new_block))
1550 p_new_block(:, :) = data_copy(:, :)
1551
1552 ! if requested copy eigenvalues into a cp_dbcsr matrix
1553 IF (do_eigenvalues) THEN
1554 NULLIFY (p_new_block)
1555 CALL dbcsr_reserve_block2d(e, iblock_row, iblock_col, p_new_block)
1556 cpassert(ASSOCIATED(p_new_block))
1557 p_new_block(:, :) = 0.0_dp
1558 DO orbital = 1, iblock_size
1559 p_new_block(orbital, orbital) = eigenvalues(orbital)
1560 END DO
1561 END IF
1562
1563 DEALLOCATE (work)
1564 DEALLOCATE (data_copy)
1565 DEALLOCATE (eigenvalues)
1566
1567 END IF
1568
1569 END DO
1570
1571 CALL dbcsr_iterator_stop(iter)
1572
1573 CALL dbcsr_finalize(c)
1574 IF (do_eigenvalues) CALL dbcsr_finalize(e)
1575
1576 CALL timestop(handle)
1577
1578 END SUBROUTINE diagonalize_diagonal_blocks
1579
1580! **************************************************************************************************
1581!> \brief Transforms a matrix M_out = tr(U1) * M_in * U2
1582!> \param matrix ...
1583!> \param u1 ...
1584!> \param u2 ...
1585!> \param eps_filter ...
1586!> \par History
1587!> 2011.10 created [Rustam Z Khaliullin]
1588!> \author Rustam Z Khaliullin
1589! **************************************************************************************************
1590 SUBROUTINE matrix_forward_transform(matrix, u1, u2, eps_filter)
1591
1592 TYPE(dbcsr_type), INTENT(INOUT) :: matrix
1593 TYPE(dbcsr_type), INTENT(IN) :: u1, u2
1594 REAL(kind=dp), INTENT(IN) :: eps_filter
1595
1596 CHARACTER(len=*), PARAMETER :: routinen = 'matrix_forward_transform'
1597
1598 INTEGER :: handle
1599 TYPE(dbcsr_type) :: tmp
1600
1601 CALL timeset(routinen, handle)
1602
1603 CALL dbcsr_create(tmp, template=matrix, &
1604 matrix_type=dbcsr_type_no_symmetry)
1605 CALL dbcsr_multiply("N", "N", 1.0_dp, matrix, u2, 0.0_dp, tmp, &
1606 filter_eps=eps_filter)
1607 CALL dbcsr_multiply("T", "N", 1.0_dp, u1, tmp, 0.0_dp, matrix, &
1608 filter_eps=eps_filter)
1609 CALL dbcsr_release(tmp)
1610
1611 CALL timestop(handle)
1612
1613 END SUBROUTINE matrix_forward_transform
1614
1615! **************************************************************************************************
1616!> \brief Transforms a matrix M_out = U1 * M_in * tr(U2)
1617!> \param matrix ...
1618!> \param u1 ...
1619!> \param u2 ...
1620!> \param eps_filter ...
1621!> \par History
1622!> 2011.10 created [Rustam Z Khaliullin]
1623!> \author Rustam Z Khaliullin
1624! **************************************************************************************************
1625 SUBROUTINE matrix_backward_transform(matrix, u1, u2, eps_filter)
1626
1627 TYPE(dbcsr_type), INTENT(INOUT) :: matrix
1628 TYPE(dbcsr_type), INTENT(IN) :: u1, u2
1629 REAL(kind=dp), INTENT(IN) :: eps_filter
1630
1631 CHARACTER(len=*), PARAMETER :: routinen = 'matrix_backward_transform'
1632
1633 INTEGER :: handle
1634 TYPE(dbcsr_type) :: tmp
1635
1636 CALL timeset(routinen, handle)
1637
1638 CALL dbcsr_create(tmp, template=matrix, &
1639 matrix_type=dbcsr_type_no_symmetry)
1640 CALL dbcsr_multiply("N", "T", 1.0_dp, matrix, u2, 0.0_dp, tmp, &
1641 filter_eps=eps_filter)
1642 CALL dbcsr_multiply("N", "N", 1.0_dp, u1, tmp, 0.0_dp, matrix, &
1643 filter_eps=eps_filter)
1644 CALL dbcsr_release(tmp)
1645
1646 CALL timestop(handle)
1647
1648 END SUBROUTINE matrix_backward_transform
1649
1650!! **************************************************************************************************
1651!!> \brief Transforms to a representation in which diagonal blocks
1652!!> of qq and pp matrices are diagonal. This can improve convergence
1653!!> of PCG
1654!!> \par History
1655!!> 2011.07 created [Rustam Z Khaliullin]
1656!!> \author Rustam Z Khaliullin
1657!! **************************************************************************************************
1658! SUBROUTINE transform_matrices_to_blk_diag(matrix_pp,matrix_qq,matrix_qp,&
1659! matrix_pq,eps_filter)
1660!
1661! TYPE(dbcsr_type), INTENT(INOUT) :: matrix_pp, matrix_qq,&
1662! matrix_qp, matrix_pq
1663! REAL(KIND=dp), INTENT(IN) :: eps_filter
1664!
1665! CHARACTER(len=*), PARAMETER :: routineN = 'transform_matrices_to_blk_diag',&
1666! routineP = moduleN//':'//routineN
1667!
1668! TYPE(dbcsr_type) :: tmp_pp, tmp_qq,&
1669! tmp_qp, tmp_pq,&
1670! blk, blk2
1671! INTEGER :: handle
1672!
1673! CALL timeset(routineN,handle)
1674!
1675! ! find a better basis by diagonalizing diagonal blocks
1676! ! first pp
1677! CALL dbcsr_init(blk)
1678! CALL dbcsr_create(blk,template=matrix_pp)
1679! CALL diagonalize_diagonal_blocks(matrix_pp,blk)
1680!
1681! ! convert matrices to the new basis
1682! CALL dbcsr_init(tmp_pp)
1683! CALL dbcsr_create(tmp_pp,template=matrix_pp)
1684! CALL dbcsr_multiply("N","N",1.0_dp,matrix_pp,blk,0.0_dp,tmp_pp,&
1685! filter_eps=eps_filter)
1686! CALL dbcsr_multiply("T","N",1.0_dp,blk,tmp_pp,0.0_dp,matrix_pp,&
1687! filter_eps=eps_filter)
1688! CALL dbcsr_release(tmp_pp)
1689!
1690! ! now qq
1691! CALL dbcsr_init(blk2)
1692! CALL dbcsr_create(blk2,template=matrix_qq)
1693! CALL diagonalize_diagonal_blocks(matrix_qq,blk2)
1694!
1695! CALL dbcsr_init(tmp_qq)
1696! CALL dbcsr_create(tmp_qq,template=matrix_qq)
1697! CALL dbcsr_multiply("N","N",1.0_dp,matrix_qq,blk2,0.0_dp,tmp_qq,&
1698! filter_eps=eps_filter)
1699! CALL dbcsr_multiply("T","N",1.0_dp,blk2,tmp_qq,0.0_dp,matrix_qq,&
1700! filter_eps=eps_filter)
1701! CALL dbcsr_release(tmp_qq)
1702!
1703! ! transform pq
1704! CALL dbcsr_init(tmp_pq)
1705! CALL dbcsr_create(tmp_pq,template=matrix_pq)
1706! CALL dbcsr_multiply("T","N",1.0_dp,blk,matrix_pq,0.0_dp,tmp_pq,&
1707! filter_eps=eps_filter)
1708! CALL dbcsr_multiply("N","N",1.0_dp,tmp_pq,blk2,0.0_dp,matrix_pq,&
1709! filter_eps=eps_filter)
1710! CALL dbcsr_release(tmp_pq)
1711!
1712! ! transform qp
1713! CALL dbcsr_init(tmp_qp)
1714! CALL dbcsr_create(tmp_qp,template=matrix_qp)
1715! CALL dbcsr_multiply("N","N",1.0_dp,matrix_qp,blk,0.0_dp,tmp_qp,&
1716! filter_eps=eps_filter)
1717! CALL dbcsr_multiply("T","N",1.0_dp,blk2,tmp_qp,0.0_dp,matrix_qp,&
1718! filter_eps=eps_filter)
1719! CALL dbcsr_release(tmp_qp)
1720!
1721! CALL dbcsr_release(blk2)
1722! CALL dbcsr_release(blk)
1723!
1724! CALL timestop(handle)
1725!
1726! END SUBROUTINE transform_matrices_to_blk_diag
1727
1728! **************************************************************************************************
1729!> \brief computes oo, ov, vo, and vv blocks of the ks matrix
1730!> \par History
1731!> 2011.06 created [Rustam Z Khaliullin]
1732!> \author Rustam Z Khaliullin
1733! **************************************************************************************************
1734! SUBROUTINE ct_step_env_execute(env)
1735!
1736! TYPE(ct_step_env_type) :: env
1737!
1738! CHARACTER(len=*), PARAMETER :: routineN = 'ct_step_env_execute', &
1739! routineP = moduleN//':'//routineN
1740!
1741! INTEGER :: handle
1742!
1743! CALL timeset(routineN,handle)
1744!
1745!
1746! CALL timestop(handle)
1747!
1748! END SUBROUTINE ct_step_env_execute
1749
1750END MODULE ct_methods
1751
Interface to (sca)lapack for the Cholesky based procedures.
subroutine, public cp_dbcsr_cholesky_decompose(matrix, n, para_env, blacs_env)
used to replace a symmetric positive def. matrix M with its cholesky decomposition U: M = U^T * U,...
subroutine, public cp_dbcsr_cholesky_invert(matrix, n, para_env, blacs_env, upper_to_full)
used to replace the cholesky decomposition by the inverse
Interface to (sca)lapack for the Cholesky based procedures.
subroutine, public cp_dbcsr_syevd(matrix, eigenvectors, eigenvalues, para_env, blacs_env)
...
various routines to log and control the output. The idea is that decisions about where to log should ...
recursive integer function, public cp_logger_get_default_unit_nr(logger, local, skip_not_ionode)
asks the default unit number of the given logger. try to use cp_logger_get_unit_nr
type(cp_logger_type) function, pointer, public cp_get_default_logger()
returns the default logger
Cayley transformation methods.
Definition ct_methods.F:14
subroutine, public analytic_line_search(a, b, c, d, minima, nmins)
Finds real roots of a cubic equation ‍ a*x**3 + b*x**2 + c*x + d = 0 and returns only those roots for...
subroutine, public diagonalize_diagonal_blocks(matrix, c, e)
Diagonalizes diagonal blocks of a symmetric dbcsr matrix and returs its eigenvectors.
subroutine, public ct_step_execute(cts_env)
Performs Cayley transformation.
Definition ct_methods.F:59
Types for all cayley transformation methods.
Definition ct_types.F:14
collects all constants needed in input so that they can be used without circular dependencies
integer, parameter, public cg_hestenes_stiefel
integer, parameter, public cg_fletcher
integer, parameter, public cg_fletcher_reeves
integer, parameter, public tensor_up_down
integer, parameter, public tensor_orthogonal
integer, parameter, public cg_dai_yuan
integer, parameter, public cg_liu_storey
integer, parameter, public cg_hager_zhang
integer, parameter, public cg_zero
integer, parameter, public cg_polak_ribiere
Routines useful for iterative matrix calculations.
subroutine, public matrix_sqrt_newton_schulz(matrix_sqrt, matrix_sqrt_inv, matrix, threshold, order, eps_lanczos, max_iter_lanczos, symmetrize, converged)
compute the sqrt of a matrix via the sign function and the corresponding Newton-Schulz iterations the...
Defines the basic variable types.
Definition kinds.F:23
integer, parameter, public dp
Definition kinds.F:34
integer, parameter, public sp
Definition kinds.F:33
Machine interface based on Fortran 2003 and POSIX.
Definition machine.F:17
real(kind=dp) function, public m_walltime()
returns time from a real-time clock, protected against rolling early/easily
Definition machine.F:123
type of a logger, at the moment it contains just a print level starting at which level it should be l...
Orbital angular momentum.