(git:6344619)
Loading...
Searching...
No Matches
qs_fb_env_methods.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
9
15 USE cell_types, ONLY: cell_type
18 USE cp_dbcsr_api, ONLY: &
22 dbcsr_set, dbcsr_type, dbcsr_type_no_symmetry
39 USE cp_fm_types, ONLY: cp_fm_create,&
57 USE kinds, ONLY: default_string_length,&
58 dp
60 USE orbital_pointers, ONLY: nco,&
61 ncoset
65 USE qs_diis, ONLY: qs_diis_b_step
68 USE qs_fb_atomic_halo_types, ONLY: &
74 USE qs_fb_env_types, ONLY: fb_env_get,&
85 USE qs_kind_types, ONLY: get_qs_kind,&
88 USE qs_mo_types, ONLY: allocate_mo_set,&
96 USE string_utilities, ONLY: compress,&
98#include "./base/base_uses.f90"
99
100 IMPLICIT NONE
101
102 PRIVATE
103
104 CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'qs_fb_env_methods'
105
106 PUBLIC :: fb_env_do_diag, &
111
112CONTAINS
113
114! **************************************************************************************************
115!> \brief Do filtered matrix method diagonalisation
116!> \param fb_env : the filter matrix environment
117!> \param qs_env : quickstep environment
118!> \param matrix_ks : DBCSR system (unfiltered) input KS matrix
119!> \param matrix_s : DBCSR system (unfiltered) input overlap matrix
120!> \param scf_section : SCF input section
121!> \param diis_step : whether we are doing a DIIS step
122!> \author Lianheng Tong (LT) lianheng.tong@kcl.ac.uk
123! **************************************************************************************************
124 SUBROUTINE fb_env_do_diag(fb_env, &
125 qs_env, &
126 matrix_ks, &
127 matrix_s, &
128 scf_section, &
129 diis_step)
130 TYPE(fb_env_obj), INTENT(INOUT) :: fb_env
131 TYPE(qs_environment_type), POINTER :: qs_env
132 TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: matrix_ks, matrix_s
133 TYPE(section_vals_type), POINTER :: scf_section
134 LOGICAL, INTENT(INOUT) :: diis_step
135
136 CHARACTER(LEN=*), PARAMETER :: routinen = 'fb_env_do_diag'
137
138 CHARACTER(len=2) :: spin_string
139 CHARACTER(len=default_string_length) :: name
140 INTEGER :: filtered_nfullrowsorcols_total, handle, homo_filtered, ispin, lfomo_filtered, &
141 my_nmo, nao, ndep, nelectron, nmo, nmo_filtered, nspin, original_nfullrowsorcols_total
142 INTEGER, DIMENSION(:), POINTER :: filtered_roworcol_block_sizes, &
143 original_roworcol_block_sizes
144 LOGICAL :: collective_com
145 REAL(kind=dp) :: diis_error, eps_default, eps_diis, eps_eigval, fermi_level, filter_temp, &
146 flexible_electron_count, kts_filtered, maxocc, mu_filtered
147 REAL(kind=dp), DIMENSION(:), POINTER :: eigenvalues, eigenvalues_filtered, occ, &
148 occ_filtered
149 TYPE(cp_blacs_env_type), POINTER :: blacs_env
150 TYPE(cp_fm_struct_type), POINTER :: filter_fm_struct, fm_struct
151 TYPE(cp_fm_type) :: fm_matrix_filter, fm_matrix_filtered_ks, &
152 fm_matrix_filtered_s, fm_matrix_ortho, &
153 fm_matrix_work
154 TYPE(cp_fm_type), POINTER :: mo_coeff, mo_coeff_filtered
155 TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: matrix_filter
156 TYPE(dbcsr_type) :: matrix_filtered_ks, matrix_filtered_s, &
157 matrix_tmp
158 TYPE(dbcsr_type), POINTER :: matrix_filtered_p
159 TYPE(fb_atomic_halo_list_obj) :: atomic_halos
160 TYPE(fb_trial_fns_obj) :: trial_fns
161 TYPE(mo_set_type), DIMENSION(:), POINTER :: mos, mos_filtered
162 TYPE(mp_para_env_type), POINTER :: para_env
163 TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
164 TYPE(qs_scf_env_type), POINTER :: scf_env
165 TYPE(scf_control_type), POINTER :: scf_control
166
167! TYPE(neighbor_list_set_p_type), DIMENSION(:), POINTER :: sab_orb
168
169 CALL timeset(routinen, handle)
170
171 NULLIFY (scf_env, scf_control, para_env, blacs_env, particle_set)
172 NULLIFY (eigenvalues, eigenvalues_filtered, occ, occ_filtered)
173 NULLIFY (mos, mos_filtered)
174 NULLIFY (matrix_filter, matrix_filtered_p)
175 NULLIFY (fm_struct, filter_fm_struct)
176 NULLIFY (mo_coeff_filtered, mo_coeff)
177 ! NULLIFY(sab_orb)
178 CALL fb_atomic_halo_list_nullify(atomic_halos)
179 CALL fb_trial_fns_nullify(trial_fns)
180 NULLIFY (original_roworcol_block_sizes, filtered_roworcol_block_sizes)
181
182 ! get qs_env information
183 CALL get_qs_env(qs_env=qs_env, &
184 scf_env=scf_env, &
185 scf_control=scf_control, &
186 para_env=para_env, &
187 blacs_env=blacs_env, &
188 particle_set=particle_set, &
189 mos=mos)
190
191 nspin = SIZE(matrix_ks)
192
193 ! ----------------------------------------------------------------------
194 ! DIIS step - based on non-filtered matrices and MOs
195 ! ----------------------------------------------------------------------
196
197 DO ispin = 1, nspin
198 CALL copy_dbcsr_to_fm(matrix_ks(ispin)%matrix, &
199 scf_env%scf_work1(ispin))
200 END DO
201
202 eps_diis = scf_control%eps_diis
203 eps_eigval = epsilon(0.0_dp)
204
205 IF (scf_env%iter_count > 1 .AND. .NOT. scf_env%skip_diis) THEN
206 CALL qs_diis_b_step(scf_env%scf_diis_buffer, mos, scf_env%scf_work1, &
207 scf_env%scf_work2, scf_env%iter_delta, &
208 diis_error, diis_step, eps_diis, scf_control%nmixing, &
209 s_matrix=matrix_s, scf_section=scf_section)
210 ELSE
211 diis_step = .false.
212 END IF
213
214 IF (diis_step) THEN
215 scf_env%iter_param = diis_error
216 scf_env%iter_method = "DIIS/Filter"
217 ELSE
218 IF (scf_env%mixing_method == 0) THEN
219 scf_env%iter_method = "NoMix/Filter"
220 ELSE IF (scf_env%mixing_method == 1) THEN
221 scf_env%iter_param = scf_env%p_mix_alpha
222 scf_env%iter_method = "P_Mix/Filter"
223 ELSE IF (scf_env%mixing_method > 1) THEN
224 scf_env%iter_param = scf_env%mixing_store%alpha
225 scf_env%iter_method = trim(scf_env%mixing_store%iter_method)//"/Filter"
226 END IF
227 END IF
228
229 ! ----------------------------------------------------------------------
230 ! Construct Filter Matrix
231 ! ----------------------------------------------------------------------
232
233 CALL fb_env_get(fb_env=fb_env, &
234 filter_temperature=filter_temp, &
235 atomic_halos=atomic_halos, &
236 eps_default=eps_default)
237
238 ! construct trial functions
239 CALL get_mo_set(mo_set=mos(1), maxocc=maxocc)
240 CALL fb_env_build_trial_fns_auto(fb_env, qs_env, maxocc)
241 CALL fb_env_get(fb_env=fb_env, &
242 trial_fns=trial_fns)
243
244 ! allocate filter matrix (matrix_filter(ispin)%matrix are
245 ! nullified by dbcsr_allocate_matrix_set)
246 CALL dbcsr_allocate_matrix_set(matrix_filter, nspin)
247 DO ispin = 1, nspin
248 ! get system-wide fermi energy and occupancy, we use this to
249 ! define the filter function used for the filter matrix
250 CALL get_mo_set(mo_set=mos(ispin), &
251 mu=fermi_level, &
252 maxocc=maxocc)
253 ! get filter matrix name
254 WRITE (spin_string, fmt="(I1)") ispin
255 name = trim("FILTER MATRIX SPIN "//spin_string)
256 CALL compress(name)
257 CALL uppercase(name)
258 ! calculate filter matrix (matrix_s(1) is the overlap, the rest
259 ! in the array are its derivatives)
260 CALL fb_env_get(fb_env=fb_env, &
261 collective_com=collective_com)
262 IF (collective_com) THEN
263 CALL fb_fltrmat_build_2(h_mat=matrix_ks(ispin)%matrix, &
264 s_mat=matrix_s(1)%matrix, &
265 atomic_halos=atomic_halos, &
266 trial_fns=trial_fns, &
267 para_env=para_env, &
268 particle_set=particle_set, &
269 fermi_level=fermi_level, &
270 filter_temp=filter_temp, &
271 name=name, &
272 filter_mat=matrix_filter(ispin)%matrix, &
273 tolerance=eps_default)
274 ELSE
275 CALL fb_fltrmat_build(h_mat=matrix_ks(ispin)%matrix, &
276 s_mat=matrix_s(1)%matrix, &
277 atomic_halos=atomic_halos, &
278 trial_fns=trial_fns, &
279 para_env=para_env, &
280 particle_set=particle_set, &
281 fermi_level=fermi_level, &
282 filter_temp=filter_temp, &
283 name=name, &
284 filter_mat=matrix_filter(ispin)%matrix, &
285 tolerance=eps_default)
286 END IF
287 END DO ! ispin
288
289 ! ----------------------------------------------------------------------
290 ! Do Filtered Diagonalisation
291 ! ----------------------------------------------------------------------
292
293 ! Obtain matrix dimensions. KS and S matrices are symmetric, so
294 ! row_block_sizes and col_block_sizes should be identical. The
295 ! same applies to the filtered block sizes. Note that filter
296 ! matrix will have row_block_sizes equal to that of the original,
297 ! and col_block_sizes equal to that of the filtered. We assume
298 ! also that the matrix dimensions are identical for both spin
299 ! channels.
300 CALL dbcsr_get_info(matrix_ks(1)%matrix, &
301 row_blk_size=original_roworcol_block_sizes, &
302 nfullrows_total=original_nfullrowsorcols_total)
303 CALL dbcsr_get_info(matrix_filter(1)%matrix, &
304 col_blk_size=filtered_roworcol_block_sizes, &
305 nfullcols_total=filtered_nfullrowsorcols_total)
306
307 ! filter diagonalisation works on a smaller basis set, and thus
308 ! requires a new mo_set (molecular orbitals | eigenvectors) and
309 ! the corresponding matrix pools for the eigenvector coefficients
310 ALLOCATE (mos_filtered(nspin))
311 DO ispin = 1, nspin
312 CALL get_mo_set(mo_set=mos(ispin), &
313 maxocc=maxocc, &
314 nelectron=nelectron, &
315 flexible_electron_count=flexible_electron_count)
316 CALL allocate_mo_set(mo_set=mos_filtered(ispin), &
317 nao=filtered_nfullrowsorcols_total, &
318 nmo=filtered_nfullrowsorcols_total, &
319 nelectron=nelectron, &
320 n_el_f=real(nelectron, dp), &
321 maxocc=maxocc, &
322 flexible_electron_count=flexible_electron_count)
323 END DO ! ispin
324
325 ! create DBCSR filtered KS matrix, this is reused for each spin
326 ! channel
327 ! both row_blk_size and col_blk_size should be that of
328 ! col_blk_size of the filter matrix
329 CALL dbcsr_create(matrix=matrix_filtered_ks, template=matrix_ks(1)%matrix, &
330 name=trim("FILTERED_KS_MATRIX"), &
331 matrix_type=dbcsr_type_no_symmetry, &
332 row_blk_size=filtered_roworcol_block_sizes, &
333 col_blk_size=filtered_roworcol_block_sizes)
334 CALL dbcsr_finalize(matrix_filtered_ks)
335
336 ! create DBCSR filtered S (overlap) matrix. Note that
337 ! matrix_s(1)%matrix is the original overlap matrix---the rest in
338 ! the array are derivatives, and it should not depend on
339 ! spin. HOWEVER, since the filter matrix is constructed from KS
340 ! matrix, and does depend on spin, the filtered S also becomes
341 ! spin dependent. Nevertheless this matrix is reused for each spin
342 ! channel
343 ! both row_blk_size and col_blk_size should be that of
344 ! col_blk_size of the filter matrix
345 CALL dbcsr_create(matrix=matrix_filtered_s, template=matrix_s(1)%matrix, &
346 name=trim("FILTERED_S_MATRIX"), &
347 matrix_type=dbcsr_type_no_symmetry, &
348 row_blk_size=filtered_roworcol_block_sizes, &
349 col_blk_size=filtered_roworcol_block_sizes)
350 CALL dbcsr_finalize(matrix_filtered_s)
351
352 ! create temporary matrix for constructing filtered KS and S
353 ! the temporary matrix won't be square
354 CALL dbcsr_create(matrix=matrix_tmp, template=matrix_s(1)%matrix, &
355 name=trim("TEMPORARY_MATRIX"), &
356 matrix_type=dbcsr_type_no_symmetry, &
357 row_blk_size=original_roworcol_block_sizes, &
358 col_blk_size=filtered_roworcol_block_sizes)
359 CALL dbcsr_finalize(matrix_tmp)
360
361 ! create fm format matrices used for diagonalisation
362 CALL cp_fm_struct_create(fmstruct=fm_struct, &
363 para_env=para_env, &
364 context=blacs_env, &
365 nrow_global=filtered_nfullrowsorcols_total, &
366 ncol_global=filtered_nfullrowsorcols_total)
367 ! both fm_matrix_filtered_s and fm_matrix_filtered_ks are reused
368 ! for each spin channel
369 CALL cp_fm_create(fm_matrix_filtered_s, &
370 fm_struct, &
371 name="FM_MATRIX_FILTERED_S")
372 CALL cp_fm_create(fm_matrix_filtered_ks, &
373 fm_struct, &
374 name="FM_MATRIX_FILTERED_KS")
375 ! creaate work matrix
376 CALL cp_fm_create(fm_matrix_work, fm_struct, name="FM_MATRIX_WORK")
377 CALL cp_fm_create(fm_matrix_ortho, fm_struct, name="FM_MATRIX_ORTHO")
378 ! all fm matrices are created, so can release fm_struct
379 CALL cp_fm_struct_release(fm_struct)
380
381 ! construct filtered KS, S matrix and diagonalise
382 DO ispin = 1, nspin
383
384 ! construct filtered KS matrix
385 CALL dbcsr_multiply("N", "N", 1.0_dp, &
386 matrix_ks(ispin)%matrix, matrix_filter(ispin)%matrix, &
387 0.0_dp, matrix_tmp)
388 CALL dbcsr_multiply("T", "N", 1.0_dp, &
389 matrix_filter(ispin)%matrix, matrix_tmp, &
390 0.0_dp, matrix_filtered_ks)
391 ! construct filtered S_matrix
392 CALL dbcsr_multiply("N", "N", 1.0_dp, &
393 matrix_s(1)%matrix, matrix_filter(ispin)%matrix, &
394 0.0_dp, matrix_tmp)
395 CALL dbcsr_multiply("T", "N", 1.0_dp, &
396 matrix_filter(ispin)%matrix, matrix_tmp, &
397 0.0_dp, matrix_filtered_s)
398
399 ! now that we have the filtered KS and S matrices for this spin
400 ! channel, perform ordinary diagonalisation
401
402 ! convert DBCSR matrices to fm format
403 CALL copy_dbcsr_to_fm(matrix_filtered_s, fm_matrix_filtered_s)
404 CALL copy_dbcsr_to_fm(matrix_filtered_ks, fm_matrix_filtered_ks)
405
406 CALL get_mo_set(mos_filtered(ispin), nmo=nmo, nao=nao)
407
408 CALL cp_fm_struct_create(fm_struct, nrow_global=nao, &
409 ncol_global=nmo, para_env=para_env, &
410 context=blacs_env)
411
412 ! setup matrix pools for the molecular orbitals
413 CALL init_mo_set(mos_filtered(ispin), &
414 fm_struct=fm_struct, &
415 name="FILTERED_MOS")
416 CALL cp_fm_struct_release(fm_struct)
417
418 ! now diagonalise
419 CALL fb_env_eigensolver(fm_matrix_filtered_ks, &
420 fm_matrix_filtered_s, &
421 mos_filtered(ispin), &
422 fm_matrix_ortho, &
423 fm_matrix_work, &
424 eps_eigval, &
425 ndep, &
426 scf_env%cholesky_method)
427 END DO ! ispin
428
429 ! release temporary matrices
430 CALL dbcsr_release(matrix_filtered_s)
431 CALL dbcsr_release(matrix_filtered_ks)
432 CALL cp_fm_release(fm_matrix_filtered_s)
433 CALL cp_fm_release(fm_matrix_filtered_ks)
434 CALL cp_fm_release(fm_matrix_work)
435 CALL cp_fm_release(fm_matrix_ortho)
436
437 ! ----------------------------------------------------------------------
438 ! Construct New Density Matrix
439 ! ----------------------------------------------------------------------
440
441 ! calculate filtered molecular orbital occupation numbers and fermi
442 ! level etc
443 CALL set_mo_occupation(mo_array=mos_filtered, &
444 smear=scf_control%smear)
445
446 ! get the filtered density matrix and then convert back to the
447 ! full basis version in scf_env ready to be used outside this
448 ! subroutine
449 ALLOCATE (matrix_filtered_p)
450 ! the filtered density matrix should have the same sparse
451 ! structure as the original density matrix, we must copy the
452 ! sparse structure here, since construction of the density matrix
453 ! preserves its sparse form, and therefore matrix_filtered_p must
454 ! have its blocks allocated here now. We assume the original
455 ! density matrix scf_env%p_mix_new has the same sparse structure
456 ! in both spin channels.
457 CALL dbcsr_create(matrix=matrix_filtered_p, template=scf_env%p_mix_new(1, 1)%matrix, &
458 name=trim("FILTERED_MATRIX_P"), &
459 row_blk_size=filtered_roworcol_block_sizes, &
460 col_blk_size=filtered_roworcol_block_sizes)
461 CALL dbcsr_finalize(matrix_filtered_p)
462 CALL fb_dbcsr_copy_sparse_struct(matrix_filtered_p, &
463 scf_env%p_mix_new(1, 1)%matrix)
464 ! old implementation, using sab_orb to allocate the blocks in matrix_filtered_p
465 ! CALL get_qs_env(qs_env=qs_env, sab_orb=sab_orb)
466 ! CALL cp_dbcsr_alloc_block_from_nbl(matrix_filtered_p, sab_orb)
467 CALL dbcsr_set(matrix_filtered_p, 0.0_dp)
468
469 DO ispin = 1, nspin
470 ! calculate matrix_filtered_p
471 CALL calculate_density_matrix(mos_filtered(ispin), &
472 matrix_filtered_p)
473 ! convert back to full basis p
474 CALL dbcsr_multiply("N", "N", 1.0_dp, &
475 matrix_filter(ispin)%matrix, matrix_filtered_p, &
476 0.0_dp, matrix_tmp)
477 CALL dbcsr_multiply("N", "T", 1.0_dp, &
478 matrix_tmp, matrix_filter(ispin)%matrix, &
479 0.0_dp, scf_env%p_mix_new(ispin, 1)%matrix, &
480 retain_sparsity=.true.)
481 ! note that we want to retain the sparse structure of
482 ! scf_env%p_mix_new
483 END DO ! ispin
484
485 ! release temporary matrices
486 CALL dbcsr_release(matrix_tmp)
487 CALL dbcsr_release(matrix_filtered_p)
488 DEALLOCATE (matrix_filtered_p)
489
490 ! ----------------------------------------------------------------------
491 ! Update MOs
492 ! ----------------------------------------------------------------------
493
494 ! we still need to convert mos_filtered back to the full basis
495 ! version (mos) for this, we need to update mo_coeff (and/or
496 ! mo_coeff_b --- the DBCSR version, if used) of mos
497
498 ! note also that mo_eigenvalues cannot be fully updated, given
499 ! that the eigenvalues are computed in a smaller basis, and thus
500 ! do not give the full spectron. Printing of molecular states
501 ! (molecular DOS) at each SCF step is therefore not recommended
502 ! when using this method. The idea is that if one wants a full
503 ! molecular DOS, then one should perform a full diagonalisation
504 ! without the filters once the SCF has been achieved.
505
506 ! NOTE: from reading the source code, it appears that mo_coeff_b
507 ! is actually never used by default (DOUBLE CHECK?!). Even
508 ! subroutine eigensolver_dbcsr updates mo_coeff, and not
509 ! mo_coeff_b.
510
511 ! create FM format filter matrix
512 CALL cp_fm_struct_create(fmstruct=filter_fm_struct, &
513 para_env=para_env, &
514 context=blacs_env, &
515 nrow_global=original_nfullrowsorcols_total, &
516 ncol_global=filtered_nfullrowsorcols_total)
517 CALL cp_fm_create(fm_matrix_filter, &
518 filter_fm_struct, &
519 name="FM_MATRIX_FILTER")
520 CALL cp_fm_struct_release(filter_fm_struct)
521
522 DO ispin = 1, nspin
523 ! now the full basis mo_set should only contain the reduced
524 ! number of eigenvectors and eigenvalues
525 CALL get_mo_set(mo_set=mos_filtered(ispin), &
526 homo=homo_filtered, &
527 lfomo=lfomo_filtered, &
528 nmo=nmo_filtered, &
529 eigenvalues=eigenvalues_filtered, &
530 occupation_numbers=occ_filtered, &
531 mo_coeff=mo_coeff_filtered, &
532 kts=kts_filtered, &
533 mu=mu_filtered)
534 ! first set all the relevant scalars
535 CALL set_mo_set(mo_set=mos(ispin), &
536 homo=homo_filtered, &
537 lfomo=lfomo_filtered, &
538 kts=kts_filtered, &
539 mu=mu_filtered)
540 ! now set the arrays and fm_matrices
541 CALL get_mo_set(mo_set=mos(ispin), &
542 nmo=nmo, &
543 occupation_numbers=occ, &
544 eigenvalues=eigenvalues, &
545 mo_coeff=mo_coeff)
546 ! number of mos in original mo_set may sometimes be less than
547 ! nmo_filtered, so we must make sure we do not go out of bounds
548 my_nmo = min(nmo, nmo_filtered)
549 eigenvalues(:) = 0.0_dp
550 eigenvalues(1:my_nmo) = eigenvalues_filtered(1:my_nmo)
551 occ(:) = 0.0_dp
552 occ(1:my_nmo) = occ_filtered(1:my_nmo)
553 ! convert mo_coeff_filtered back to original basis
554 CALL cp_fm_set_all(matrix=mo_coeff, alpha=0.0_dp)
555 CALL copy_dbcsr_to_fm(matrix_filter(ispin)%matrix, fm_matrix_filter)
556 CALL cp_fm_gemm("N", "N", &
557 original_nfullrowsorcols_total, &
558 my_nmo, &
559 filtered_nfullrowsorcols_total, &
560 1.0_dp, fm_matrix_filter, mo_coeff_filtered, &
561 0.0_dp, mo_coeff)
562
563 END DO ! ispin
564
565 ! release temporary matrices
566 CALL cp_fm_release(fm_matrix_filter)
567
568 ! ----------------------------------------------------------------------
569 ! Final Clean Up
570 ! ----------------------------------------------------------------------
571
572 DO ispin = 1, nspin
573 CALL deallocate_mo_set(mo_set=mos_filtered(ispin))
574 END DO
575 DEALLOCATE (mos_filtered)
576 CALL dbcsr_deallocate_matrix_set(matrix_filter)
577
578 CALL timestop(handle)
579
580 END SUBROUTINE fb_env_do_diag
581
582! **************************************************************************************************
583!> \brief The main parallel eigensolver engine for filter matrix diagonalisation
584!> \param fm_KS : the BLACS distributed Kohn-Sham matrix, input only
585!> \param fm_S : the BLACS distributed overlap matrix, input only
586!> \param mo_set : upon output contains the molecular orbitals (eigenvectors)
587!> and eigenvalues
588!> \param fm_ortho : one of the work matrices, on output, the BLACS distributed
589!> matrix for orthogalising the eigen problem. E.g. if using
590!> Cholesky inversse, then the upper triangle part contains
591!> the inverse of Cholesky U; if not using Cholesky, then it
592!> contains the S^-1/2.
593!> \param fm_work : work matrix used by eigen solver
594!> \param eps_eigval : used for quenching the small numbers when computing S^-1/2
595!> any values less than eps_eigval is truncated to zero.
596!> \param ndep : if the overlap is not positive definite, then ndep > 0,
597!> and equals to the number of linear dependent basis functions
598!> in the filtered basis set
599!> \param method : method for solving generalised eigenvalue problem
600!> \author Lianheng Tong (LT) lianheng.tong@kcl.ac.uk
601! **************************************************************************************************
602 SUBROUTINE fb_env_eigensolver(fm_KS, fm_S, mo_set, fm_ortho, &
603 fm_work, eps_eigval, ndep, method)
604 TYPE(cp_fm_type), INTENT(IN) :: fm_ks, fm_s
605 TYPE(mo_set_type), INTENT(IN) :: mo_set
606 TYPE(cp_fm_type), INTENT(IN) :: fm_ortho, fm_work
607 REAL(kind=dp), INTENT(IN) :: eps_eigval
608 INTEGER, INTENT(OUT) :: ndep
609 INTEGER, INTENT(IN) :: method
610
611 CHARACTER(len=*), PARAMETER :: routinen = 'fb_env_eigensolver'
612
613 CHARACTER(len=8) :: ndep_string
614 INTEGER :: handle, info, my_method, nao, nmo
615 REAL(kind=dp), DIMENSION(:), POINTER :: mo_eigenvalues
616 TYPE(cp_fm_type), POINTER :: mo_coeff
617
618 CALL timeset(routinen, handle)
619
620 CALL get_mo_set(mo_set=mo_set, &
621 nao=nao, &
622 nmo=nmo, &
623 eigenvalues=mo_eigenvalues, &
624 mo_coeff=mo_coeff)
625 my_method = method
626 ndep = 0
627
628 ! first, obtain orthogonalisation (ortho) matrix
629 IF (my_method /= cholesky_off) THEN
630 CALL cp_fm_to_fm(fm_s, fm_ortho)
631 CALL cp_fm_cholesky_decompose(fm_ortho, info_out=info)
632 IF (info /= 0) THEN
633 CALL cp_warn(__location__, &
634 "Unable to perform Cholesky decomposition on the overlap "// &
635 "matrix. The new filtered basis may not be linearly "// &
636 "independent set. Revert to using inverse square-root "// &
637 "of the overlap. To avoid this warning, you can try "// &
638 "to use a higher filter termperature.")
639 my_method = cholesky_off
640 ELSE
641 SELECT CASE (my_method)
642 CASE (cholesky_dbcsr)
643 CALL cp_abort(__location__, &
644 "filter matrix method with CHOLESKY_DBCSR is not yet implemented")
645 CASE (cholesky_reduce)
646 CALL cp_fm_cholesky_reduce(fm_ks, fm_ortho)
647 CALL choose_eigv_solver(fm_ks, fm_work, mo_eigenvalues)
648 CALL cp_fm_cholesky_restore(fm_work, nmo, fm_ortho, mo_coeff, "SOLVE")
649 CASE (cholesky_restore)
650 CALL cp_fm_uplo_to_full(fm_ks, fm_work)
651 CALL cp_fm_cholesky_restore(fm_ks, nao, fm_ortho, fm_work, "SOLVE", &
652 pos="RIGHT")
653 CALL cp_fm_cholesky_restore(fm_work, nao, fm_ortho, fm_ks, "SOLVE", &
654 pos="LEFT", transa="T")
655 CALL choose_eigv_solver(fm_ks, fm_work, mo_eigenvalues)
656 CALL cp_fm_cholesky_restore(fm_work, nmo, fm_ortho, mo_coeff, "SOLVE")
657 CASE (cholesky_inverse)
658 CALL cp_fm_triangular_invert(fm_ortho)
659 CALL cp_fm_uplo_to_full(fm_ks, fm_work)
660 CALL cp_fm_triangular_multiply(fm_ortho, &
661 fm_ks, &
662 side="R", &
663 transpose_tr=.false., &
664 invert_tr=.false., &
665 uplo_tr="U", &
666 n_rows=nao, &
667 n_cols=nao, &
668 alpha=1.0_dp)
669 CALL cp_fm_triangular_multiply(fm_ortho, &
670 fm_ks, &
671 side="L", &
672 transpose_tr=.true., &
673 invert_tr=.false., &
674 uplo_tr="U", &
675 n_rows=nao, &
676 n_cols=nao, &
677 alpha=1.0_dp)
678 CALL choose_eigv_solver(fm_ks, fm_work, mo_eigenvalues)
679 CALL cp_fm_triangular_multiply(fm_ortho, &
680 fm_work, &
681 side="L", &
682 transpose_tr=.false., &
683 invert_tr=.false., &
684 uplo_tr="U", &
685 n_rows=nao, &
686 n_cols=nmo, &
687 alpha=1.0_dp)
688 CALL cp_fm_to_fm(fm_work, mo_coeff, nmo, 1, 1)
689 END SELECT
690 END IF
691 END IF
692 IF (my_method == cholesky_off) THEN
693 ! calculating ortho as S^-1/2 using diagonalisation of S, and
694 ! solve accordingly
695 CALL cp_fm_to_fm(fm_s, fm_ortho)
696 CALL cp_fm_power(fm_ortho, fm_work, -0.5_dp, &
697 eps_eigval, ndep)
698 IF (ndep > 0) THEN
699 WRITE (ndep_string, fmt="(I8)") ndep
700 CALL cp_warn(__location__, &
701 "Number of linearly dependent filtered orbitals: "//ndep_string)
702 END IF
703 ! solve eigen equatoin using S^-1/2
704 CALL cp_fm_symm("L", "U", nao, nao, 1.0_dp, fm_ks, fm_ortho, &
705 0.0_dp, fm_work)
706 CALL parallel_gemm("T", "N", nao, nao, nao, 1.0_dp, fm_ortho, &
707 fm_work, 0.0_dp, fm_ks)
708 CALL choose_eigv_solver(fm_ks, fm_work, mo_eigenvalues)
709 CALL parallel_gemm("N", "N", nao, nmo, nao, 1.0_dp, fm_ortho, &
710 fm_work, 0.0_dp, mo_coeff)
711 END IF
712
713 CALL timestop(handle)
714
715 END SUBROUTINE fb_env_eigensolver
716
717! **************************************************************************************************
718!> \brief Read input sections for filter matrix method
719!> \param fb_env : the filter matrix environment
720!> \param scf_section : SCF input section
721!> \author Lianheng Tong (LT) lianheng.tong@kcl.ac.uk
722! **************************************************************************************************
723 SUBROUTINE fb_env_read_input(fb_env, scf_section)
724
725 TYPE(fb_env_obj), INTENT(INOUT) :: fb_env
726 TYPE(section_vals_type), POINTER :: scf_section
727
728 CHARACTER(len=*), PARAMETER :: routinen = 'fb_env_read_input'
729
730 INTEGER :: handle
731 LOGICAL :: l_val
732 REAL(kind=dp) :: r_val
733 TYPE(section_vals_type), POINTER :: fb_section
734
735 CALL timeset(routinen, handle)
736
737 NULLIFY (fb_section)
738 fb_section => section_vals_get_subs_vals(scf_section, &
739 "DIAGONALIZATION%FILTER_MATRIX")
740 ! filter_temperature
741 CALL section_vals_val_get(fb_section, "FILTER_TEMPERATURE", &
742 r_val=r_val)
743 CALL fb_env_set(fb_env=fb_env, &
744 filter_temperature=r_val)
745 ! auto_cutoff_scale
746 CALL section_vals_val_get(fb_section, "AUTO_CUTOFF_SCALE", &
747 r_val=r_val)
748 CALL fb_env_set(fb_env=fb_env, &
749 auto_cutoff_scale=r_val)
750 ! communication model
751 CALL section_vals_val_get(fb_section, "COLLECTIVE_COMMUNICATION", &
752 l_val=l_val)
753 CALL fb_env_set(fb_env=fb_env, &
754 collective_com=l_val)
755 ! eps_default
756 CALL section_vals_val_get(fb_section, "EPS_FB", &
757 r_val=r_val)
758 CALL fb_env_set(fb_env=fb_env, &
759 eps_default=r_val)
760
761 CALL timestop(handle)
762
763 END SUBROUTINE fb_env_read_input
764
765! **************************************************************************************************
766!> \brief Automatically generate the cutoff radii of atoms used for
767!> constructing the atomic halos, based on basis set cutoff
768!> ranges for each kind
769!> \param fb_env : the filter matrix environment
770!> \param qs_env : quickstep environment
771!> \author Lianheng Tong (LT) lianheng.tong@kcl.ac.uk
772! **************************************************************************************************
773 SUBROUTINE fb_env_build_rcut_auto(fb_env, qs_env)
774 TYPE(fb_env_obj), INTENT(INOUT) :: fb_env
775 TYPE(qs_environment_type), POINTER :: qs_env
776
777 CHARACTER(len=*), PARAMETER :: routinen = 'fb_env_build_rcut_auto'
778
779 INTEGER :: handle, ikind, nkinds
780 REAL(kind=dp) :: auto_cutoff_scale, kind_radius
781 REAL(kind=dp), DIMENSION(:), POINTER :: rcut
782 TYPE(dft_control_type), POINTER :: dft_control
783 TYPE(gto_basis_set_p_type), DIMENSION(:), POINTER :: basis_set_list
784 TYPE(gto_basis_set_type), POINTER :: basis_set
785 TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
786
787 CALL timeset(routinen, handle)
788
789 NULLIFY (rcut, qs_kind_set, dft_control)
790
791 CALL get_qs_env(qs_env=qs_env, &
792 qs_kind_set=qs_kind_set, &
793 dft_control=dft_control)
794 CALL fb_env_get(fb_env=fb_env, &
795 auto_cutoff_scale=auto_cutoff_scale)
796
797 nkinds = SIZE(qs_kind_set)
798 ALLOCATE (rcut(nkinds))
799
800 ! reading from the other parts of the code, it seemed that
801 ! aux_fit_basis_set is only used when do_admm is TRUE. This can be
802 ! seen from the calls to generate_qs_task_list subroutine in
803 ! qs_create_task_list, found in qs_environment_methods.F:
804 ! basis_type is only set as input parameter for do_admm
805 ! calculations, and if not set, the task list is generated using
806 ! the default basis_set="ORB".
807 ALLOCATE (basis_set_list(nkinds))
808 IF (dft_control%do_admm) THEN
809 CALL basis_set_list_setup(basis_set_list, "AUX_FIT", qs_kind_set)
810 ELSE
811 CALL basis_set_list_setup(basis_set_list, "ORB", qs_kind_set)
812 END IF
813
814 DO ikind = 1, nkinds
815 basis_set => basis_set_list(ikind)%gto_basis_set
816 CALL get_gto_basis_set(gto_basis_set=basis_set, kind_radius=kind_radius)
817 rcut(ikind) = kind_radius*auto_cutoff_scale
818 END DO
819
820 CALL fb_env_set(fb_env=fb_env, &
821 rcut=rcut)
822
823 ! cleanup
824 DEALLOCATE (basis_set_list)
825
826 CALL timestop(handle)
827
828 END SUBROUTINE fb_env_build_rcut_auto
829
830! **************************************************************************************************
831!> \brief Builds an fb_atomic_halo_list object using information
832!> from fb_env
833!> \param fb_env the fb_env object
834!> \param qs_env : quickstep environment (need this to access particle)
835!> positions and their kinds as well as which particles
836!> are local to this process
837!> \param scf_section : SCF input section, for printing output
838!> \author Lianheng Tong (LT) lianheng.tong@kcl.ac.uk
839! **************************************************************************************************
840 SUBROUTINE fb_env_build_atomic_halos(fb_env, qs_env, scf_section)
841 TYPE(fb_env_obj), INTENT(INOUT) :: fb_env
842 TYPE(qs_environment_type), POINTER :: qs_env
843 TYPE(section_vals_type), POINTER :: scf_section
844
845 CHARACTER(len=*), PARAMETER :: routinen = 'fb_env_build_atomic_halos'
846
847 INTEGER :: handle, iatom, ihalo, max_natoms_local, natoms_global, natoms_local, nelectrons, &
848 nhalo_atoms, nkinds_global, owner_id_in_halo
849 INTEGER, DIMENSION(:), POINTER :: halo_atoms, local_atoms
850 REAL(kind=dp) :: cost
851 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :) :: pair_radii
852 REAL(kind=dp), DIMENSION(:), POINTER :: rcut
853 TYPE(cell_type), POINTER :: cell
854 TYPE(fb_atomic_halo_list_obj) :: atomic_halos
855 TYPE(fb_atomic_halo_obj), DIMENSION(:), POINTER :: halos
856 TYPE(mp_para_env_type), POINTER :: para_env
857 TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
858 TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
859
860 CALL timeset(routinen, handle)
861
862 cpassert(fb_env_has_data(fb_env))
863
864 NULLIFY (cell, halos, halo_atoms, rcut, particle_set, para_env, &
865 qs_kind_set, local_atoms)
866 CALL fb_atomic_halo_list_nullify(atomic_halos)
867
868 ! get relevant data from fb_env
869 CALL fb_env_get(fb_env=fb_env, &
870 rcut=rcut, &
871 local_atoms=local_atoms, &
872 nlocal_atoms=natoms_local)
873
874 ! create atomic_halos
875 CALL fb_atomic_halo_list_create(atomic_halos)
876
877 ! get the number of atoms and kinds:
878 CALL get_qs_env(qs_env=qs_env, &
879 natom=natoms_global, &
880 particle_set=particle_set, &
881 qs_kind_set=qs_kind_set, &
882 nkind=nkinds_global, &
883 para_env=para_env, &
884 cell=cell)
885
886 ! get the maximum number of local atoms across the procs.
887 max_natoms_local = natoms_local
888 CALL para_env%max(max_natoms_local)
889
890 ! create the halos, one for each local atom
891 ALLOCATE (halos(natoms_local))
892 DO ihalo = 1, natoms_local
893 CALL fb_atomic_halo_nullify(halos(ihalo))
894 CALL fb_atomic_halo_create(halos(ihalo))
895 END DO
896 CALL fb_atomic_halo_list_set(atomic_halos=atomic_halos, &
897 nhalos=natoms_local, &
898 max_nhalos=max_natoms_local)
899 ! build halos
900 ALLOCATE (pair_radii(nkinds_global, nkinds_global))
901 CALL fb_build_pair_radii(rcut, nkinds_global, pair_radii)
902 ihalo = 0
903 DO iatom = 1, natoms_local
904 ihalo = ihalo + 1
905 CALL fb_atomic_halo_build_halo_atoms(local_atoms(iatom), &
906 particle_set, &
907 cell, &
908 pair_radii, &
909 halo_atoms, &
910 nhalo_atoms, &
911 owner_id_in_halo)
912 CALL fb_atomic_halo_set(atomic_halo=halos(ihalo), &
913 owner_atom=local_atoms(iatom), &
914 owner_id_in_halo=owner_id_in_halo, &
915 natoms=nhalo_atoms, &
916 halo_atoms=halo_atoms)
917 ! prepare halo_atoms for another halo, do not deallocate, as
918 ! original data is being pointed at by the atomic halo data
919 ! structure
920 NULLIFY (halo_atoms)
921 ! calculate the number of electrons in each halo
922 nelectrons = fb_atomic_halo_nelectrons_estimate_z(halos(ihalo), &
923 particle_set)
924 ! calculate cost
925 cost = fb_atomic_halo_cost(halos(ihalo), particle_set, qs_kind_set)
926 CALL fb_atomic_halo_set(atomic_halo=halos(ihalo), &
927 nelectrons=nelectrons, &
928 cost=cost)
929 ! sort atomic halo
930 CALL fb_atomic_halo_sort(halos(ihalo))
931 END DO ! iatom
932 DEALLOCATE (pair_radii)
933
934 ! finalise
935 CALL fb_atomic_halo_list_set(atomic_halos=atomic_halos, &
936 halos=halos)
937 CALL fb_env_set(fb_env=fb_env, &
938 atomic_halos=atomic_halos)
939
940 ! print info
941 CALL fb_atomic_halo_list_write_info(atomic_halos, &
942 para_env, &
943 scf_section)
944
945 CALL timestop(handle)
946
947 END SUBROUTINE fb_env_build_atomic_halos
948
949! **************************************************************************************************
950!> \brief Automatically construct the trial functiosn used for generating
951!> the filter matrix. It tries to use the single zeta subset from
952!> the system GTO basis set as the trial functions
953!> \param fb_env : the filter matrix environment
954!> \param qs_env : quickstep environment
955!> \param maxocc : maximum occupancy for an orbital
956!> \author Lianheng Tong (LT) lianheng.tong@kcl.ac.uk
957! **************************************************************************************************
958 SUBROUTINE fb_env_build_trial_fns_auto(fb_env, qs_env, maxocc)
959
960 TYPE(fb_env_obj), INTENT(INOUT) :: fb_env
961 TYPE(qs_environment_type), POINTER :: qs_env
962 REAL(kind=dp), INTENT(IN) :: maxocc
963
964 CHARACTER(len=*), PARAMETER :: routinen = 'fb_env_build_trial_fns_auto'
965
966 INTEGER :: counter, handle, icgf, ico, ikind, iset, &
967 ishell, itrial, lshell, max_n_trial, &
968 nkinds, nset, old_lshell
969 INTEGER, DIMENSION(:), POINTER :: lmax, nfunctions, nshell
970 INTEGER, DIMENSION(:, :), POINTER :: functions
971 REAL(kind=dp) :: zeff
972 TYPE(dft_control_type), POINTER :: dft_control
973 TYPE(fb_trial_fns_obj) :: trial_fns
974 TYPE(gto_basis_set_p_type), DIMENSION(:), POINTER :: basis_set_list
975 TYPE(gto_basis_set_type), POINTER :: basis_set
976 TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
977
978 CALL timeset(routinen, handle)
979
980 cpassert(fb_env_has_data(fb_env))
981 NULLIFY (nfunctions, functions, basis_set, basis_set_list, qs_kind_set, dft_control)
982 CALL fb_trial_fns_nullify(trial_fns)
983
984 ! create a new trial_fn object
985 CALL fb_trial_fns_create(trial_fns)
986
987 CALL get_qs_env(qs_env=qs_env, &
988 qs_kind_set=qs_kind_set, &
989 dft_control=dft_control)
990
991 nkinds = SIZE(qs_kind_set)
992
993 ! reading from the other parts of the code, it seemed that
994 ! aux_fit_basis_set is only used when do_admm is TRUE. This can be
995 ! seen from the calls to generate_qs_task_list subroutine in
996 ! qs_create_task_list, found in qs_environment_methods.F:
997 ! basis_type is only set as input parameter for do_admm
998 ! calculations, and if not set, the task list is generated using
999 ! the default basis_set="ORB".
1000 ALLOCATE (basis_set_list(nkinds))
1001 IF (dft_control%do_admm) THEN
1002 CALL basis_set_list_setup(basis_set_list, "AUX_FIT", qs_kind_set)
1003 ELSE
1004 CALL basis_set_list_setup(basis_set_list, "ORB", qs_kind_set)
1005 END IF
1006
1007 ALLOCATE (nfunctions(nkinds))
1008 nfunctions = 0
1009
1010 DO ikind = 1, nkinds
1011 ! "gto = gaussian type orbital"
1012 basis_set => basis_set_list(ikind)%gto_basis_set
1013 CALL get_gto_basis_set(gto_basis_set=basis_set, &
1014 nset=nset, &
1015 lmax=lmax, &
1016 nshell=nshell)
1017 CALL get_qs_kind(qs_kind=qs_kind_set(ikind), &
1018 zeff=zeff)
1019
1020 bset1: DO iset = 1, nset
1021! old_lshell = lmax(iset)
1022 old_lshell = -1
1023 DO ishell = 1, nshell(iset)
1024 lshell = basis_set%l(ishell, iset)
1025 counter = 0
1026 ! loop over orbitals within the same l
1027 DO ico = ncoset(lshell - 1) + 1, ncoset(lshell)
1028 counter = counter + 1
1029 ! only include the first zeta orbitals
1030 IF ((lshell > old_lshell) .AND. (counter <= nco(lshell))) THEN
1031 nfunctions(ikind) = nfunctions(ikind) + 1
1032 END IF
1033 END DO
1034 ! we have got enough trial functions when we have enough
1035 ! basis functions to accommodate the number of electrons,
1036 ! AND that that we have included all the first zeta
1037 ! orbitals of an angular momentum quantum number l
1038 IF (((lshell > old_lshell) .OR. (lshell == lmax(iset))) .AND. &
1039 (maxocc*real(nfunctions(ikind), dp) >= zeff)) THEN
1040 EXIT bset1
1041 END IF
1042 old_lshell = lshell
1043 END DO
1044 END DO bset1
1045 END DO ! ikind
1046
1047 ! now that we have the number of trial functions get the trial
1048 ! functions
1049 max_n_trial = maxval(nfunctions)
1050 ALLOCATE (functions(max_n_trial, nkinds))
1051 functions(:, :) = 0
1052 ! redo the loops to get the trial function indices within the basis set
1053 DO ikind = 1, nkinds
1054 ! "gto = gaussian type orbital"
1055 basis_set => basis_set_list(ikind)%gto_basis_set
1056 CALL get_gto_basis_set(gto_basis_set=basis_set, &
1057 nset=nset, &
1058 lmax=lmax, &
1059 nshell=nshell)
1060 CALL get_qs_kind(qs_kind=qs_kind_set(ikind), &
1061 zeff=zeff)
1062 icgf = 0
1063 itrial = 0
1064 bset2: DO iset = 1, nset
1065 old_lshell = -1
1066 DO ishell = 1, nshell(iset)
1067 lshell = basis_set%l(ishell, iset)
1068 counter = 0
1069 ! loop over orbitals within the same l
1070 DO ico = ncoset(lshell - 1) + 1, ncoset(lshell)
1071 icgf = icgf + 1
1072 counter = counter + 1
1073 ! only include the first zeta orbitals
1074 IF ((lshell > old_lshell) .AND. (counter <= nco(lshell))) THEN
1075 itrial = itrial + 1
1076 functions(itrial, ikind) = icgf
1077 END IF
1078 END DO
1079 ! we have got enough trial functions when we have more
1080 ! basis functions than the number of electrons (obtained
1081 ! from atomic z), AND that that we have included all the
1082 ! first zeta orbitals of an angular momentum quantum
1083 ! number l
1084 IF (((lshell > old_lshell) .OR. (lshell == lmax(iset))) .AND. &
1085 (maxocc*real(itrial, dp) >= zeff)) THEN
1086 EXIT bset2
1087 END IF
1088 old_lshell = lshell
1089 END DO
1090 END DO bset2
1091 END DO ! ikind
1092
1093 ! set trial_functions
1094 CALL fb_trial_fns_set(trial_fns=trial_fns, &
1095 nfunctions=nfunctions, &
1096 functions=functions)
1097 ! set fb_env
1098 CALL fb_env_set(fb_env=fb_env, &
1099 trial_fns=trial_fns)
1100
1101 ! cleanup
1102 DEALLOCATE (basis_set_list)
1103
1104 CALL timestop(handle)
1105
1106 END SUBROUTINE fb_env_build_trial_fns_auto
1107
1108! **************************************************************************************************
1109!> \brief Copy the sparse structure of a DBCSR matrix to another, this
1110!> means the other matrix will have the same number of blocks
1111!> and their corresponding logical locations allocated, although
1112!> the blocks does not have to be the same size as the original
1113!> \param matrix_out : DBCSR matrix whose blocks are to be allocated
1114!> \param matrix_in : DBCSR matrix with existing sparse structure that
1115!> is to be copied
1116!> \author Lianheng Tong (LT) lianheng.tong@kcl.ac.uk
1117! **************************************************************************************************
1118 SUBROUTINE fb_dbcsr_copy_sparse_struct(matrix_out, matrix_in)
1119
1120 TYPE(dbcsr_type), INTENT(INOUT) :: matrix_out
1121 TYPE(dbcsr_type), INTENT(IN) :: matrix_in
1122
1123 INTEGER :: iatom, jatom, nblkcols_total, &
1124 nblkrows_total, nblks
1125 INTEGER, ALLOCATABLE, DIMENSION(:) :: cols, rows
1126 TYPE(dbcsr_iterator_type) :: iter
1127
1128 CALL dbcsr_get_info(matrix=matrix_in, &
1129 nblkrows_total=nblkrows_total, &
1130 nblkcols_total=nblkcols_total)
1131
1132 nblks = nblkrows_total*nblkcols_total
1133 ALLOCATE (rows(nblks))
1134 ALLOCATE (cols(nblks))
1135 rows(:) = 0
1136 cols(:) = 0
1137 nblks = 0
1138 CALL dbcsr_iterator_readonly_start(iter, matrix_in)
1139 DO WHILE (dbcsr_iterator_blocks_left(iter))
1140 CALL dbcsr_iterator_next_block(iter, iatom, jatom)
1141 nblks = nblks + 1
1142 rows(nblks) = iatom
1143 cols(nblks) = jatom
1144 END DO
1145 CALL dbcsr_iterator_stop(iter)
1146 CALL dbcsr_reserve_blocks(matrix_out, rows(1:nblks), cols(1:nblks))
1147 CALL dbcsr_finalize(matrix_out)
1148
1149 ! cleanup
1150 DEALLOCATE (rows)
1151 DEALLOCATE (cols)
1152
1153 END SUBROUTINE fb_dbcsr_copy_sparse_struct
1154
1155! **************************************************************************************************
1156!> \brief Write out parameters used for the filter matrix method to
1157!> output
1158!> \param fb_env : the filter matrix environment
1159!> \param qs_env : quickstep environment
1160!> \param scf_section : SCF input section
1161!> \author Lianheng Tong (LT) lianheng.tong@kcl.ac.uk
1162! **************************************************************************************************
1163 SUBROUTINE fb_env_write_info(fb_env, qs_env, scf_section)
1164 TYPE(fb_env_obj), INTENT(IN) :: fb_env
1165 TYPE(qs_environment_type), POINTER :: qs_env
1166 TYPE(section_vals_type), POINTER :: scf_section
1167
1168 CHARACTER(len=*), PARAMETER :: routinen = 'fb_env_write_info'
1169
1170 CHARACTER(LEN=2) :: element_symbol
1171 INTEGER :: handle, ikind, nkinds, unit_nr
1172 LOGICAL :: collective_com
1173 REAL(kind=dp) :: auto_cutoff_scale, filter_temperature
1174 REAL(kind=dp), DIMENSION(:), POINTER :: rcut
1175 TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set
1176 TYPE(cp_logger_type), POINTER :: logger
1177
1178 CALL timeset(routinen, handle)
1179
1180 NULLIFY (rcut, atomic_kind_set, logger)
1181
1182 CALL get_qs_env(qs_env=qs_env, &
1183 atomic_kind_set=atomic_kind_set)
1184 CALL fb_env_get(fb_env=fb_env, &
1185 filter_temperature=filter_temperature, &
1186 auto_cutoff_scale=auto_cutoff_scale, &
1187 rcut=rcut, &
1188 collective_com=collective_com)
1189
1190 nkinds = SIZE(atomic_kind_set)
1191
1192 logger => cp_get_default_logger()
1193 unit_nr = cp_print_key_unit_nr(logger, scf_section, &
1194 "PRINT%FILTER_MATRIX", &
1195 extension="")
1196 IF (unit_nr > 0) THEN
1197 IF (collective_com) THEN
1198 WRITE (unit=unit_nr, fmt="(/,A,T71,A)") &
1199 " FILTER_MAT_DIAG| MPI communication method:", &
1200 "Collective"
1201 ELSE
1202 WRITE (unit=unit_nr, fmt="(/,A,T71,A)") &
1203 " FILTER_MAT_DIAG| MPI communication method:", &
1204 "At each step"
1205 END IF
1206 WRITE (unit=unit_nr, fmt="(A,T71,g10.4)") &
1207 " FILTER_MAT_DIAG| Filter temperature [K]:", &
1208 cp_unit_from_cp2k(filter_temperature, "K")
1209 WRITE (unit=unit_nr, fmt="(A,T71,f10.4)") &
1210 " FILTER_MAT_DIAG| Filter temperature [a.u.]:", &
1211 filter_temperature
1212 WRITE (unit=unit_nr, fmt="(A,T71,f10.4)") &
1213 " FILTER_MAT_DIAG| Auto atomic cutoff radius scale:", &
1214 auto_cutoff_scale
1215 WRITE (unit=unit_nr, fmt="(A)") &
1216 " FILTER_MAT_DIAG| atomic cutoff radii [a.u.]"
1217 DO ikind = 1, nkinds
1218 CALL get_atomic_kind(atomic_kind=atomic_kind_set(ikind), &
1219 element_symbol=element_symbol)
1220 WRITE (unit=unit_nr, fmt="(A,A,T71,f10.4)") &
1221 " FILTER_MAT_DIAG| ", element_symbol, rcut(ikind)
1222 END DO ! ikind
1223 END IF
1224 CALL cp_print_key_finished_output(unit_nr, logger, scf_section, &
1225 "PRINT%FILTER_MATRIX")
1226
1227 CALL timestop(handle)
1228
1229 END SUBROUTINE fb_env_write_info
1230
1231END MODULE qs_fb_env_methods
Define the atomic kind types and their sub types.
subroutine, public get_atomic_kind(atomic_kind, fist_potential, element_symbol, name, mass, kind_number, natom, atom_list, rcov, rvdw, z, qeff, apol, cpol, mm_radius, shell, shell_active, damping)
Get attributes of an atomic kind.
subroutine, public get_gto_basis_set(gto_basis_set, name, aliases, norm_type, kind_radius, ncgf, nset, nsgf, cgf_symbol, sgf_symbol, norm_cgf, set_radius, lmax, lmin, lx, ly, lz, m, ncgf_set, npgf, nsgf_set, nshell, cphi, pgf_radius, sphi, scon, zet, first_cgf, first_sgf, l, last_cgf, last_sgf, n, gcc, maxco, maxl, maxpgf, maxsgf_set, maxshell, maxso, nco_sum, npgf_sum, nshell_sum, maxder, short_kind_radius, npgf_seg_sum, ccon)
...
Handles all functions related to the CELL.
Definition cell_types.F:15
methods related to the blacs parallel environment
Defines control structures, which contain the parameters and the settings for the DFT-based calculati...
logical function, public dbcsr_iterator_blocks_left(iterator)
...
subroutine, public dbcsr_iterator_stop(iterator)
...
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_reserve_blocks(matrix, rows, cols)
...
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_finalize(matrix)
...
subroutine, public dbcsr_set(matrix, alpha)
...
subroutine, public dbcsr_release(matrix)
...
subroutine, public dbcsr_iterator_readonly_start(iterator, matrix, shared, dynamic, dynamic_byrows)
Like dbcsr_iterator_start() but with matrix being INTENT(IN). When invoking this routine,...
DBCSR operations in CP2K.
subroutine, public copy_dbcsr_to_fm(matrix, fm, plan, check_plan)
Copy a DBCSR matrix to a BLACS matrix.
Basic linear algebra operations for full matrices.
subroutine, public cp_fm_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)
computes matrix_c = beta * matrix_c + alpha * ( matrix_a ** transa ) * ( matrix_b ** transb )
subroutine, public cp_fm_uplo_to_full(matrix, work, uplo)
given a triangular matrix according to uplo, computes the corresponding full matrix
subroutine, public cp_fm_triangular_invert(matrix_a, uplo_tr)
inverts a triangular matrix
subroutine, public cp_fm_symm(side, uplo, m, n, alpha, matrix_a, matrix_b, beta, matrix_c)
computes matrix_c = beta * matrix_c + alpha * matrix_a * matrix_b computes matrix_c = beta * matrix_c...
subroutine, public cp_fm_triangular_multiply(triangular_matrix, matrix_b, side, transpose_tr, invert_tr, uplo_tr, unit_diag_tr, n_rows, n_cols, alpha)
multiplies in place by a triangular matrix: matrix_b = alpha op(triangular_matrix) matrix_b or (if si...
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...
subroutine, public cp_fm_cholesky_decompose(matrix, n, info_out)
used to replace a symmetric positive def. matrix M with its cholesky decomposition U: M = U^T * U,...
subroutine, public cp_fm_cholesky_reduce(matrix, matrixb, itype)
reduce a matrix pencil A,B to normal form B has to be cholesky decomposed with cp_fm_cholesky_decompo...
used for collecting some of the diagonalization schemes available for cp_fm_type. cp_fm_power also mo...
Definition cp_fm_diag.F:17
subroutine, public cp_fm_power(matrix, work, exponent, threshold, n_dependent, verbose, eigvals)
...
subroutine, public choose_eigv_solver(matrix, eigenvectors, eigenvalues, info)
Choose the Eigensolver depending on which library is available ELPA seems to be unstable for small sy...
Definition cp_fm_diag.F:262
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_set_all(matrix, alpha, beta)
set all elements of a matrix to the same value, and optionally the diagonal to a different one
subroutine, public cp_fm_create(matrix, matrix_struct, name, nrow, ncol, set_zero)
creates a new full matrix with the given structure
various routines to log and control the output. The idea is that decisions about where to log should ...
type(cp_logger_type) function, pointer, public cp_get_default_logger()
returns the default logger
routines to handle the output, The idea is to remove the decision of wheter to output and what to out...
integer function, public cp_print_key_unit_nr(logger, basis_section, print_key_path, extension, middle_name, local, log_filename, ignore_should_output, file_form, file_position, file_action, file_status, do_backup, on_file, is_new_file, mpi_io, fout)
...
subroutine, public cp_print_key_finished_output(unit_nr, logger, basis_section, print_key_path, local, ignore_should_output, on_file, mpi_io)
should be called after you finish working with a unit obtained with cp_print_key_unit_nr,...
unit conversion facility
Definition cp_units.F:30
real(kind=dp) function, public cp_unit_from_cp2k(value, unit_str, defaults, power)
converts from the internal cp2k units to the given unit
Definition cp_units.F:1311
collects all constants needed in input so that they can be used without circular dependencies
integer, parameter, public cholesky_restore
integer, parameter, public cholesky_dbcsr
integer, parameter, public cholesky_off
integer, parameter, public cholesky_reduce
integer, parameter, public cholesky_inverse
objects that represent the structure of input sections and the data contained in an input section
recursive type(section_vals_type) function, pointer, public section_vals_get_subs_vals(section_vals, subsection_name, i_rep_section, can_return_null)
returns the values of the requested subsection
subroutine, public section_vals_val_get(section_vals, keyword_name, i_rep_section, i_rep_val, n_rep_val, val, l_val, i_val, r_val, c_val, l_vals, i_vals, r_vals, c_vals, explicit)
returns the requested value
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.
Provides Cartesian and spherical orbital pointers and indices.
integer, dimension(:), allocatable, public nco
integer, dimension(:), allocatable, public ncoset
basic linear algebra operations for full matrixes
Define the data structure for the particle information.
collects routines that calculate density matrices
Apply the direct inversion in the iterative subspace (DIIS) of Pulay in the framework of an SCF itera...
Definition qs_diis.F:21
subroutine, public qs_diis_b_step(diis_buffer, mo_array, kc, sc, delta, error_max, diis_step, eps_diis, nmixing, s_matrix, scf_section, roks)
Update the SCF DIIS buffer, and if appropriate does a diis step.
Definition qs_diis.F:233
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.
real(kind=dp) function, public fb_atomic_halo_cost(atomic_halo, particle_set, qs_kind_set)
Estimates the computational cost with respect to the filter matrix calculation associated to an atomi...
subroutine, public fb_atomic_halo_build_halo_atoms(owner_atom, particle_set, cell, pair_radii, halo_atoms, nhalo_atoms, owner_id_in_halo)
Builds halo atoms for a given (owner) atom.
subroutine, public fb_atomic_halo_set(atomic_halo, owner_atom, owner_id_in_halo, natoms, nelectrons, halo_atoms, sorted, cost)
Sets attributes in a fb_atomic_halo object, one should only set the data content in a fb_atomic_halo ...
subroutine, public fb_atomic_halo_sort(atomic_halo)
Sort the list of atomic indices in the halo in ascending order. The atomic_halo must not be empty.
subroutine, public fb_atomic_halo_create(atomic_halo)
Creates and initialises an empty fb_atomic_halo object.
subroutine, public fb_atomic_halo_list_create(atomic_halos)
Creates and initialises an empty fb_atomic_halo_list object.
pure subroutine, public fb_build_pair_radii(rcut, nkinds, pair_radii)
Builds the required pair_radii array required for building the halo atoms from a given set of cut off...
subroutine, public fb_atomic_halo_list_set(atomic_halos, nhalos, max_nhalos, halos)
Sets attributes from an fb_atomic_halo_list object, one should only set the data content in a fb_atom...
subroutine, public fb_atomic_halo_nullify(atomic_halo)
Nullifies a fb_atomic_halo object, note that it does not release the original object....
integer function, public fb_atomic_halo_nelectrons_estimate_z(atomic_halo, particle_set)
Estimates the total number of electrons in a halo using atomic numbers.
subroutine, public fb_atomic_halo_list_write_info(atomic_halos, para_env, scf_section)
Writes out the atomic halo list summary, no detailed neighbour lists, just average,...
subroutine, public fb_atomic_halo_list_nullify(atomic_halos)
Nullifies a fb_atomic_halo_list object, note that it does not release the original object....
subroutine, public fb_env_do_diag(fb_env, qs_env, matrix_ks, matrix_s, scf_section, diis_step)
Do filtered matrix method diagonalisation.
subroutine, public fb_env_read_input(fb_env, scf_section)
Read input sections for filter matrix method.
subroutine, public fb_env_build_atomic_halos(fb_env, qs_env, scf_section)
Builds an fb_atomic_halo_list object using information from fb_env.
subroutine, public fb_env_write_info(fb_env, qs_env, scf_section)
Write out parameters used for the filter matrix method to output.
subroutine, public fb_env_build_rcut_auto(fb_env, qs_env)
Automatically generate the cutoff radii of atoms used for constructing the atomic halos,...
logical function, public fb_env_has_data(fb_env)
Checks if a fb_env object is associated with an actual data content or not.
subroutine, public fb_env_get(fb_env, rcut, filter_temperature, auto_cutoff_scale, eps_default, atomic_halos, trial_fns, collective_com, local_atoms, nlocal_atoms)
method to get attributes from a given fb_env object
subroutine, public fb_env_set(fb_env, rcut, filter_temperature, auto_cutoff_scale, eps_default, atomic_halos, trial_fns, collective_com, local_atoms, nlocal_atoms)
method to set attributes from a given fb_env object
subroutine, public fb_fltrmat_build_2(h_mat, s_mat, atomic_halos, trial_fns, para_env, particle_set, fermi_level, filter_temp, name, filter_mat, tolerance)
Build the filter matrix, with MPI communications grouped together. More effcient on communication,...
subroutine, public fb_fltrmat_build(h_mat, s_mat, atomic_halos, trial_fns, para_env, particle_set, fermi_level, filter_temp, name, filter_mat, tolerance)
Build the filter matrix, with MPI communications happening at each step. Less efficient on communicat...
subroutine, public fb_trial_fns_set(trial_fns, nfunctions, functions)
sets the attributes of a fb_trial_fns object
subroutine, public fb_trial_fns_nullify(trial_fns)
nullifies the content of given object
subroutine, public fb_trial_fns_create(trial_fns)
creates an fb_trial_fns object and initialises it
Some utility functions for the calculation of integrals.
subroutine, public basis_set_list_setup(basis_set_list, basis_type, qs_kind_set)
Set up an easy accessible list of the basis sets for all kinds.
Define the quickstep kind type and their sub types.
subroutine, public get_qs_kind(qs_kind, basis_set, basis_type, ncgf, nsgf, all_potential, tnadd_potential, gth_potential, sgp_potential, upf_potential, cneo_potential, se_parameter, dftb_parameter, xtb_parameter, dftb3_param, zatom, zeff, elec_conf, mao, lmax_dftb, alpha_core_charge, ccore_charge, core_charge, core_charge_radius, paw_proj_set, paw_atom, hard_radius, hard0_radius, max_rad_local, covalent_radius, vdw_radius, gpw_type_forced, harmonics, max_iso_not0, max_s_harm, grid_atom, ngrid_ang, ngrid_rad, lmax_rho0, dft_plus_u_atom, l_of_dft_plus_u, n_of_dft_plus_u, u_minus_j, hund_j, u_of_dft_plus_u, j_of_dft_plus_u, alpha_of_dft_plus_u, beta_of_dft_plus_u, j0_of_dft_plus_u, occupation_of_dft_plus_u, dispersion, bs_occupation, magnetization, no_optimize, addel, laddel, naddel, orbitals, max_scf, eps_scf, smear, u_ramping, u_minus_j_target, eps_u_ramping, proj_shell_charge, lr_atom, do_mtlr, u_j_loop, ao_coef, init_u_ramping_each_scf, reltmat, ghost, monovalent, floating, name, element_symbol, pao_basis_size, pao_model_file, pao_potentials, pao_descriptors, nelec)
Get attributes of an atomic kind.
Set occupation of molecular orbitals.
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 init_mo_set(mo_set, fm_pool, fm_ref, fm_struct, name, counter, complex_coeff)
initializes an allocated mo_set. eigenvalues, mo_coeff, occupation_numbers are valid only after this ...
subroutine, public allocate_mo_set(mo_set, nao, nmo, nelectron, n_el_f, maxocc, flexible_electron_count)
Allocates a mo set and partially initializes it (nao,nmo,nelectron, and flexible_electron_count are v...
subroutine, public deallocate_mo_set(mo_set)
Deallocate a wavefunction 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, cmo_coeff)
Get the components of a MO set data structure.
module that contains the definitions of the scf types
parameters that control an scf iteration
Utilities for string manipulations.
subroutine, public compress(string, full)
Eliminate multiple space characters in a string. If full is .TRUE., then all spaces are eliminated.
elemental subroutine, public uppercase(string)
Convert all lower case characters in a string to upper case.
Provides all information about an atomic kind.
Type defining parameters related to the simulation cell.
Definition cell_types.F:60
represent a blacs multidimensional parallel environment (for the mpi corrispective see cp_paratypes/m...
keeps the information about the structure of a full matrix
represent a full matrix
type of a logger, at the moment it contains just a print level starting at which level it should be l...
stores all the informations relevant to an mpi environment
the object container which allows for the creation of an array of pointers to fb_env
the object container which allows for the creation of an array of pointers to fb_trial_fns objects
Provides all information about a quickstep kind.