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