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