(git:b6ef100)
Loading...
Searching...
No Matches
preconditioner.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,&
22 USE cp_dbcsr_api, ONLY: dbcsr_get_info,&
29 USE cp_fm_types, ONLY: cp_fm_create,&
34 USE input_constants, ONLY: &
38 USE kinds, ONLY: default_string_length,&
39 dp
61 USE qs_mo_types, ONLY: get_mo_set,&
64#include "./base/base_uses.f90"
65
66 IMPLICIT NONE
67
68 PRIVATE
69
70 CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'preconditioner'
71
79
80! The public interface for apply preconditioner, the routines can be found in preconditioner_apply.F
83 MODULE PROCEDURE apply_preconditioner_dbcsr
85 MODULE PROCEDURE apply_preconditioner_fm
86 END INTERFACE
87
88! **************************************************************************************************
89
90CONTAINS
91
92! **************************************************************************************************
93
94! creates a preconditioner for the system (H-energy_homo S)
95! this preconditioner is (must be) symmetric positive definite.
96! currently uses a atom-block-diagonal form
97! each block will be ....
98! might overwrite matrix_h, matrix_t
99
100! **************************************************************************************************
101!> \brief ...
102!> \param preconditioner_env ...
103!> \param precon_type ...
104!> \param solver_type ...
105!> \param matrix_h ...
106!> \param matrix_s ...
107!> \param matrix_t ...
108!> \param mo_set ...
109!> \param energy_gap ...
110!> \param convert_precond_to_dbcsr ...
111!> \param chol_type ...
112!> \par History
113!> 09.2014 removed some unused or unfinished methods
114!> removed sparse preconditioners and the
115!> sparse approximate inverse at rev 14341 [Florian Schiffmann]
116! **************************************************************************************************
117 SUBROUTINE make_preconditioner(preconditioner_env, precon_type, solver_type, matrix_h, matrix_s, &
118 matrix_t, mo_set, energy_gap, convert_precond_to_dbcsr, chol_type)
119
120 TYPE(preconditioner_type) :: preconditioner_env
121 INTEGER, INTENT(IN) :: precon_type, solver_type
122 TYPE(dbcsr_type), POINTER :: matrix_h
123 TYPE(dbcsr_type), OPTIONAL, POINTER :: matrix_s, matrix_t
124 TYPE(mo_set_type), INTENT(IN) :: mo_set
125 REAL(kind=dp) :: energy_gap
126 LOGICAL, INTENT(IN), OPTIONAL :: convert_precond_to_dbcsr
127 INTEGER, INTENT(IN), OPTIONAL :: chol_type
128
129 CHARACTER(len=*), PARAMETER :: routinen = 'make_preconditioner'
130
131 INTEGER :: handle, k, my_solver_type, nao, nhomo
132 LOGICAL :: my_convert_precond_to_dbcsr, &
133 needs_full_spectrum, needs_homo, &
134 use_mo_coeff_b
135 REAL(kind=dp) :: energy_homo
136 REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: eigenvalues_ot
137 TYPE(cp_fm_struct_type), POINTER :: fm_struct
138 TYPE(cp_fm_type) :: mo_occ
139 TYPE(cp_fm_type), POINTER :: mo_coeff
140 TYPE(dbcsr_type), POINTER :: mo_coeff_b
141
142 CALL timeset(routinen, handle)
143
144 CALL get_mo_set(mo_set=mo_set, mo_coeff=mo_coeff, mo_coeff_b=mo_coeff_b, homo=nhomo)
145 use_mo_coeff_b = mo_set%use_mo_coeff_b
146 CALL cp_fm_get_info(mo_coeff, ncol_global=k, nrow_global=nao)
147
148 ! Starting some matrix mess, check where to store the result in preconditioner_env, fm or dbcsr_matrix
149 my_convert_precond_to_dbcsr = .false.
150 IF (PRESENT(convert_precond_to_dbcsr)) my_convert_precond_to_dbcsr = convert_precond_to_dbcsr
151
152 ! Thanks to the mess with the matrices we need to make sure in this case that the
153 ! Previous inverse is properly stored as a sparse matrix, fm gets deallocated here
154 ! if it wasn't anyway
155 IF (preconditioner_env%solver == ot_precond_solver_update) THEN
156 CALL transfer_fm_to_dbcsr(preconditioner_env%fm, preconditioner_env%dbcsr_matrix, matrix_h)
157 END IF
158
159 needs_full_spectrum = .false.
160 needs_homo = .false.
161
162 SELECT CASE (precon_type)
164 needs_full_spectrum = .true.
165 ! both of them need the coefficients as fm's, more matrix mess
166 IF (use_mo_coeff_b) THEN
167 CALL copy_dbcsr_to_fm(mo_coeff_b, mo_coeff)
168 END IF
170 needs_homo = .true.
171 ! XXXX to be removed if homo estimate only is implemented
172 needs_full_spectrum = .true.
174 ! these should be happy without an estimate for the homo energy
175 ! preconditioning can not depend on an absolute eigenvalue, only on eigenvalue differences
176 CASE DEFAULT
177 cpabort("The preconditioner is unknown ...")
178 END SELECT
179
180 ALLOCATE (eigenvalues_ot(k))
181 energy_homo = 0.0_dp
182 IF (needs_full_spectrum) THEN
183 ! XXXXXXXXXXXXXXXX do not touch the initial MOs, could be harmful for either
184 ! the case of non-equivalent MOs but also for the derivate
185 ! we could already have all eigenvalues e.g. full_all and we could skip this
186 ! to be optimised later.
187 ! one flaw is that not all SCF methods (i.e. that go over mo_derivs directly)
188 ! have a 'valid' matrix_h... (we even don't know what evals are in that case)
189 IF (use_mo_coeff_b) THEN
190 CALL calculate_subspace_eigenvalues(mo_coeff_b, matrix_h, &
191 eigenvalues_ot, do_rotation=.false., &
192 para_env=mo_coeff%matrix_struct%para_env, &
193 blacs_env=mo_coeff%matrix_struct%context)
194 ELSE
195 CALL calculate_subspace_eigenvalues(mo_coeff, matrix_h, &
196 eigenvalues_ot, do_rotation=.false.)
197 END IF
198 IF (k > 0) THEN
199 cpassert(nhomo > 0 .AND. nhomo <= k)
200 energy_homo = eigenvalues_ot(nhomo)
201 END IF
202 ELSE
203 IF (needs_homo) THEN
204 cpabort("Not yet implemented")
205 END IF
206 END IF
207
208 ! After all bits and pieces of checking and initialization, here comes the
209 ! part where the preconditioner matrix gets created and solved.
210 ! This will give the matrices for later use
211 my_solver_type = solver_type
212 preconditioner_env%in_use = precon_type
213 preconditioner_env%cholesky_use = cholesky_reduce
214 IF (PRESENT(chol_type)) preconditioner_env%cholesky_use = chol_type
215 preconditioner_env%in_use = precon_type
216 IF (nhomo == k) THEN
217 CALL make_preconditioner_matrix(preconditioner_env, matrix_h, matrix_s, matrix_t, mo_coeff, &
218 energy_homo, eigenvalues_ot, energy_gap, my_solver_type)
219 ELSE
220 CALL cp_fm_struct_create(fm_struct, nrow_global=nao, ncol_global=nhomo, &
221 context=preconditioner_env%ctxt, &
222 para_env=preconditioner_env%para_env)
223 CALL cp_fm_create(mo_occ, fm_struct)
224 CALL cp_fm_to_fm(mo_coeff, mo_occ, nhomo)
225 CALL cp_fm_struct_release(fm_struct)
226 !
227 CALL make_preconditioner_matrix(preconditioner_env, matrix_h, matrix_s, matrix_t, mo_occ, &
228 energy_homo, eigenvalues_ot(1:nhomo), energy_gap, my_solver_type)
229 !
230 CALL cp_fm_release(mo_occ)
231 END IF
232
233 CALL solve_preconditioner(my_solver_type, preconditioner_env, matrix_s, matrix_h)
234
235 ! Here comes more matrix mess, make sure to output the correct matrix format,
236 ! A bit pointless to convert the cholesky factorized version as it doesn't work in
237 ! dbcsr form and will crash later,...
238 IF (my_convert_precond_to_dbcsr) THEN
239 CALL transfer_fm_to_dbcsr(preconditioner_env%fm, preconditioner_env%dbcsr_matrix, matrix_h)
240 ELSE
241 CALL transfer_dbcsr_to_fm(preconditioner_env%dbcsr_matrix, preconditioner_env%fm, &
242 preconditioner_env%para_env, preconditioner_env%ctxt)
243 END IF
244
245 DEALLOCATE (eigenvalues_ot)
246
247 CALL timestop(handle)
248
249 END SUBROUTINE make_preconditioner
250
251! **************************************************************************************************
252!> \brief Construct FULL_ALL directly from one complex H(k), S(k), and C(k) channel.
253!> \param preconditioner_env preconditioner storage
254!> \param matrix_c_re real part of the active OT reference orbitals
255!> \param matrix_c_im imaginary part of the active OT reference orbitals
256!> \param matrix_h_re real part of H(k)
257!> \param matrix_h_im imaginary part of H(k)
258!> \param matrix_s_re real part of S(k)
259!> \param matrix_s_im imaginary part of S(k)
260!> \param mo_set reference-orbital energy labels
261!> \param energy_gap denominator floor
262!> \param solver_type inverse application selected in the OT input
263! **************************************************************************************************
264 SUBROUTINE make_preconditioner_complex_full_all(preconditioner_env, &
265 matrix_c_re, matrix_c_im, &
266 matrix_h_re, matrix_h_im, &
267 matrix_s_re, matrix_s_im, &
268 mo_set, energy_gap, solver_type)
269
270 TYPE(preconditioner_type) :: preconditioner_env
271 TYPE(dbcsr_type), POINTER :: matrix_c_re, matrix_c_im, matrix_h_re, &
272 matrix_h_im, matrix_s_re, matrix_s_im
273 TYPE(mo_set_type), INTENT(IN) :: mo_set
274 REAL(kind=dp), INTENT(IN) :: energy_gap
275 INTEGER, INTENT(IN) :: solver_type
276
277 CHARACTER(len=*), PARAMETER :: routinen = 'make_preconditioner_complex_full_all'
278
279 INTEGER :: handle, k
280 REAL(kind=dp), DIMENSION(:), POINTER :: eigenvalues
281 TYPE(cp_cfm_type) :: matrix_c, matrix_h, matrix_s
282
283 CALL timeset(routinen, handle)
284
285 NULLIFY (eigenvalues)
286 cpassert(ASSOCIATED(matrix_c_re))
287 cpassert(ASSOCIATED(matrix_c_im))
288 cpassert(ASSOCIATED(matrix_h_re))
289 cpassert(ASSOCIATED(matrix_h_im))
290 cpassert(ASSOCIATED(matrix_s_re))
291 cpassert(ASSOCIATED(matrix_s_im))
292 IF (solver_type /= ot_precond_solver_default) THEN
293 cpabort('Complex FULL_ALL supports only PRECOND_SOLVER DEFAULT')
294 END IF
295 CALL dbcsr_get_info(matrix_c_re, nfullcols_total=k)
296 cpassert(k > 0)
297 CALL get_mo_set(mo_set, eigenvalues=eigenvalues)
298 cpassert(ASSOCIATED(eigenvalues))
299 cpassert(SIZE(eigenvalues) >= k)
300
301 CALL dbcsr_pair_to_cfm(matrix_c_re, matrix_c_im, preconditioner_env, &
302 'complex FULL_ALL C', matrix_c)
303 CALL dbcsr_pair_to_cfm(matrix_h_re, matrix_h_im, preconditioner_env, &
304 'complex FULL_ALL H', matrix_h)
305 CALL dbcsr_pair_to_cfm(matrix_s_re, matrix_s_im, preconditioner_env, &
306 'complex FULL_ALL S', matrix_s)
307 CALL make_complex_full_all(preconditioner_env, matrix_c, matrix_h, matrix_s, &
308 eigenvalues(1:k), energy_gap)
309
310 CALL cp_cfm_release(matrix_c)
311 CALL cp_cfm_release(matrix_s)
312 CALL cp_cfm_release(matrix_h)
313
314 CALL timestop(handle)
315
317
318! **************************************************************************************************
319!> \brief Construct a complex FULL_SINGLE preconditioner from H(k) and S(k).
320!> \param preconditioner_env preconditioner storage
321!> \param matrix_h_re real part of H(k)
322!> \param matrix_h_im imaginary part of H(k)
323!> \param matrix_s_re real part of S(k)
324!> \param matrix_s_im imaginary part of S(k)
325!> \param mo_set orbital energy labels defining the occupied edge
326!> \param energy_gap denominator floor
327!> \param solver_type requested inverse solver
328! **************************************************************************************************
329 SUBROUTINE make_preconditioner_complex_full_single(preconditioner_env, &
330 matrix_h_re, matrix_h_im, &
331 matrix_s_re, matrix_s_im, &
332 mo_set, energy_gap, solver_type)
333
334 TYPE(preconditioner_type) :: preconditioner_env
335 TYPE(dbcsr_type), POINTER :: matrix_h_re, matrix_h_im, matrix_s_re, &
336 matrix_s_im
337 TYPE(mo_set_type), INTENT(IN) :: mo_set
338 REAL(kind=dp), INTENT(IN) :: energy_gap
339 INTEGER, INTENT(IN) :: solver_type
340
341 INTEGER :: homo
342 REAL(kind=dp), DIMENSION(:), POINTER :: eigenvalues
343 TYPE(cp_cfm_type) :: matrix_h, matrix_s
344
345 NULLIFY (eigenvalues)
346 cpassert(ASSOCIATED(matrix_h_re))
347 cpassert(ASSOCIATED(matrix_h_im))
348 cpassert(ASSOCIATED(matrix_s_re))
349 cpassert(ASSOCIATED(matrix_s_im))
350 IF (solver_type /= ot_precond_solver_default) THEN
351 cpabort('Complex FULL_SINGLE supports only PRECOND_SOLVER DEFAULT')
352 END IF
353 CALL get_mo_set(mo_set, homo=homo, eigenvalues=eigenvalues)
354 cpassert(ASSOCIATED(eigenvalues))
355 cpassert(homo > 0 .AND. homo <= SIZE(eigenvalues))
356
357 CALL dbcsr_pair_to_cfm(matrix_h_re, matrix_h_im, preconditioner_env, &
358 'complex FULL_SINGLE H', matrix_h)
359 CALL dbcsr_pair_to_cfm(matrix_s_re, matrix_s_im, preconditioner_env, &
360 'complex FULL_SINGLE S', matrix_s)
361 CALL make_complex_full_single(preconditioner_env, matrix_h, matrix_s, &
362 eigenvalues(homo), energy_gap)
363 CALL cp_cfm_release(matrix_s)
364 CALL cp_cfm_release(matrix_h)
365
367
368! **************************************************************************************************
369!> \brief Construct a complex FULL_SINGLE_INVERSE preconditioner without discarding Im(H,S,C).
370!> \param preconditioner_env preconditioner storage
371!> \param matrix_c_re real part of the occupied reference orbitals
372!> \param matrix_c_im imaginary part of the occupied reference orbitals
373!> \param matrix_h_re real part of H(k)
374!> \param matrix_h_im imaginary part of H(k)
375!> \param matrix_s_re real part of S(k)
376!> \param matrix_s_im imaginary part of S(k)
377!> \param energy_gap lower spectral bound
378!> \param solver_type requested inverse solver
379! **************************************************************************************************
380 SUBROUTINE make_preconditioner_complex_full_single_inverse(preconditioner_env, &
381 matrix_c_re, matrix_c_im, &
382 matrix_h_re, matrix_h_im, &
383 matrix_s_re, matrix_s_im, &
384 energy_gap, solver_type)
385
386 TYPE(preconditioner_type) :: preconditioner_env
387 TYPE(dbcsr_type), POINTER :: matrix_c_re, matrix_c_im, matrix_h_re, &
388 matrix_h_im, matrix_s_re, matrix_s_im
389 REAL(kind=dp), INTENT(IN) :: energy_gap
390 INTEGER, INTENT(IN) :: solver_type
391
392 INTEGER :: k, n
393 TYPE(cp_cfm_type) :: matrix_c, matrix_h, matrix_s
394 TYPE(cp_fm_struct_type), POINTER :: fm_struct_mo, fm_struct_square
395 TYPE(cp_fm_type) :: matrix_c_im_fm, matrix_c_re_fm, &
396 matrix_h_im_fm, matrix_h_re_fm, &
397 matrix_s_im_fm, matrix_s_re_fm
398
399 NULLIFY (fm_struct_mo, fm_struct_square)
400 cpassert(ASSOCIATED(matrix_c_re))
401 cpassert(ASSOCIATED(matrix_c_im))
402 cpassert(ASSOCIATED(matrix_h_re))
403 cpassert(ASSOCIATED(matrix_h_im))
404 cpassert(ASSOCIATED(matrix_s_re))
405 cpassert(ASSOCIATED(matrix_s_im))
406 IF (solver_type /= ot_precond_solver_default .AND. &
407 solver_type /= ot_precond_solver_inv_chol) THEN
408 cpabort("Complex FULL_SINGLE_INVERSE supports only PRECOND_SOLVER DEFAULT/INVERSE_CHOLESKY")
409 END IF
410 CALL dbcsr_get_info(matrix_c_re, nfullrows_total=n, nfullcols_total=k)
411 cpassert(n > 0 .AND. k > 0 .AND. k <= n)
412
413 CALL cp_fm_struct_create(fm_struct_mo, nrow_global=n, ncol_global=k, &
414 context=preconditioner_env%ctxt, &
415 para_env=preconditioner_env%para_env)
416 CALL cp_fm_struct_create(fm_struct_square, nrow_global=n, ncol_global=n, &
417 context=preconditioner_env%ctxt, &
418 para_env=preconditioner_env%para_env)
419 CALL cp_fm_create(matrix_c_re_fm, fm_struct_mo, name='complex preconditioner C real')
420 CALL cp_fm_create(matrix_c_im_fm, fm_struct_mo, name='complex preconditioner C imaginary')
421 CALL cp_fm_create(matrix_h_re_fm, fm_struct_square, name='complex preconditioner H real')
422 CALL cp_fm_create(matrix_h_im_fm, fm_struct_square, name='complex preconditioner H imaginary')
423 CALL cp_fm_create(matrix_s_re_fm, fm_struct_square, name='complex preconditioner S real')
424 CALL cp_fm_create(matrix_s_im_fm, fm_struct_square, name='complex preconditioner S imaginary')
425 CALL cp_fm_struct_release(fm_struct_mo)
426 CALL cp_fm_struct_release(fm_struct_square)
427 CALL copy_dbcsr_to_fm(matrix_c_re, matrix_c_re_fm)
428 CALL copy_dbcsr_to_fm(matrix_c_im, matrix_c_im_fm)
429 CALL copy_dbcsr_to_fm(matrix_h_re, matrix_h_re_fm)
430 CALL copy_dbcsr_to_fm(matrix_h_im, matrix_h_im_fm)
431 CALL copy_dbcsr_to_fm(matrix_s_re, matrix_s_re_fm)
432 CALL copy_dbcsr_to_fm(matrix_s_im, matrix_s_im_fm)
433
434 CALL cp_cfm_create(matrix_c, matrix_c_re_fm%matrix_struct, name='complex preconditioner C')
435 CALL cp_cfm_create(matrix_h, matrix_h_re_fm%matrix_struct, name='complex preconditioner H')
436 CALL cp_cfm_create(matrix_s, matrix_s_re_fm%matrix_struct, name='complex preconditioner S')
437 CALL cp_fm_to_cfm(matrix_c_re_fm, matrix_c_im_fm, matrix_c)
438 CALL cp_fm_to_cfm(matrix_h_re_fm, matrix_h_im_fm, matrix_h)
439 CALL cp_fm_to_cfm(matrix_s_re_fm, matrix_s_im_fm, matrix_s)
440 CALL make_complex_full_single_inverse(preconditioner_env, matrix_c, matrix_h, matrix_s, &
441 energy_gap)
442 preconditioner_env%solver = solver_type
443
444 CALL cp_cfm_release(matrix_s)
445 CALL cp_cfm_release(matrix_h)
446 CALL cp_cfm_release(matrix_c)
447 CALL cp_fm_release(matrix_s_im_fm)
448 CALL cp_fm_release(matrix_s_re_fm)
449 CALL cp_fm_release(matrix_h_im_fm)
450 CALL cp_fm_release(matrix_h_re_fm)
451 CALL cp_fm_release(matrix_c_im_fm)
452 CALL cp_fm_release(matrix_c_re_fm)
453
455
456! **************************************************************************************************
457!> \brief Construct a complex FULL_S_INVERSE preconditioner.
458!> \param preconditioner_env preconditioner storage
459!> \param matrix_s_re real part of S(k)
460!> \param matrix_s_im imaginary part of S(k)
461!> \param solver_type requested inverse solver
462! **************************************************************************************************
463 SUBROUTINE make_preconditioner_complex_full_s_inverse(preconditioner_env, &
464 matrix_s_re, matrix_s_im, solver_type)
465
466 TYPE(preconditioner_type) :: preconditioner_env
467 TYPE(dbcsr_type), POINTER :: matrix_s_re, matrix_s_im
468 INTEGER, INTENT(IN) :: solver_type
469
470 TYPE(cp_cfm_type) :: matrix_s
471
472 IF (solver_type /= ot_precond_solver_default .AND. &
473 solver_type /= ot_precond_solver_inv_chol) THEN
474 cpabort("Complex FULL_S_INVERSE supports only PRECOND_SOLVER DEFAULT/INVERSE_CHOLESKY")
475 END IF
476 CALL dbcsr_pair_to_cfm(matrix_s_re, matrix_s_im, preconditioner_env, &
477 'complex preconditioner S', matrix_s)
478 CALL make_complex_full_s_inverse(preconditioner_env, matrix_s)
479 preconditioner_env%solver = solver_type
480 CALL cp_cfm_release(matrix_s)
481
483
484! **************************************************************************************************
485!> \brief Construct a complex FULL_KINETIC preconditioner.
486!> \param preconditioner_env preconditioner storage
487!> \param matrix_t_re real part of T(k)
488!> \param matrix_t_im imaginary part of T(k)
489!> \param matrix_s_re real part of S(k)
490!> \param matrix_s_im imaginary part of S(k)
491!> \param energy_gap non-negative overlap shift
492!> \param solver_type requested inverse solver
493! **************************************************************************************************
494 SUBROUTINE make_preconditioner_complex_full_kinetic(preconditioner_env, &
495 matrix_t_re, matrix_t_im, &
496 matrix_s_re, matrix_s_im, &
497 energy_gap, solver_type)
498
499 TYPE(preconditioner_type) :: preconditioner_env
500 TYPE(dbcsr_type), POINTER :: matrix_t_re, matrix_t_im, matrix_s_re, &
501 matrix_s_im
502 REAL(kind=dp), INTENT(IN) :: energy_gap
503 INTEGER, INTENT(IN) :: solver_type
504
505 TYPE(cp_cfm_type) :: matrix_s, matrix_t
506
507 IF (solver_type /= ot_precond_solver_default .AND. &
508 solver_type /= ot_precond_solver_inv_chol) THEN
509 cpabort("Complex FULL_KINETIC supports only PRECOND_SOLVER DEFAULT/INVERSE_CHOLESKY")
510 END IF
511 CALL dbcsr_pair_to_cfm(matrix_t_re, matrix_t_im, preconditioner_env, &
512 'complex preconditioner T', matrix_t)
513 CALL dbcsr_pair_to_cfm(matrix_s_re, matrix_s_im, preconditioner_env, &
514 'complex preconditioner S', matrix_s)
515 CALL make_complex_full_kinetic(preconditioner_env, matrix_t, matrix_s, energy_gap)
516 preconditioner_env%solver = solver_type
517 CALL cp_cfm_release(matrix_s)
518 CALL cp_cfm_release(matrix_t)
519
521
522! **************************************************************************************************
523!> \brief Copy a real/imaginary DBCSR pair to one distributed complex full matrix.
524!> \param matrix_re real matrix component
525!> \param matrix_im imaginary matrix component
526!> \param preconditioner_env source of the distribution context
527!> \param matrix_name matrix label
528!> \param matrix complex output matrix
529! **************************************************************************************************
530 SUBROUTINE dbcsr_pair_to_cfm(matrix_re, matrix_im, preconditioner_env, matrix_name, matrix)
531
532 TYPE(dbcsr_type), POINTER :: matrix_re, matrix_im
533 TYPE(preconditioner_type) :: preconditioner_env
534 CHARACTER(LEN=*), INTENT(IN) :: matrix_name
535 TYPE(cp_cfm_type), INTENT(OUT) :: matrix
536
537 INTEGER :: ncol, nrow
538 TYPE(cp_fm_struct_type), POINTER :: fm_struct
539 TYPE(cp_fm_type) :: matrix_im_fm, matrix_re_fm
540
541 NULLIFY (fm_struct)
542 cpassert(ASSOCIATED(matrix_re))
543 cpassert(ASSOCIATED(matrix_im))
544 CALL dbcsr_get_info(matrix_re, nfullrows_total=nrow, nfullcols_total=ncol)
545 CALL cp_fm_struct_create(fm_struct, nrow_global=nrow, ncol_global=ncol, &
546 context=preconditioner_env%ctxt, &
547 para_env=preconditioner_env%para_env)
548 CALL cp_fm_create(matrix_re_fm, fm_struct, name=trim(matrix_name)//' real')
549 CALL cp_fm_create(matrix_im_fm, fm_struct, name=trim(matrix_name)//' imaginary')
550 CALL cp_fm_struct_release(fm_struct)
551 CALL copy_dbcsr_to_fm(matrix_re, matrix_re_fm)
552 CALL copy_dbcsr_to_fm(matrix_im, matrix_im_fm)
553 CALL cp_cfm_create(matrix, matrix_re_fm%matrix_struct, name=matrix_name)
554 CALL cp_fm_to_cfm(matrix_re_fm, matrix_im_fm, matrix)
555 CALL cp_fm_release(matrix_im_fm)
556 CALL cp_fm_release(matrix_re_fm)
557
558 END SUBROUTINE dbcsr_pair_to_cfm
559
560! **************************************************************************************************
561!> \brief Allows for a restart of the preconditioner
562!> depending on the method it purges all arrays or keeps them
563!> \param qs_env ...
564!> \param preconditioner ...
565!> \param prec_type ...
566!> \param nspins ...
567! **************************************************************************************************
568 SUBROUTINE restart_preconditioner(qs_env, preconditioner, prec_type, nspins)
569
570 TYPE(qs_environment_type), POINTER :: qs_env
571 TYPE(preconditioner_p_type), DIMENSION(:), POINTER :: preconditioner
572 INTEGER, INTENT(IN) :: prec_type, nspins
573
574 INTEGER :: ispin
575 TYPE(cp_blacs_env_type), POINTER :: blacs_env
576 TYPE(mp_para_env_type), POINTER :: para_env
577
578 NULLIFY (para_env, blacs_env)
579 CALL get_qs_env(qs_env, para_env=para_env, blacs_env=blacs_env)
580
581 IF (ASSOCIATED(preconditioner)) THEN
582 SELECT CASE (prec_type)
583 CASE (ot_precond_full_all, ot_precond_full_single) ! these depend on the ks matrix
584 DO ispin = 1, SIZE(preconditioner)
585 CALL destroy_preconditioner(preconditioner(ispin)%preconditioner)
586 DEALLOCATE (preconditioner(ispin)%preconditioner)
587 END DO
588 DEALLOCATE (preconditioner)
590 ot_precond_full_single_inverse) ! these are 'independent'
591 ! do nothing
592 CASE DEFAULT
593 cpabort("Unknown preconditioner type")
594 END SELECT
595 END IF
596
597 ! add an OT preconditioner if none is present
598 IF (.NOT. ASSOCIATED(preconditioner)) THEN
599 SELECT CASE (prec_type)
601 ALLOCATE (preconditioner(nspins))
602 CASE DEFAULT
603 ALLOCATE (preconditioner(1))
604 END SELECT
605 DO ispin = 1, SIZE(preconditioner)
606 ALLOCATE (preconditioner(ispin)%preconditioner)
607 CALL init_preconditioner(preconditioner(ispin)%preconditioner, &
608 para_env=para_env, &
609 blacs_env=blacs_env)
610 END DO
611 END IF
612
613 END SUBROUTINE restart_preconditioner
614
615! **************************************************************************************************
616!> \brief ...
617!> \param qs_env ...
618!> \param mos ...
619!> \param matrix_ks ...
620!> \param matrix_s ...
621!> \param ot_preconditioner ...
622!> \param prec_type ...
623!> \param solver_type ...
624!> \param energy_gap ...
625!> \param nspins ...
626!> \param has_unit_metric ...
627!> \param convert_to_dbcsr ...
628!> \param chol_type ...
629!> \param full_mo_set ...
630!> \param chebyshev_degree ...
631! **************************************************************************************************
632 SUBROUTINE prepare_preconditioner(qs_env, mos, matrix_ks, matrix_s, &
633 ot_preconditioner, prec_type, solver_type, &
634 energy_gap, nspins, has_unit_metric, &
635 convert_to_dbcsr, chol_type, full_mo_set, chebyshev_degree)
636
637 TYPE(qs_environment_type), POINTER :: qs_env
638 TYPE(mo_set_type), DIMENSION(:), INTENT(INOUT) :: mos
639 TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: matrix_ks, matrix_s
640 TYPE(preconditioner_p_type), DIMENSION(:), POINTER :: ot_preconditioner
641 INTEGER, INTENT(IN) :: prec_type, solver_type
642 REAL(dp), INTENT(IN) :: energy_gap
643 INTEGER, INTENT(IN) :: nspins
644 LOGICAL, INTENT(IN), OPTIONAL :: has_unit_metric, convert_to_dbcsr
645 INTEGER, INTENT(IN), OPTIONAL :: chol_type
646 LOGICAL, INTENT(IN), OPTIONAL :: full_mo_set
647 INTEGER, INTENT(IN), OPTIONAL :: chebyshev_degree
648
649 CHARACTER(LEN=*), PARAMETER :: routinen = 'prepare_preconditioner'
650
651 CHARACTER(LEN=default_string_length) :: msg
652 INTEGER :: handle, icall, ispin, &
653 my_chebyshev_degree, n_loops
654 INTEGER, DIMENSION(5) :: nocc, norb
655 LOGICAL :: do_co_rotate, my_convert_to_dbcsr, &
656 my_full_mo_set, my_has_unit_metric, &
657 use_mo_coeff_b
658 TYPE(cp_blacs_env_type), POINTER :: blacs_env
659 TYPE(cp_fm_type), POINTER :: mo_coeff
660 TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: kinetic
661 TYPE(dbcsr_type), POINTER :: matrix_t, mo_coeff_b
662 TYPE(dft_control_type), POINTER :: dft_control
663 TYPE(mp_para_env_type), POINTER :: para_env
664
665 CALL timeset(routinen, handle)
666 NULLIFY (matrix_t, mo_coeff_b, mo_coeff, kinetic, dft_control, para_env, blacs_env)
667 my_has_unit_metric = .false.
668 IF (PRESENT(has_unit_metric)) my_has_unit_metric = has_unit_metric
669 my_convert_to_dbcsr = .true.
670 IF (PRESENT(convert_to_dbcsr)) my_convert_to_dbcsr = convert_to_dbcsr
671 my_full_mo_set = .false.
672 IF (PRESENT(full_mo_set)) my_full_mo_set = full_mo_set
673 my_chebyshev_degree = 8
674 IF (PRESENT(chebyshev_degree)) my_chebyshev_degree = chebyshev_degree
675
676 CALL get_qs_env(qs_env, &
677 dft_control=dft_control, &
678 para_env=para_env, &
679 blacs_env=blacs_env)
680
681 IF (dft_control%qs_control%semi_empirical .OR. dft_control%qs_control%dftb .OR. &
682 dft_control%qs_control%xtb) THEN
683 IF (prec_type == ot_precond_full_kinetic) THEN
684 msg = "Full_kinetic not available for semi-empirical methods"
685 cpabort(trim(msg))
686 END IF
687 matrix_t => matrix_s(1)%matrix
688 ELSE
689 cpassert(.NOT. my_has_unit_metric)
690 CALL get_qs_env(qs_env, kinetic=kinetic)
691 matrix_t => kinetic(1)%matrix
692 END IF
693
694 ! use full set of MOs or just occupied MOs
695 nocc = 0
696 norb = 0
697 IF (my_full_mo_set) THEN
698 DO ispin = 1, nspins
699 CALL get_mo_set(mo_set=mos(ispin), homo=nocc(ispin), nmo=norb(ispin))
700 CALL set_mo_set(mo_set=mos(ispin), homo=norb(ispin))
701 END DO
702 END IF
703 !determines how often make preconditioner is called, spin dependent methods have to be called twice
704 n_loops = 1
705 IF (prec_type == ot_precond_full_single_inverse) n_loops = nspins
706 ! check whether we need the ev and rotate the MOs
707 SELECT CASE (prec_type)
709 ! if one of these preconditioners is used every spin needs to call make_preconditioner
710 n_loops = nspins
711
712 do_co_rotate = ASSOCIATED(qs_env%mo_derivs)
713 DO ispin = 1, nspins
714 CALL get_mo_set(mo_set=mos(ispin), mo_coeff_b=mo_coeff_b, mo_coeff=mo_coeff)
715 use_mo_coeff_b = mos(ispin)%use_mo_coeff_b
716 IF (use_mo_coeff_b .AND. do_co_rotate) THEN
717 CALL calculate_subspace_eigenvalues(mo_coeff_b, matrix_ks(ispin)%matrix, &
718 do_rotation=.true., &
719 co_rotate=qs_env%mo_derivs(ispin)%matrix, &
720 para_env=para_env, &
721 blacs_env=blacs_env)
722 ELSE IF (use_mo_coeff_b) THEN
723 CALL calculate_subspace_eigenvalues(mo_coeff_b, matrix_ks(ispin)%matrix, &
724 do_rotation=.true., &
725 para_env=para_env, &
726 blacs_env=blacs_env)
727 ELSE
728 CALL calculate_subspace_eigenvalues(mo_coeff, matrix_ks(ispin)%matrix, &
729 do_rotation=.true.)
730 END IF
731 END DO
732 CASE DEFAULT
733 ! No need to rotate the MOs
734 END SELECT
735
736 ! check whether we have a preconditioner
737 SELECT CASE (prec_type)
738 CASE (ot_precond_none)
739 DO ispin = 1, SIZE(ot_preconditioner)
740 ot_preconditioner(ispin)%preconditioner%in_use = 0
741 END DO
742 CASE DEFAULT
743 DO icall = 1, n_loops
744 ot_preconditioner(icall)%preconditioner%polynomial_degree = my_chebyshev_degree
745 IF (my_has_unit_metric) THEN
746 CALL make_preconditioner(ot_preconditioner(icall)%preconditioner, &
747 prec_type, &
748 solver_type, &
749 matrix_h=matrix_ks(icall)%matrix, &
750 mo_set=mos(icall), &
751 energy_gap=energy_gap, &
752 convert_precond_to_dbcsr=my_convert_to_dbcsr)
753 ELSE
754 CALL make_preconditioner(ot_preconditioner(icall)%preconditioner, &
755 prec_type, &
756 solver_type, &
757 matrix_h=matrix_ks(icall)%matrix, &
758 matrix_s=matrix_s(1)%matrix, &
759 matrix_t=matrix_t, &
760 mo_set=mos(icall), &
761 energy_gap=energy_gap, &
762 convert_precond_to_dbcsr=my_convert_to_dbcsr, chol_type=chol_type)
763 END IF
764 END DO
765 END SELECT
766
767 ! reset homo values
768 IF (my_full_mo_set) THEN
769 DO ispin = 1, nspins
770 CALL set_mo_set(mo_set=mos(ispin), homo=nocc(ispin))
771 END DO
772 END IF
773
774 CALL timestop(handle)
775
776 END SUBROUTINE prepare_preconditioner
777
778END MODULE preconditioner
methods related to the blacs parallel environment
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.
Defines control structures, which contain the parameters and the settings for the DFT-based calculati...
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)
...
DBCSR operations in CP2K.
subroutine, public copy_dbcsr_to_fm(matrix, fm)
Copy a DBCSR matrix to a BLACS matrix.
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_full_kinetic
integer, parameter, public cholesky_reduce
integer, parameter, public ot_precond_solver_default
integer, parameter, public ot_precond_full_single
integer, parameter, public ot_precond_solver_inv_chol
integer, parameter, public ot_precond_none
integer, parameter, public ot_precond_full_single_inverse
integer, parameter, public ot_precond_s_inverse
integer, parameter, public ot_precond_solver_update
integer, parameter, public ot_precond_full_all
Defines the basic variable types.
Definition kinds.F:23
integer, parameter, public dp
Definition kinds.F:34
integer, parameter, public default_string_length
Definition kinds.F:57
Interface to the message passing library MPI.
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)
...
computes preconditioners, and implements methods to apply them currently used in qs_ot
subroutine, public make_complex_full_single_inverse(preconditioner_env, matrix_c0, matrix_h, matrix_s, energy_gap)
Build a gauge-covariant FULL_SINGLE_INVERSE operator for a complex k-point channel.
subroutine, public make_complex_full_kinetic(preconditioner_env, matrix_t, matrix_s, energy_gap)
Build the inverse complex kinetic-plus-overlap preconditioner.
subroutine, public make_complex_full_s_inverse(preconditioner_env, matrix_s)
Build the inverse complex overlap preconditioner.
subroutine, public make_complex_full_single(preconditioner_env, matrix_h, matrix_s, energy_homo, energy_gap)
Build the complex spectral FULL_SINGLE preconditioner.
subroutine, public make_preconditioner_matrix(preconditioner_env, matrix_h, matrix_s, matrix_t, mo_coeff, energy_homo, eigenvalues_ot, energy_gap, my_solver_type)
...
subroutine, public make_complex_full_all(preconditioner_env, matrix_c0, matrix_h, matrix_s, c0_evals, energy_gap)
Build the state-selective FULL_ALL operator for a complex k-point channel. The occupied/reference sub...
solves the preconditioner, contains to utility function for fm<->dbcsr transfers, should be moved soo...
subroutine, public transfer_dbcsr_to_fm(dbcsr_matrix, fm_matrix, para_env, context)
transfers a dbcsr to a full matrix
subroutine, public solve_preconditioner(my_solver_type, preconditioner_env, matrix_s, matrix_h)
...
subroutine, public transfer_fm_to_dbcsr(fm_matrix, dbcsr_matrix, template_mat)
transfers a full matrix to a dbcsr
types of preconditioners
subroutine, public init_preconditioner(preconditioner_env, para_env, blacs_env)
...
subroutine, public destroy_preconditioner(preconditioner_env)
...
computes preconditioners, and implements methods to apply them currently used in qs_ot
subroutine, public make_preconditioner_complex_full_all(preconditioner_env, matrix_c_re, matrix_c_im, matrix_h_re, matrix_h_im, matrix_s_re, matrix_s_im, mo_set, energy_gap, solver_type)
Construct FULL_ALL directly from one complex H(k), S(k), and C(k) channel.
subroutine, public make_preconditioner_complex_full_s_inverse(preconditioner_env, matrix_s_re, matrix_s_im, solver_type)
Construct a complex FULL_S_INVERSE preconditioner.
subroutine, public make_preconditioner_complex_full_single(preconditioner_env, matrix_h_re, matrix_h_im, matrix_s_re, matrix_s_im, mo_set, energy_gap, solver_type)
Construct a complex FULL_SINGLE preconditioner from H(k) and S(k).
subroutine, public dbcsr_pair_to_cfm(matrix_re, matrix_im, preconditioner_env, matrix_name, matrix)
Copy a real/imaginary DBCSR pair to one distributed complex full matrix.
subroutine, public make_preconditioner_complex_full_single_inverse(preconditioner_env, matrix_c_re, matrix_c_im, matrix_h_re, matrix_h_im, matrix_s_re, matrix_s_im, energy_gap, solver_type)
Construct a complex FULL_SINGLE_INVERSE preconditioner without discarding Im(H,S,C).
subroutine, public restart_preconditioner(qs_env, preconditioner, prec_type, nspins)
Allows for a restart of the preconditioner depending on the method it purges all arrays or keeps them...
subroutine, public prepare_preconditioner(qs_env, mos, matrix_ks, matrix_s, ot_preconditioner, prec_type, solver_type, energy_gap, nspins, has_unit_metric, convert_to_dbcsr, chol_type, full_mo_set, chebyshev_degree)
...
subroutine, public make_preconditioner_complex_full_kinetic(preconditioner_env, matrix_t_re, matrix_t_im, matrix_s_re, matrix_s_im, energy_gap, solver_type)
Construct a complex FULL_KINETIC preconditioner.
subroutine, public make_preconditioner(preconditioner_env, precon_type, solver_type, matrix_h, matrix_s, matrix_t, mo_set, energy_gap, convert_precond_to_dbcsr, chol_type)
...
subroutine, public get_qs_env(qs_env, atomic_kind_set, qs_kind_set, cell, super_cell, cell_ref, use_ref_cell, kpoints, dft_control, mos, sab_orb, sab_all, qmmm, qmmm_periodic, mimic, sac_ae, sac_ppl, sac_lri, sap_ppnl, sab_vdw, sab_scp, sap_oce, sab_lrc, sab_se, sab_xtbe, sab_tbe, sab_core, sab_xb, sab_xtb_pp, sab_xtb_nonbond, sab_almo, sab_kp, sab_kp_nosym, sab_cneo, particle_set, energy, force, matrix_h, matrix_h_im, matrix_ks, matrix_ks_im, matrix_vxc, run_rtp, rtp, matrix_h_kp, matrix_h_im_kp, matrix_ks_kp, matrix_ks_im_kp, matrix_vxc_kp, kinetic_kp, matrix_s_kp, matrix_w_kp, matrix_s_ri_aux_kp, matrix_s, matrix_s_ri_aux, matrix_w, matrix_p_mp2, matrix_p_mp2_admm, matrix_vhxc, rho, rho_xc, pw_env, ewald_env, ewald_pw, active_space, mpools, input, para_env, blacs_env, scf_control, rel_control, kinetic, qs_charges, vppl, xcint_weights, rho_core, rho_nlcc, rho_nlcc_g, ks_env, ks_qmmm_env, wf_history, scf_env, local_particles, local_molecules, distribution_2d, dbcsr_dist, molecule_kind_set, molecule_set, subsys, cp_subsys, oce, local_rho_set, rho_atom_set, task_list, task_list_soft, rho0_atom_set, rho0_mpole, rhoz_set, rhoz_cneo_set, ecoul_1c, rho0_s_rs, rho0_s_gs, rhoz_cneo_s_rs, rhoz_cneo_s_gs, do_kpoints, has_unit_metric, requires_mo_derivs, mo_derivs, mo_loc_history, nkind, natom, nelectron_total, nelectron_spin, efield, neighbor_list_id, linres_control, xas_env, virial, cp_ddapc_env, cp_ddapc_ewald, outer_scf_history, outer_scf_ihistory, x_data, et_coupling, dftb_potential, results, se_taper, se_store_int_env, se_nddo_mpole, se_nonbond_env, admm_env, lri_env, lri_density, exstate_env, ec_env, harris_env, dispersion_env, gcp_env, vee, rho_external, external_vxc, mask, mp2_env, bs_env, kg_env, wanniercentres, atprop, ls_scf_env, do_transport, transport_env, v_hartree_rspace, s_mstruct_changed, rho_changed, potential_changed, forces_up_to_date, mscfg_env, almo_scf_env, gradient_history, variable_history, embed_pot, spin_embed_pot, polar_env, mos_last_converged, eeq, rhs, do_rixs, tb_tblite)
Get the QUICKSTEP environment.
collects routines that perform operations directly related to MOs
Definition and initialisation of the mo data type.
Definition qs_mo_types.F:22
subroutine, public set_mo_set(mo_set, maxocc, homo, lfomo, nao, nelectron, n_el_f, nmo, eigenvalues, occupation_numbers, uniform_occupation, kts, mu, flexible_electron_count)
Set the components of a MO set data structure.
subroutine, public get_mo_set(mo_set, maxocc, homo, lfomo, nao, nelectron, n_el_f, nmo, eigenvalues, occupation_numbers, mo_coeff, mo_coeff_b, uniform_occupation, kts, mu, flexible_electron_count)
Get the components of a MO set data structure.
represent a blacs multidimensional parallel environment (for the mpi corrispective see cp_paratypes/m...
Represent a complex full matrix.
keeps the information about the structure of a full matrix
represent a full matrix
stores all the informations relevant to an mpi environment