(git:0a7030e)
Loading...
Searching...
No Matches
preconditioner_apply.F
Go to the documentation of this file.
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 computes preconditioners, and implements methods to apply them
10!> currently used in qs_ot
11!> \par History
12!> - [UB] 2009-05-13 Adding stable approximate inverse (full and sparse)
13!> \author Joost VandeVondele (09.2002)
14! **************************************************************************************************
17 USE cp_cfm_types, ONLY: cp_cfm_create,&
23 USE cp_dbcsr_api, ONLY: &
26 dbcsr_multiply, dbcsr_release, dbcsr_set, dbcsr_type, dbcsr_type_no_symmetry
36 USE cp_fm_types, ONLY: cp_fm_create,&
41 USE input_constants, ONLY: &
47 USE kinds, ONLY: dp
51 USE mathconstants, ONLY: z_one,&
52 z_zero
57#include "./base/base_uses.f90"
58
59 IMPLICIT NONE
60 PRIVATE
61
62 CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'preconditioner_apply'
63
66
67CONTAINS
68
69! **************************************************************************************************
70!> \brief applies a previously created preconditioner to a full matrix
71!> \param preconditioner_env ...
72!> \param matrix_in ...
73!> \param matrix_out ...
74! **************************************************************************************************
75 SUBROUTINE apply_preconditioner_fm(preconditioner_env, matrix_in, matrix_out)
76
77 TYPE(preconditioner_type) :: preconditioner_env
78 TYPE(cp_fm_type), INTENT(IN) :: matrix_in, matrix_out
79
80 CHARACTER(len=*), PARAMETER :: routinen = 'apply_preconditioner_fm'
81
82 INTEGER :: handle
83
84 CALL timeset(routinen, handle)
85
86 SELECT CASE (preconditioner_env%in_use)
87 CASE (0)
88 cpabort("No preconditioner in use")
90 CALL apply_full_single(preconditioner_env, matrix_in, matrix_out)
92 CALL apply_full_all(preconditioner_env, matrix_in, matrix_out)
94 CALL apply_low_rank_fm(preconditioner_env, matrix_in, matrix_out)
96 CALL apply_full_all_covariant(preconditioner_env, matrix_in, matrix_out)
98 IF (preconditioner_env%lattice_fft_active) THEN
99 CALL apply_lattice_operator_fm(preconditioner_env, matrix_in, matrix_out)
100 ELSE
101 SELECT CASE (preconditioner_env%solver)
103 CALL apply_full_single(preconditioner_env, matrix_in, matrix_out)
105 CALL apply_full_direct(preconditioner_env, matrix_in, matrix_out)
107 CALL apply_chebyshev_fm(preconditioner_env, matrix_in, matrix_out)
108 CASE DEFAULT
109 cpabort("Solver not implemented")
110 END SELECT
111 END IF
112 CASE DEFAULT
113 cpabort("Unknown preconditioner")
114 END SELECT
115
116 CALL timestop(handle)
117
118 END SUBROUTINE apply_preconditioner_fm
119
120! **************************************************************************************************
121!> \brief ...
122!> \param preconditioner_env ...
123!> \param matrix_in ...
124!> \param matrix_out ...
125! **************************************************************************************************
126 SUBROUTINE apply_preconditioner_dbcsr(preconditioner_env, matrix_in, matrix_out)
127
128 TYPE(preconditioner_type) :: preconditioner_env
129 TYPE(dbcsr_type) :: matrix_in, matrix_out
130
131 CHARACTER(len=*), PARAMETER :: routinen = 'apply_preconditioner_dbcsr'
132
133 INTEGER :: handle
134
135 CALL timeset(routinen, handle)
136
137 SELECT CASE (preconditioner_env%in_use)
138 CASE (0)
139 cpabort("No preconditioner in use")
141 CALL apply_single(preconditioner_env, matrix_in, matrix_out)
143 CALL apply_all(preconditioner_env, matrix_in, matrix_out)
145 CALL apply_low_rank_dbcsr(preconditioner_env, matrix_in, matrix_out)
147 CALL apply_all_covariant(preconditioner_env, matrix_in, matrix_out)
149 IF (preconditioner_env%lattice_fft_active) THEN
150 CALL apply_lattice_operator_dbcsr(preconditioner_env, matrix_in, matrix_out)
151 ELSE
152 SELECT CASE (preconditioner_env%solver)
154 CALL apply_single(preconditioner_env, matrix_in, matrix_out)
156 cpabort("Apply_full_direct not supported with ot")
157 !CALL apply_full_direct(preconditioner_env, matrix_in, matrix_out)
159 CALL apply_chebyshev_dbcsr(preconditioner_env, matrix_in, matrix_out)
160 CASE DEFAULT
161 cpabort("Wrong solver")
162 END SELECT
163 END IF
164 CASE DEFAULT
165 cpabort("Wrong preconditioner")
166 END SELECT
167
168 CALL timestop(handle)
169
170 END SUBROUTINE apply_preconditioner_dbcsr
171
172! **************************************************************************************************
173!> \brief Apply a complex k-point orbital preconditioner.
174!> \param preconditioner_env complex preconditioner storage
175!> \param matrix_in complex input channel
176!> \param matrix_out complex output channel
177! **************************************************************************************************
178 SUBROUTINE apply_preconditioner_cfm_complex(preconditioner_env, matrix_in, matrix_out)
179
180 TYPE(preconditioner_type) :: preconditioner_env
181 TYPE(cp_cfm_type), INTENT(IN) :: matrix_in, matrix_out
182
183 CHARACTER(len=*), PARAMETER :: routinen = 'apply_preconditioner_cfm_complex'
184
185 INTEGER :: handle, k, n, npre
186 TYPE(cp_cfm_type) :: canonical_in, canonical_out
187
188 CALL timeset(routinen, handle)
189
190 SELECT CASE (preconditioner_env%in_use)
194 CASE DEFAULT
195 cpabort("Unsupported complex K-point OT preconditioner")
196 END SELECT
197 cpassert(ASSOCIATED(preconditioner_env%complex_fm))
198 CALL cp_cfm_get_info(matrix_in, nrow_global=n, ncol_global=k)
199 CALL cp_cfm_get_info(preconditioner_env%complex_fm, nrow_global=npre)
200 cpassert(n == npre)
201
202 SELECT CASE (preconditioner_env%in_use)
204 CALL apply_complex_full_all_spectral(preconditioner_env, matrix_in, matrix_out)
206 cpassert(ASSOCIATED(preconditioner_env%occ_rotation_complex))
207 CALL cp_cfm_create(canonical_in, matrix_in%matrix_struct, &
208 name='complex covariant FULL_ALL input')
209 CALL cp_cfm_create(canonical_out, matrix_out%matrix_struct, &
210 name='complex covariant FULL_ALL output')
211 CALL cp_cfm_gemm('N', 'N', n, k, k, z_one, matrix_in, &
212 preconditioner_env%occ_rotation_complex, z_zero, canonical_in)
213 CALL apply_complex_full_all_spectral(preconditioner_env, canonical_in, canonical_out)
214 CALL cp_cfm_gemm('N', 'C', n, k, k, z_one, canonical_out, &
215 preconditioner_env%occ_rotation_complex, z_zero, matrix_out)
216 CALL cp_cfm_release(canonical_out)
217 CALL cp_cfm_release(canonical_in)
219 CALL apply_complex_fermi_low_rank(preconditioner_env, matrix_in, matrix_out)
220 CASE DEFAULT
221 CALL cp_cfm_gemm('N', 'N', n, k, n, z_one, preconditioner_env%complex_fm, &
222 matrix_in, z_zero, matrix_out)
223 END SELECT
224
225 CALL timestop(handle)
226
228
229! **************************************************************************************************
230!> \brief Apply the spectral FULL_ALL inverse in its canonical complex basis.
231!> \param preconditioner_env complex spectral preconditioner
232!> \param matrix_in input orbital-gradient matrix
233!> \param matrix_out preconditioned orbital-gradient matrix
234! **************************************************************************************************
235 SUBROUTINE apply_complex_full_all_spectral(preconditioner_env, matrix_in, matrix_out)
236
237 TYPE(preconditioner_type) :: preconditioner_env
238 TYPE(cp_cfm_type), INTENT(IN) :: matrix_in, matrix_out
239
240 COMPLEX(KIND=dp), CONTIGUOUS, DIMENSION(:, :), &
241 POINTER :: local_data
242 INTEGER :: i, j, k, n, ncol_local, nrow_local
243 INTEGER, DIMENSION(:), POINTER :: col_indices, row_indices
244 REAL(kind=dp) :: scale
245 TYPE(cp_cfm_type) :: matrix_spectral
246
247 cpassert(ASSOCIATED(preconditioner_env%full_evals))
248 cpassert(ASSOCIATED(preconditioner_env%occ_evals))
249 CALL cp_cfm_get_info(matrix_in, nrow_global=n, ncol_global=k)
250 cpassert(n == SIZE(preconditioner_env%full_evals))
251 cpassert(k == SIZE(preconditioner_env%occ_evals))
252 CALL cp_cfm_create(matrix_spectral, matrix_in%matrix_struct, &
253 name='complex FULL_ALL spectral input')
254 CALL cp_cfm_gemm('C', 'N', n, k, n, z_one, preconditioner_env%complex_fm, &
255 matrix_in, z_zero, matrix_spectral)
256 CALL cp_cfm_get_info(matrix_spectral, nrow_local=nrow_local, ncol_local=ncol_local, &
257 row_indices=row_indices, col_indices=col_indices, local_data=local_data)
258 DO j = 1, ncol_local
259 DO i = 1, nrow_local
260 scale = 1.0_dp/max(preconditioner_env%energy_gap, &
261 preconditioner_env%full_evals(row_indices(i)) - &
262 preconditioner_env%occ_evals(col_indices(j)))
263 local_data(i, j) = scale*local_data(i, j)
264 END DO
265 END DO
266 CALL cp_cfm_gemm('N', 'N', n, k, n, z_one, preconditioner_env%complex_fm, &
267 matrix_spectral, z_zero, matrix_out)
268 CALL cp_cfm_release(matrix_spectral)
269
270 END SUBROUTINE apply_complex_full_all_spectral
271
272! **************************************************************************************************
273!> \brief Apply an exact-overlap base plus bounded complex complementary low-rank correction.
274!> \param preconditioner_env complex low-rank preconditioner
275!> \param matrix_in input orbital-gradient matrix
276!> \param matrix_out preconditioned orbital-gradient matrix
277! **************************************************************************************************
278 SUBROUTINE apply_complex_fermi_low_rank(preconditioner_env, matrix_in, matrix_out)
279
280 TYPE(preconditioner_type) :: preconditioner_env
281 TYPE(cp_cfm_type), INTENT(IN) :: matrix_in, matrix_out
282
283 COMPLEX(KIND=dp), CONTIGUOUS, DIMENSION(:, :), &
284 POINTER :: local_data
285 INTEGER :: i, j, k, n, ncol_local, nocc, &
286 nrow_local, rank_used
287 INTEGER, DIMENSION(:), POINTER :: col_indices, row_indices
288 REAL(kind=dp) :: scale
289 TYPE(cp_cfm_type) :: matrix_spectral
290
291 cpassert(ASSOCIATED(preconditioner_env%complex_fm))
292 cpassert(ASSOCIATED(preconditioner_env%full_evals))
293 cpassert(ASSOCIATED(preconditioner_env%occ_evals))
294 CALL cp_cfm_get_info(matrix_in, nrow_global=n, ncol_global=k)
295 nocc = SIZE(preconditioner_env%occ_evals)
296 rank_used = min(preconditioner_env%spectral_rank, n - nocc)
297 cpassert(n == SIZE(preconditioner_env%full_evals))
298
299 CALL cp_cfm_create(matrix_spectral, matrix_in%matrix_struct, &
300 name='complex FERMI_LOW_RANK spectral input')
301 CALL cp_cfm_gemm('C', 'N', n, k, n, z_one, preconditioner_env%complex_fm, &
302 matrix_in, z_zero, matrix_spectral)
303 CALL cp_cfm_get_info(matrix_spectral, nrow_local=nrow_local, ncol_local=ncol_local, &
304 row_indices=row_indices, col_indices=col_indices, local_data=local_data)
305 DO j = 1, ncol_local
306 DO i = 1, nrow_local
307 scale = preconditioner_env%spectral_base_scale
308 IF (row_indices(i) > nocc .AND. row_indices(i) <= nocc + rank_used) THEN
309 scale = low_rank_inverse_weight( &
310 preconditioner_env%full_evals(row_indices(i)), &
311 preconditioner_env%spectral_reference, preconditioner_env%energy_gap)
312 END IF
313 local_data(i, j) = scale*local_data(i, j)
314 END DO
315 END DO
316 CALL cp_cfm_gemm('N', 'N', n, k, n, z_one, preconditioner_env%complex_fm, &
317 matrix_spectral, z_zero, matrix_out)
318 CALL cp_cfm_release(matrix_spectral)
319
320 END SUBROUTINE apply_complex_fermi_low_rank
321
322! **************************************************************************************************
323!> \brief Apply a complex orbital preconditioner to paired real/imaginary DBCSR matrices.
324!> \param preconditioner_env complex k-point preconditioner
325!> \param matrix_in_re real input channel
326!> \param matrix_in_im imaginary input channel
327!> \param matrix_out_re real output channel
328!> \param matrix_out_im imaginary output channel
329! **************************************************************************************************
330 SUBROUTINE apply_preconditioner_dbcsr_complex(preconditioner_env, matrix_in_re, matrix_in_im, &
331 matrix_out_re, matrix_out_im)
332
333 TYPE(preconditioner_type) :: preconditioner_env
334 TYPE(dbcsr_type) :: matrix_in_re, matrix_in_im, &
335 matrix_out_re, matrix_out_im
336
337 CHARACTER(len=*), PARAMETER :: routinen = 'apply_preconditioner_dbcsr_complex'
338
339 INTEGER :: handle, k, n
340 TYPE(cp_cfm_type) :: matrix_in, matrix_out
341 TYPE(cp_fm_type) :: matrix_in_im_fm, matrix_in_re_fm, &
342 matrix_out_im_fm, matrix_out_re_fm
343
344 CALL timeset(routinen, handle)
345
346 CALL dbcsr_get_info(matrix_in_re, nfullrows_total=n, nfullcols_total=k)
347 cpassert(ASSOCIATED(preconditioner_env%complex_fm))
348
349 CALL cp_fm_create(matrix_in_re_fm, preconditioner_env%complex_fm%matrix_struct, &
350 nrow=n, ncol=k, name='complex preconditioner input real')
351 CALL cp_fm_create(matrix_in_im_fm, preconditioner_env%complex_fm%matrix_struct, &
352 nrow=n, ncol=k, name='complex preconditioner input imaginary')
353 CALL cp_fm_create(matrix_out_re_fm, preconditioner_env%complex_fm%matrix_struct, &
354 nrow=n, ncol=k, name='complex preconditioner output real')
355 CALL cp_fm_create(matrix_out_im_fm, preconditioner_env%complex_fm%matrix_struct, &
356 nrow=n, ncol=k, name='complex preconditioner output imaginary')
357 CALL copy_dbcsr_to_fm(matrix_in_re, matrix_in_re_fm)
358 CALL copy_dbcsr_to_fm(matrix_in_im, matrix_in_im_fm)
359
360 CALL cp_cfm_create(matrix_in, matrix_in_re_fm%matrix_struct, &
361 name='complex preconditioner input')
362 CALL cp_cfm_create(matrix_out, matrix_in_re_fm%matrix_struct, &
363 name='complex preconditioner output')
364 CALL cp_fm_to_cfm(matrix_in_re_fm, matrix_in_im_fm, matrix_in)
365 CALL apply_preconditioner_cfm_complex(preconditioner_env, matrix_in, matrix_out)
366 CALL cp_cfm_to_fm(matrix_out, matrix_out_re_fm, matrix_out_im_fm)
367 CALL dbcsr_set(matrix_out_re, 0.0_dp)
368 CALL dbcsr_set(matrix_out_im, 0.0_dp)
369 CALL copy_fm_to_dbcsr(matrix_out_re_fm, matrix_out_re)
370 CALL copy_fm_to_dbcsr(matrix_out_im_fm, matrix_out_im)
371
372 CALL cp_cfm_release(matrix_out)
373 CALL cp_cfm_release(matrix_in)
374 CALL cp_fm_release(matrix_out_im_fm)
375 CALL cp_fm_release(matrix_out_re_fm)
376 CALL cp_fm_release(matrix_in_im_fm)
377 CALL cp_fm_release(matrix_in_re_fm)
378
379 CALL timestop(handle)
380
382
383! **************************************************************************************************
384!> \brief apply to full matrix, complete inversion has already been done
385!> \param preconditioner_env ...
386!> \param matrix_in ...
387!> \param matrix_out ...
388! **************************************************************************************************
389 SUBROUTINE apply_full_single(preconditioner_env, matrix_in, matrix_out)
390
391 TYPE(preconditioner_type) :: preconditioner_env
392 TYPE(cp_fm_type), INTENT(IN) :: matrix_in, matrix_out
393
394 CHARACTER(len=*), PARAMETER :: routinen = 'apply_full_single'
395
396 INTEGER :: handle, k, n
397
398 CALL timeset(routinen, handle)
399
400 CALL cp_fm_get_info(matrix_in, nrow_global=n, ncol_global=k)
401 CALL parallel_gemm('N', 'N', n, k, n, 1.0_dp, preconditioner_env%fm, &
402 matrix_in, 0.0_dp, matrix_out)
403 CALL timestop(handle)
404
405 END SUBROUTINE apply_full_single
406
407! **************************************************************************************************
408!> \brief apply to dbcsr matrix, complete inversion has already been done
409!> \param preconditioner_env ...
410!> \param matrix_in ...
411!> \param matrix_out ...
412! **************************************************************************************************
413 SUBROUTINE apply_single(preconditioner_env, matrix_in, matrix_out)
414
415 TYPE(preconditioner_type) :: preconditioner_env
416 TYPE(dbcsr_type) :: matrix_in, matrix_out
417
418 CHARACTER(len=*), PARAMETER :: routinen = 'apply_single'
419
420 INTEGER :: handle
421
422 CALL timeset(routinen, handle)
423
424 IF (.NOT. ASSOCIATED(preconditioner_env%dbcsr_matrix)) THEN
425 cpabort("NOT ASSOCIATED preconditioner_env%dbcsr_matrix")
426 END IF
427 CALL dbcsr_multiply('N', 'N', 1.0_dp, preconditioner_env%dbcsr_matrix, matrix_in, &
428 0.0_dp, matrix_out)
429
430 CALL timestop(handle)
431
432 END SUBROUTINE apply_single
433
434! **************************************************************************************************
435!> \brief preconditioner contains the factorization, application done by
436!> solving the linear system
437!> \param preconditioner_env ...
438!> \param matrix_in ...
439!> \param matrix_out ...
440! **************************************************************************************************
441 SUBROUTINE apply_full_direct(preconditioner_env, matrix_in, matrix_out)
442
443 TYPE(preconditioner_type) :: preconditioner_env
444 TYPE(cp_fm_type), INTENT(IN) :: matrix_in, matrix_out
445
446 CHARACTER(len=*), PARAMETER :: routinen = 'apply_full_direct'
447
448 INTEGER :: handle, k, n
449 TYPE(cp_fm_type) :: work
450
451 CALL timeset(routinen, handle)
452
453 CALL cp_fm_get_info(matrix_in, nrow_global=n, ncol_global=k)
454 CALL cp_fm_create(work, matrix_in%matrix_struct, name="apply_full_single")
455 CALL cp_fm_cholesky_restore(matrix_in, k, preconditioner_env%fm, work,&
456 & "SOLVE", transa="T")
457 CALL cp_fm_cholesky_restore(work, k, preconditioner_env%fm, matrix_out,&
458 & "SOLVE", transa="N")
459 CALL cp_fm_release(work)
460
461 CALL timestop(handle)
462
463 END SUBROUTINE apply_full_direct
464
465! **************************************************************************************************
466!> \brief Apply a Chebyshev approximation to the inverse of the stored dense SPD operator.
467!> \param preconditioner_env ...
468!> \param matrix_in ...
469!> \param matrix_out ...
470! **************************************************************************************************
471 SUBROUTINE apply_chebyshev_fm(preconditioner_env, matrix_in, matrix_out)
472
473 TYPE(preconditioner_type) :: preconditioner_env
474 TYPE(cp_fm_type), INTENT(IN) :: matrix_in, matrix_out
475
476 INTEGER :: degree, iteration, k, n
477 REAL(kind=dp) :: delta, rho, rho_previous, sigma, theta
478 TYPE(cp_fm_type) :: direction, residual
479
480 cpassert(ASSOCIATED(preconditioner_env%fm))
481 degree = preconditioner_env%polynomial_degree
482 cpassert(degree >= 1)
483 theta = 0.5_dp*(preconditioner_env%polynomial_max + preconditioner_env%polynomial_min)
484 delta = 0.5_dp*(preconditioner_env%polynomial_max - preconditioner_env%polynomial_min)
485 sigma = theta/delta
486 rho_previous = 1.0_dp/sigma
487 CALL cp_fm_get_info(matrix_in, nrow_global=n, ncol_global=k)
488 CALL cp_fm_create(direction, matrix_in%matrix_struct, name='Chebyshev direction')
489 CALL cp_fm_create(residual, matrix_in%matrix_struct, name='Chebyshev residual')
490 CALL cp_fm_to_fm(matrix_in, direction)
491 CALL cp_fm_scale(1.0_dp/theta, direction)
492 CALL cp_fm_to_fm(direction, matrix_out)
493 DO iteration = 2, degree
494 CALL cp_fm_to_fm(matrix_in, residual)
495 CALL parallel_gemm('N', 'N', n, k, n, -1.0_dp, preconditioner_env%fm, &
496 matrix_out, 1.0_dp, residual)
497 rho = 1.0_dp/(2.0_dp*sigma - rho_previous)
498 CALL cp_fm_scale(rho*rho_previous, direction)
499 CALL cp_fm_scale_and_add(1.0_dp, direction, 2.0_dp*rho/delta, residual)
500 CALL cp_fm_scale_and_add(1.0_dp, matrix_out, 1.0_dp, direction)
501 rho_previous = rho
502 END DO
503 CALL cp_fm_release(residual)
504 CALL cp_fm_release(direction)
505
506 END SUBROUTINE apply_chebyshev_fm
507
508! **************************************************************************************************
509!> \brief Apply a Chebyshev approximation to the inverse of the stored sparse SPD operator.
510!> \param preconditioner_env ...
511!> \param matrix_in ...
512!> \param matrix_out ...
513! **************************************************************************************************
514 SUBROUTINE apply_chebyshev_dbcsr(preconditioner_env, matrix_in, matrix_out)
515
516 TYPE(preconditioner_type) :: preconditioner_env
517 TYPE(dbcsr_type) :: matrix_in, matrix_out
518
519 INTEGER :: degree, iteration
520 REAL(kind=dp) :: delta, rho, rho_previous, sigma, theta
521 TYPE(dbcsr_type) :: direction, residual
522
523 cpassert(ASSOCIATED(preconditioner_env%dbcsr_matrix))
524 degree = preconditioner_env%polynomial_degree
525 cpassert(degree >= 1)
526 theta = 0.5_dp*(preconditioner_env%polynomial_max + preconditioner_env%polynomial_min)
527 delta = 0.5_dp*(preconditioner_env%polynomial_max - preconditioner_env%polynomial_min)
528 sigma = theta/delta
529 rho_previous = 1.0_dp/sigma
530 CALL dbcsr_copy(direction, matrix_in, name='Chebyshev direction')
531 CALL dbcsr_copy(residual, matrix_in, name='Chebyshev residual')
532 CALL dbcsr_set(matrix_out, 0.0_dp)
533 CALL dbcsr_add(matrix_out, direction, 1.0_dp, 1.0_dp/theta)
534 CALL dbcsr_set(direction, 0.0_dp)
535 CALL dbcsr_add(direction, matrix_in, 1.0_dp, 1.0_dp/theta)
536 DO iteration = 2, degree
537 CALL dbcsr_set(residual, 0.0_dp)
538 CALL dbcsr_add(residual, matrix_in, 1.0_dp, 1.0_dp)
539 CALL dbcsr_multiply('N', 'N', -1.0_dp, preconditioner_env%dbcsr_matrix, &
540 matrix_out, 1.0_dp, residual)
541 rho = 1.0_dp/(2.0_dp*sigma - rho_previous)
542 CALL dbcsr_add(direction, residual, rho*rho_previous, 2.0_dp*rho/delta)
543 CALL dbcsr_add(matrix_out, direction, 1.0_dp, 1.0_dp)
544 rho_previous = rho
545 END DO
546 CALL dbcsr_release(residual)
547 CALL dbcsr_release(direction)
548
549 END SUBROUTINE apply_chebyshev_dbcsr
550
551! **************************************************************************************************
552!> \brief Applies the overlap-inverse base and a bounded low-rank spectral correction.
553!> \param preconditioner_env ...
554!> \param matrix_in ...
555!> \param matrix_out ...
556! **************************************************************************************************
557 SUBROUTINE apply_low_rank_fm(preconditioner_env, matrix_in, matrix_out)
558
559 TYPE(preconditioner_type) :: preconditioner_env
560 TYPE(cp_fm_type), INTENT(IN) :: matrix_in, matrix_out
561
562 CHARACTER(len=*), PARAMETER :: routinen = 'apply_low_rank_fm'
563
564 INTEGER :: handle, i, j, k, n, ncol_local, nocc, &
565 nrow_local, rank_used
566 INTEGER, DIMENSION(:), POINTER :: col_indices, row_indices
567 REAL(kind=dp) :: correction
568 REAL(kind=dp), CONTIGUOUS, DIMENSION(:, :), &
569 POINTER :: local_data
570 TYPE(cp_fm_type) :: matrix_tmp
571
572 CALL timeset(routinen, handle)
573
574 cpassert(ASSOCIATED(preconditioner_env%fm))
575 cpassert(ASSOCIATED(preconditioner_env%full_evals))
576 cpassert(ASSOCIATED(preconditioner_env%occ_evals))
577
578 CALL cp_fm_get_info(matrix_in, nrow_global=n, ncol_global=k)
579 nocc = SIZE(preconditioner_env%occ_evals)
580 cpassert(n == SIZE(preconditioner_env%full_evals))
581 rank_used = min(preconditioner_env%spectral_rank, n - nocc)
582
583 ! With the exact base V V^T = S^-1. The optional lattice base replaces
584 ! S^-1 by the inverse of its block-circulant translational projection:
585 ! P = B^-1/window + V_r diag(1/max(gap, epsilon_a-mu) - 1/window) V_r^T.
586 ! The common reference mu makes the operator right-covariant for any number
587 ! of orbital columns. The lattice path retains only non-negative corrections.
588 SELECT CASE (preconditioner_env%low_rank_base)
590 cpassert(ASSOCIATED(preconditioner_env%base_fm))
591 CALL parallel_gemm('N', 'N', n, k, n, preconditioner_env%spectral_base_scale, &
592 preconditioner_env%base_fm, matrix_in, 0.0_dp, matrix_out)
594 CALL apply_lattice_operator_fm(preconditioner_env, matrix_in, matrix_out, &
595 preconditioner_env%spectral_base_scale)
596 CASE DEFAULT
597 cpabort("Unknown FERMI_LOW_RANK base operator during application")
598 END SELECT
599
600 IF (rank_used > 0) THEN
601 CALL cp_fm_create(matrix_tmp, matrix_in%matrix_struct, name=routinen, &
602 nrow=rank_used, ncol=k)
603 CALL cp_fm_get_info(matrix_tmp, nrow_local=nrow_local, ncol_local=ncol_local, &
604 row_indices=row_indices, col_indices=col_indices, local_data=local_data)
605
606 CALL parallel_gemm('T', 'N', rank_used, k, n, 1.0_dp, preconditioner_env%fm, &
607 matrix_in, 0.0_dp, matrix_tmp, a_first_col=nocc + 1)
608
609 DO j = 1, ncol_local
610 DO i = 1, nrow_local
611 correction = low_rank_inverse_weight( &
612 preconditioner_env%full_evals(nocc + row_indices(i)), &
613 preconditioner_env%spectral_reference, &
614 preconditioner_env%energy_gap) &
615 - preconditioner_env%spectral_base_scale
616 local_data(i, j) = local_data(i, j)*correction
617 END DO
618 END DO
619
620 CALL parallel_gemm('N', 'N', n, k, rank_used, 1.0_dp, preconditioner_env%fm, &
621 matrix_tmp, 1.0_dp, matrix_out, a_first_col=nocc + 1)
622 CALL cp_fm_release(matrix_tmp)
623 END IF
624
625 CALL timestop(handle)
626
627 END SUBROUTINE apply_low_rank_fm
628
629! **************************************************************************************************
630!> \brief Apply a replicated-cell inverse operator to a distributed full matrix.
631!> \param preconditioner_env ...
632!> \param matrix_in ...
633!> \param matrix_out ...
634!> \param scale_factor ...
635! **************************************************************************************************
636 SUBROUTINE apply_lattice_operator_fm(preconditioner_env, matrix_in, matrix_out, scale_factor)
637
638 TYPE(preconditioner_type) :: preconditioner_env
639 TYPE(cp_fm_type), INTENT(IN) :: matrix_in, matrix_out
640 REAL(kind=dp), INTENT(IN), OPTIONAL :: scale_factor
641
642 CHARACTER(LEN=*), PARAMETER :: routinen = 'apply_lattice_operator_fm'
643
644 INTEGER :: fft_ok, handle, i
645 LOGICAL :: used_fft
646 REAL(kind=dp) :: imaginary_residual, output_max, scale
647 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :) :: base_input, coarse_projected, &
648 coarse_residual, coarse_rhs, &
649 local_input, local_output
650
651 CALL timeset(routinen, handle)
652 cpassert(ALLOCATED(preconditioner_env%lattice_inverse_k))
653 scale = 1.0_dp
654 IF (PRESENT(scale_factor)) scale = scale_factor
655 CALL distribute_lattice_rhs(preconditioner_env, matrix_in, &
656 preconditioner_env%lattice_rhs_distribution, local_input)
657 ALLOCATE (local_output(SIZE(local_input, 1), SIZE(local_input, 2)))
658 IF (ALLOCATED(preconditioner_env%lattice_local_indices)) THEN
659 cpassert(ALLOCATED(preconditioner_env%lattice_local_operator))
660 cpassert(ALLOCATED(preconditioner_env%lattice_local_coarse_inverse))
661 ALLOCATE (base_input(SIZE(local_input, 1), SIZE(local_input, 2)), &
662 coarse_projected(SIZE(preconditioner_env%lattice_local_indices), SIZE(local_input, 2)), &
663 coarse_rhs(SIZE(preconditioner_env%lattice_local_indices), SIZE(local_input, 2)))
664 DO i = 1, SIZE(preconditioner_env%lattice_local_indices)
665 coarse_projected(i, :) = local_input(preconditioner_env%lattice_local_indices(i), :)
666 END DO
667 coarse_rhs(:, :) = matmul(preconditioner_env%lattice_local_coarse_inverse, &
668 coarse_projected)
669 base_input(:, :) = local_input - &
670 matmul(preconditioner_env%lattice_local_operator, coarse_rhs)
671 ELSE
672 ALLOCATE (base_input(SIZE(local_input, 1), SIZE(local_input, 2)), source=local_input)
673 END IF
674 used_fft = .true.
675 imaginary_residual = 0.0_dp
676 IF (SIZE(local_input, 2) > 0) THEN
677 CALL apply_lattice_inverse_dense(preconditioner_env%lattice_inverse_k, &
678 preconditioner_env%lattice_dims, base_input, local_output, &
679 used_fft, imaginary_residual)
680 END IF
681 IF (ALLOCATED(preconditioner_env%lattice_local_indices)) THEN
682 ALLOCATE (coarse_residual(SIZE(coarse_rhs, 1), SIZE(coarse_rhs, 2)))
683 coarse_projected(:, :) = matmul(transpose(preconditioner_env%lattice_local_operator), &
684 local_output)
685 coarse_residual(:, :) = matmul(preconditioner_env%lattice_local_coarse_inverse, &
686 coarse_projected)
687 local_output(preconditioner_env%lattice_local_indices, :) = &
688 local_output(preconditioner_env%lattice_local_indices, :) + coarse_rhs - coarse_residual
689 DEALLOCATE (coarse_projected, coarse_residual, coarse_rhs)
690 END IF
691 fft_ok = merge(1, 0, used_fft)
692 output_max = 0.0_dp
693 IF (SIZE(local_output) > 0) output_max = maxval(abs(local_output))
694 CALL preconditioner_env%para_env%min(fft_ok)
695 CALL preconditioner_env%para_env%max(imaginary_residual)
696 CALL preconditioner_env%para_env%max(output_max)
697 IF (fft_ok == 0) cpabort("Lattice preconditioner inverse failed to use FFTs")
698 IF (imaginary_residual > 1.0e-10_dp*max(1.0_dp, output_max)) THEN
699 cpabort("Lattice preconditioner inverse produced a non-real Gamma-point result")
700 END IF
701 CALL collect_lattice_rhs(preconditioner_env, preconditioner_env%lattice_rhs_distribution, &
702 local_output, matrix_out, scale)
703 DEALLOCATE (base_input, local_input, local_output)
704 CALL timestop(handle)
705
706 END SUBROUTINE apply_lattice_operator_fm
707
708! **************************************************************************************************
709!> \brief Apply state-dependent replicated-cell inverse operators to a distributed full matrix.
710!> \param preconditioner_env ...
711!> \param matrix_in ...
712!> \param matrix_out ...
713! **************************************************************************************************
714 SUBROUTINE apply_lattice_state_operator_fm(preconditioner_env, matrix_in, matrix_out)
715
716 TYPE(preconditioner_type) :: preconditioner_env
717 TYPE(cp_fm_type), INTENT(IN) :: matrix_in, matrix_out
718
719 CHARACTER(LEN=*), PARAMETER :: routinen = 'apply_lattice_state_operator_fm'
720
721 INTEGER :: fft_ok, global_column, handle, i, j, k, &
722 n, state
723 LOGICAL :: used_fft
724 REAL(kind=dp) :: imaginary_residual, output_max
725 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :) :: base_input, coarse_projected, &
726 coarse_residual, coarse_rhs, complement_input, local_input, local_output, &
727 occupied_component, occupied_update
728
729 CALL timeset(routinen, handle)
730 cpassert(ALLOCATED(preconditioner_env%lattice_state_inverse_k))
731 CALL cp_fm_get_info(matrix_in, nrow_global=n, ncol_global=k)
732 cpassert(SIZE(preconditioner_env%lattice_state_inverse_k, 4) == k)
733 CALL distribute_lattice_rhs(preconditioner_env, matrix_in, &
734 preconditioner_env%lattice_rhs_distribution, local_input)
735 cpassert(ALLOCATED(preconditioner_env%lattice_occ_vectors))
736 cpassert(ALLOCATED(preconditioner_env%lattice_occ_dual))
737 ALLOCATE (complement_input(n, SIZE(local_input, 2)), &
738 local_output(n, SIZE(local_input, 2)), &
739 occupied_component(k, SIZE(local_input, 2)), &
740 occupied_update(n, SIZE(local_input, 2)))
741 occupied_component(:, :) = matmul(transpose(preconditioner_env%lattice_occ_vectors), &
742 local_input)
743 complement_input(:, :) = local_input - &
744 matmul(preconditioner_env%lattice_occ_dual, occupied_component)
745 ALLOCATE (base_input(n, SIZE(local_input, 2)), source=complement_input)
746 IF (ALLOCATED(preconditioner_env%lattice_state_local_indices)) THEN
747 cpassert(ALLOCATED(preconditioner_env%lattice_state_local_operator))
748 cpassert(ALLOCATED(preconditioner_env%lattice_state_local_coarse_inverse))
749 ALLOCATE (coarse_rhs(SIZE(preconditioner_env%lattice_state_local_indices, 1), &
750 SIZE(local_input, 2)), &
751 coarse_projected(SIZE(preconditioner_env%lattice_state_local_indices, 1), &
752 SIZE(local_input, 2)))
753 DO j = 1, SIZE(local_input, 2)
754 state = preconditioner_env%lattice_rhs_distribution%global_columns(j)
755 DO i = 1, SIZE(preconditioner_env%lattice_state_local_indices, 1)
756 coarse_projected(i, j) = &
757 complement_input(preconditioner_env%lattice_state_local_indices(i, state), j)
758 END DO
759 coarse_rhs(:, j) = matmul( &
760 preconditioner_env%lattice_state_local_coarse_inverse(:, :, state), &
761 coarse_projected(:, j))
762 base_input(:, j) = complement_input(:, j) - &
763 matmul(preconditioner_env%lattice_state_local_operator(:, :, state), &
764 coarse_rhs(:, j))
765 END DO
766 END IF
767 used_fft = .true.
768 imaginary_residual = 0.0_dp
769 IF (SIZE(local_input, 2) > 0) THEN
770 CALL apply_lattice_state_inverse_dense(preconditioner_env%lattice_state_inverse_k, &
771 preconditioner_env%lattice_dims, &
772 base_input, local_output, used_fft, imaginary_residual, &
773 preconditioner_env%lattice_rhs_distribution%global_columns)
774 END IF
775 IF (ALLOCATED(preconditioner_env%lattice_state_local_indices)) THEN
776 ALLOCATE (coarse_residual(SIZE(coarse_rhs, 1), SIZE(coarse_rhs, 2)))
777 DO j = 1, SIZE(local_input, 2)
778 state = preconditioner_env%lattice_rhs_distribution%global_columns(j)
779 coarse_projected(:, j) = &
780 matmul(transpose(preconditioner_env%lattice_state_local_operator(:, :, state)), &
781 local_output(:, j))
782 coarse_residual(:, j) = matmul( &
783 preconditioner_env%lattice_state_local_coarse_inverse(:, :, state), &
784 coarse_projected(:, j))
785 local_output(preconditioner_env%lattice_state_local_indices(:, state), j) = &
786 local_output(preconditioner_env%lattice_state_local_indices(:, state), j) + &
787 coarse_rhs(:, j) - coarse_residual(:, j)
788 END DO
789 DEALLOCATE (coarse_projected, coarse_residual, coarse_rhs)
790 END IF
791 fft_ok = merge(1, 0, used_fft)
792 output_max = 0.0_dp
793 IF (SIZE(local_output) > 0) output_max = maxval(abs(local_output))
794 CALL preconditioner_env%para_env%min(fft_ok)
795 CALL preconditioner_env%para_env%max(imaginary_residual)
796 CALL preconditioner_env%para_env%max(output_max)
797 IF (fft_ok == 0) THEN
798 cpabort("State-dependent lattice preconditioner inverse failed to use FFTs")
799 END IF
800 IF (imaginary_residual > 1.0e-10_dp*max(1.0_dp, output_max)) THEN
801 cpabort("State-dependent lattice preconditioner produced a non-real Gamma-point result")
802 END IF
803 occupied_component(:, :) = matmul(transpose(preconditioner_env%lattice_occ_dual), &
804 local_output)
805 occupied_update(:, :) = matmul(preconditioner_env%lattice_occ_vectors, occupied_component)
806 local_output(:, :) = local_output - occupied_update
807 occupied_component(:, :) = matmul(transpose(preconditioner_env%lattice_occ_vectors), &
808 local_input)
809 DO j = 1, SIZE(local_input, 2)
810 global_column = preconditioner_env%lattice_rhs_distribution%global_columns(j)
811 DO i = 1, k
812 occupied_component(i, j) = occupied_component(i, j)/max( &
813 preconditioner_env%energy_gap, &
814 preconditioner_env%full_evals(i) - &
815 preconditioner_env%occ_evals(global_column))
816 END DO
817 END DO
818 occupied_update(:, :) = matmul(preconditioner_env%lattice_occ_vectors, occupied_component)
819 local_output(:, :) = local_output + occupied_update
820 CALL collect_lattice_rhs(preconditioner_env, preconditioner_env%lattice_rhs_distribution, &
821 local_output, matrix_out)
822 DEALLOCATE (base_input, complement_input, local_input, local_output, occupied_component, occupied_update)
823 CALL timestop(handle)
824
825 END SUBROUTINE apply_lattice_state_operator_fm
826
827! **************************************************************************************************
828!> \brief Route complete orbital columns to distinct ranks for lattice-FFT application.
829!> \param preconditioner_env ...
830!> \param matrix_in distributed input matrix
831!> \param distribution communication map retained for the reverse route
832!> \param local_input complete columns owned by this rank
833! **************************************************************************************************
834 SUBROUTINE distribute_lattice_rhs(preconditioner_env, matrix_in, distribution, local_input)
835
836 TYPE(preconditioner_type) :: preconditioner_env
837 TYPE(cp_fm_type), INTENT(IN) :: matrix_in
838 TYPE(lattice_rhs_distribution_type), INTENT(INOUT) :: distribution
839 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :), &
840 INTENT(OUT) :: local_input
841
842 INTEGER :: destination, i, ientry, j, k, n, &
843 ncol_local, nowned, nrow_local, &
844 num_pe, slot
845 INTEGER, ALLOCATABLE, DIMENSION(:) :: cursor, send_global_columns, &
846 send_global_rows
847 INTEGER, DIMENSION(:), POINTER :: col_indices, row_indices
848 LOGICAL :: rebuild
849 REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: recv_values, send_values
850 REAL(kind=dp), CONTIGUOUS, DIMENSION(:, :), &
851 POINTER :: input_data
852
853 num_pe = preconditioner_env%para_env%num_pe
854 CALL cp_fm_get_info(matrix_in, nrow_global=n, ncol_global=k, &
855 nrow_local=nrow_local, ncol_local=ncol_local, &
856 row_indices=row_indices, col_indices=col_indices, local_data=input_data)
857 rebuild = distribution%nrow_global /= n .OR. distribution%ncol_global /= k .OR. &
858 distribution%nrow_local /= nrow_local .OR. distribution%ncol_local /= ncol_local .OR. &
859 distribution%num_pe /= num_pe
860 IF (.NOT. rebuild) THEN
861 rebuild = .NOT. ALLOCATED(distribution%local_rows) .OR. &
862 .NOT. ALLOCATED(distribution%local_columns)
863 END IF
864 IF (.NOT. rebuild) THEN
865 rebuild = any(distribution%local_rows /= row_indices) .OR. &
866 any(distribution%local_columns /= col_indices)
867 END IF
868 IF (rebuild) THEN
869 CALL release_lattice_rhs_distribution(distribution)
870 distribution%nrow_global = n
871 distribution%ncol_global = k
872 distribution%nrow_local = nrow_local
873 distribution%ncol_local = ncol_local
874 distribution%num_pe = num_pe
875 ALLOCATE (distribution%local_rows(nrow_local), distribution%local_columns(ncol_local))
876 distribution%local_rows(:) = row_indices
877 distribution%local_columns(:) = col_indices
878 ALLOCATE (distribution%send_counts(num_pe), distribution%send_displacements(num_pe), &
879 distribution%recv_counts(num_pe), distribution%recv_displacements(num_pe), &
880 cursor(num_pe))
881 distribution%send_counts = 0
882 DO j = 1, ncol_local
883 destination = modulo(col_indices(j) - 1, num_pe) + 1
884 distribution%send_counts(destination) = &
885 distribution%send_counts(destination) + nrow_local
886 END DO
887 CALL preconditioner_env%para_env%alltoall(distribution%send_counts, &
888 distribution%recv_counts, 1)
889 distribution%send_displacements(1) = 0
890 distribution%recv_displacements(1) = 0
891 DO i = 2, num_pe
892 distribution%send_displacements(i) = distribution%send_displacements(i - 1) + &
893 distribution%send_counts(i - 1)
894 distribution%recv_displacements(i) = distribution%recv_displacements(i - 1) + &
895 distribution%recv_counts(i - 1)
896 END DO
897
898 ALLOCATE (send_global_rows(sum(distribution%send_counts)), &
899 send_global_columns(sum(distribution%send_counts)), &
900 distribution%send_local_rows(sum(distribution%send_counts)), &
901 distribution%send_local_columns(sum(distribution%send_counts)), &
902 distribution%recv_global_rows(sum(distribution%recv_counts)), &
903 distribution%recv_global_columns(sum(distribution%recv_counts)))
904 cursor(:) = distribution%send_displacements
905 DO j = 1, ncol_local
906 destination = modulo(col_indices(j) - 1, num_pe) + 1
907 DO i = 1, nrow_local
908 cursor(destination) = cursor(destination) + 1
909 ientry = cursor(destination)
910 send_global_rows(ientry) = row_indices(i)
911 send_global_columns(ientry) = col_indices(j)
912 distribution%send_local_rows(ientry) = i
913 distribution%send_local_columns(ientry) = j
914 END DO
915 END DO
916 CALL preconditioner_env%para_env%alltoall( &
917 send_global_rows, distribution%send_counts, distribution%send_displacements, &
918 distribution%recv_global_rows, distribution%recv_counts, distribution%recv_displacements)
919 CALL preconditioner_env%para_env%alltoall( &
920 send_global_columns, distribution%send_counts, distribution%send_displacements, &
921 distribution%recv_global_columns, distribution%recv_counts, distribution%recv_displacements)
922
923 nowned = 0
924 DO j = preconditioner_env%para_env%mepos + 1, k, num_pe
925 nowned = nowned + 1
926 END DO
927 ALLOCATE (distribution%global_columns(nowned))
928 nowned = 0
929 DO j = preconditioner_env%para_env%mepos + 1, k, num_pe
930 nowned = nowned + 1
931 distribution%global_columns(nowned) = j
932 END DO
933 DEALLOCATE (cursor, send_global_columns, send_global_rows)
934 END IF
935
936 nowned = SIZE(distribution%global_columns)
937 ALLOCATE (local_input(n, nowned), source=0.0_dp)
938 ALLOCATE (send_values(sum(distribution%send_counts)), &
939 recv_values(sum(distribution%recv_counts)))
940 DO ientry = 1, SIZE(send_values)
941 send_values(ientry) = input_data(distribution%send_local_rows(ientry), &
942 distribution%send_local_columns(ientry))
943 END DO
944 CALL preconditioner_env%para_env%alltoall( &
945 send_values, distribution%send_counts, distribution%send_displacements, &
946 recv_values, distribution%recv_counts, distribution%recv_displacements)
947 DO ientry = 1, SIZE(recv_values)
948 slot = (distribution%recv_global_columns(ientry) - 1)/num_pe + 1
949 local_input(distribution%recv_global_rows(ientry), slot) = recv_values(ientry)
950 END DO
951
952 DEALLOCATE (recv_values, send_values)
953
954 END SUBROUTINE distribute_lattice_rhs
955
956! **************************************************************************************************
957!> \brief Return rank-owned lattice-FFT columns to their original full-matrix layout.
958!> \param preconditioner_env ...
959!> \param distribution communication map from distribute_lattice_rhs
960!> \param local_output complete preconditioned columns owned by this rank
961!> \param matrix_out distributed output matrix
962!> \param scale_factor optional final scaling
963! **************************************************************************************************
964 SUBROUTINE collect_lattice_rhs(preconditioner_env, distribution, local_output, matrix_out, scale_factor)
965
966 TYPE(preconditioner_type) :: preconditioner_env
967 TYPE(lattice_rhs_distribution_type), INTENT(IN) :: distribution
968 REAL(kind=dp), DIMENSION(:, :), INTENT(IN) :: local_output
969 TYPE(cp_fm_type), INTENT(IN) :: matrix_out
970 REAL(kind=dp), INTENT(IN), OPTIONAL :: scale_factor
971
972 INTEGER :: ientry, num_pe, slot
973 REAL(kind=dp) :: scale
974 REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: recv_values, send_values
975 REAL(kind=dp), CONTIGUOUS, DIMENSION(:, :), &
976 POINTER :: output_data
977
978 num_pe = preconditioner_env%para_env%num_pe
979 cpassert(SIZE(local_output, 1) == distribution%nrow_global)
980 cpassert(SIZE(local_output, 2) == SIZE(distribution%global_columns))
981 scale = 1.0_dp
982 IF (PRESENT(scale_factor)) scale = scale_factor
983 ALLOCATE (send_values(sum(distribution%recv_counts)), &
984 recv_values(sum(distribution%send_counts)))
985 DO ientry = 1, SIZE(send_values)
986 slot = (distribution%recv_global_columns(ientry) - 1)/num_pe + 1
987 send_values(ientry) = local_output(distribution%recv_global_rows(ientry), slot)
988 END DO
989 CALL preconditioner_env%para_env%alltoall( &
990 send_values, distribution%recv_counts, distribution%recv_displacements, &
991 recv_values, distribution%send_counts, distribution%send_displacements)
992
993 CALL cp_fm_get_info(matrix_out, local_data=output_data)
994 output_data = 0.0_dp
995 DO ientry = 1, SIZE(recv_values)
996 output_data(distribution%send_local_rows(ientry), &
997 distribution%send_local_columns(ientry)) = scale*recv_values(ientry)
998 END DO
999 DEALLOCATE (recv_values, send_values)
1000
1001 END SUBROUTINE collect_lattice_rhs
1002
1003! **************************************************************************************************
1004!> \brief Bridge a DBCSR OT gradient to the full-matrix lattice-FFT operator.
1005!> \param preconditioner_env ...
1006!> \param matrix_in ...
1007!> \param matrix_out ...
1008! **************************************************************************************************
1009 SUBROUTINE apply_lattice_operator_dbcsr(preconditioner_env, matrix_in, matrix_out)
1010
1011 TYPE(preconditioner_type) :: preconditioner_env
1012 TYPE(dbcsr_type) :: matrix_in, matrix_out
1013
1014 INTEGER :: k, n
1015 TYPE(cp_fm_struct_type), POINTER :: fm_struct
1016 TYPE(cp_fm_type) :: input_fm, output_fm
1017
1018 NULLIFY (fm_struct)
1019 CALL dbcsr_get_info(matrix_in, nfullrows_total=n, nfullcols_total=k)
1020 CALL cp_fm_struct_create(fm_struct, nrow_global=n, ncol_global=k, &
1021 context=preconditioner_env%ctxt, &
1022 para_env=preconditioner_env%para_env)
1023 CALL cp_fm_create(input_fm, fm_struct, name="lattice preconditioner input")
1024 CALL cp_fm_create(output_fm, fm_struct, name="lattice preconditioner output")
1025 CALL cp_fm_struct_release(fm_struct)
1026 CALL copy_dbcsr_to_fm(matrix_in, input_fm)
1027 CALL apply_lattice_operator_fm(preconditioner_env, input_fm, output_fm)
1028 CALL copy_fm_to_dbcsr(output_fm, matrix_out)
1029 CALL cp_fm_release(input_fm)
1030 CALL cp_fm_release(output_fm)
1031
1032 END SUBROUTINE apply_lattice_operator_dbcsr
1033
1034! **************************************************************************************************
1035!> \brief DBCSR variant of the bounded low-rank spectral correction.
1036!> \param preconditioner_env ...
1037!> \param matrix_in ...
1038!> \param matrix_out ...
1039! **************************************************************************************************
1040 SUBROUTINE apply_low_rank_dbcsr(preconditioner_env, matrix_in, matrix_out)
1041
1042 TYPE(preconditioner_type) :: preconditioner_env
1043 TYPE(dbcsr_type) :: matrix_in, matrix_out
1044
1045 CHARACTER(len=*), PARAMETER :: routinen = 'apply_low_rank_dbcsr'
1046
1047 INTEGER :: col, col_offset, col_size, handle, i, j, &
1048 k, n, nocc, rank_used, row, &
1049 row_offset, row_size
1050 REAL(kind=dp) :: correction
1051 REAL(kind=dp), DIMENSION(:, :), POINTER :: DATA
1052 TYPE(dbcsr_iterator_type) :: iter
1053 TYPE(dbcsr_type) :: matrix_tmp
1054
1055 CALL timeset(routinen, handle)
1056
1057 IF (preconditioner_env%low_rank_base == ot_low_rank_base_lattice_fft) THEN
1058 CALL apply_low_rank_dbcsr_via_fm(preconditioner_env, matrix_in, matrix_out)
1059 CALL timestop(handle)
1060 RETURN
1061 END IF
1062
1063 cpassert(ASSOCIATED(preconditioner_env%base_dbcsr_matrix))
1064 cpassert(ASSOCIATED(preconditioner_env%dbcsr_matrix))
1065 cpassert(ASSOCIATED(preconditioner_env%full_evals))
1066 cpassert(ASSOCIATED(preconditioner_env%occ_evals))
1067
1068 CALL dbcsr_get_info(matrix_in, nfullrows_total=n, nfullcols_total=k)
1069 nocc = SIZE(preconditioner_env%occ_evals)
1070 cpassert(n == SIZE(preconditioner_env%full_evals))
1071 rank_used = min(preconditioner_env%spectral_rank, n - nocc)
1072
1073 ! DBCSR form of the same overlap-inverse base plus positive low-rank update.
1074 CALL dbcsr_multiply('N', 'N', preconditioner_env%spectral_base_scale, &
1075 preconditioner_env%base_dbcsr_matrix, matrix_in, 0.0_dp, matrix_out)
1076
1077 IF (rank_used > 0) THEN
1078 CALL dbcsr_copy(matrix_tmp, matrix_in, name=routinen)
1079 CALL dbcsr_set(matrix_tmp, 0.0_dp)
1080 CALL dbcsr_multiply('T', 'N', 1.0_dp, preconditioner_env%dbcsr_matrix, &
1081 matrix_in, 0.0_dp, matrix_tmp, &
1082 first_row=nocc + 1, last_row=nocc + rank_used)
1083
1084 CALL dbcsr_iterator_start(iter, matrix_tmp)
1085 DO WHILE (dbcsr_iterator_blocks_left(iter))
1086 CALL dbcsr_iterator_next_block(iter, row, col, DATA, &
1087 row_size=row_size, col_size=col_size, &
1088 row_offset=row_offset, col_offset=col_offset)
1089 DO j = 1, col_size
1090 DO i = 1, row_size
1091 IF (row_offset + i - 1 >= nocc + 1 .AND. &
1092 row_offset + i - 1 <= nocc + rank_used) THEN
1093 correction = low_rank_inverse_weight( &
1094 preconditioner_env%full_evals(row_offset + i - 1), &
1095 preconditioner_env%spectral_reference, &
1096 preconditioner_env%energy_gap) &
1097 - preconditioner_env%spectral_base_scale
1098 DATA(i, j) = DATA(i, j)*correction
1099 END IF
1100 END DO
1101 END DO
1102 END DO
1103 CALL dbcsr_iterator_stop(iter)
1104
1105 CALL dbcsr_multiply('N', 'N', 1.0_dp, preconditioner_env%dbcsr_matrix, &
1106 matrix_tmp, 1.0_dp, matrix_out, &
1107 first_k=nocc + 1, last_k=nocc + rank_used)
1108 CALL dbcsr_release(matrix_tmp)
1109 END IF
1110
1111 CALL timestop(handle)
1112
1113 END SUBROUTINE apply_low_rank_dbcsr
1114
1115! **************************************************************************************************
1116!> \brief Bridge DBCSR OT gradients to the full-matrix lattice-FFT implementation.
1117!> \param preconditioner_env ...
1118!> \param matrix_in ...
1119!> \param matrix_out ...
1120! **************************************************************************************************
1121 SUBROUTINE apply_low_rank_dbcsr_via_fm(preconditioner_env, matrix_in, matrix_out)
1122
1123 TYPE(preconditioner_type) :: preconditioner_env
1124 TYPE(dbcsr_type) :: matrix_in, matrix_out
1125
1126 INTEGER :: k, n
1127 TYPE(cp_fm_struct_type), POINTER :: fm_struct
1128 TYPE(cp_fm_type) :: input_fm, output_fm
1129
1130 NULLIFY (fm_struct)
1131 CALL dbcsr_get_info(matrix_in, nfullrows_total=n, nfullcols_total=k)
1132 CALL cp_fm_struct_create(fm_struct, nrow_global=n, ncol_global=k, &
1133 context=preconditioner_env%ctxt, &
1134 para_env=preconditioner_env%para_env)
1135 CALL cp_fm_create(input_fm, fm_struct, name="lattice low-rank input")
1136 CALL cp_fm_create(output_fm, fm_struct, name="lattice low-rank output")
1137 CALL cp_fm_struct_release(fm_struct)
1138 CALL copy_dbcsr_to_fm(matrix_in, input_fm)
1139 CALL apply_low_rank_fm(preconditioner_env, input_fm, output_fm)
1140 CALL copy_fm_to_dbcsr(output_fm, matrix_out)
1141 CALL cp_fm_release(input_fm)
1142 CALL cp_fm_release(output_fm)
1143
1144 END SUBROUTINE apply_low_rank_dbcsr_via_fm
1145
1146! **************************************************************************************************
1147!> \brief full all to a full matrix
1148!> \param preconditioner_env ...
1149!> \param matrix_in ...
1150!> \param matrix_out ...
1151! **************************************************************************************************
1152 SUBROUTINE apply_full_all(preconditioner_env, matrix_in, matrix_out)
1153
1154 TYPE(preconditioner_type) :: preconditioner_env
1155 TYPE(cp_fm_type), INTENT(IN) :: matrix_in, matrix_out
1156
1157 CHARACTER(len=*), PARAMETER :: routinen = 'apply_full_all'
1158
1159 INTEGER :: handle, i, j, k, n, ncol_local, &
1160 nrow_local
1161 INTEGER, DIMENSION(:), POINTER :: col_indices, row_indices
1162 REAL(kind=dp) :: dum
1163 REAL(kind=dp), CONTIGUOUS, DIMENSION(:, :), &
1164 POINTER :: local_data
1165 TYPE(cp_fm_type) :: matrix_tmp
1166
1167 CALL timeset(routinen, handle)
1168
1169 CALL cp_fm_get_info(matrix_in, nrow_global=n, ncol_global=k)
1170
1171 CALL cp_fm_create(matrix_tmp, matrix_in%matrix_struct, name="apply_full_all")
1172 CALL cp_fm_get_info(matrix_tmp, nrow_local=nrow_local, ncol_local=ncol_local, &
1173 row_indices=row_indices, col_indices=col_indices, local_data=local_data)
1174
1175 !
1176 CALL parallel_gemm('T', 'N', n, k, n, 1.0_dp, preconditioner_env%fm, &
1177 matrix_in, 0.0_dp, matrix_tmp)
1178
1179 ! do the right scaling
1180 DO j = 1, ncol_local
1181 DO i = 1, nrow_local
1182 dum = 1.0_dp/max(preconditioner_env%energy_gap, &
1183 preconditioner_env%full_evals(row_indices(i)) - preconditioner_env%occ_evals(col_indices(j)))
1184 local_data(i, j) = local_data(i, j)*dum
1185 END DO
1186 END DO
1187
1188 ! mult back
1189 CALL parallel_gemm('N', 'N', n, k, n, 1.0_dp, preconditioner_env%fm, &
1190 matrix_tmp, 0.0_dp, matrix_out)
1191
1192 CALL cp_fm_release(matrix_tmp)
1193
1194 CALL timestop(handle)
1195
1196 END SUBROUTINE apply_full_all
1197
1198! **************************************************************************************************
1199!> \brief full all to a dbcsr matrix
1200!> \param preconditioner_env ...
1201!> \param matrix_in ...
1202!> \param matrix_out ...
1203! **************************************************************************************************
1204 SUBROUTINE apply_all(preconditioner_env, matrix_in, matrix_out)
1205
1206 TYPE(preconditioner_type) :: preconditioner_env
1207 TYPE(dbcsr_type) :: matrix_in, matrix_out
1208
1209 CHARACTER(len=*), PARAMETER :: routinen = 'apply_all'
1210
1211 INTEGER :: col, col_offset, col_size, handle, i, j, &
1212 row, row_offset, row_size
1213 REAL(kind=dp) :: dum
1214 REAL(kind=dp), DIMENSION(:, :), POINTER :: DATA
1215 TYPE(dbcsr_iterator_type) :: iter
1216 TYPE(dbcsr_type) :: matrix_tmp
1217
1218 CALL timeset(routinen, handle)
1219
1220 CALL dbcsr_copy(matrix_tmp, matrix_in, name="apply_full_all")
1221 CALL dbcsr_multiply('T', 'N', 1.0_dp, preconditioner_env%dbcsr_matrix, &
1222 matrix_in, 0.0_dp, matrix_tmp)
1223 ! do the right scaling
1224 CALL dbcsr_iterator_start(iter, matrix_tmp)
1225 DO WHILE (dbcsr_iterator_blocks_left(iter))
1226 CALL dbcsr_iterator_next_block(iter, row, col, DATA, &
1227 row_size=row_size, col_size=col_size, &
1228 row_offset=row_offset, col_offset=col_offset)
1229 DO j = 1, col_size
1230 DO i = 1, row_size
1231 dum = 1.0_dp/max(preconditioner_env%energy_gap, &
1232 preconditioner_env%full_evals(row_offset + i - 1) &
1233 - preconditioner_env%occ_evals(col_offset + j - 1))
1234 DATA(i, j) = DATA(i, j)*dum
1235 END DO
1236 END DO
1237 END DO
1238 CALL dbcsr_iterator_stop(iter)
1239
1240 ! mult back
1241 CALL dbcsr_multiply('N', 'N', 1.0_dp, preconditioner_env%dbcsr_matrix, &
1242 matrix_tmp, 0.0_dp, matrix_out)
1243 CALL dbcsr_release(matrix_tmp)
1244 CALL timestop(handle)
1245
1246 END SUBROUTINE apply_all
1247
1248! **************************************************************************************************
1249!> \brief Apply the state-selective inverse in a private canonical occupied gauge.
1250!> \param preconditioner_env ...
1251!> \param matrix_in ...
1252!> \param matrix_out ...
1253! **************************************************************************************************
1254 SUBROUTINE apply_full_all_covariant(preconditioner_env, matrix_in, matrix_out)
1255
1256 TYPE(preconditioner_type) :: preconditioner_env
1257 TYPE(cp_fm_type), INTENT(IN) :: matrix_in, matrix_out
1258
1259 CHARACTER(len=*), PARAMETER :: routinen = 'apply_full_all_covariant'
1260
1261 INTEGER :: handle, k, n
1262 TYPE(cp_fm_type) :: canonical_in, canonical_out
1263
1264 CALL timeset(routinen, handle)
1265 cpassert(ASSOCIATED(preconditioner_env%occ_rotation))
1266 CALL cp_fm_get_info(matrix_in, nrow_global=n, ncol_global=k)
1267
1268 CALL cp_fm_create(canonical_in, matrix_in%matrix_struct, name=routinen)
1269 CALL cp_fm_create(canonical_out, matrix_out%matrix_struct, name=routinen)
1270 CALL parallel_gemm('N', 'N', n, k, k, 1.0_dp, matrix_in, &
1271 preconditioner_env%occ_rotation, 0.0_dp, canonical_in)
1272 IF (preconditioner_env%lattice_fft_active) THEN
1273 CALL apply_lattice_state_operator_fm(preconditioner_env, canonical_in, canonical_out)
1274 ELSE
1275 CALL apply_full_all(preconditioner_env, canonical_in, canonical_out)
1276 END IF
1277 CALL parallel_gemm('N', 'T', n, k, k, 1.0_dp, canonical_out, &
1278 preconditioner_env%occ_rotation, 0.0_dp, matrix_out)
1279 CALL cp_fm_release(canonical_in)
1280 CALL cp_fm_release(canonical_out)
1281 CALL timestop(handle)
1282
1283 END SUBROUTINE apply_full_all_covariant
1284
1285! **************************************************************************************************
1286!> \brief DBCSR form of the rotation-covariant state-selective inverse.
1287!> \param preconditioner_env ...
1288!> \param matrix_in ...
1289!> \param matrix_out ...
1290! **************************************************************************************************
1291 SUBROUTINE apply_all_covariant(preconditioner_env, matrix_in, matrix_out)
1292
1293 TYPE(preconditioner_type) :: preconditioner_env
1294 TYPE(dbcsr_type) :: matrix_in, matrix_out
1295
1296 CHARACTER(len=*), PARAMETER :: routinen = 'apply_all_covariant'
1297
1298 INTEGER :: handle, k, n
1299 TYPE(cp_fm_struct_type), POINTER :: fm_struct
1300 TYPE(cp_fm_type) :: input_fm, output_fm
1301 TYPE(dbcsr_type) :: canonical_in, canonical_out
1302
1303 CALL timeset(routinen, handle)
1304 cpassert(ASSOCIATED(preconditioner_env%occ_rotation))
1305 CALL dbcsr_get_info(matrix_in, nfullrows_total=n, nfullcols_total=k)
1306
1307 IF (preconditioner_env%lattice_fft_active) THEN
1308 NULLIFY (fm_struct)
1309 CALL cp_fm_struct_create(fm_struct, nrow_global=n, ncol_global=k, &
1310 context=preconditioner_env%ctxt, &
1311 para_env=preconditioner_env%para_env)
1312 CALL cp_fm_create(input_fm, fm_struct, name=routinen)
1313 CALL cp_fm_create(output_fm, fm_struct, name=routinen)
1314 CALL cp_fm_struct_release(fm_struct)
1315 CALL copy_dbcsr_to_fm(matrix_in, input_fm)
1316 CALL apply_full_all_covariant(preconditioner_env, input_fm, output_fm)
1317 CALL copy_fm_to_dbcsr(output_fm, matrix_out)
1318 CALL cp_fm_release(input_fm)
1319 CALL cp_fm_release(output_fm)
1320 CALL timestop(handle)
1321 RETURN
1322 END IF
1323
1324 IF (.NOT. ASSOCIATED(preconditioner_env%occ_rotation_dbcsr)) THEN
1325 CALL dbcsr_init_p(preconditioner_env%occ_rotation_dbcsr)
1326 CALL cp_dbcsr_m_by_n_from_template(preconditioner_env%occ_rotation_dbcsr, &
1327 template=matrix_in, m=k, n=k, &
1328 sym=dbcsr_type_no_symmetry)
1329 CALL copy_fm_to_dbcsr(preconditioner_env%occ_rotation, &
1330 preconditioner_env%occ_rotation_dbcsr)
1331 END IF
1332
1333 CALL dbcsr_copy(canonical_in, matrix_in, name=routinen)
1334 CALL dbcsr_set(canonical_in, 0.0_dp)
1335 CALL dbcsr_copy(canonical_out, matrix_out, name=routinen)
1336 CALL dbcsr_set(canonical_out, 0.0_dp)
1337 CALL dbcsr_multiply('N', 'N', 1.0_dp, matrix_in, &
1338 preconditioner_env%occ_rotation_dbcsr, 0.0_dp, canonical_in)
1339 CALL apply_all(preconditioner_env, canonical_in, canonical_out)
1340 CALL dbcsr_multiply('N', 'T', 1.0_dp, canonical_out, &
1341 preconditioner_env%occ_rotation_dbcsr, 0.0_dp, matrix_out)
1342 CALL dbcsr_release(canonical_in)
1343 CALL dbcsr_release(canonical_out)
1344 CALL timestop(handle)
1345
1346 END SUBROUTINE apply_all_covariant
1347
1348END MODULE preconditioner_apply
static GRID_HOST_DEVICE int modulo(int a, int m)
Equivalent of Fortran's MODULO, which always return a positive number. https://gcc....
Basic linear algebra operations for complex full matrices.
subroutine, public cp_cfm_gemm(transa, transb, m, n, k, alpha, matrix_a, matrix_b, beta, matrix_c, a_first_col, a_first_row, b_first_col, b_first_row, c_first_col, c_first_row)
Performs one of the matrix-matrix operations: matrix_c = alpha * op1( matrix_a ) * op2( matrix_b ) + ...
Represents a complex full matrix distributed on many processors.
subroutine, public cp_cfm_release(matrix)
Releases a full matrix.
subroutine, public cp_fm_to_cfm(msourcer, msourcei, mtarget)
Construct a complex full matrix by taking its real and imaginary parts from two separate real-value f...
subroutine, public cp_cfm_create(matrix, matrix_struct, name, nrow, ncol, set_zero)
Creates a new full matrix with the given structure.
subroutine, public cp_cfm_get_info(matrix, name, nrow_global, ncol_global, nrow_block, ncol_block, nrow_local, ncol_local, row_indices, col_indices, local_data, context, matrix_struct, para_env)
Returns information about a full matrix.
subroutine, public cp_cfm_to_fm(msource, mtargetr, mtargeti)
Copy real and imaginary parts of a complex full matrix into separate real-value full matrices.
logical function, public dbcsr_iterator_blocks_left(iterator)
...
subroutine, public dbcsr_iterator_stop(iterator)
...
subroutine, public dbcsr_copy(matrix_b, matrix_a, name, keep_sparsity, keep_imaginary)
...
subroutine, public dbcsr_multiply(transa, transb, alpha, matrix_a, matrix_b, beta, matrix_c, first_row, last_row, first_column, last_column, first_k, last_k, retain_sparsity, filter_eps, flop)
...
subroutine, public dbcsr_get_info(matrix, nblkrows_total, nblkcols_total, nfullrows_total, nfullcols_total, nblkrows_local, nblkcols_local, nfullrows_local, nfullcols_local, my_prow, my_pcol, local_rows, local_cols, proc_row_dist, proc_col_dist, row_blk_size, col_blk_size, row_blk_offset, col_blk_offset, distribution, name, matrix_type, group)
...
subroutine, public dbcsr_init_p(matrix)
...
subroutine, public dbcsr_iterator_next_block(iterator, row, column, block, block_number_argument_has_been_removed, row_size, col_size, row_offset, col_offset, transposed)
...
subroutine, public dbcsr_iterator_start(iterator, matrix, shared, dynamic, dynamic_byrows)
...
subroutine, public dbcsr_set(matrix, alpha)
...
subroutine, public dbcsr_release(matrix)
...
subroutine, public dbcsr_add(matrix_a, matrix_b, alpha_scalar, beta_scalar)
...
DBCSR operations in CP2K.
subroutine, public copy_dbcsr_to_fm(matrix, fm)
Copy a DBCSR matrix to a BLACS matrix.
subroutine, public cp_dbcsr_m_by_n_from_template(matrix, template, m, n, sym)
Utility function to create an arbitrary shaped dbcsr matrix with the same processor grid as the templ...
subroutine, public copy_fm_to_dbcsr(fm, matrix, keep_sparsity)
Copy a BLACS matrix to a dbcsr matrix.
Basic linear algebra operations for full matrices.
subroutine, public cp_fm_scale_and_add(alpha, matrix_a, beta, matrix_b)
calc A <- alpha*A + beta*B optimized for alpha == 1.0 (just add beta*B) and beta == 0....
subroutine, public cp_fm_scale(alpha, matrix_a)
scales a matrix matrix_a = alpha * matrix_b
various cholesky decomposition related routines
subroutine, public cp_fm_cholesky_restore(fm_matrix, neig, fm_matrixb, fm_matrixout, op, pos, transa)
apply Cholesky decomposition op can be "SOLVE" (out = U^-1 * in) or "MULTIPLY" (out = U * in) pos can...
represent the structure of a full matrix
subroutine, public cp_fm_struct_create(fmstruct, para_env, context, nrow_global, ncol_global, nrow_block, ncol_block, descriptor, first_p_pos, local_leading_dimension, template_fmstruct, square_blocks, force_block)
allocates and initializes a full matrix structure
subroutine, public cp_fm_struct_release(fmstruct)
releases a full matrix structure
represent a full matrix distributed on many processors
Definition cp_fm_types.F:15
subroutine, public cp_fm_get_info(matrix, name, nrow_global, ncol_global, nrow_block, ncol_block, nrow_local, ncol_local, row_indices, col_indices, local_data, context, nrow_locals, ncol_locals, matrix_struct, para_env)
returns all kind of information about the full matrix
subroutine, public cp_fm_create(matrix, matrix_struct, name, nrow, ncol, set_zero)
creates a new full matrix with the given structure
collects all constants needed in input so that they can be used without circular dependencies
integer, parameter, public ot_precond_solver_chebyshev
integer, parameter, public ot_low_rank_base_overlap
integer, parameter, public ot_precond_full_all_covariant
integer, parameter, public ot_low_rank_base_lattice_fft
integer, parameter, public ot_precond_full_kinetic
integer, parameter, public ot_precond_full_single
integer, parameter, public ot_precond_solver_inv_chol
integer, parameter, public ot_precond_full_single_inverse
integer, parameter, public ot_precond_fermi_low_rank
integer, parameter, public ot_precond_s_inverse
integer, parameter, public ot_precond_solver_update
integer, parameter, public ot_precond_full_all
integer, parameter, public ot_precond_solver_direct
Defines the basic variable types.
Definition kinds.F:23
integer, parameter, public dp
Definition kinds.F:34
Block-circulant inverse operators for replicated-cell OT preconditioners.
subroutine, public apply_lattice_inverse_dense(inverse_k, lattice_dims, matrix_in, matrix_out, used_fft, imaginary_residual)
Apply inverse Fourier blocks to a dense cell-major real matrix.
subroutine, public apply_lattice_state_inverse_dense(inverse_k, lattice_dims, matrix_in, matrix_out, used_fft, imaginary_residual, state_indices)
Apply one inverse Fourier operator to every column of a dense real matrix.
Small algebraic helpers for the rotationally covariant low-rank OT preconditioner.
pure elemental real(kind=dp) function, public low_rank_inverse_weight(eigenvalue, reference, energy_gap)
Spectral inverse weight relative to a common occupied reference level.
Definition of mathematical constants and functions.
complex(kind=dp), parameter, public z_one
real(kind=dp), parameter, public degree
complex(kind=dp), parameter, public z_zero
basic linear algebra operations for full matrixes
computes preconditioners, and implements methods to apply them currently used in qs_ot
subroutine, public apply_preconditioner_dbcsr_complex(preconditioner_env, matrix_in_re, matrix_in_im, matrix_out_re, matrix_out_im)
Apply a complex orbital preconditioner to paired real/imaginary DBCSR matrices.
subroutine, public apply_preconditioner_fm(preconditioner_env, matrix_in, matrix_out)
applies a previously created preconditioner to a full matrix
subroutine, public apply_preconditioner_cfm_complex(preconditioner_env, matrix_in, matrix_out)
Apply a complex k-point orbital preconditioner.
subroutine, public apply_preconditioner_dbcsr(preconditioner_env, matrix_in, matrix_out)
...
types of preconditioners
subroutine, public release_lattice_rhs_distribution(distribution)
Release a cached lattice right-hand-side communication map.
Represent a complex full matrix.
keeps the information about the structure of a full matrix
represent a full matrix