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