(git:ed6f26b)
Loading...
Searching...
No Matches
gw_utils.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
8! **************************************************************************************************
9!> \brief
10!> \author Jan Wilhelm
11!> \date 07.2023
12! **************************************************************************************************
18 USE bibliography, ONLY: graml2024,&
19 cite_reference
20 USE cell_types, ONLY: cell_type,&
21 pbc
25 USE cp_cfm_types, ONLY: cp_cfm_create,&
31 USE cp_dbcsr_api, ONLY: &
33 dbcsr_release, dbcsr_set, dbcsr_type, dbcsr_type_no_symmetry, dbcsr_type_symmetric
39 USE cp_files, ONLY: close_file,&
45 USE cp_fm_types, ONLY: cp_fm_create,&
53 USE dbt_api, ONLY: &
54 dbt_clear, dbt_create, dbt_destroy, dbt_filter, dbt_iterator_blocks_left, &
55 dbt_iterator_next_block, dbt_iterator_start, dbt_iterator_stop, dbt_iterator_type, &
56 dbt_mp_environ_pgrid, dbt_pgrid_create, dbt_pgrid_destroy, dbt_pgrid_type, dbt_type
72 USE kinds, ONLY: default_string_length,&
73 dp,&
74 int_8
76 USE kpoint_types, ONLY: get_kpoint_info,&
82 USE machine, ONLY: m_memory,&
84 USE mathconstants, ONLY: gaussi,&
85 z_one,&
86 z_zero
87 USE mathlib, ONLY: diag_complex,&
88 gcd
89 USE message_passing, ONLY: mp_cart_type,&
95 USE mp2_gpw, ONLY: create_mat_munu
103 USE physcon, ONLY: angstrom,&
104 evolt
113 USE qs_kind_types, ONLY: get_qs_kind,&
118 USE qs_tensors, ONLY: build_2c_integrals,&
129 USE rpa_gw, ONLY: continuation_pade
130#include "base/base_uses.f90"
131
132 IMPLICIT NONE
133
134 PRIVATE
135
139
140 CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'gw_utils'
141
142CONTAINS
143
144! **************************************************************************************************
145!> \brief ...
146!> \param qs_env ...
147!> \param bs_env ...
148!> \param bs_sec ...
149! **************************************************************************************************
150 SUBROUTINE create_and_init_bs_env_for_gw(qs_env, bs_env, bs_sec)
151 TYPE(qs_environment_type), POINTER :: qs_env
152 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
153 TYPE(section_vals_type), POINTER :: bs_sec
154
155 CHARACTER(LEN=*), PARAMETER :: routinen = 'create_and_init_bs_env_for_gw'
156
157 INTEGER :: handle
158
159 CALL timeset(routinen, handle)
160
161 CALL cite_reference(graml2024)
162
163 CALL read_gw_input_parameters(bs_env, bs_sec)
164
165 CALL print_header_and_input_parameters(bs_env)
166
167 CALL setup_ao_and_ri_basis_set(qs_env, bs_env)
168
169 CALL get_ri_basis_and_basis_function_indices(qs_env, bs_env)
170
171 CALL set_heuristic_parameters(bs_env, qs_env)
172
174
175 CALL setup_kpoints_chi_eps_w(bs_env, bs_env%kpoints_chi_eps_W)
176
177 IF (bs_env%small_cell_full_kp_or_large_cell_Gamma == small_cell_full_kp) THEN
178 CALL setup_cells_3c(qs_env, bs_env)
179 END IF
180
181 CALL set_parallelization_parameters(qs_env, bs_env)
182
183 CALL allocate_matrices(qs_env, bs_env)
184
185 CALL compute_v_xc(qs_env, bs_env)
186
187 CALL create_tensors(qs_env, bs_env)
188
189 SELECT CASE (bs_env%small_cell_full_kp_or_large_cell_Gamma)
190 CASE (large_cell_gamma)
191
192 CALL allocate_gw_eigenvalues(bs_env)
193
194 CALL check_sparsity_3c(qs_env, bs_env)
195
196 CALL set_sparsity_parallelization_parameters(bs_env)
197
198 CALL check_for_restart_files(qs_env, bs_env)
199
200 CASE (small_cell_full_kp)
201
202 CALL compute_3c_integrals(qs_env, bs_env)
203
204 CALL setup_cells_delta_r(bs_env)
205
206 CALL setup_parallelization_delta_r(bs_env)
207
208 CALL allocate_matrices_small_cell_full_kp(qs_env, bs_env)
209
210 CALL trafo_v_xc_r_to_kp(qs_env, bs_env)
211
212 CALL heuristic_ri_regularization(qs_env, bs_env)
213
214 END SELECT
215
216 CALL setup_time_and_frequency_minimax_grid(bs_env)
217
218 ! free memory in qs_env; only if one is not calculating the LDOS because
219 ! we need real-space grid operations in pw_env, task_list for the LDOS
220 ! Recommendation in case of memory issues: first perform GW calculation without calculating
221 ! LDOS (to safe memor). Then, use GW restart files
222 ! in a subsequent calculation to calculate the LDOS
223 ! Marek : TODO - boolean that does not interfere with RTP init but sets this to correct value
224 IF (.NOT. bs_env%do_ldos .AND. .false.) THEN
225 CALL qs_env_part_release(qs_env)
226 END IF
227
228 CALL timestop(handle)
229
230 END SUBROUTINE create_and_init_bs_env_for_gw
231
232! **************************************************************************************************
233!> \brief ...
234!> \param bs_env ...
235! **************************************************************************************************
236 SUBROUTINE de_init_bs_env(bs_env)
237 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
238
239 CHARACTER(LEN=*), PARAMETER :: routinen = 'de_init_bs_env'
240
241 INTEGER :: handle
242
243 CALL timeset(routinen, handle)
244 ! deallocate quantities here which:
245 ! 1. cannot be deallocated in bs_env_release due to circular dependencies
246 ! 2. consume a lot of memory and should not be kept until the quantity is
247 ! deallocated in bs_env_release
248
249 IF (ASSOCIATED(bs_env%nl_3c%ij_list) .AND. (bs_env%rtp_method == rtp_method_bse)) THEN
250 IF (bs_env%unit_nr > 0) WRITE (bs_env%unit_nr, *) "Retaining nl_3c for RTBSE"
251 ELSE
252 CALL neighbor_list_3c_destroy(bs_env%nl_3c)
253 END IF
254
256
257 CALL timestop(handle)
258
259 END SUBROUTINE de_init_bs_env
260
261! **************************************************************************************************
262!> \brief ...
263!> \param bs_env ...
264!> \param bs_sec ...
265! **************************************************************************************************
266 SUBROUTINE read_gw_input_parameters(bs_env, bs_sec)
267 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
268 TYPE(section_vals_type), POINTER :: bs_sec
269
270 CHARACTER(LEN=*), PARAMETER :: routinen = 'read_gw_input_parameters'
271
272 INTEGER :: handle
273 TYPE(section_vals_type), POINTER :: gw_sec
274
275 CALL timeset(routinen, handle)
276
277 NULLIFY (gw_sec)
278 gw_sec => section_vals_get_subs_vals(bs_sec, "GW")
279
280 CALL section_vals_val_get(gw_sec, "NUM_TIME_FREQ_POINTS", i_val=bs_env%num_time_freq_points)
281 CALL section_vals_val_get(gw_sec, "EPS_FILTER", r_val=bs_env%eps_filter)
282 CALL section_vals_val_get(gw_sec, "REGULARIZATION_RI", r_val=bs_env%input_regularization_RI)
283 CALL section_vals_val_get(gw_sec, "CUTOFF_RADIUS_RI", r_val=bs_env%ri_metric%cutoff_radius)
284 CALL section_vals_val_get(gw_sec, "MEMORY_PER_PROC", r_val=bs_env%input_memory_per_proc_GB)
285 CALL section_vals_val_get(gw_sec, "APPROX_KP_EXTRAPOL", l_val=bs_env%approx_kp_extrapol)
286 CALL section_vals_val_get(gw_sec, "SIZE_LATTICE_SUM", i_val=bs_env%size_lattice_sum_V)
287 CALL section_vals_val_get(gw_sec, "KPOINTS_W", i_vals=bs_env%nkp_grid_chi_eps_W_input)
288 CALL section_vals_val_get(gw_sec, "HEDIN_SHIFT", l_val=bs_env%do_hedin_shift)
289 CALL section_vals_val_get(gw_sec, "FREQ_MAX_FIT", r_val=bs_env%freq_max_fit)
290
291 CALL timestop(handle)
292
293 END SUBROUTINE read_gw_input_parameters
294
295! **************************************************************************************************
296!> \brief ...
297!> \param qs_env ...
298!> \param bs_env ...
299! **************************************************************************************************
300 SUBROUTINE setup_ao_and_ri_basis_set(qs_env, bs_env)
301 TYPE(qs_environment_type), POINTER :: qs_env
302 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
303
304 CHARACTER(LEN=*), PARAMETER :: routinen = 'setup_AO_and_RI_basis_set'
305
306 INTEGER :: handle, natom, nkind
307 TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
308 TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
309
310 CALL timeset(routinen, handle)
311
312 CALL get_qs_env(qs_env, &
313 qs_kind_set=qs_kind_set, &
314 particle_set=particle_set, &
315 natom=natom, nkind=nkind)
316
317 ! set up basis
318 ALLOCATE (bs_env%sizes_RI(natom), bs_env%sizes_AO(natom))
319 ALLOCATE (bs_env%basis_set_RI(nkind), bs_env%basis_set_AO(nkind))
320
321 CALL basis_set_list_setup(bs_env%basis_set_RI, "RI_AUX", qs_kind_set)
322 CALL basis_set_list_setup(bs_env%basis_set_AO, "ORB", qs_kind_set)
323
324 CALL get_particle_set(particle_set, qs_kind_set, nsgf=bs_env%sizes_RI, &
325 basis=bs_env%basis_set_RI)
326 CALL get_particle_set(particle_set, qs_kind_set, nsgf=bs_env%sizes_AO, &
327 basis=bs_env%basis_set_AO)
328
329 CALL timestop(handle)
330
331 END SUBROUTINE setup_ao_and_ri_basis_set
332
333! **************************************************************************************************
334!> \brief ...
335!> \param qs_env ...
336!> \param bs_env ...
337! **************************************************************************************************
338 SUBROUTINE get_ri_basis_and_basis_function_indices(qs_env, bs_env)
339 TYPE(qs_environment_type), POINTER :: qs_env
340 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
341
342 CHARACTER(LEN=*), PARAMETER :: routinen = 'get_RI_basis_and_basis_function_indices'
343
344 INTEGER :: handle, i_ri, iatom, ikind, iset, &
345 max_ao_bf_per_atom, n_ao_test, n_atom, &
346 n_kind, n_ri, nset, nsgf, u
347 INTEGER, ALLOCATABLE, DIMENSION(:) :: kind_of
348 INTEGER, DIMENSION(:), POINTER :: l_max, l_min, nsgf_set
349 TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set
350 TYPE(gto_basis_set_type), POINTER :: basis_set_a
351 TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
352
353 CALL timeset(routinen, handle)
354
355 ! determine RI basis set size
356 CALL get_qs_env(qs_env, atomic_kind_set=atomic_kind_set, qs_kind_set=qs_kind_set)
357
358 n_kind = SIZE(qs_kind_set)
359 n_atom = bs_env%n_atom
360
361 CALL get_atomic_kind_set(atomic_kind_set, kind_of=kind_of)
362
363 DO ikind = 1, n_kind
364 CALL get_qs_kind(qs_kind=qs_kind_set(ikind), basis_set=basis_set_a, &
365 basis_type="RI_AUX")
366 IF (.NOT. ASSOCIATED(basis_set_a)) THEN
367 CALL cp_abort(__location__, &
368 "At least one RI_AUX basis set was not explicitly invoked in &KIND-section.")
369 END IF
370 END DO
371
372 ALLOCATE (bs_env%i_RI_start_from_atom(n_atom))
373 ALLOCATE (bs_env%i_RI_end_from_atom(n_atom))
374 ALLOCATE (bs_env%i_ao_start_from_atom(n_atom))
375 ALLOCATE (bs_env%i_ao_end_from_atom(n_atom))
376
377 n_ri = 0
378 DO iatom = 1, n_atom
379 bs_env%i_RI_start_from_atom(iatom) = n_ri + 1
380 ikind = kind_of(iatom)
381 CALL get_qs_kind(qs_kind=qs_kind_set(ikind), nsgf=nsgf, basis_type="RI_AUX")
382 n_ri = n_ri + nsgf
383 bs_env%i_RI_end_from_atom(iatom) = n_ri
384 END DO
385 bs_env%n_RI = n_ri
386
387 max_ao_bf_per_atom = 0
388 n_ao_test = 0
389 DO iatom = 1, n_atom
390 bs_env%i_ao_start_from_atom(iatom) = n_ao_test + 1
391 ikind = kind_of(iatom)
392 CALL get_qs_kind(qs_kind=qs_kind_set(ikind), nsgf=nsgf, basis_type="ORB")
393 n_ao_test = n_ao_test + nsgf
394 bs_env%i_ao_end_from_atom(iatom) = n_ao_test
395 max_ao_bf_per_atom = max(max_ao_bf_per_atom, nsgf)
396 END DO
397 cpassert(n_ao_test == bs_env%n_ao)
398 bs_env%max_AO_bf_per_atom = max_ao_bf_per_atom
399
400 ALLOCATE (bs_env%l_RI(n_ri))
401 i_ri = 0
402 DO iatom = 1, n_atom
403 ikind = kind_of(iatom)
404
405 nset = bs_env%basis_set_RI(ikind)%gto_basis_set%nset
406 l_max => bs_env%basis_set_RI(ikind)%gto_basis_set%lmax
407 l_min => bs_env%basis_set_RI(ikind)%gto_basis_set%lmin
408 nsgf_set => bs_env%basis_set_RI(ikind)%gto_basis_set%nsgf_set
409
410 DO iset = 1, nset
411 cpassert(l_max(iset) == l_min(iset))
412 bs_env%l_RI(i_ri + 1:i_ri + nsgf_set(iset)) = l_max(iset)
413 i_ri = i_ri + nsgf_set(iset)
414 END DO
415
416 END DO
417 cpassert(i_ri == n_ri)
418
419 u = bs_env%unit_nr
420
421 IF (u > 0) THEN
422 WRITE (u, fmt="(T2,A)") " "
423 WRITE (u, fmt="(T2,2A,T75,I8)") "Number of auxiliary Gaussian basis functions ", &
424 χε"for , , W", n_ri
425 END IF
426
427 CALL timestop(handle)
428
429 END SUBROUTINE get_ri_basis_and_basis_function_indices
430
431! **************************************************************************************************
432!> \brief ...
433!> \param bs_env ...
434!> \param kpoints ...
435! **************************************************************************************************
436 SUBROUTINE setup_kpoints_chi_eps_w(bs_env, kpoints)
437
438 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
439 TYPE(kpoint_type), POINTER :: kpoints
440
441 CHARACTER(LEN=*), PARAMETER :: routinen = 'setup_kpoints_chi_eps_W'
442
443 INTEGER :: handle, i_dim, n_dim, nkp, nkp_extra, &
444 nkp_orig, u
445 INTEGER, DIMENSION(3) :: nkp_grid, nkp_grid_extra, periodic
446 REAL(kind=dp) :: exp_s_p, n_dim_inv
447
448 CALL timeset(routinen, handle)
449
450 ! routine adapted from mp2_integrals.F
451 NULLIFY (kpoints)
452 CALL kpoint_create(kpoints)
453
454 kpoints%kp_scheme = "GENERAL"
455
456 periodic(1:3) = bs_env%periodic(1:3)
457
458 cpassert(SIZE(bs_env%nkp_grid_chi_eps_W_input) == 3)
459
460 IF (bs_env%nkp_grid_chi_eps_W_input(1) > 0 .AND. &
461 bs_env%nkp_grid_chi_eps_W_input(2) > 0 .AND. &
462 bs_env%nkp_grid_chi_eps_W_input(3) > 0) THEN
463 ! 1. k-point mesh for χ, ε, W from input
464 DO i_dim = 1, 3
465 SELECT CASE (periodic(i_dim))
466 CASE (0)
467 nkp_grid(i_dim) = 1
468 nkp_grid_extra(i_dim) = 1
469 CASE (1)
470 nkp_grid(i_dim) = bs_env%nkp_grid_chi_eps_W_input(i_dim)
471 nkp_grid_extra(i_dim) = nkp_grid(i_dim)*2
472 CASE DEFAULT
473 cpabort("Error in periodicity.")
474 END SELECT
475 END DO
476
477 ELSE IF (bs_env%nkp_grid_chi_eps_W_input(1) == -1 .AND. &
478 bs_env%nkp_grid_chi_eps_W_input(2) == -1 .AND. &
479 bs_env%nkp_grid_chi_eps_W_input(3) == -1) THEN
480 ! 2. automatic k-point mesh for χ, ε, W
481
482 DO i_dim = 1, 3
483
484 cpassert(periodic(i_dim) == 0 .OR. periodic(i_dim) == 1)
485
486 SELECT CASE (periodic(i_dim))
487 CASE (0)
488 nkp_grid(i_dim) = 1
489 nkp_grid_extra(i_dim) = 1
490 CASE (1)
491 SELECT CASE (bs_env%small_cell_full_kp_or_large_cell_Gamma)
492 CASE (large_cell_gamma)
493 nkp_grid(i_dim) = 4
494 nkp_grid_extra(i_dim) = 6
495 CASE (small_cell_full_kp)
496 nkp_grid(i_dim) = bs_env%kpoints_scf_desymm%nkp_grid(i_dim)*4
497 nkp_grid_extra(i_dim) = bs_env%kpoints_scf_desymm%nkp_grid(i_dim)*8
498 END SELECT
499 CASE DEFAULT
500 cpabort("Error in periodicity.")
501 END SELECT
502
503 END DO
504
505 ELSE
506
507 cpabort("An error occured when setting up the k-mesh for W.")
508
509 END IF
510
511 nkp_orig = max(nkp_grid(1)*nkp_grid(2)*nkp_grid(3)/2, 1)
512
513 nkp_extra = nkp_grid_extra(1)*nkp_grid_extra(2)*nkp_grid_extra(3)/2
514
515 nkp = nkp_orig + nkp_extra
516
517 kpoints%nkp_grid(1:3) = nkp_grid(1:3)
518 kpoints%nkp = nkp
519
520 bs_env%nkp_grid_chi_eps_W_orig(1:3) = nkp_grid(1:3)
521 bs_env%nkp_grid_chi_eps_W_extra(1:3) = nkp_grid_extra(1:3)
522 bs_env%nkp_chi_eps_W_orig = nkp_orig
523 bs_env%nkp_chi_eps_W_extra = nkp_extra
524 bs_env%nkp_chi_eps_W_orig_plus_extra = nkp
525
526 ALLOCATE (kpoints%xkp(3, nkp), kpoints%wkp(nkp))
527 ALLOCATE (bs_env%wkp_no_extra(nkp), bs_env%wkp_s_p(nkp))
528
529 CALL compute_xkp(kpoints%xkp, 1, nkp_orig, nkp_grid)
530 CALL compute_xkp(kpoints%xkp, nkp_orig + 1, nkp, nkp_grid_extra)
531
532 n_dim = sum(periodic)
533 IF (n_dim == 0) THEN
534 ! molecules
535 kpoints%wkp(1) = 1.0_dp
536 bs_env%wkp_s_p(1) = 1.0_dp
537 bs_env%wkp_no_extra(1) = 1.0_dp
538 ELSE
539
540 n_dim_inv = 1.0_dp/real(n_dim, kind=dp)
541
542 ! k-point weights are chosen to automatically extrapolate the k-point mesh
543 CALL compute_wkp(kpoints%wkp(1:nkp_orig), nkp_orig, nkp_extra, n_dim_inv)
544 CALL compute_wkp(kpoints%wkp(nkp_orig + 1:nkp), nkp_extra, nkp_orig, n_dim_inv)
545
546 bs_env%wkp_no_extra(1:nkp_orig) = 0.0_dp
547 bs_env%wkp_no_extra(nkp_orig + 1:nkp) = 1.0_dp/real(nkp_extra, kind=dp)
548
549 IF (n_dim == 3) THEN
550 ! W_PQ(k) for an s-function P and a p-function Q diverges as 1/k at k=0
551 ! (instead of 1/k^2 for P and Q both being s-functions).
552 exp_s_p = 2.0_dp*n_dim_inv
553 CALL compute_wkp(bs_env%wkp_s_p(1:nkp_orig), nkp_orig, nkp_extra, exp_s_p)
554 CALL compute_wkp(bs_env%wkp_s_p(nkp_orig + 1:nkp), nkp_extra, nkp_orig, exp_s_p)
555 ELSE
556 bs_env%wkp_s_p(1:nkp) = bs_env%wkp_no_extra(1:nkp)
557 END IF
558
559 END IF
560
561 IF (bs_env%approx_kp_extrapol) THEN
562 bs_env%wkp_orig = 1.0_dp/real(nkp_orig, kind=dp)
563 END IF
564
565 ! heuristic parameter: how many k-points for χ, ε, and W are used simultaneously
566 ! (less simultaneous k-points: less memory, but more computational effort because of
567 ! recomputation of V(k))
568 bs_env%nkp_chi_eps_W_batch = 4
569
570 bs_env%num_chi_eps_W_batches = (bs_env%nkp_chi_eps_W_orig_plus_extra - 1)/ &
571 bs_env%nkp_chi_eps_W_batch + 1
572
573 u = bs_env%unit_nr
574
575 IF (u > 0) THEN
576 WRITE (u, fmt="(T2,A)") " "
577 WRITE (u, fmt="(T2,1A,T71,3I4)") χε"K-point mesh 1 for , , W", nkp_grid(1:3)
578 WRITE (u, fmt="(T2,2A,T71,3I4)") χε"K-point mesh 2 for , , W ", &
579 "(for k-point extrapolation of W)", nkp_grid_extra(1:3)
580 WRITE (u, fmt="(T2,A,T80,L)") "Approximate the k-point extrapolation", &
581 bs_env%approx_kp_extrapol
582 END IF
583
584 CALL timestop(handle)
585
586 END SUBROUTINE setup_kpoints_chi_eps_w
587
588! **************************************************************************************************
589!> \brief ...
590!> \param kpoints ...
591!> \param qs_env ...
592! **************************************************************************************************
593 SUBROUTINE kpoint_init_cell_index_simple(kpoints, qs_env)
594
595 TYPE(kpoint_type), POINTER :: kpoints
596 TYPE(qs_environment_type), POINTER :: qs_env
597
598 CHARACTER(LEN=*), PARAMETER :: routinen = 'kpoint_init_cell_index_simple'
599
600 INTEGER :: handle
601 TYPE(dft_control_type), POINTER :: dft_control
602 TYPE(mp_para_env_type), POINTER :: para_env
603 TYPE(neighbor_list_set_p_type), DIMENSION(:), &
604 POINTER :: sab_orb
605
606 CALL timeset(routinen, handle)
607
608 NULLIFY (dft_control, para_env, sab_orb)
609 CALL get_qs_env(qs_env=qs_env, para_env=para_env, dft_control=dft_control, sab_orb=sab_orb)
610 CALL kpoint_init_cell_index(kpoints, sab_orb, para_env, dft_control)
611
612 CALL timestop(handle)
613
614 END SUBROUTINE kpoint_init_cell_index_simple
615
616! **************************************************************************************************
617!> \brief ...
618!> \param xkp ...
619!> \param ikp_start ...
620!> \param ikp_end ...
621!> \param grid ...
622! **************************************************************************************************
623 SUBROUTINE compute_xkp(xkp, ikp_start, ikp_end, grid)
624
625 REAL(kind=dp), DIMENSION(:, :), POINTER :: xkp
626 INTEGER :: ikp_start, ikp_end
627 INTEGER, DIMENSION(3) :: grid
628
629 CHARACTER(LEN=*), PARAMETER :: routinen = 'compute_xkp'
630
631 INTEGER :: handle, i, ix, iy, iz
632
633 CALL timeset(routinen, handle)
634
635 i = ikp_start
636 DO ix = 1, grid(1)
637 DO iy = 1, grid(2)
638 DO iz = 1, grid(3)
639
640 IF (i > ikp_end) cycle
641
642 xkp(1, i) = real(2*ix - grid(1) - 1, kind=dp)/(2._dp*real(grid(1), kind=dp))
643 xkp(2, i) = real(2*iy - grid(2) - 1, kind=dp)/(2._dp*real(grid(2), kind=dp))
644 xkp(3, i) = real(2*iz - grid(3) - 1, kind=dp)/(2._dp*real(grid(3), kind=dp))
645 i = i + 1
646
647 END DO
648 END DO
649 END DO
650
651 CALL timestop(handle)
652
653 END SUBROUTINE compute_xkp
654
655! **************************************************************************************************
656!> \brief ...
657!> \param wkp ...
658!> \param nkp_1 ...
659!> \param nkp_2 ...
660!> \param exponent ...
661! **************************************************************************************************
662 SUBROUTINE compute_wkp(wkp, nkp_1, nkp_2, exponent)
663 REAL(kind=dp), DIMENSION(:) :: wkp
664 INTEGER :: nkp_1, nkp_2
665 REAL(kind=dp) :: exponent
666
667 CHARACTER(LEN=*), PARAMETER :: routinen = 'compute_wkp'
668
669 INTEGER :: handle
670 REAL(kind=dp) :: nkp_ratio
671
672 CALL timeset(routinen, handle)
673
674 nkp_ratio = real(nkp_2, kind=dp)/real(nkp_1, kind=dp)
675
676 wkp(:) = 1.0_dp/real(nkp_1, kind=dp)/(1.0_dp - nkp_ratio**exponent)
677
678 CALL timestop(handle)
679
680 END SUBROUTINE compute_wkp
681
682! **************************************************************************************************
683!> \brief ...
684!> \param qs_env ...
685!> \param bs_env ...
686! **************************************************************************************************
687 SUBROUTINE allocate_matrices(qs_env, bs_env)
688 TYPE(qs_environment_type), POINTER :: qs_env
689 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
690
691 CHARACTER(LEN=*), PARAMETER :: routinen = 'allocate_matrices'
692
693 INTEGER :: handle, i_t
694 TYPE(cp_blacs_env_type), POINTER :: blacs_env, blacs_env_tensor
695 TYPE(cp_fm_struct_type), POINTER :: fm_struct, fm_struct_ri_global
696 TYPE(mp_para_env_type), POINTER :: para_env
697
698 CALL timeset(routinen, handle)
699
700 CALL get_qs_env(qs_env, para_env=para_env, blacs_env=blacs_env)
701
702 fm_struct => bs_env%fm_ks_Gamma(1)%matrix_struct
703
704 CALL cp_fm_create(bs_env%fm_Gocc, fm_struct)
705 CALL cp_fm_create(bs_env%fm_Gvir, fm_struct)
706
707 NULLIFY (fm_struct_ri_global)
708 CALL cp_fm_struct_create(fm_struct_ri_global, context=blacs_env, nrow_global=bs_env%n_RI, &
709 ncol_global=bs_env%n_RI, para_env=para_env)
710 CALL cp_fm_create(bs_env%fm_RI_RI, fm_struct_ri_global)
711 CALL cp_fm_create(bs_env%fm_chi_Gamma_freq, fm_struct_ri_global)
712 CALL cp_fm_create(bs_env%fm_W_MIC_freq, fm_struct_ri_global)
713 IF (bs_env%approx_kp_extrapol) THEN
714 CALL cp_fm_create(bs_env%fm_W_MIC_freq_1_extra, fm_struct_ri_global)
715 CALL cp_fm_create(bs_env%fm_W_MIC_freq_1_no_extra, fm_struct_ri_global)
716 CALL cp_fm_set_all(bs_env%fm_W_MIC_freq_1_extra, 0.0_dp)
717 CALL cp_fm_set_all(bs_env%fm_W_MIC_freq_1_no_extra, 0.0_dp)
718 END IF
719 CALL cp_fm_struct_release(fm_struct_ri_global)
720
721 ! create blacs_env for subgroups of tensor operations
722 NULLIFY (blacs_env_tensor)
723 CALL cp_blacs_env_create(blacs_env=blacs_env_tensor, para_env=bs_env%para_env_tensor)
724
725 ! allocate dbcsr matrices in the tensor subgroup; actually, one only needs a small
726 ! subset of blocks in the tensor subgroup, however, all atomic blocks are allocated.
727 ! One might think of creating a dbcsr matrix with only the blocks that are needed
728 ! in the tensor subgroup
729 CALL create_mat_munu(bs_env%mat_ao_ao_tensor, qs_env, bs_env%eps_atom_grid_2d_mat, &
730 blacs_env_tensor, do_ri_aux_basis=.false.)
731
732 CALL create_mat_munu(bs_env%mat_RI_RI_tensor, qs_env, bs_env%eps_atom_grid_2d_mat, &
733 blacs_env_tensor, do_ri_aux_basis=.true.)
734
735 CALL create_mat_munu(bs_env%mat_RI_RI, qs_env, bs_env%eps_atom_grid_2d_mat, &
736 blacs_env, do_ri_aux_basis=.true.)
737
738 CALL cp_blacs_env_release(blacs_env_tensor)
739
740 NULLIFY (bs_env%mat_chi_Gamma_tau)
741 CALL dbcsr_allocate_matrix_set(bs_env%mat_chi_Gamma_tau, bs_env%num_time_freq_points)
742
743 DO i_t = 1, bs_env%num_time_freq_points
744 ALLOCATE (bs_env%mat_chi_Gamma_tau(i_t)%matrix)
745 CALL dbcsr_create(bs_env%mat_chi_Gamma_tau(i_t)%matrix, template=bs_env%mat_RI_RI%matrix)
746 END DO
747
748 CALL timestop(handle)
749
750 END SUBROUTINE allocate_matrices
751
752! **************************************************************************************************
753!> \brief ...
754!> \param bs_env ...
755! **************************************************************************************************
756 SUBROUTINE allocate_gw_eigenvalues(bs_env)
757 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
758
759 CHARACTER(LEN=*), PARAMETER :: routinen = 'allocate_GW_eigenvalues'
760
761 INTEGER :: handle
762
763 CALL timeset(routinen, handle)
764
765 ALLOCATE (bs_env%eigenval_G0W0(bs_env%n_ao, bs_env%nkp_bs_and_DOS, bs_env%n_spin))
766 ALLOCATE (bs_env%eigenval_HF(bs_env%n_ao, bs_env%nkp_bs_and_DOS, bs_env%n_spin))
767
768 CALL timestop(handle)
769
770 END SUBROUTINE allocate_gw_eigenvalues
771
772! **************************************************************************************************
773!> \brief ...
774!> \param qs_env ...
775!> \param bs_env ...
776! **************************************************************************************************
777 SUBROUTINE create_tensors(qs_env, bs_env)
778 TYPE(qs_environment_type), POINTER :: qs_env
779 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
780
781 CHARACTER(LEN=*), PARAMETER :: routinen = 'create_tensors'
782
783 INTEGER :: handle
784
785 CALL timeset(routinen, handle)
786
787 CALL init_interaction_radii(bs_env)
788
789 ! split blocks does not improve load balancing/efficienfy for tensor contraction, so we go
790 ! with the standard atomic blocks
791 CALL create_3c_t(bs_env%t_RI_AO__AO, bs_env%para_env_tensor, "(RI AO | AO)", [1, 2], [3], &
792 bs_env%sizes_RI, bs_env%sizes_AO, &
793 create_nl_3c=.true., nl_3c=bs_env%nl_3c, qs_env=qs_env)
794 CALL create_3c_t(bs_env%t_RI__AO_AO, bs_env%para_env_tensor, "(RI | AO AO)", [1], [2, 3], &
795 bs_env%sizes_RI, bs_env%sizes_AO)
796
797 CALL create_2c_t(bs_env, bs_env%sizes_RI, bs_env%sizes_AO)
798
799 CALL timestop(handle)
800
801 END SUBROUTINE create_tensors
802
803! **************************************************************************************************
804!> \brief ...
805!> \param qs_env ...
806!> \param bs_env ...
807! **************************************************************************************************
808 SUBROUTINE check_sparsity_3c(qs_env, bs_env)
809 TYPE(qs_environment_type), POINTER :: qs_env
810 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
811
812 CHARACTER(LEN=*), PARAMETER :: routinen = 'check_sparsity_3c'
813
814 INTEGER :: handle, n_atom_step, ri_atom
815 INTEGER(int_8) :: mem, non_zero_elements_sum, nze
816 REAL(dp) :: max_dist_ao_atoms, occ, occupation_sum
817 REAL(kind=dp) :: t1, t2
818 TYPE(dbt_type) :: t_3c_global
819 TYPE(dbt_type), ALLOCATABLE, DIMENSION(:, :) :: t_3c_global_array
820 TYPE(neighbor_list_3c_type) :: nl_3c_global
821
822 CALL timeset(routinen, handle)
823
824 ! check the sparsity of 3c integral tensor (µν|P); calculate maximum distance between
825 ! AO atoms µ, ν where at least a single integral (µν|P) is larger than the filter threshold
826 CALL create_3c_t(t_3c_global, bs_env%para_env, "(RI AO | AO)", [1, 2], [3], &
827 bs_env%sizes_RI, bs_env%sizes_AO, &
828 create_nl_3c=.true., nl_3c=nl_3c_global, qs_env=qs_env)
829
830 CALL m_memory(mem)
831 CALL bs_env%para_env%max(mem)
832
833 ALLOCATE (t_3c_global_array(1, 1))
834 CALL dbt_create(t_3c_global, t_3c_global_array(1, 1))
835
836 CALL bs_env%para_env%sync()
837 t1 = m_walltime()
838
839 occupation_sum = 0.0_dp
840 non_zero_elements_sum = 0
841 max_dist_ao_atoms = 0.0_dp
842 n_atom_step = int(sqrt(real(bs_env%n_atom, kind=dp)))
843 ! do not compute full 3c integrals at once because it may cause out of memory
844 DO ri_atom = 1, bs_env%n_atom, n_atom_step
845
846 CALL build_3c_integrals(t_3c_global_array, &
847 bs_env%eps_filter, &
848 qs_env, &
849 nl_3c_global, &
850 int_eps=bs_env%eps_filter, &
851 basis_i=bs_env%basis_set_RI, &
852 basis_j=bs_env%basis_set_AO, &
853 basis_k=bs_env%basis_set_AO, &
854 bounds_i=[ri_atom, min(ri_atom + n_atom_step - 1, bs_env%n_atom)], &
855 potential_parameter=bs_env%ri_metric, &
856 desymmetrize=.false.)
857
858 CALL dbt_filter(t_3c_global_array(1, 1), bs_env%eps_filter)
859
860 CALL bs_env%para_env%sync()
861
862 CALL get_tensor_occupancy(t_3c_global_array(1, 1), nze, occ)
863 non_zero_elements_sum = non_zero_elements_sum + nze
864 occupation_sum = occupation_sum + occ
865
866 CALL get_max_dist_ao_atoms(t_3c_global_array(1, 1), max_dist_ao_atoms, qs_env)
867
868 CALL dbt_clear(t_3c_global_array(1, 1))
869
870 END DO
871
872 t2 = m_walltime()
873
874 bs_env%occupation_3c_int = occupation_sum
875 bs_env%max_dist_AO_atoms = max_dist_ao_atoms
876
877 CALL dbt_destroy(t_3c_global)
878 CALL dbt_destroy(t_3c_global_array(1, 1))
879 DEALLOCATE (t_3c_global_array)
880
881 CALL neighbor_list_3c_destroy(nl_3c_global)
882
883 IF (bs_env%unit_nr > 0) THEN
884 WRITE (bs_env%unit_nr, '(T2,A)') ''
885 WRITE (bs_env%unit_nr, '(T2,A,F27.1,A)') &
886 µν'Computed 3-center integrals (|P), execution time', t2 - t1, ' s'
887 WRITE (bs_env%unit_nr, '(T2,A,F48.3,A)') µν'Percentage of non-zero (|P)', &
888 occupation_sum*100, ' %'
889 WRITE (bs_env%unit_nr, '(T2,A,F33.1,A)') µνµν'Max. distance between , in non-zero (|P)', &
890 max_dist_ao_atoms*angstrom, ' A'
891 WRITE (bs_env%unit_nr, '(T2,2A,I20,A)') 'Required memory if storing all 3-center ', &
892 µν'integrals (|P)', int(real(non_zero_elements_sum, kind=dp)*8.0e-9_dp), ' GB'
893 END IF
894
895 CALL timestop(handle)
896
897 END SUBROUTINE check_sparsity_3c
898
899! **************************************************************************************************
900!> \brief ...
901!> \param bs_env ...
902!> \param sizes_RI ...
903!> \param sizes_AO ...
904! **************************************************************************************************
905 SUBROUTINE create_2c_t(bs_env, sizes_RI, sizes_AO)
906 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
907 INTEGER, ALLOCATABLE, DIMENSION(:) :: sizes_ri, sizes_ao
908
909 CHARACTER(LEN=*), PARAMETER :: routinen = 'create_2c_t'
910
911 INTEGER :: handle
912 INTEGER, ALLOCATABLE, DIMENSION(:) :: dist_1, dist_2
913 INTEGER, DIMENSION(2) :: pdims_2d
914 TYPE(dbt_pgrid_type) :: pgrid_2d
915
916 CALL timeset(routinen, handle)
917
918 ! inspired from rpa_im_time.F / hfx_types.F
919
920 pdims_2d = 0
921 CALL dbt_pgrid_create(bs_env%para_env_tensor, pdims_2d, pgrid_2d)
922
923 CALL create_2c_tensor(bs_env%t_G, dist_1, dist_2, pgrid_2d, sizes_ao, sizes_ao, &
924 name="(AO | AO)")
925 DEALLOCATE (dist_1, dist_2)
926 CALL create_2c_tensor(bs_env%t_chi, dist_1, dist_2, pgrid_2d, sizes_ri, sizes_ri, &
927 name="(RI | RI)")
928 DEALLOCATE (dist_1, dist_2)
929 CALL create_2c_tensor(bs_env%t_W, dist_1, dist_2, pgrid_2d, sizes_ri, sizes_ri, &
930 name="(RI | RI)")
931 DEALLOCATE (dist_1, dist_2)
932 CALL dbt_pgrid_destroy(pgrid_2d)
933
934 CALL timestop(handle)
935
936 END SUBROUTINE create_2c_t
937
938! **************************************************************************************************
939!> \brief ...
940!> \param tensor ...
941!> \param para_env ...
942!> \param tensor_name ...
943!> \param map1 ...
944!> \param map2 ...
945!> \param sizes_RI ...
946!> \param sizes_AO ...
947!> \param create_nl_3c ...
948!> \param nl_3c ...
949!> \param qs_env ...
950! **************************************************************************************************
951 SUBROUTINE create_3c_t(tensor, para_env, tensor_name, map1, map2, sizes_RI, sizes_AO, &
952 create_nl_3c, nl_3c, qs_env)
953 TYPE(dbt_type) :: tensor
954 TYPE(mp_para_env_type), POINTER :: para_env
955 CHARACTER(LEN=12) :: tensor_name
956 INTEGER, DIMENSION(:) :: map1, map2
957 INTEGER, ALLOCATABLE, DIMENSION(:) :: sizes_ri, sizes_ao
958 LOGICAL, OPTIONAL :: create_nl_3c
959 TYPE(neighbor_list_3c_type), OPTIONAL :: nl_3c
960 TYPE(qs_environment_type), OPTIONAL, POINTER :: qs_env
961
962 CHARACTER(LEN=*), PARAMETER :: routinen = 'create_3c_t'
963
964 INTEGER :: handle, nkind
965 INTEGER, ALLOCATABLE, DIMENSION(:) :: dist_ao_1, dist_ao_2, dist_ri
966 INTEGER, DIMENSION(3) :: pcoord, pdims, pdims_3d
967 LOGICAL :: my_create_nl_3c
968 TYPE(dbt_pgrid_type) :: pgrid_3d
969 TYPE(distribution_3d_type) :: dist_3d
970 TYPE(mp_cart_type) :: mp_comm_t3c_2
971 TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
972
973 CALL timeset(routinen, handle)
974
975 pdims_3d = 0
976 CALL dbt_pgrid_create(para_env, pdims_3d, pgrid_3d)
977 CALL create_3c_tensor(tensor, dist_ri, dist_ao_1, dist_ao_2, &
978 pgrid_3d, sizes_ri, sizes_ao, sizes_ao, &
979 map1=map1, map2=map2, name=tensor_name)
980
981 IF (PRESENT(create_nl_3c)) THEN
982 my_create_nl_3c = create_nl_3c
983 ELSE
984 my_create_nl_3c = .false.
985 END IF
986
987 IF (my_create_nl_3c) THEN
988 CALL get_qs_env(qs_env, nkind=nkind, particle_set=particle_set)
989 CALL dbt_mp_environ_pgrid(pgrid_3d, pdims, pcoord)
990 CALL mp_comm_t3c_2%create(pgrid_3d%mp_comm_2d, 3, pdims)
991 CALL distribution_3d_create(dist_3d, dist_ri, dist_ao_1, dist_ao_2, &
992 nkind, particle_set, mp_comm_t3c_2, own_comm=.true.)
993
994 CALL build_3c_neighbor_lists(nl_3c, &
995 qs_env%bs_env%basis_set_RI, &
996 qs_env%bs_env%basis_set_AO, &
997 qs_env%bs_env%basis_set_AO, &
998 dist_3d, qs_env%bs_env%ri_metric, &
999 "GW_3c_nl", qs_env, own_dist=.true.)
1000 END IF
1001
1002 DEALLOCATE (dist_ri, dist_ao_1, dist_ao_2)
1003 CALL dbt_pgrid_destroy(pgrid_3d)
1004
1005 CALL timestop(handle)
1006
1007 END SUBROUTINE create_3c_t
1008
1009! **************************************************************************************************
1010!> \brief ...
1011!> \param bs_env ...
1012! **************************************************************************************************
1013 SUBROUTINE init_interaction_radii(bs_env)
1014 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
1015
1016 CHARACTER(LEN=*), PARAMETER :: routinen = 'init_interaction_radii'
1017
1018 INTEGER :: handle, ibasis
1019 TYPE(gto_basis_set_type), POINTER :: orb_basis, ri_basis
1020
1021 CALL timeset(routinen, handle)
1022
1023 DO ibasis = 1, SIZE(bs_env%basis_set_AO)
1024
1025 orb_basis => bs_env%basis_set_AO(ibasis)%gto_basis_set
1026 CALL init_interaction_radii_orb_basis(orb_basis, bs_env%eps_filter)
1027
1028 ri_basis => bs_env%basis_set_RI(ibasis)%gto_basis_set
1029 CALL init_interaction_radii_orb_basis(ri_basis, bs_env%eps_filter)
1030
1031 END DO
1032
1033 CALL timestop(handle)
1034
1035 END SUBROUTINE init_interaction_radii
1036
1037! **************************************************************************************************
1038!> \brief ...
1039!> \param t_3c_int ...
1040!> \param max_dist_AO_atoms ...
1041!> \param qs_env ...
1042! **************************************************************************************************
1043 SUBROUTINE get_max_dist_ao_atoms(t_3c_int, max_dist_AO_atoms, qs_env)
1044 TYPE(dbt_type) :: t_3c_int
1045 REAL(kind=dp) :: max_dist_ao_atoms
1046 TYPE(qs_environment_type), POINTER :: qs_env
1047
1048 CHARACTER(LEN=*), PARAMETER :: routinen = 'get_max_dist_AO_atoms'
1049
1050 INTEGER :: atom_1, atom_2, handle, num_cells
1051 INTEGER, DIMENSION(3) :: atom_ind
1052 INTEGER, DIMENSION(:, :), POINTER :: index_to_cell
1053 REAL(kind=dp) :: abs_rab
1054 REAL(kind=dp), DIMENSION(3) :: rab
1055 TYPE(cell_type), POINTER :: cell
1056 TYPE(dbt_iterator_type) :: iter
1057 TYPE(mp_para_env_type), POINTER :: para_env
1058 TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
1059
1060 CALL timeset(routinen, handle)
1061
1062 NULLIFY (cell, particle_set, para_env)
1063 CALL get_qs_env(qs_env, cell=cell, particle_set=particle_set, para_env=para_env)
1064
1065!$OMP PARALLEL DEFAULT(NONE) &
1066!$OMP SHARED(t_3c_int, max_dist_AO_atoms, num_cells, index_to_cell, particle_set, cell) &
1067!$OMP PRIVATE(iter,atom_ind,rab, abs_rab, atom_1, atom_2)
1068 CALL dbt_iterator_start(iter, t_3c_int)
1069 DO WHILE (dbt_iterator_blocks_left(iter))
1070 CALL dbt_iterator_next_block(iter, atom_ind)
1071
1072 atom_1 = atom_ind(2)
1073 atom_2 = atom_ind(3)
1074
1075 rab = pbc(particle_set(atom_1)%r(1:3), particle_set(atom_2)%r(1:3), cell)
1076
1077 abs_rab = sqrt(rab(1)**2 + rab(2)**2 + rab(3)**2)
1078
1079 max_dist_ao_atoms = max(max_dist_ao_atoms, abs_rab)
1080
1081 END DO
1082 CALL dbt_iterator_stop(iter)
1083!$OMP END PARALLEL
1084
1085 CALL para_env%max(max_dist_ao_atoms)
1086
1087 CALL timestop(handle)
1088
1089 END SUBROUTINE get_max_dist_ao_atoms
1090
1091! **************************************************************************************************
1092!> \brief ...
1093!> \param bs_env ...
1094! **************************************************************************************************
1095 SUBROUTINE set_sparsity_parallelization_parameters(bs_env)
1096 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
1097
1098 CHARACTER(LEN=*), PARAMETER :: routinen = 'set_sparsity_parallelization_parameters'
1099
1100 INTEGER :: handle, i_ivl, il_ivl, j_ivl, n_atom_per_il_ivl, n_atom_per_ivl, n_intervals_i, &
1101 n_intervals_inner_loop_atoms, n_intervals_j, u
1102 INTEGER(KIND=int_8) :: input_memory_per_proc
1103
1104 CALL timeset(routinen, handle)
1105
1106 ! heuristic parameter to prevent out of memory
1107 bs_env%safety_factor_memory = 0.10_dp
1108
1109 input_memory_per_proc = int(bs_env%input_memory_per_proc_GB*1.0e9_dp, kind=int_8)
1110
1111 ! choose atomic range for λ ("i_atom"), ν ("j_atom") in
1112 ! M_λνP(iτ) = sum_µ (µν|P) G^occ_µλ(i|τ|,k=0)
1113 ! N_νλQ(iτ) = sum_σ (σλ|Q) G^vir_σν(i|τ|,k=0)
1114 ! such that M and N fit into the memory
1115 n_atom_per_ivl = int(sqrt(bs_env%safety_factor_memory*input_memory_per_proc &
1116 *bs_env%group_size_tensor/24/bs_env%n_RI &
1117 /sqrt(bs_env%occupation_3c_int)))/bs_env%max_AO_bf_per_atom
1118
1119 n_intervals_i = (bs_env%n_atom_i - 1)/n_atom_per_ivl + 1
1120 n_intervals_j = (bs_env%n_atom_j - 1)/n_atom_per_ivl + 1
1121
1122 bs_env%n_atom_per_interval_ij = n_atom_per_ivl
1123 bs_env%n_intervals_i = n_intervals_i
1124 bs_env%n_intervals_j = n_intervals_j
1125
1126 ALLOCATE (bs_env%i_atom_intervals(2, n_intervals_i))
1127 ALLOCATE (bs_env%j_atom_intervals(2, n_intervals_j))
1128
1129 DO i_ivl = 1, n_intervals_i
1130 bs_env%i_atom_intervals(1, i_ivl) = (i_ivl - 1)*n_atom_per_ivl + bs_env%atoms_i(1)
1131 bs_env%i_atom_intervals(2, i_ivl) = min(i_ivl*n_atom_per_ivl + bs_env%atoms_i(1) - 1, &
1132 bs_env%atoms_i(2))
1133 END DO
1134
1135 DO j_ivl = 1, n_intervals_j
1136 bs_env%j_atom_intervals(1, j_ivl) = (j_ivl - 1)*n_atom_per_ivl + bs_env%atoms_j(1)
1137 bs_env%j_atom_intervals(2, j_ivl) = min(j_ivl*n_atom_per_ivl + bs_env%atoms_j(1) - 1, &
1138 bs_env%atoms_j(2))
1139 END DO
1140
1141 ALLOCATE (bs_env%skip_Sigma_occ(n_intervals_i, n_intervals_j))
1142 ALLOCATE (bs_env%skip_Sigma_vir(n_intervals_i, n_intervals_j))
1143 bs_env%skip_Sigma_occ(:, :) = .false.
1144 bs_env%skip_Sigma_vir(:, :) = .false.
1145
1146 ! choose atomic range for µ and σ ("inner loop (IL) atom") in
1147 ! M_λνP(iτ) = sum_µ (µν|P) G^occ_µλ(i|τ|,k=0)
1148 ! N_νλQ(iτ) = sum_σ (σλ|Q) G^vir_σν(i|τ|,k=0)
1149 n_atom_per_il_ivl = min(int(bs_env%safety_factor_memory*input_memory_per_proc &
1150 *bs_env%group_size_tensor/n_atom_per_ivl &
1151 /bs_env%max_AO_bf_per_atom &
1152 /bs_env%n_RI/8/sqrt(bs_env%occupation_3c_int) &
1153 /bs_env%max_AO_bf_per_atom), bs_env%n_atom)
1154
1155 n_intervals_inner_loop_atoms = (bs_env%n_atom - 1)/n_atom_per_il_ivl + 1
1156
1157 bs_env%n_atom_per_IL_interval = n_atom_per_il_ivl
1158 bs_env%n_intervals_inner_loop_atoms = n_intervals_inner_loop_atoms
1159
1160 ALLOCATE (bs_env%inner_loop_atom_intervals(2, n_intervals_inner_loop_atoms))
1161 DO il_ivl = 1, n_intervals_inner_loop_atoms
1162 bs_env%inner_loop_atom_intervals(1, il_ivl) = (il_ivl - 1)*n_atom_per_il_ivl + 1
1163 bs_env%inner_loop_atom_intervals(2, il_ivl) = min(il_ivl*n_atom_per_il_ivl, bs_env%n_atom)
1164 END DO
1165
1166 u = bs_env%unit_nr
1167 IF (u > 0) THEN
1168 WRITE (u, '(T2,A)') ''
1169 WRITE (u, '(T2,A,I33)') λντνλτ'Number of i and j atoms in M_P(), N_Q():', n_atom_per_ivl
1170 WRITE (u, '(T2,A,I18)') µλνµµνµλ'Number of inner loop atoms for in M_P = sum_ (|P) G_', &
1171 n_atom_per_il_ivl
1172 END IF
1173
1174 CALL timestop(handle)
1175
1176 END SUBROUTINE set_sparsity_parallelization_parameters
1177
1178! **************************************************************************************************
1179!> \brief ...
1180!> \param qs_env ...
1181!> \param bs_env ...
1182! **************************************************************************************************
1183 SUBROUTINE check_for_restart_files(qs_env, bs_env)
1184 TYPE(qs_environment_type), POINTER :: qs_env
1185 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
1186
1187 CHARACTER(LEN=*), PARAMETER :: routinen = 'check_for_restart_files'
1188
1189 CHARACTER(LEN=9) :: frmt
1190 CHARACTER(LEN=default_string_length) :: f_chi, f_s_n, f_s_p, f_s_x, f_w_t, &
1191 prefix, project_name
1192 INTEGER :: handle, i_spin, i_t_or_w, ind, n_spin, &
1193 num_time_freq_points
1194 LOGICAL :: chi_exists, sigma_neg_time_exists, &
1195 sigma_pos_time_exists, &
1196 sigma_x_spin_exists, w_time_exists
1197 TYPE(cp_logger_type), POINTER :: logger
1198 TYPE(section_vals_type), POINTER :: input, print_key
1199
1200 CALL timeset(routinen, handle)
1201
1202 num_time_freq_points = bs_env%num_time_freq_points
1203 n_spin = bs_env%n_spin
1204
1205 ALLOCATE (bs_env%read_chi(num_time_freq_points))
1206 ALLOCATE (bs_env%calc_chi(num_time_freq_points))
1207 ALLOCATE (bs_env%Sigma_c_exists(num_time_freq_points, n_spin))
1208
1209 CALL get_qs_env(qs_env, input=input)
1210
1211 logger => cp_get_default_logger()
1212 print_key => section_vals_get_subs_vals(input, 'PROPERTIES%BANDSTRUCTURE%GW%PRINT%RESTART')
1213 project_name = cp_print_key_generate_filename(logger, print_key, extension="", &
1214 my_local=.false.)
1215 WRITE (prefix, '(2A)') trim(project_name), "-RESTART_"
1216 bs_env%prefix = prefix
1217
1218 bs_env%all_W_exist = .true.
1219
1220 DO i_t_or_w = 1, num_time_freq_points
1221
1222 IF (i_t_or_w < 10) THEN
1223 WRITE (frmt, '(A)') '(3A,I1,A)'
1224 WRITE (f_chi, frmt) trim(prefix), bs_env%chi_name, "_0", i_t_or_w, ".matrix"
1225 WRITE (f_w_t, frmt) trim(prefix), bs_env%W_time_name, "_0", i_t_or_w, ".matrix"
1226 ELSE IF (i_t_or_w < 100) THEN
1227 WRITE (frmt, '(A)') '(3A,I2,A)'
1228 WRITE (f_chi, frmt) trim(prefix), bs_env%chi_name, "_", i_t_or_w, ".matrix"
1229 WRITE (f_w_t, frmt) trim(prefix), bs_env%W_time_name, "_", i_t_or_w, ".matrix"
1230 ELSE
1231 cpabort('Please implement more than 99 time/frequency points.')
1232 END IF
1233
1234 INQUIRE (file=trim(f_chi), exist=chi_exists)
1235 INQUIRE (file=trim(f_w_t), exist=w_time_exists)
1236
1237 bs_env%read_chi(i_t_or_w) = chi_exists
1238 bs_env%calc_chi(i_t_or_w) = .NOT. chi_exists
1239
1240 bs_env%all_W_exist = bs_env%all_W_exist .AND. w_time_exists
1241
1242 ! the self-energy is spin-dependent
1243 DO i_spin = 1, n_spin
1244
1245 ind = i_t_or_w + (i_spin - 1)*num_time_freq_points
1246
1247 IF (ind < 10) THEN
1248 WRITE (frmt, '(A)') '(3A,I1,A)'
1249 WRITE (f_s_p, frmt) trim(prefix), bs_env%Sigma_p_name, "_0", ind, ".matrix"
1250 WRITE (f_s_n, frmt) trim(prefix), bs_env%Sigma_n_name, "_0", ind, ".matrix"
1251 ELSE IF (i_t_or_w < 100) THEN
1252 WRITE (frmt, '(A)') '(3A,I2,A)'
1253 WRITE (f_s_p, frmt) trim(prefix), bs_env%Sigma_p_name, "_", ind, ".matrix"
1254 WRITE (f_s_n, frmt) trim(prefix), bs_env%Sigma_n_name, "_", ind, ".matrix"
1255 END IF
1256
1257 INQUIRE (file=trim(f_s_p), exist=sigma_pos_time_exists)
1258 INQUIRE (file=trim(f_s_n), exist=sigma_neg_time_exists)
1259
1260 bs_env%Sigma_c_exists(i_t_or_w, i_spin) = sigma_pos_time_exists .AND. &
1261 sigma_neg_time_exists
1262
1263 END DO
1264
1265 END DO
1266
1267 ! Marek : In the RTBSE run, check also for zero frequency W
1268 IF (bs_env%rtp_method == rtp_method_bse) THEN
1269 WRITE (f_w_t, '(3A,I1,A)') trim(prefix), "W_freq_rtp", "_0", 0, ".matrix"
1270 INQUIRE (file=trim(f_w_t), exist=w_time_exists)
1271 bs_env%all_W_exist = bs_env%all_W_exist .AND. w_time_exists
1272 END IF
1273
1274 IF (bs_env%all_W_exist) THEN
1275 bs_env%read_chi(:) = .false.
1276 bs_env%calc_chi(:) = .false.
1277 END IF
1278
1279 bs_env%Sigma_x_exists = .true.
1280 DO i_spin = 1, n_spin
1281 WRITE (f_s_x, '(3A,I1,A)') trim(prefix), bs_env%Sigma_x_name, "_0", i_spin, ".matrix"
1282 INQUIRE (file=trim(f_s_x), exist=sigma_x_spin_exists)
1283 bs_env%Sigma_x_exists = bs_env%Sigma_x_exists .AND. sigma_x_spin_exists
1284 END DO
1285
1286 CALL timestop(handle)
1287
1288 END SUBROUTINE check_for_restart_files
1289
1290! **************************************************************************************************
1291!> \brief ...
1292!> \param qs_env ...
1293!> \param bs_env ...
1294! **************************************************************************************************
1295 SUBROUTINE set_parallelization_parameters(qs_env, bs_env)
1296 TYPE(qs_environment_type), POINTER :: qs_env
1297 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
1298
1299 CHARACTER(LEN=*), PARAMETER :: routinen = 'set_parallelization_parameters'
1300
1301 INTEGER :: color_sub, dummy_1, dummy_2, handle, &
1302 num_pe, num_t_groups, u
1303 INTEGER(KIND=int_8) :: mem
1304 TYPE(mp_para_env_type), POINTER :: para_env
1305
1306 CALL timeset(routinen, handle)
1307
1308 CALL get_qs_env(qs_env, para_env=para_env)
1309
1310 num_pe = para_env%num_pe
1311 ! if not already set, use all processors for the group (for large-cell GW, performance
1312 ! seems to be best for a single group with all MPI processes per group)
1313 IF (bs_env%group_size_tensor < 0 .OR. bs_env%group_size_tensor > num_pe) &
1314 bs_env%group_size_tensor = num_pe
1315
1316 ! group_size_tensor must divide num_pe without rest; otherwise everything will be complicated
1317 IF (modulo(num_pe, bs_env%group_size_tensor) .NE. 0) THEN
1318 CALL find_good_group_size(num_pe, bs_env%group_size_tensor)
1319 END IF
1320
1321 ! para_env_tensor for tensor subgroups
1322 color_sub = para_env%mepos/bs_env%group_size_tensor
1323 bs_env%tensor_group_color = color_sub
1324
1325 ALLOCATE (bs_env%para_env_tensor)
1326 CALL bs_env%para_env_tensor%from_split(para_env, color_sub)
1327
1328 num_t_groups = para_env%num_pe/bs_env%group_size_tensor
1329 bs_env%num_tensor_groups = num_t_groups
1330
1331 CALL get_i_j_atoms(bs_env%atoms_i, bs_env%atoms_j, bs_env%n_atom_i, bs_env%n_atom_j, &
1332 color_sub, bs_env)
1333
1334 ALLOCATE (bs_env%atoms_i_t_group(2, num_t_groups))
1335 ALLOCATE (bs_env%atoms_j_t_group(2, num_t_groups))
1336 DO color_sub = 0, num_t_groups - 1
1337 CALL get_i_j_atoms(bs_env%atoms_i_t_group(1:2, color_sub + 1), &
1338 bs_env%atoms_j_t_group(1:2, color_sub + 1), &
1339 dummy_1, dummy_2, color_sub, bs_env)
1340 END DO
1341
1342 CALL m_memory(mem)
1343 CALL bs_env%para_env%max(mem)
1344
1345 u = bs_env%unit_nr
1346 IF (u > 0) THEN
1347 WRITE (u, '(T2,A,I47)') 'Group size for tensor operations', bs_env%group_size_tensor
1348 IF (bs_env%group_size_tensor > 1 .AND. bs_env%n_atom < 5) THEN
1349 WRITE (u, '(T2,A)') 'The requested group size is > 1 which can lead to bad performance.'
1350 WRITE (u, '(T2,A)') 'Using more memory per MPI process might improve performance.'
1351 WRITE (u, '(T2,A)') '(Also increase MEMORY_PER_PROC when using more memory per process.)'
1352 END IF
1353 END IF
1354
1355 CALL timestop(handle)
1356
1357 END SUBROUTINE set_parallelization_parameters
1358
1359! **************************************************************************************************
1360!> \brief ...
1361!> \param num_pe ...
1362!> \param group_size ...
1363! **************************************************************************************************
1364 SUBROUTINE find_good_group_size(num_pe, group_size)
1365
1366 INTEGER :: num_pe, group_size
1367
1368 CHARACTER(LEN=*), PARAMETER :: routinen = 'find_good_group_size'
1369
1370 INTEGER :: group_size_minus, group_size_orig, &
1371 group_size_plus, handle, i_diff
1372
1373 CALL timeset(routinen, handle)
1374
1375 group_size_orig = group_size
1376
1377 DO i_diff = 1, num_pe
1378
1379 group_size_minus = group_size - i_diff
1380
1381 IF (modulo(num_pe, group_size_minus) == 0 .AND. group_size_minus > 0) THEN
1382 group_size = group_size_minus
1383 EXIT
1384 END IF
1385
1386 group_size_plus = group_size + i_diff
1387
1388 IF (modulo(num_pe, group_size_plus) == 0 .AND. group_size_plus <= num_pe) THEN
1389 group_size = group_size_plus
1390 EXIT
1391 END IF
1392
1393 END DO
1394
1395 IF (group_size_orig == group_size) cpabort("Group size error")
1396
1397 CALL timestop(handle)
1398
1399 END SUBROUTINE find_good_group_size
1400
1401! **************************************************************************************************
1402!> \brief ...
1403!> \param atoms_i ...
1404!> \param atoms_j ...
1405!> \param n_atom_i ...
1406!> \param n_atom_j ...
1407!> \param color_sub ...
1408!> \param bs_env ...
1409! **************************************************************************************************
1410 SUBROUTINE get_i_j_atoms(atoms_i, atoms_j, n_atom_i, n_atom_j, color_sub, bs_env)
1411
1412 INTEGER, DIMENSION(2) :: atoms_i, atoms_j
1413 INTEGER :: n_atom_i, n_atom_j, color_sub
1414 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
1415
1416 CHARACTER(LEN=*), PARAMETER :: routinen = 'get_i_j_atoms'
1417
1418 INTEGER :: handle, i_atoms_per_group, i_group, &
1419 ipcol, ipcol_loop, iprow, iprow_loop, &
1420 j_atoms_per_group, npcol, nprow
1421
1422 CALL timeset(routinen, handle)
1423
1424 ! create a square mesh of tensor groups for iatom and jatom; code from blacs_env_create
1425 CALL square_mesh(nprow, npcol, bs_env%num_tensor_groups)
1426
1427 i_group = 0
1428 DO ipcol_loop = 0, npcol - 1
1429 DO iprow_loop = 0, nprow - 1
1430 IF (i_group == color_sub) THEN
1431 iprow = iprow_loop
1432 ipcol = ipcol_loop
1433 END IF
1434 i_group = i_group + 1
1435 END DO
1436 END DO
1437
1438 IF (modulo(bs_env%n_atom, nprow) == 0) THEN
1439 i_atoms_per_group = bs_env%n_atom/nprow
1440 ELSE
1441 i_atoms_per_group = bs_env%n_atom/nprow + 1
1442 END IF
1443
1444 IF (modulo(bs_env%n_atom, npcol) == 0) THEN
1445 j_atoms_per_group = bs_env%n_atom/npcol
1446 ELSE
1447 j_atoms_per_group = bs_env%n_atom/npcol + 1
1448 END IF
1449
1450 atoms_i(1) = iprow*i_atoms_per_group + 1
1451 atoms_i(2) = min((iprow + 1)*i_atoms_per_group, bs_env%n_atom)
1452 n_atom_i = atoms_i(2) - atoms_i(1) + 1
1453
1454 atoms_j(1) = ipcol*j_atoms_per_group + 1
1455 atoms_j(2) = min((ipcol + 1)*j_atoms_per_group, bs_env%n_atom)
1456 n_atom_j = atoms_j(2) - atoms_j(1) + 1
1457
1458 CALL timestop(handle)
1459
1460 END SUBROUTINE get_i_j_atoms
1461
1462! **************************************************************************************************
1463!> \brief ...
1464!> \param nprow ...
1465!> \param npcol ...
1466!> \param nproc ...
1467! **************************************************************************************************
1468 SUBROUTINE square_mesh(nprow, npcol, nproc)
1469 INTEGER :: nprow, npcol, nproc
1470
1471 CHARACTER(LEN=*), PARAMETER :: routinen = 'square_mesh'
1472
1473 INTEGER :: gcd_max, handle, ipe, jpe
1474
1475 CALL timeset(routinen, handle)
1476
1477 gcd_max = -1
1478 DO ipe = 1, ceiling(sqrt(real(nproc, dp)))
1479 jpe = nproc/ipe
1480 IF (ipe*jpe .NE. nproc) cycle
1481 IF (gcd(ipe, jpe) >= gcd_max) THEN
1482 nprow = ipe
1483 npcol = jpe
1484 gcd_max = gcd(ipe, jpe)
1485 END IF
1486 END DO
1487
1488 CALL timestop(handle)
1489
1490 END SUBROUTINE square_mesh
1491
1492! **************************************************************************************************
1493!> \brief ...
1494!> \param bs_env ...
1495!> \param qs_env ...
1496! **************************************************************************************************
1497 SUBROUTINE set_heuristic_parameters(bs_env, qs_env)
1498 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
1499 TYPE(qs_environment_type), OPTIONAL, POINTER :: qs_env
1500
1501 CHARACTER(LEN=*), PARAMETER :: routinen = 'set_heuristic_parameters'
1502
1503 INTEGER :: handle, u
1504 LOGICAL :: do_bvk_cell
1505
1506 CALL timeset(routinen, handle)
1507
1508 ! for generating numerically stable minimax Fourier integration weights
1509 bs_env%num_points_per_magnitude = 200
1510
1511 ! for periodic systems and for 20 minimax points, we use a regularized minimax mesh
1512 ! (from experience: regularized minimax meshes converges faster for periodic systems
1513 ! and for 20 pts)
1514 IF (sum(bs_env%periodic) .NE. 0 .OR. bs_env%num_time_freq_points >= 20) THEN
1515 bs_env%regularization_minimax = 1.0e-6_dp
1516 ELSE
1517 bs_env%regularization_minimax = 0.0_dp
1518 END IF
1519
1520 bs_env%stabilize_exp = 70.0_dp
1521 bs_env%eps_atom_grid_2d_mat = 1.0e-50_dp
1522
1523 ! use a 16-parameter Padé fit
1524 bs_env%nparam_pade = 16
1525
1526 ! resolution of the identity with the truncated Coulomb metric, cutoff radius 3 Angström
1527 bs_env%ri_metric%potential_type = do_potential_truncated
1528 bs_env%ri_metric%omega = 0.0_dp
1529 ! cutoff radius is specified in the input
1530 bs_env%ri_metric%filename = "t_c_g.dat"
1531
1532 bs_env%eps_eigval_mat_RI = 0.0_dp
1533
1534 IF (bs_env%input_regularization_RI > -1.0e-12_dp) THEN
1535 bs_env%regularization_RI = bs_env%input_regularization_RI
1536 ELSE
1537 ! default case:
1538
1539 ! 1. for periodic systems, we use the regularized resolution of the identity per default
1540 bs_env%regularization_RI = 1.0e-2_dp
1541
1542 ! 2. for molecules, no regularization is necessary
1543 IF (sum(bs_env%periodic) == 0) bs_env%regularization_RI = 0.0_dp
1544
1545 END IF
1546
1547 ! truncated Coulomb operator for exchange self-energy
1548 ! (see details in Guidon, VandeVondele, Hutter, JCTC 5, 3010 (2009) and references therein)
1549 do_bvk_cell = bs_env%small_cell_full_kp_or_large_cell_Gamma == small_cell_full_kp
1550 CALL trunc_coulomb_for_exchange(qs_env, bs_env%trunc_coulomb, &
1551 rel_cutoff_trunc_coulomb_ri_x=0.5_dp, &
1552 cell_grid=bs_env%cell_grid_scf_desymm, &
1553 do_bvk_cell=do_bvk_cell)
1554
1555 ! for small-cell GW, we need more cells than normally used by the filter bs_env%eps_filter
1556 ! (in particular for computing the self-energy because of higher number of cells needed)
1557 bs_env%heuristic_filter_factor = 1.0e-4
1558
1559 u = bs_env%unit_nr
1560 IF (u > 0) THEN
1561 WRITE (u, fmt="(T2,2A,F21.1,A)") "Cutoff radius for the truncated Coulomb ", &
1562 Σ"operator in ^x:", bs_env%trunc_coulomb%cutoff_radius*angstrom, Å" "
1563 WRITE (u, fmt="(T2,2A,F15.1,A)") "Cutoff radius for the truncated Coulomb ", &
1564 "operator in RI metric:", bs_env%ri_metric%cutoff_radius*angstrom, Å" "
1565 WRITE (u, fmt="(T2,A,ES48.1)") "Regularization parameter of RI ", bs_env%regularization_RI
1566 WRITE (u, fmt="(T2,A,I53)") "Lattice sum size for V(k):", bs_env%size_lattice_sum_V
1567 END IF
1568
1569 CALL timestop(handle)
1570
1571 END SUBROUTINE set_heuristic_parameters
1572
1573! **************************************************************************************************
1574!> \brief ...
1575!> \param bs_env ...
1576! **************************************************************************************************
1577 SUBROUTINE print_header_and_input_parameters(bs_env)
1578
1579 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
1580
1581 CHARACTER(LEN=*), PARAMETER :: routinen = 'print_header_and_input_parameters'
1582
1583 INTEGER :: handle, u
1584
1585 CALL timeset(routinen, handle)
1586
1587 u = bs_env%unit_nr
1588
1589 IF (u > 0) THEN
1590 WRITE (u, '(T2,A)') ' '
1591 WRITE (u, '(T2,A)') repeat('-', 79)
1592 WRITE (u, '(T2,A,A78)') '-', '-'
1593 WRITE (u, '(T2,A,A46,A32)') '-', 'GW CALCULATION', '-'
1594 WRITE (u, '(T2,A,A78)') '-', '-'
1595 WRITE (u, '(T2,A)') repeat('-', 79)
1596 WRITE (u, '(T2,A)') ' '
1597 WRITE (u, '(T2,A,I45)') 'Input: Number of time/freq. points', bs_env%num_time_freq_points
1598 WRITE (u, "(T2,A,F44.1,A)") ωΣω'Input: _max for fitting (i) (eV)', bs_env%freq_max_fit*evolt
1599 WRITE (u, '(T2,A,ES27.1)') 'Input: Filter threshold for sparse tensor operations', &
1600 bs_env%eps_filter
1601 WRITE (u, "(T2,A,L55)") 'Input: Apply Hedin shift', bs_env%do_hedin_shift
1602 END IF
1603
1604 CALL timestop(handle)
1605
1606 END SUBROUTINE print_header_and_input_parameters
1607
1608! **************************************************************************************************
1609!> \brief ...
1610!> \param qs_env ...
1611!> \param bs_env ...
1612! **************************************************************************************************
1613 SUBROUTINE compute_v_xc(qs_env, bs_env)
1614 TYPE(qs_environment_type), POINTER :: qs_env
1615 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
1616
1617 CHARACTER(LEN=*), PARAMETER :: routinen = 'compute_V_xc'
1618
1619 INTEGER :: handle, img, ispin, myfun, nimages
1620 LOGICAL :: hf_present
1621 REAL(kind=dp) :: energy_ex, energy_exc, energy_total, &
1622 myfraction
1623 TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: mat_ks_without_v_xc
1624 TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: matrix_ks_kp
1625 TYPE(dft_control_type), POINTER :: dft_control
1626 TYPE(qs_energy_type), POINTER :: energy
1627 TYPE(section_vals_type), POINTER :: hf_section, input, xc_section
1628
1629 CALL timeset(routinen, handle)
1630
1631 CALL get_qs_env(qs_env, input=input, energy=energy, dft_control=dft_control)
1632
1633 ! previously, dft_control%nimages set to # neighbor cells, revert for Γ-only KS matrix
1634 nimages = dft_control%nimages
1635 dft_control%nimages = bs_env%nimages_scf
1636
1637 ! we need to reset XC functional, therefore, get XC input
1638 xc_section => section_vals_get_subs_vals(input, "DFT%XC")
1639 CALL section_vals_val_get(xc_section, "XC_FUNCTIONAL%_SECTION_PARAMETERS_", i_val=myfun)
1640 CALL section_vals_val_set(xc_section, "XC_FUNCTIONAL%_SECTION_PARAMETERS_", i_val=xc_none)
1641 ! IF (ASSOCIATED(section_vals_get_subs_vals(xc_section, "HF", can_return_null=.TRUE.))) THEN
1642 hf_section => section_vals_get_subs_vals(input, "DFT%XC%HF", can_return_null=.true.)
1643 hf_present = .false.
1644 IF (ASSOCIATED(hf_section)) THEN
1645 CALL section_vals_get(hf_section, explicit=hf_present)
1646 END IF
1647 IF (hf_present) THEN
1648 ! Special case for handling hfx
1649 CALL section_vals_val_get(xc_section, "HF%FRACTION", r_val=myfraction)
1650 CALL section_vals_val_set(xc_section, "HF%FRACTION", r_val=0.0_dp)
1651 END IF
1652
1653 ! save the energy before the energy gets updated
1654 energy_total = energy%total
1655 energy_exc = energy%exc
1656 energy_ex = energy%ex
1657
1658 SELECT CASE (bs_env%small_cell_full_kp_or_large_cell_Gamma)
1659 CASE (large_cell_gamma)
1660
1661 NULLIFY (mat_ks_without_v_xc)
1662 CALL dbcsr_allocate_matrix_set(mat_ks_without_v_xc, bs_env%n_spin)
1663
1664 DO ispin = 1, bs_env%n_spin
1665 ALLOCATE (mat_ks_without_v_xc(ispin)%matrix)
1666 IF (hf_present) THEN
1667 CALL dbcsr_create(mat_ks_without_v_xc(ispin)%matrix, template=bs_env%mat_ao_ao%matrix, &
1668 matrix_type=dbcsr_type_symmetric)
1669 ELSE
1670 CALL dbcsr_create(mat_ks_without_v_xc(ispin)%matrix, template=bs_env%mat_ao_ao%matrix)
1671 END IF
1672 END DO
1673
1674 ! calculate KS-matrix without XC
1675 CALL qs_ks_build_kohn_sham_matrix(qs_env, calculate_forces=.false., just_energy=.false., &
1676 ext_ks_matrix=mat_ks_without_v_xc)
1677
1678 DO ispin = 1, bs_env%n_spin
1679 ! transfer dbcsr matrix to fm
1680 CALL cp_fm_create(bs_env%fm_V_xc_Gamma(ispin), bs_env%fm_s_Gamma%matrix_struct)
1681 CALL copy_dbcsr_to_fm(mat_ks_without_v_xc(ispin)%matrix, bs_env%fm_V_xc_Gamma(ispin))
1682
1683 ! v_xc = h_ks - h_ks(v_xc = 0)
1684 CALL cp_fm_scale_and_add(alpha=-1.0_dp, matrix_a=bs_env%fm_V_xc_Gamma(ispin), &
1685 beta=1.0_dp, matrix_b=bs_env%fm_ks_Gamma(ispin))
1686 END DO
1687
1688 CALL dbcsr_deallocate_matrix_set(mat_ks_without_v_xc)
1689
1690 CASE (small_cell_full_kp)
1691
1692 ! calculate KS-matrix without XC
1693 CALL qs_ks_build_kohn_sham_matrix(qs_env, calculate_forces=.false., just_energy=.false.)
1694 CALL get_qs_env(qs_env=qs_env, matrix_ks_kp=matrix_ks_kp)
1695
1696 ALLOCATE (bs_env%fm_V_xc_R(dft_control%nimages, bs_env%n_spin))
1697 DO ispin = 1, bs_env%n_spin
1698 DO img = 1, dft_control%nimages
1699 ! safe fm_V_xc_R in fm_matrix because saving in dbcsr matrix caused trouble...
1700 CALL copy_dbcsr_to_fm(matrix_ks_kp(ispin, img)%matrix, bs_env%fm_work_mo(1))
1701 CALL cp_fm_create(bs_env%fm_V_xc_R(img, ispin), bs_env%fm_work_mo(1)%matrix_struct)
1702 ! store h_ks(v_xc = 0) in fm_V_xc_R
1703 CALL cp_fm_scale_and_add(alpha=1.0_dp, matrix_a=bs_env%fm_V_xc_R(img, ispin), &
1704 beta=1.0_dp, matrix_b=bs_env%fm_work_mo(1))
1705 END DO
1706 END DO
1707
1708 END SELECT
1709
1710 ! set back the energy
1711 energy%total = energy_total
1712 energy%exc = energy_exc
1713 energy%ex = energy_ex
1714
1715 ! set back nimages
1716 dft_control%nimages = nimages
1717
1718 ! set the DFT functional and HF fraction back
1719 CALL section_vals_val_set(xc_section, "XC_FUNCTIONAL%_SECTION_PARAMETERS_", &
1720 i_val=myfun)
1721 IF (hf_present) THEN
1722 CALL section_vals_val_set(xc_section, "HF%FRACTION", &
1723 r_val=myfraction)
1724 END IF
1725
1726 IF (bs_env%small_cell_full_kp_or_large_cell_Gamma == small_cell_full_kp) THEN
1727 ! calculate KS-matrix again with XC
1728 CALL qs_ks_build_kohn_sham_matrix(qs_env, calculate_forces=.false., just_energy=.false.)
1729 DO ispin = 1, bs_env%n_spin
1730 DO img = 1, dft_control%nimages
1731 ! store h_ks in fm_work_mo
1732 CALL copy_dbcsr_to_fm(matrix_ks_kp(ispin, img)%matrix, bs_env%fm_work_mo(1))
1733 ! v_xc = h_ks - h_ks(v_xc = 0)
1734 CALL cp_fm_scale_and_add(alpha=-1.0_dp, matrix_a=bs_env%fm_V_xc_R(img, ispin), &
1735 beta=1.0_dp, matrix_b=bs_env%fm_work_mo(1))
1736 END DO
1737 END DO
1738 END IF
1739
1740 CALL timestop(handle)
1741
1742 END SUBROUTINE compute_v_xc
1743
1744! **************************************************************************************************
1745!> \brief ...
1746!> \param bs_env ...
1747! **************************************************************************************************
1748 SUBROUTINE setup_time_and_frequency_minimax_grid(bs_env)
1749 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
1750
1751 CHARACTER(LEN=*), PARAMETER :: routinen = 'setup_time_and_frequency_minimax_grid'
1752
1753 INTEGER :: handle, homo, i_w, ierr, ispin, j_w, &
1754 n_mo, num_time_freq_points, u
1755 REAL(kind=dp) :: e_max, e_max_ispin, e_min, e_min_ispin, &
1756 e_range, max_error_min
1757 REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: points_and_weights
1758
1759 CALL timeset(routinen, handle)
1760
1761 n_mo = bs_env%n_ao
1762 num_time_freq_points = bs_env%num_time_freq_points
1763
1764 ALLOCATE (bs_env%imag_freq_points(num_time_freq_points))
1765 ALLOCATE (bs_env%imag_time_points(num_time_freq_points))
1766 ALLOCATE (bs_env%imag_time_weights_freq_zero(num_time_freq_points))
1767 ALLOCATE (bs_env%weights_cos_t_to_w(num_time_freq_points, num_time_freq_points))
1768 ALLOCATE (bs_env%weights_cos_w_to_t(num_time_freq_points, num_time_freq_points))
1769 ALLOCATE (bs_env%weights_sin_t_to_w(num_time_freq_points, num_time_freq_points))
1770
1771 ! minimum and maximum difference between eigenvalues of unoccupied and an occupied MOs
1772 e_min = 1000.0_dp
1773 e_max = -1000.0_dp
1774 DO ispin = 1, bs_env%n_spin
1775 homo = bs_env%n_occ(ispin)
1776 SELECT CASE (bs_env%small_cell_full_kp_or_large_cell_Gamma)
1777 CASE (large_cell_gamma)
1778 e_min_ispin = bs_env%eigenval_scf_Gamma(homo + 1, ispin) - &
1779 bs_env%eigenval_scf_Gamma(homo, ispin)
1780 e_max_ispin = bs_env%eigenval_scf_Gamma(n_mo, ispin) - &
1781 bs_env%eigenval_scf_Gamma(1, ispin)
1782 CASE (small_cell_full_kp)
1783 e_min_ispin = minval(bs_env%eigenval_scf(homo + 1, :, ispin)) - &
1784 maxval(bs_env%eigenval_scf(homo, :, ispin))
1785 e_max_ispin = maxval(bs_env%eigenval_scf(n_mo, :, ispin)) - &
1786 minval(bs_env%eigenval_scf(1, :, ispin))
1787 END SELECT
1788 e_min = min(e_min, e_min_ispin)
1789 e_max = max(e_max, e_max_ispin)
1790 END DO
1791
1792 e_range = e_max/e_min
1793
1794 ALLOCATE (points_and_weights(2*num_time_freq_points))
1795
1796 ! frequency points
1797 IF (num_time_freq_points .LE. 20) THEN
1798 CALL get_rpa_minimax_coeff(num_time_freq_points, e_range, points_and_weights, ierr, .false.)
1799 ELSE
1800 CALL get_rpa_minimax_coeff_larger_grid(num_time_freq_points, e_range, points_and_weights)
1801 END IF
1802
1803 ! one needs to scale the minimax grids, see Azizi, Wilhelm, Golze, Panades-Barrueta,
1804 ! Giantomassi, Rinke, Draxl, Gonze et al., 2 publications
1805 bs_env%imag_freq_points(:) = points_and_weights(1:num_time_freq_points)*e_min
1806
1807 ! determine number of fit points in the interval [0,ω_max] for virt, or [-ω_max,0] for occ
1808 bs_env%num_freq_points_fit = 0
1809 DO i_w = 1, num_time_freq_points
1810 IF (bs_env%imag_freq_points(i_w) < bs_env%freq_max_fit) THEN
1811 bs_env%num_freq_points_fit = bs_env%num_freq_points_fit + 1
1812 END IF
1813 END DO
1814
1815 ! iω values for the analytic continuation Σ^c_n(iω,k) -> Σ^c_n(ϵ,k)
1816 ALLOCATE (bs_env%imag_freq_points_fit(bs_env%num_freq_points_fit))
1817 j_w = 0
1818 DO i_w = 1, num_time_freq_points
1819 IF (bs_env%imag_freq_points(i_w) < bs_env%freq_max_fit) THEN
1820 j_w = j_w + 1
1821 bs_env%imag_freq_points_fit(j_w) = bs_env%imag_freq_points(i_w)
1822 END IF
1823 END DO
1824
1825 ! reset the number of Padé parameters if smaller than the number of
1826 ! imaginary-frequency points for the fit
1827 IF (bs_env%num_freq_points_fit < bs_env%nparam_pade) THEN
1828 bs_env%nparam_pade = bs_env%num_freq_points_fit
1829 END IF
1830
1831 ! time points
1832 IF (num_time_freq_points .LE. 20) THEN
1833 CALL get_exp_minimax_coeff(num_time_freq_points, e_range, points_and_weights)
1834 ELSE
1835 CALL get_exp_minimax_coeff_gw(num_time_freq_points, e_range, points_and_weights)
1836 END IF
1837
1838 bs_env%imag_time_points(:) = points_and_weights(1:num_time_freq_points)/(2.0_dp*e_min)
1839 bs_env%imag_time_weights_freq_zero(:) = points_and_weights(num_time_freq_points + 1:)/(e_min)
1840
1841 DEALLOCATE (points_and_weights)
1842
1843 u = bs_env%unit_nr
1844 IF (u > 0) THEN
1845 WRITE (u, '(T2,A)') ''
1846 WRITE (u, '(T2,A,F55.2)') 'SCF direct band gap (eV)', e_min*evolt
1847 WRITE (u, '(T2,A,F53.2)') 'Max. SCF eigval diff. (eV)', e_max*evolt
1848 WRITE (u, '(T2,A,F55.2)') 'E-Range for minimax grid', e_range
1849 WRITE (u, '(T2,A,I27)') é'Number of Pad parameters for analytic continuation:', &
1850 bs_env%nparam_pade
1851 WRITE (u, '(T2,A)') ''
1852 END IF
1853
1854 ! in minimax grids, Fourier transforms t -> w and w -> t are split using
1855 ! e^(iwt) = cos(wt) + i sin(wt); we thus calculate weights for trafos with a cos and
1856 ! sine prefactor; details in Azizi, Wilhelm, Golze, Giantomassi, Panades-Barrueta,
1857 ! Rinke, Draxl, Gonze et al., 2 publications
1858
1859 ! cosine transform weights imaginary time to imaginary frequency
1860 CALL get_l_sq_wghts_cos_tf_t_to_w(num_time_freq_points, &
1861 bs_env%imag_time_points, &
1862 bs_env%weights_cos_t_to_w, &
1863 bs_env%imag_freq_points, &
1864 e_min, e_max, max_error_min, &
1865 bs_env%num_points_per_magnitude, &
1866 bs_env%regularization_minimax)
1867
1868 ! cosine transform weights imaginary frequency to imaginary time
1869 CALL get_l_sq_wghts_cos_tf_w_to_t(num_time_freq_points, &
1870 bs_env%imag_time_points, &
1871 bs_env%weights_cos_w_to_t, &
1872 bs_env%imag_freq_points, &
1873 e_min, e_max, max_error_min, &
1874 bs_env%num_points_per_magnitude, &
1875 bs_env%regularization_minimax)
1876
1877 ! sine transform weights imaginary time to imaginary frequency
1878 CALL get_l_sq_wghts_sin_tf_t_to_w(num_time_freq_points, &
1879 bs_env%imag_time_points, &
1880 bs_env%weights_sin_t_to_w, &
1881 bs_env%imag_freq_points, &
1882 e_min, e_max, max_error_min, &
1883 bs_env%num_points_per_magnitude, &
1884 bs_env%regularization_minimax)
1885
1886 CALL timestop(handle)
1887
1888 END SUBROUTINE setup_time_and_frequency_minimax_grid
1889
1890! **************************************************************************************************
1891!> \brief ...
1892!> \param qs_env ...
1893!> \param bs_env ...
1894! **************************************************************************************************
1895 SUBROUTINE setup_cells_3c(qs_env, bs_env)
1896
1897 TYPE(qs_environment_type), POINTER :: qs_env
1898 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
1899
1900 CHARACTER(LEN=*), PARAMETER :: routinen = 'setup_cells_3c'
1901
1902 INTEGER :: atom_i, atom_j, atom_k, cell_pair_count, handle, i, i_cell_x, i_cell_x_max, &
1903 i_cell_x_min, i_size, ikind, img, j, j_cell, j_cell_max, j_cell_y, j_cell_y_max, &
1904 j_cell_y_min, j_size, k_cell, k_cell_max, k_cell_z, k_cell_z_max, k_cell_z_min, k_size, &
1905 nimage_pairs_3c, nimages_3c, nimages_3c_max, nkind, u
1906 INTEGER(KIND=int_8) :: mem_occ_per_proc
1907 INTEGER, ALLOCATABLE, DIMENSION(:) :: n_other_3c_images_max
1908 INTEGER, ALLOCATABLE, DIMENSION(:, :) :: index_to_cell_3c_max, nblocks_3c_max
1909 INTEGER, DIMENSION(3) :: cell_index, n_max
1910 REAL(kind=dp) :: avail_mem_per_proc_gb, cell_dist, cell_radius_3c, eps, exp_min_ao, &
1911 exp_min_ri, frobenius_norm, mem_3c_gb, mem_occ_per_proc_gb, radius_ao, radius_ao_product, &
1912 radius_ri
1913 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :, :) :: int_3c
1914 REAL(kind=dp), DIMENSION(:, :), POINTER :: exp_ao, exp_ri
1915
1916 CALL timeset(routinen, handle)
1917
1918 CALL get_qs_env(qs_env, nkind=nkind)
1919
1920 exp_min_ri = 10.0_dp
1921 exp_min_ao = 10.0_dp
1922
1923 DO ikind = 1, nkind
1924
1925 CALL get_gto_basis_set(bs_env%basis_set_RI(ikind)%gto_basis_set, zet=exp_ri)
1926 CALL get_gto_basis_set(bs_env%basis_set_ao(ikind)%gto_basis_set, zet=exp_ao)
1927
1928 ! we need to remove all exponents lower than a lower bound, e.g. 1E-3, because
1929 ! for contracted basis sets, there might be exponents = 0 in zet
1930 DO i = 1, SIZE(exp_ri, 1)
1931 DO j = 1, SIZE(exp_ri, 2)
1932 IF (exp_ri(i, j) < exp_min_ri .AND. exp_ri(i, j) > 1e-3_dp) exp_min_ri = exp_ri(i, j)
1933 END DO
1934 END DO
1935 DO i = 1, SIZE(exp_ao, 1)
1936 DO j = 1, SIZE(exp_ao, 2)
1937 IF (exp_ao(i, j) < exp_min_ao .AND. exp_ao(i, j) > 1e-3_dp) exp_min_ao = exp_ao(i, j)
1938 END DO
1939 END DO
1940
1941 END DO
1942
1943 eps = bs_env%eps_filter*bs_env%heuristic_filter_factor
1944
1945 radius_ao = sqrt(-log(eps)/exp_min_ao)
1946 radius_ao_product = sqrt(-log(eps)/(2.0_dp*exp_min_ao))
1947 radius_ri = sqrt(-log(eps)/exp_min_ri)
1948
1949 ! For a 3c integral (μR υS | P0) we have that cell R and cell S need to be within radius_3c
1950 cell_radius_3c = radius_ao_product + radius_ri + bs_env%ri_metric%cutoff_radius
1951
1952 n_max(1:3) = bs_env%periodic(1:3)*30
1953
1954 nimages_3c_max = 0
1955
1956 i_cell_x_min = 0
1957 i_cell_x_max = 0
1958 j_cell_y_min = 0
1959 j_cell_y_max = 0
1960 k_cell_z_min = 0
1961 k_cell_z_max = 0
1962
1963 DO i_cell_x = -n_max(1), n_max(1)
1964 DO j_cell_y = -n_max(2), n_max(2)
1965 DO k_cell_z = -n_max(3), n_max(3)
1966
1967 cell_index(1:3) = (/i_cell_x, j_cell_y, k_cell_z/)
1968
1969 CALL get_cell_dist(cell_index, bs_env%hmat, cell_dist)
1970
1971 IF (cell_dist < cell_radius_3c) THEN
1972 nimages_3c_max = nimages_3c_max + 1
1973 i_cell_x_min = min(i_cell_x_min, i_cell_x)
1974 i_cell_x_max = max(i_cell_x_max, i_cell_x)
1975 j_cell_y_min = min(j_cell_y_min, j_cell_y)
1976 j_cell_y_max = max(j_cell_y_max, j_cell_y)
1977 k_cell_z_min = min(k_cell_z_min, k_cell_z)
1978 k_cell_z_max = max(k_cell_z_max, k_cell_z)
1979 END IF
1980
1981 END DO
1982 END DO
1983 END DO
1984
1985 ! get index_to_cell_3c_max for the maximum possible cell range;
1986 ! compute 3c integrals later in this routine and check really which cell is needed
1987 ALLOCATE (index_to_cell_3c_max(nimages_3c_max, 3))
1988
1989 img = 0
1990 DO i_cell_x = -n_max(1), n_max(1)
1991 DO j_cell_y = -n_max(2), n_max(2)
1992 DO k_cell_z = -n_max(3), n_max(3)
1993
1994 cell_index(1:3) = (/i_cell_x, j_cell_y, k_cell_z/)
1995
1996 CALL get_cell_dist(cell_index, bs_env%hmat, cell_dist)
1997
1998 IF (cell_dist < cell_radius_3c) THEN
1999 img = img + 1
2000 index_to_cell_3c_max(img, 1:3) = cell_index(1:3)
2001 END IF
2002
2003 END DO
2004 END DO
2005 END DO
2006
2007 ! get pairs of R and S which have non-zero 3c integral (μR υS | P0)
2008 ALLOCATE (nblocks_3c_max(nimages_3c_max, nimages_3c_max))
2009 nblocks_3c_max(:, :) = 0
2010
2011 cell_pair_count = 0
2012 DO j_cell = 1, nimages_3c_max
2013 DO k_cell = 1, nimages_3c_max
2014
2015 cell_pair_count = cell_pair_count + 1
2016
2017 ! trivial parallelization over cell pairs
2018 IF (modulo(cell_pair_count, bs_env%para_env%num_pe) .NE. bs_env%para_env%mepos) cycle
2019
2020 DO atom_j = 1, bs_env%n_atom
2021 DO atom_k = 1, bs_env%n_atom
2022 DO atom_i = 1, bs_env%n_atom
2023
2024 j_size = bs_env%i_ao_end_from_atom(atom_j) - bs_env%i_ao_start_from_atom(atom_j) + 1
2025 k_size = bs_env%i_ao_end_from_atom(atom_k) - bs_env%i_ao_start_from_atom(atom_k) + 1
2026 i_size = bs_env%i_RI_end_from_atom(atom_i) - bs_env%i_RI_start_from_atom(atom_i) + 1
2027
2028 ALLOCATE (int_3c(j_size, k_size, i_size))
2029
2030 ! compute 3-c int. ( μ(atom j) R , ν (atom k) S | P (atom i) 0 )
2031 ! ("|": truncated Coulomb operator), inside build_3c_integrals: (j k | i)
2032 CALL build_3c_integral_block(int_3c, qs_env, bs_env%ri_metric, &
2033 basis_j=bs_env%basis_set_AO, &
2034 basis_k=bs_env%basis_set_AO, &
2035 basis_i=bs_env%basis_set_RI, &
2036 cell_j=index_to_cell_3c_max(j_cell, 1:3), &
2037 cell_k=index_to_cell_3c_max(k_cell, 1:3), &
2038 atom_k=atom_k, atom_j=atom_j, atom_i=atom_i)
2039
2040 frobenius_norm = sqrt(sum(int_3c(:, :, :)**2))
2041
2042 DEALLOCATE (int_3c)
2043
2044 ! we use a higher threshold here to safe memory when storing the 3c integrals
2045 ! in every tensor group
2046 IF (frobenius_norm > eps) THEN
2047 nblocks_3c_max(j_cell, k_cell) = nblocks_3c_max(j_cell, k_cell) + 1
2048 END IF
2049
2050 END DO
2051 END DO
2052 END DO
2053
2054 END DO
2055 END DO
2056
2057 CALL bs_env%para_env%sum(nblocks_3c_max)
2058
2059 ALLOCATE (n_other_3c_images_max(nimages_3c_max))
2060 n_other_3c_images_max(:) = 0
2061
2062 nimages_3c = 0
2063 nimage_pairs_3c = 0
2064
2065 DO j_cell = 1, nimages_3c_max
2066 DO k_cell = 1, nimages_3c_max
2067 IF (nblocks_3c_max(j_cell, k_cell) > 0) THEN
2068 n_other_3c_images_max(j_cell) = n_other_3c_images_max(j_cell) + 1
2069 nimage_pairs_3c = nimage_pairs_3c + 1
2070 END IF
2071 END DO
2072
2073 IF (n_other_3c_images_max(j_cell) > 0) nimages_3c = nimages_3c + 1
2074
2075 END DO
2076
2077 bs_env%nimages_3c = nimages_3c
2078 ALLOCATE (bs_env%index_to_cell_3c(nimages_3c, 3))
2079 ALLOCATE (bs_env%cell_to_index_3c(i_cell_x_min:i_cell_x_max, &
2080 j_cell_y_min:j_cell_y_max, &
2081 k_cell_z_min:k_cell_z_max))
2082 bs_env%cell_to_index_3c(:, :, :) = -1
2083
2084 ALLOCATE (bs_env%nblocks_3c(nimages_3c, nimages_3c))
2085 bs_env%nblocks_3c(nimages_3c, nimages_3c) = 0
2086
2087 j_cell = 0
2088 DO j_cell_max = 1, nimages_3c_max
2089 IF (n_other_3c_images_max(j_cell_max) == 0) cycle
2090 j_cell = j_cell + 1
2091 cell_index(1:3) = index_to_cell_3c_max(j_cell_max, 1:3)
2092 bs_env%index_to_cell_3c(j_cell, 1:3) = cell_index(1:3)
2093 bs_env%cell_to_index_3c(cell_index(1), cell_index(2), cell_index(3)) = j_cell
2094
2095 k_cell = 0
2096 DO k_cell_max = 1, nimages_3c_max
2097 IF (n_other_3c_images_max(k_cell_max) == 0) cycle
2098 k_cell = k_cell + 1
2099
2100 bs_env%nblocks_3c(j_cell, k_cell) = nblocks_3c_max(j_cell_max, k_cell_max)
2101 END DO
2102
2103 END DO
2104
2105 ! we use: 8*10^-9 GB / double precision number
2106 mem_3c_gb = real(bs_env%n_RI, kind=dp)*real(bs_env%n_ao, kind=dp)**2 &
2107 *real(nimage_pairs_3c, kind=dp)*8e-9_dp
2108
2109 CALL m_memory(mem_occ_per_proc)
2110 CALL bs_env%para_env%max(mem_occ_per_proc)
2111
2112 mem_occ_per_proc_gb = real(mem_occ_per_proc, kind=dp)/1.0e9_dp
2113
2114 ! number of processors per group that entirely stores the 3c integrals and does tensor ops
2115 avail_mem_per_proc_gb = bs_env%input_memory_per_proc_GB - mem_occ_per_proc_gb
2116
2117 ! careful: downconvering real to integer, 1.9 -> 1; thus add 1.0 for upconversion, 1.9 -> 2
2118 bs_env%group_size_tensor = max(int(mem_3c_gb/avail_mem_per_proc_gb + 1.0_dp), 1)
2119
2120 u = bs_env%unit_nr
2121
2122 IF (u > 0) THEN
2123 WRITE (u, fmt="(T2,A,F52.1,A)") "Radius of atomic orbitals", radius_ao*angstrom, Å" "
2124 WRITE (u, fmt="(T2,A,F55.1,A)") "Radius of RI functions", radius_ri*angstrom, Å" "
2125 WRITE (u, fmt="(T2,A,I47)") "Number of cells for 3c integrals", nimages_3c
2126 WRITE (u, fmt="(T2,A,I42)") "Number of cell pairs for 3c integrals", nimage_pairs_3c
2127 WRITE (u, '(T2,A)') ''
2128 WRITE (u, '(T2,A,F37.1,A)') 'Input: Available memory per MPI process', &
2129 bs_env%input_memory_per_proc_GB, ' GB'
2130 WRITE (u, '(T2,A,F35.1,A)') 'Used memory per MPI process before GW run', &
2131 mem_occ_per_proc_gb, ' GB'
2132 WRITE (u, '(T2,A,F44.1,A)') 'Memory of three-center integrals', mem_3c_gb, ' GB'
2133 END IF
2134
2135 CALL timestop(handle)
2136
2137 END SUBROUTINE setup_cells_3c
2138
2139! **************************************************************************************************
2140!> \brief ...
2141!> \param index_to_cell_1 ...
2142!> \param index_to_cell_2 ...
2143!> \param nimages_1 ...
2144!> \param nimages_2 ...
2145!> \param index_to_cell ...
2146!> \param cell_to_index ...
2147!> \param nimages ...
2148! **************************************************************************************************
2149 SUBROUTINE sum_two_r_grids(index_to_cell_1, index_to_cell_2, nimages_1, nimages_2, &
2150 index_to_cell, cell_to_index, nimages)
2151
2152 INTEGER, DIMENSION(:, :) :: index_to_cell_1, index_to_cell_2
2153 INTEGER :: nimages_1, nimages_2
2154 INTEGER, ALLOCATABLE, DIMENSION(:, :) :: index_to_cell
2155 INTEGER, DIMENSION(:, :, :), POINTER :: cell_to_index
2156 INTEGER :: nimages
2157
2158 CHARACTER(LEN=*), PARAMETER :: routinen = 'sum_two_R_grids'
2159
2160 INTEGER :: handle, i_dim, img_1, img_2, nimages_max
2161 INTEGER, ALLOCATABLE, DIMENSION(:, :) :: index_to_cell_tmp
2162 INTEGER, DIMENSION(3) :: cell_1, cell_2, r, r_max, r_min
2163
2164 CALL timeset(routinen, handle)
2165
2166 DO i_dim = 1, 3
2167 r_min(i_dim) = minval(index_to_cell_1(:, i_dim)) + minval(index_to_cell_2(:, i_dim))
2168 r_max(i_dim) = maxval(index_to_cell_1(:, i_dim)) + maxval(index_to_cell_2(:, i_dim))
2169 END DO
2170
2171 nimages_max = (r_max(1) - r_min(1) + 1)*(r_max(2) - r_min(2) + 1)*(r_max(3) - r_min(3) + 1)
2172
2173 ALLOCATE (index_to_cell_tmp(nimages_max, 3))
2174 index_to_cell_tmp(:, :) = -1
2175
2176 ALLOCATE (cell_to_index(r_min(1):r_max(1), r_min(2):r_max(2), r_min(3):r_max(3)))
2177 cell_to_index(:, :, :) = -1
2178
2179 nimages = 0
2180
2181 DO img_1 = 1, nimages_1
2182
2183 DO img_2 = 1, nimages_2
2184
2185 cell_1(1:3) = index_to_cell_1(img_1, 1:3)
2186 cell_2(1:3) = index_to_cell_2(img_2, 1:3)
2187
2188 r(1:3) = cell_1(1:3) + cell_2(1:3)
2189
2190 ! check whether we have found a new cell
2191 IF (cell_to_index(r(1), r(2), r(3)) == -1) THEN
2192
2193 nimages = nimages + 1
2194 cell_to_index(r(1), r(2), r(3)) = nimages
2195 index_to_cell_tmp(nimages, 1:3) = r(1:3)
2196
2197 END IF
2198
2199 END DO
2200
2201 END DO
2202
2203 ALLOCATE (index_to_cell(nimages, 3))
2204 index_to_cell(:, :) = index_to_cell_tmp(1:nimages, 1:3)
2205
2206 CALL timestop(handle)
2207
2208 END SUBROUTINE sum_two_r_grids
2209
2210! **************************************************************************************************
2211!> \brief ...
2212!> \param qs_env ...
2213!> \param bs_env ...
2214! **************************************************************************************************
2215 SUBROUTINE compute_3c_integrals(qs_env, bs_env)
2216
2217 TYPE(qs_environment_type), POINTER :: qs_env
2218 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
2219
2220 CHARACTER(LEN=*), PARAMETER :: routinen = 'compute_3c_integrals'
2221
2222 INTEGER :: handle, j_cell, k_cell, nimages_3c
2223
2224 CALL timeset(routinen, handle)
2225
2226 nimages_3c = bs_env%nimages_3c
2227 ALLOCATE (bs_env%t_3c_int(nimages_3c, nimages_3c))
2228 DO j_cell = 1, nimages_3c
2229 DO k_cell = 1, nimages_3c
2230 CALL dbt_create(bs_env%t_RI_AO__AO, bs_env%t_3c_int(j_cell, k_cell))
2231 END DO
2232 END DO
2233
2234 CALL build_3c_integrals(bs_env%t_3c_int, &
2235 bs_env%eps_filter, &
2236 qs_env, &
2237 bs_env%nl_3c, &
2238 int_eps=bs_env%eps_filter*0.05_dp, &
2239 basis_i=bs_env%basis_set_RI, &
2240 basis_j=bs_env%basis_set_AO, &
2241 basis_k=bs_env%basis_set_AO, &
2242 potential_parameter=bs_env%ri_metric, &
2243 desymmetrize=.false., do_kpoints=.true., cell_sym=.true., &
2244 cell_to_index_ext=bs_env%cell_to_index_3c)
2245
2246 CALL bs_env%para_env%sync()
2247
2248 CALL timestop(handle)
2249
2250 END SUBROUTINE compute_3c_integrals
2251
2252! **************************************************************************************************
2253!> \brief ...
2254!> \param cell_index ...
2255!> \param hmat ...
2256!> \param cell_dist ...
2257! **************************************************************************************************
2258 SUBROUTINE get_cell_dist(cell_index, hmat, cell_dist)
2259
2260 INTEGER, DIMENSION(3) :: cell_index
2261 REAL(kind=dp) :: hmat(3, 3), cell_dist
2262
2263 CHARACTER(LEN=*), PARAMETER :: routinen = 'get_cell_dist'
2264
2265 INTEGER :: handle, i_dim
2266 INTEGER, DIMENSION(3) :: cell_index_adj
2267 REAL(kind=dp) :: cell_dist_3(3)
2268
2269 CALL timeset(routinen, handle)
2270
2271 ! the distance of cells needs to be taken to adjacent neighbors, not
2272 ! between the center of the cells. We thus need to rescale the cell index
2273 DO i_dim = 1, 3
2274 IF (cell_index(i_dim) > 0) cell_index_adj(i_dim) = cell_index(i_dim) - 1
2275 IF (cell_index(i_dim) < 0) cell_index_adj(i_dim) = cell_index(i_dim) + 1
2276 IF (cell_index(i_dim) == 0) cell_index_adj(i_dim) = cell_index(i_dim)
2277 END DO
2278
2279 cell_dist_3(1:3) = matmul(hmat, real(cell_index_adj, kind=dp))
2280
2281 cell_dist = sqrt(abs(sum(cell_dist_3(1:3)**2)))
2282
2283 CALL timestop(handle)
2284
2285 END SUBROUTINE get_cell_dist
2286
2287! **************************************************************************************************
2288!> \brief ...
2289!> \param qs_env ...
2290!> \param bs_env ...
2291!> \param kpoints ...
2292!> \param do_print ...
2293! **************************************************************************************************
2294 SUBROUTINE setup_kpoints_scf_desymm(qs_env, bs_env, kpoints, do_print)
2295 TYPE(qs_environment_type), POINTER :: qs_env
2296 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
2297 TYPE(kpoint_type), POINTER :: kpoints
2298
2299 CHARACTER(LEN=*), PARAMETER :: routinen = 'setup_kpoints_scf_desymm'
2300
2301 INTEGER :: handle, i_cell_x, i_dim, img, j_cell_y, &
2302 k_cell_z, nimages, nkp, u
2303 INTEGER, DIMENSION(3) :: cell_grid, cixd, nkp_grid
2304 TYPE(kpoint_type), POINTER :: kpoints_scf
2305
2306 LOGICAL:: do_print
2307
2308 CALL timeset(routinen, handle)
2309
2310 NULLIFY (kpoints)
2311 CALL kpoint_create(kpoints)
2312
2313 CALL get_qs_env(qs_env=qs_env, kpoints=kpoints_scf)
2314
2315 nkp_grid(1:3) = kpoints_scf%nkp_grid(1:3)
2316 nkp = nkp_grid(1)*nkp_grid(2)*nkp_grid(3)
2317
2318 ! we need in periodic directions at least 2 k-points in the SCF
2319 DO i_dim = 1, 3
2320 IF (bs_env%periodic(i_dim) == 1) THEN
2321 cpassert(nkp_grid(i_dim) > 1)
2322 END IF
2323 END DO
2324
2325 kpoints%kp_scheme = "GENERAL"
2326 kpoints%nkp_grid(1:3) = nkp_grid(1:3)
2327 kpoints%nkp = nkp
2328 bs_env%nkp_scf_desymm = nkp
2329
2330 ALLOCATE (kpoints%xkp(1:3, nkp))
2331 CALL compute_xkp(kpoints%xkp, 1, nkp, nkp_grid)
2332
2333 ALLOCATE (kpoints%wkp(nkp))
2334 kpoints%wkp(:) = 1.0_dp/real(nkp, kind=dp)
2335
2336 ! for example 4x3x6 kpoint grid -> 3x3x5 cell grid because we need the same number of
2337 ! neighbor cells on both sides of the unit cell
2338 cell_grid(1:3) = nkp_grid(1:3) - modulo(nkp_grid(1:3) + 1, 2)
2339 ! cell index: for example for x: from -n_x/2 to +n_x/2, n_x: number of cells in x direction
2340 cixd(1:3) = cell_grid(1:3)/2
2341
2342 nimages = cell_grid(1)*cell_grid(2)*cell_grid(3)
2343
2344 bs_env%nimages_scf_desymm = nimages
2345
2346 ALLOCATE (kpoints%cell_to_index(-cixd(1):cixd(1), -cixd(2):cixd(2), -cixd(3):cixd(3)))
2347 ALLOCATE (kpoints%index_to_cell(nimages, 3))
2348
2349 img = 0
2350 DO i_cell_x = -cixd(1), cixd(1)
2351 DO j_cell_y = -cixd(2), cixd(2)
2352 DO k_cell_z = -cixd(3), cixd(3)
2353 img = img + 1
2354 kpoints%cell_to_index(i_cell_x, j_cell_y, k_cell_z) = img
2355 kpoints%index_to_cell(img, 1:3) = (/i_cell_x, j_cell_y, k_cell_z/)
2356 END DO
2357 END DO
2358 END DO
2359
2360 u = bs_env%unit_nr
2361 IF (u > 0 .AND. do_print) THEN
2362 WRITE (u, fmt="(T2,A,I49)") χΣ"Number of cells for G, , W, ", nimages
2363 END IF
2364
2365 CALL timestop(handle)
2366
2367 END SUBROUTINE setup_kpoints_scf_desymm
2368
2369! **************************************************************************************************
2370!> \brief ...
2371!> \param bs_env ...
2372! **************************************************************************************************
2373 SUBROUTINE setup_cells_delta_r(bs_env)
2374
2375 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
2376
2377 CHARACTER(LEN=*), PARAMETER :: routinen = 'setup_cells_Delta_R'
2378
2379 INTEGER :: handle
2380
2381 CALL timeset(routinen, handle)
2382
2383 ! cell sums batch wise for fixed ΔR = S_1 - R_1; for example:
2384 ! Σ_λσ^R = sum_PR1νS1 M^G_λ0,νS1,PR1 M^W_σR,νS1,PR1
2385
2386 CALL sum_two_r_grids(bs_env%index_to_cell_3c, &
2387 bs_env%index_to_cell_3c, &
2388 bs_env%nimages_3c, bs_env%nimages_3c, &
2389 bs_env%index_to_cell_Delta_R, &
2390 bs_env%cell_to_index_Delta_R, &
2391 bs_env%nimages_Delta_R)
2392
2393 IF (bs_env%unit_nr > 0) THEN
2394 WRITE (bs_env%unit_nr, fmt="(T2,A,I61)") Δ"Number of cells R", bs_env%nimages_Delta_R
2395 END IF
2396
2397 CALL timestop(handle)
2398
2399 END SUBROUTINE setup_cells_delta_r
2400
2401! **************************************************************************************************
2402!> \brief ...
2403!> \param bs_env ...
2404! **************************************************************************************************
2405 SUBROUTINE setup_parallelization_delta_r(bs_env)
2406
2407 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
2408
2409 CHARACTER(LEN=*), PARAMETER :: routinen = 'setup_parallelization_Delta_R'
2410
2411 INTEGER :: handle, i_cell_delta_r, i_task_local, &
2412 n_tasks_local
2413 INTEGER, ALLOCATABLE, DIMENSION(:) :: i_cell_delta_r_group, &
2414 n_tensor_ops_delta_r
2415
2416 CALL timeset(routinen, handle)
2417
2418 CALL compute_n_tensor_ops_delta_r(bs_env, n_tensor_ops_delta_r)
2419
2420 CALL compute_delta_r_dist(bs_env, n_tensor_ops_delta_r, i_cell_delta_r_group, n_tasks_local)
2421
2422 bs_env%n_tasks_Delta_R_local = n_tasks_local
2423
2424 ALLOCATE (bs_env%task_Delta_R(n_tasks_local))
2425
2426 i_task_local = 0
2427 DO i_cell_delta_r = 1, bs_env%nimages_Delta_R
2428
2429 IF (i_cell_delta_r_group(i_cell_delta_r) /= bs_env%tensor_group_color) cycle
2430
2431 i_task_local = i_task_local + 1
2432
2433 bs_env%task_Delta_R(i_task_local) = i_cell_delta_r
2434
2435 END DO
2436
2437 ALLOCATE (bs_env%skip_DR_chi(n_tasks_local))
2438 bs_env%skip_DR_chi(:) = .false.
2439 ALLOCATE (bs_env%skip_DR_Sigma(n_tasks_local))
2440 bs_env%skip_DR_Sigma(:) = .false.
2441
2442 CALL allocate_skip_3xr(bs_env%skip_DR_R12_S_Goccx3c_chi, bs_env)
2443 CALL allocate_skip_3xr(bs_env%skip_DR_R12_S_Gvirx3c_chi, bs_env)
2444 CALL allocate_skip_3xr(bs_env%skip_DR_R_R2_MxM_chi, bs_env)
2445
2446 CALL allocate_skip_3xr(bs_env%skip_DR_R1_S2_Gx3c_Sigma, bs_env)
2447 CALL allocate_skip_3xr(bs_env%skip_DR_R1_R_MxM_Sigma, bs_env)
2448
2449 CALL timestop(handle)
2450
2451 END SUBROUTINE setup_parallelization_delta_r
2452
2453! **************************************************************************************************
2454!> \brief ...
2455!> \param skip ...
2456!> \param bs_env ...
2457! **************************************************************************************************
2458 SUBROUTINE allocate_skip_3xr(skip, bs_env)
2459 LOGICAL, ALLOCATABLE, DIMENSION(:, :, :) :: skip
2460 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
2461
2462 CHARACTER(LEN=*), PARAMETER :: routinen = 'allocate_skip_3xR'
2463
2464 INTEGER :: handle
2465
2466 CALL timeset(routinen, handle)
2467
2468 ALLOCATE (skip(bs_env%n_tasks_Delta_R_local, bs_env%nimages_3c, bs_env%nimages_scf_desymm))
2469 skip(:, :, :) = .false.
2470
2471 CALL timestop(handle)
2472
2473 END SUBROUTINE allocate_skip_3xr
2474
2475! **************************************************************************************************
2476!> \brief ...
2477!> \param bs_env ...
2478!> \param n_tensor_ops_Delta_R ...
2479!> \param i_cell_Delta_R_group ...
2480!> \param n_tasks_local ...
2481! **************************************************************************************************
2482 SUBROUTINE compute_delta_r_dist(bs_env, n_tensor_ops_Delta_R, i_cell_Delta_R_group, n_tasks_local)
2483 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
2484 INTEGER, ALLOCATABLE, DIMENSION(:) :: n_tensor_ops_delta_r, &
2485 i_cell_delta_r_group
2486 INTEGER :: n_tasks_local
2487
2488 CHARACTER(LEN=*), PARAMETER :: routinen = 'compute_Delta_R_dist'
2489
2490 INTEGER :: handle, i_delta_r_max_op, i_group_min, &
2491 nimages_delta_r, u
2492 INTEGER, ALLOCATABLE, DIMENSION(:) :: n_tensor_ops_delta_r_in_group
2493
2494 CALL timeset(routinen, handle)
2495
2496 nimages_delta_r = bs_env%nimages_Delta_R
2497
2498 u = bs_env%unit_nr
2499
2500 IF (u > 0 .AND. nimages_delta_r < bs_env%num_tensor_groups) THEN
2501 WRITE (u, fmt="(T2,A,I5,A,I5,A)") "There are only ", nimages_delta_r, &
2502 " tasks to work on but there are ", bs_env%num_tensor_groups, " groups."
2503 WRITE (u, fmt="(T2,A)") "Please reduce the number of MPI processes."
2504 WRITE (u, '(T2,A)') ''
2505 END IF
2506
2507 ALLOCATE (n_tensor_ops_delta_r_in_group(bs_env%num_tensor_groups))
2508 n_tensor_ops_delta_r_in_group(:) = 0
2509 ALLOCATE (i_cell_delta_r_group(nimages_delta_r))
2510 i_cell_delta_r_group(:) = -1
2511
2512 n_tasks_local = 0
2513
2514 DO WHILE (any(n_tensor_ops_delta_r(:) .NE. 0))
2515
2516 ! get largest element of n_tensor_ops_Delta_R
2517 i_delta_r_max_op = maxloc(n_tensor_ops_delta_r, 1)
2518
2519 ! distribute i_Delta_R_max_op to tensor group which has currently the smallest load
2520 i_group_min = minloc(n_tensor_ops_delta_r_in_group, 1)
2521
2522 ! the tensor groups are 0-index based; but i_group_min is 1-index based
2523 i_cell_delta_r_group(i_delta_r_max_op) = i_group_min - 1
2524 n_tensor_ops_delta_r_in_group(i_group_min) = n_tensor_ops_delta_r_in_group(i_group_min) + &
2525 n_tensor_ops_delta_r(i_delta_r_max_op)
2526
2527 ! remove i_Delta_R_max_op from n_tensor_ops_Delta_R
2528 n_tensor_ops_delta_r(i_delta_r_max_op) = 0
2529
2530 IF (bs_env%tensor_group_color == i_group_min - 1) n_tasks_local = n_tasks_local + 1
2531
2532 END DO
2533
2534 CALL timestop(handle)
2535
2536 END SUBROUTINE compute_delta_r_dist
2537
2538! **************************************************************************************************
2539!> \brief ...
2540!> \param bs_env ...
2541!> \param n_tensor_ops_Delta_R ...
2542! **************************************************************************************************
2543 SUBROUTINE compute_n_tensor_ops_delta_r(bs_env, n_tensor_ops_Delta_R)
2544 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
2545 INTEGER, ALLOCATABLE, DIMENSION(:) :: n_tensor_ops_delta_r
2546
2547 CHARACTER(LEN=*), PARAMETER :: routinen = 'compute_n_tensor_ops_Delta_R'
2548
2549 INTEGER :: handle, i_cell_delta_r, i_cell_r, i_cell_r1, i_cell_r1_minus_r, i_cell_r2, &
2550 i_cell_r2_m_r1, i_cell_s1, i_cell_s1_m_r1_p_r2, i_cell_s1_minus_r, i_cell_s2, &
2551 nimages_delta_r
2552 INTEGER, DIMENSION(3) :: cell_dr, cell_m_r1, cell_r, cell_r1, cell_r1_minus_r, cell_r2, &
2553 cell_r2_m_r1, cell_s1, cell_s1_m_r2_p_r1, cell_s1_minus_r, cell_s1_p_s2_m_r1, cell_s2
2554 LOGICAL :: cell_found
2555
2556 CALL timeset(routinen, handle)
2557
2558 nimages_delta_r = bs_env%nimages_Delta_R
2559
2560 ALLOCATE (n_tensor_ops_delta_r(nimages_delta_r))
2561 n_tensor_ops_delta_r(:) = 0
2562
2563 ! compute number of tensor operations for specific Delta_R
2564 DO i_cell_delta_r = 1, nimages_delta_r
2565
2566 IF (modulo(i_cell_delta_r, bs_env%num_tensor_groups) /= bs_env%tensor_group_color) cycle
2567
2568 DO i_cell_r1 = 1, bs_env%nimages_3c
2569
2570 cell_r1(1:3) = bs_env%index_to_cell_3c(i_cell_r1, 1:3)
2571 cell_dr(1:3) = bs_env%index_to_cell_Delta_R(i_cell_delta_r, 1:3)
2572
2573 ! S_1 = R_1 + ΔR (from ΔR = S_1 - R_1)
2574 CALL add_r(cell_r1, cell_dr, bs_env%index_to_cell_3c, cell_s1, &
2575 cell_found, bs_env%cell_to_index_3c, i_cell_s1)
2576 IF (.NOT. cell_found) cycle
2577
2578 DO i_cell_r2 = 1, bs_env%nimages_scf_desymm
2579
2580 cell_r2(1:3) = bs_env%kpoints_scf_desymm%index_to_cell(i_cell_r2, 1:3)
2581
2582 ! R_2 - R_1
2583 CALL add_r(cell_r2, -cell_r1, bs_env%index_to_cell_3c, cell_r2_m_r1, &
2584 cell_found, bs_env%cell_to_index_3c, i_cell_r2_m_r1)
2585 IF (.NOT. cell_found) cycle
2586
2587 ! S_1 - R_1 + R_2
2588 CALL add_r(cell_s1, cell_r2_m_r1, bs_env%index_to_cell_3c, cell_s1_m_r2_p_r1, &
2589 cell_found, bs_env%cell_to_index_3c, i_cell_s1_m_r1_p_r2)
2590 IF (.NOT. cell_found) cycle
2591
2592 n_tensor_ops_delta_r(i_cell_delta_r) = n_tensor_ops_delta_r(i_cell_delta_r) + 1
2593
2594 END DO ! i_cell_R2
2595
2596 DO i_cell_s2 = 1, bs_env%nimages_scf_desymm
2597
2598 cell_s2(1:3) = bs_env%kpoints_scf_desymm%index_to_cell(i_cell_s2, 1:3)
2599 cell_m_r1(1:3) = -cell_r1(1:3)
2600 cell_s1_p_s2_m_r1(1:3) = cell_s1(1:3) + cell_s2(1:3) - cell_r1(1:3)
2601
2602 CALL is_cell_in_index_to_cell(cell_m_r1, bs_env%index_to_cell_3c, cell_found)
2603 IF (.NOT. cell_found) cycle
2604
2605 CALL is_cell_in_index_to_cell(cell_s1_p_s2_m_r1, bs_env%index_to_cell_3c, cell_found)
2606 IF (.NOT. cell_found) cycle
2607
2608 END DO ! i_cell_S2
2609
2610 DO i_cell_r = 1, bs_env%nimages_scf_desymm
2611
2612 cell_r = bs_env%kpoints_scf_desymm%index_to_cell(i_cell_r, 1:3)
2613
2614 ! R_1 - R
2615 CALL add_r(cell_r1, -cell_r, bs_env%index_to_cell_3c, cell_r1_minus_r, &
2616 cell_found, bs_env%cell_to_index_3c, i_cell_r1_minus_r)
2617 IF (.NOT. cell_found) cycle
2618
2619 ! S_1 - R
2620 CALL add_r(cell_s1, -cell_r, bs_env%index_to_cell_3c, cell_s1_minus_r, &
2621 cell_found, bs_env%cell_to_index_3c, i_cell_s1_minus_r)
2622 IF (.NOT. cell_found) cycle
2623
2624 END DO ! i_cell_R
2625
2626 END DO ! i_cell_R1
2627
2628 END DO ! i_cell_Delta_R
2629
2630 CALL bs_env%para_env%sum(n_tensor_ops_delta_r)
2631
2632 CALL timestop(handle)
2633
2634 END SUBROUTINE compute_n_tensor_ops_delta_r
2635
2636! **************************************************************************************************
2637!> \brief ...
2638!> \param cell_1 ...
2639!> \param cell_2 ...
2640!> \param index_to_cell ...
2641!> \param cell_1_plus_2 ...
2642!> \param cell_found ...
2643!> \param cell_to_index ...
2644!> \param i_cell_1_plus_2 ...
2645! **************************************************************************************************
2646 SUBROUTINE add_r(cell_1, cell_2, index_to_cell, cell_1_plus_2, cell_found, &
2647 cell_to_index, i_cell_1_plus_2)
2648
2649 INTEGER, DIMENSION(3) :: cell_1, cell_2
2650 INTEGER, DIMENSION(:, :) :: index_to_cell
2651 INTEGER, DIMENSION(3) :: cell_1_plus_2
2652 LOGICAL :: cell_found
2653 INTEGER, DIMENSION(:, :, :), INTENT(IN), &
2654 OPTIONAL, POINTER :: cell_to_index
2655 INTEGER, INTENT(OUT), OPTIONAL :: i_cell_1_plus_2
2656
2657 CHARACTER(LEN=*), PARAMETER :: routinen = 'add_R'
2658
2659 INTEGER :: handle
2660
2661 CALL timeset(routinen, handle)
2662
2663 cell_1_plus_2(1:3) = cell_1(1:3) + cell_2(1:3)
2664
2665 CALL is_cell_in_index_to_cell(cell_1_plus_2, index_to_cell, cell_found)
2666
2667 IF (PRESENT(i_cell_1_plus_2)) THEN
2668 IF (cell_found) THEN
2669 cpassert(PRESENT(cell_to_index))
2670 i_cell_1_plus_2 = cell_to_index(cell_1_plus_2(1), cell_1_plus_2(2), cell_1_plus_2(3))
2671 ELSE
2672 i_cell_1_plus_2 = -1000
2673 END IF
2674 END IF
2675
2676 CALL timestop(handle)
2677
2678 END SUBROUTINE add_r
2679
2680! **************************************************************************************************
2681!> \brief ...
2682!> \param cell ...
2683!> \param index_to_cell ...
2684!> \param cell_found ...
2685! **************************************************************************************************
2686 SUBROUTINE is_cell_in_index_to_cell(cell, index_to_cell, cell_found)
2687 INTEGER, DIMENSION(3) :: cell
2688 INTEGER, DIMENSION(:, :) :: index_to_cell
2689 LOGICAL :: cell_found
2690
2691 CHARACTER(LEN=*), PARAMETER :: routinen = 'is_cell_in_index_to_cell'
2692
2693 INTEGER :: handle, i_cell, nimg
2694 INTEGER, DIMENSION(3) :: cell_i
2695
2696 CALL timeset(routinen, handle)
2697
2698 nimg = SIZE(index_to_cell, 1)
2699
2700 cell_found = .false.
2701
2702 DO i_cell = 1, nimg
2703
2704 cell_i(1:3) = index_to_cell(i_cell, 1:3)
2705
2706 IF (cell_i(1) == cell(1) .AND. cell_i(2) == cell(2) .AND. cell_i(3) == cell(3)) THEN
2707 cell_found = .true.
2708 END IF
2709
2710 END DO
2711
2712 CALL timestop(handle)
2713
2714 END SUBROUTINE is_cell_in_index_to_cell
2715
2716! **************************************************************************************************
2717!> \brief ...
2718!> \param qs_env ...
2719!> \param bs_env ...
2720! **************************************************************************************************
2721 SUBROUTINE allocate_matrices_small_cell_full_kp(qs_env, bs_env)
2722 TYPE(qs_environment_type), POINTER :: qs_env
2723 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
2724
2725 CHARACTER(LEN=*), PARAMETER :: routinen = 'allocate_matrices_small_cell_full_kp'
2726
2727 INTEGER :: handle, i_spin, i_t, img, n_spin, &
2728 nimages_scf, num_time_freq_points
2729 TYPE(cp_blacs_env_type), POINTER :: blacs_env
2730 TYPE(mp_para_env_type), POINTER :: para_env
2731
2732 CALL timeset(routinen, handle)
2733
2734 nimages_scf = bs_env%nimages_scf_desymm
2735 num_time_freq_points = bs_env%num_time_freq_points
2736 n_spin = bs_env%n_spin
2737
2738 CALL get_qs_env(qs_env, para_env=para_env, blacs_env=blacs_env)
2739
2740 ALLOCATE (bs_env%fm_G_S(nimages_scf))
2741 ALLOCATE (bs_env%fm_Sigma_x_R(nimages_scf))
2742 ALLOCATE (bs_env%fm_chi_R_t(nimages_scf, num_time_freq_points))
2743 ALLOCATE (bs_env%fm_MWM_R_t(nimages_scf, num_time_freq_points))
2744 ALLOCATE (bs_env%fm_Sigma_c_R_neg_tau(nimages_scf, num_time_freq_points, n_spin))
2745 ALLOCATE (bs_env%fm_Sigma_c_R_pos_tau(nimages_scf, num_time_freq_points, n_spin))
2746 DO img = 1, nimages_scf
2747 CALL cp_fm_create(bs_env%fm_G_S(img), bs_env%fm_work_mo(1)%matrix_struct)
2748 CALL cp_fm_create(bs_env%fm_Sigma_x_R(img), bs_env%fm_work_mo(1)%matrix_struct)
2749 DO i_t = 1, num_time_freq_points
2750 CALL cp_fm_create(bs_env%fm_chi_R_t(img, i_t), bs_env%fm_RI_RI%matrix_struct)
2751 CALL cp_fm_create(bs_env%fm_MWM_R_t(img, i_t), bs_env%fm_RI_RI%matrix_struct)
2752 CALL cp_fm_set_all(bs_env%fm_MWM_R_t(img, i_t), 0.0_dp)
2753 DO i_spin = 1, n_spin
2754 CALL cp_fm_create(bs_env%fm_Sigma_c_R_neg_tau(img, i_t, i_spin), &
2755 bs_env%fm_work_mo(1)%matrix_struct)
2756 CALL cp_fm_create(bs_env%fm_Sigma_c_R_pos_tau(img, i_t, i_spin), &
2757 bs_env%fm_work_mo(1)%matrix_struct)
2758 CALL cp_fm_set_all(bs_env%fm_Sigma_c_R_neg_tau(img, i_t, i_spin), 0.0_dp)
2759 CALL cp_fm_set_all(bs_env%fm_Sigma_c_R_pos_tau(img, i_t, i_spin), 0.0_dp)
2760 END DO
2761 END DO
2762 END DO
2763
2764 CALL timestop(handle)
2765
2766 END SUBROUTINE allocate_matrices_small_cell_full_kp
2767
2768! **************************************************************************************************
2769!> \brief ...
2770!> \param qs_env ...
2771!> \param bs_env ...
2772! **************************************************************************************************
2773 SUBROUTINE trafo_v_xc_r_to_kp(qs_env, bs_env)
2774 TYPE(qs_environment_type), POINTER :: qs_env
2775 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
2776
2777 CHARACTER(LEN=*), PARAMETER :: routinen = 'trafo_V_xc_R_to_kp'
2778
2779 INTEGER :: handle, ikp, img, ispin, n_ao
2780 INTEGER, DIMENSION(:, :, :), POINTER :: cell_to_index_scf
2781 TYPE(cp_cfm_type) :: cfm_mo_coeff, cfm_tmp, cfm_v_xc
2782 TYPE(cp_fm_type) :: fm_v_xc_re
2783 TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: matrix_ks
2784 TYPE(kpoint_type), POINTER :: kpoints_scf
2785 TYPE(neighbor_list_set_p_type), DIMENSION(:), &
2786 POINTER :: sab_nl
2787
2788 CALL timeset(routinen, handle)
2789
2790 n_ao = bs_env%n_ao
2791
2792 CALL get_qs_env(qs_env, matrix_ks_kp=matrix_ks, kpoints=kpoints_scf)
2793
2794 NULLIFY (sab_nl)
2795 CALL get_kpoint_info(kpoints_scf, sab_nl=sab_nl, cell_to_index=cell_to_index_scf)
2796
2797 CALL cp_cfm_create(cfm_v_xc, bs_env%cfm_work_mo%matrix_struct)
2798 CALL cp_cfm_create(cfm_mo_coeff, bs_env%cfm_work_mo%matrix_struct)
2799 CALL cp_cfm_create(cfm_tmp, bs_env%cfm_work_mo%matrix_struct)
2800 CALL cp_fm_create(fm_v_xc_re, bs_env%cfm_work_mo%matrix_struct)
2801
2802 DO img = 1, bs_env%nimages_scf
2803 DO ispin = 1, bs_env%n_spin
2804 ! JW kind of hack because the format of matrix_ks remains dubious...
2805 CALL dbcsr_set(matrix_ks(ispin, img)%matrix, 0.0_dp)
2806 CALL copy_fm_to_dbcsr(bs_env%fm_V_xc_R(img, ispin), matrix_ks(ispin, img)%matrix)
2807 END DO
2808 END DO
2809
2810 ALLOCATE (bs_env%v_xc_n(n_ao, bs_env%nkp_bs_and_DOS, bs_env%n_spin))
2811
2812 DO ispin = 1, bs_env%n_spin
2813 DO ikp = 1, bs_env%nkp_bs_and_DOS
2814
2815 ! v^xc^R -> v^xc(k) (matrix_ks stores v^xc^R, see SUBROUTINE compute_V_xc)
2816 CALL rsmat_to_kp(matrix_ks, ispin, bs_env%kpoints_DOS%xkp(1:3, ikp), &
2817 cell_to_index_scf, sab_nl, bs_env, cfm_v_xc)
2818
2819 ! get C_µn(k)
2820 CALL cp_cfm_to_cfm(bs_env%cfm_mo_coeff_kp(ikp, ispin), cfm_mo_coeff)
2821
2822 ! v^xc_nm(k_i) = sum_µν C^*_µn(k_i) v^xc_µν(k_i) C_νn(k_i)
2823 CALL parallel_gemm('N', 'N', n_ao, n_ao, n_ao, z_one, cfm_v_xc, cfm_mo_coeff, &
2824 z_zero, cfm_tmp)
2825 CALL parallel_gemm('C', 'N', n_ao, n_ao, n_ao, z_one, cfm_mo_coeff, cfm_tmp, &
2826 z_zero, cfm_v_xc)
2827
2828 ! get v^xc_nn(k_i) which is a real quantity as v^xc is Hermitian
2829 CALL cp_cfm_to_fm(cfm_v_xc, fm_v_xc_re)
2830 CALL cp_fm_get_diag(fm_v_xc_re, bs_env%v_xc_n(:, ikp, ispin))
2831
2832 END DO
2833
2834 END DO
2835
2836 ! just rebuild the overwritten KS matrix again
2837 CALL qs_ks_build_kohn_sham_matrix(qs_env, calculate_forces=.false., just_energy=.false.)
2838
2839 CALL cp_cfm_release(cfm_v_xc)
2840 CALL cp_cfm_release(cfm_mo_coeff)
2841 CALL cp_cfm_release(cfm_tmp)
2842 CALL cp_fm_release(fm_v_xc_re)
2843
2844 CALL timestop(handle)
2845
2846 END SUBROUTINE trafo_v_xc_r_to_kp
2847
2848! **************************************************************************************************
2849!> \brief ...
2850!> \param qs_env ...
2851!> \param bs_env ...
2852! **************************************************************************************************
2853 SUBROUTINE heuristic_ri_regularization(qs_env, bs_env)
2854 TYPE(qs_environment_type), POINTER :: qs_env
2855 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
2856
2857 CHARACTER(LEN=*), PARAMETER :: routinen = 'heuristic_RI_regularization'
2858
2859 COMPLEX(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :) :: m
2860 INTEGER :: handle, ikp, ikp_local, n_ri, nkp, &
2861 nkp_local, u
2862 REAL(kind=dp) :: cond_nr, cond_nr_max, max_ev, &
2863 max_ev_ikp, min_ev, min_ev_ikp
2864 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :, :) :: m_r
2865
2866 CALL timeset(routinen, handle)
2867
2868 ! compute M^R_PQ = <phi_P,0|V^tr(rc)|phi_Q,R> for RI metric
2869 CALL get_v_tr_r(m_r, bs_env%ri_metric, 0.0_dp, bs_env, qs_env)
2870
2871 nkp = bs_env%nkp_chi_eps_W_orig_plus_extra
2872 n_ri = bs_env%n_RI
2873
2874 nkp_local = 0
2875 DO ikp = 1, nkp
2876 ! trivial parallelization over k-points
2877 IF (modulo(ikp, bs_env%para_env%num_pe) .NE. bs_env%para_env%mepos) cycle
2878 nkp_local = nkp_local + 1
2879 END DO
2880
2881 ALLOCATE (m(n_ri, n_ri, nkp_local))
2882
2883 ikp_local = 0
2884 cond_nr_max = 0.0_dp
2885 min_ev = 1000.0_dp
2886 max_ev = -1000.0_dp
2887
2888 DO ikp = 1, nkp
2889
2890 ! trivial parallelization
2891 IF (modulo(ikp, bs_env%para_env%num_pe) .NE. bs_env%para_env%mepos) cycle
2892
2893 ikp_local = ikp_local + 1
2894
2895 ! M(k) = sum_R e^ikR M^R
2896 CALL trafo_rs_to_ikp(m_r, m(:, :, ikp_local), &
2897 bs_env%kpoints_scf_desymm%index_to_cell, &
2898 bs_env%kpoints_chi_eps_W%xkp(1:3, ikp))
2899
2900 ! compute condition number of M_PQ(k)
2901 CALL power(m(:, :, ikp_local), 1.0_dp, 0.0_dp, cond_nr, min_ev_ikp, max_ev_ikp)
2902
2903 IF (cond_nr > cond_nr_max) cond_nr_max = cond_nr
2904 IF (max_ev_ikp > max_ev) max_ev = max_ev_ikp
2905 IF (min_ev_ikp < min_ev) min_ev = min_ev_ikp
2906
2907 END DO ! ikp
2908
2909 CALL bs_env%para_env%max(cond_nr_max)
2910
2911 u = bs_env%unit_nr
2912 IF (u > 0) THEN
2913 WRITE (u, fmt="(T2,A,ES34.1)") "Min. abs. eigenvalue of RI metric matrix M(k)", min_ev
2914 WRITE (u, fmt="(T2,A,ES34.1)") "Max. abs. eigenvalue of RI metric matrix M(k)", max_ev
2915 WRITE (u, fmt="(T2,A,ES50.1)") "Max. condition number of M(k)", cond_nr_max
2916 END IF
2917
2918 CALL timestop(handle)
2919
2920 END SUBROUTINE heuristic_ri_regularization
2921
2922! **************************************************************************************************
2923!> \brief ...
2924!> \param V_tr_R ...
2925!> \param pot_type ...
2926!> \param regularization_RI ...
2927!> \param bs_env ...
2928!> \param qs_env ...
2929! **************************************************************************************************
2930 SUBROUTINE get_v_tr_r(V_tr_R, pot_type, regularization_RI, bs_env, qs_env)
2931 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :, :) :: v_tr_r
2932 TYPE(libint_potential_type) :: pot_type
2933 REAL(kind=dp) :: regularization_ri
2934 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
2935 TYPE(qs_environment_type), POINTER :: qs_env
2936
2937 CHARACTER(LEN=*), PARAMETER :: routinen = 'get_V_tr_R'
2938
2939 INTEGER :: handle, img, nimages_scf_desymm
2940 INTEGER, ALLOCATABLE, DIMENSION(:) :: sizes_ri
2941 INTEGER, DIMENSION(:), POINTER :: col_bsize, row_bsize
2942 TYPE(cp_blacs_env_type), POINTER :: blacs_env
2943 TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:) :: fm_v_tr_r
2944 TYPE(dbcsr_distribution_type) :: dbcsr_dist
2945 TYPE(dbcsr_type), ALLOCATABLE, DIMENSION(:) :: mat_v_tr_r
2946 TYPE(distribution_2d_type), POINTER :: dist_2d
2947 TYPE(neighbor_list_set_p_type), DIMENSION(:), &
2948 POINTER :: sab_ri
2949 TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
2950 TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
2951
2952 CALL timeset(routinen, handle)
2953
2954 NULLIFY (sab_ri, dist_2d)
2955
2956 CALL get_qs_env(qs_env=qs_env, &
2957 blacs_env=blacs_env, &
2958 distribution_2d=dist_2d, &
2959 qs_kind_set=qs_kind_set, &
2960 particle_set=particle_set)
2961
2962 ALLOCATE (sizes_ri(bs_env%n_atom))
2963 CALL get_particle_set(particle_set, qs_kind_set, nsgf=sizes_ri, basis=bs_env%basis_set_RI)
2964 CALL build_2c_neighbor_lists(sab_ri, bs_env%basis_set_RI, bs_env%basis_set_RI, &
2965 pot_type, "2c_nl_RI", qs_env, sym_ij=.false., &
2966 dist_2d=dist_2d)
2967 CALL cp_dbcsr_dist2d_to_dist(dist_2d, dbcsr_dist)
2968 ALLOCATE (row_bsize(SIZE(sizes_ri)))
2969 ALLOCATE (col_bsize(SIZE(sizes_ri)))
2970 row_bsize(:) = sizes_ri
2971 col_bsize(:) = sizes_ri
2972
2973 nimages_scf_desymm = bs_env%nimages_scf_desymm
2974 ALLOCATE (mat_v_tr_r(nimages_scf_desymm))
2975 CALL dbcsr_create(mat_v_tr_r(1), "(RI|RI)", dbcsr_dist, dbcsr_type_no_symmetry, &
2976 row_bsize, col_bsize)
2977 DEALLOCATE (row_bsize, col_bsize)
2978
2979 DO img = 2, nimages_scf_desymm
2980 CALL dbcsr_create(mat_v_tr_r(img), template=mat_v_tr_r(1))
2981 END DO
2982
2983 CALL build_2c_integrals(mat_v_tr_r, 0.0_dp, qs_env, sab_ri, bs_env%basis_set_RI, &
2984 bs_env%basis_set_RI, pot_type, do_kpoints=.true., &
2985 ext_kpoints=bs_env%kpoints_scf_desymm, &
2986 regularization_ri=regularization_ri)
2987
2988 ALLOCATE (fm_v_tr_r(nimages_scf_desymm))
2989 DO img = 1, nimages_scf_desymm
2990 CALL cp_fm_create(fm_v_tr_r(img), bs_env%fm_RI_RI%matrix_struct)
2991 CALL copy_dbcsr_to_fm(mat_v_tr_r(img), fm_v_tr_r(img))
2992 CALL dbcsr_release(mat_v_tr_r(img))
2993 END DO
2994
2995 IF (.NOT. ALLOCATED(v_tr_r)) THEN
2996 ALLOCATE (v_tr_r(bs_env%n_RI, bs_env%n_RI, nimages_scf_desymm))
2997 END IF
2998
2999 CALL fm_to_local_array(fm_v_tr_r, v_tr_r)
3000
3001 CALL cp_fm_release(fm_v_tr_r)
3002 CALL dbcsr_distribution_release(dbcsr_dist)
3003 CALL release_neighbor_list_sets(sab_ri)
3004
3005 CALL timestop(handle)
3006
3007 END SUBROUTINE get_v_tr_r
3008
3009! **************************************************************************************************
3010!> \brief ...
3011!> \param matrix ...
3012!> \param exponent ...
3013!> \param eps ...
3014!> \param cond_nr ...
3015!> \param min_ev ...
3016!> \param max_ev ...
3017! **************************************************************************************************
3018 SUBROUTINE power(matrix, exponent, eps, cond_nr, min_ev, max_ev)
3019 COMPLEX(KIND=dp), DIMENSION(:, :) :: matrix
3020 REAL(kind=dp) :: exponent, eps
3021 REAL(kind=dp), OPTIONAL :: cond_nr, min_ev, max_ev
3022
3023 CHARACTER(len=*), PARAMETER :: routinen = 'power'
3024
3025 COMPLEX(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: eigenvectors
3026 INTEGER :: handle, i, n
3027 REAL(kind=dp) :: pos_eval
3028 REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: eigenvalues
3029
3030 CALL timeset(routinen, handle)
3031
3032 ! make matrix perfectly Hermitian
3033 matrix(:, :) = 0.5_dp*(matrix(:, :) + conjg(transpose(matrix(:, :))))
3034
3035 n = SIZE(matrix, 1)
3036 ALLOCATE (eigenvalues(n), eigenvectors(n, n))
3037 CALL diag_complex(matrix, eigenvectors, eigenvalues)
3038
3039 IF (PRESENT(cond_nr)) cond_nr = maxval(abs(eigenvalues))/minval(abs(eigenvalues))
3040 IF (PRESENT(min_ev)) min_ev = minval(abs(eigenvalues))
3041 IF (PRESENT(max_ev)) max_ev = maxval(abs(eigenvalues))
3042
3043 DO i = 1, n
3044 IF (eps < eigenvalues(i)) THEN
3045 pos_eval = (eigenvalues(i))**(0.5_dp*exponent)
3046 ELSE
3047 pos_eval = 0.0_dp
3048 END IF
3049 eigenvectors(:, i) = eigenvectors(:, i)*pos_eval
3050 END DO
3051
3052 CALL zgemm("N", "C", n, n, n, z_one, eigenvectors, n, eigenvectors, n, z_zero, matrix, n)
3053
3054 DEALLOCATE (eigenvalues, eigenvectors)
3055
3056 CALL timestop(handle)
3057
3058 END SUBROUTINE power
3059
3060! **************************************************************************************************
3061!> \brief ...
3062!> \param bs_env ...
3063!> \param Sigma_c_n_time ...
3064!> \param Sigma_c_n_freq ...
3065!> \param ispin ...
3066! **************************************************************************************************
3067 SUBROUTINE time_to_freq(bs_env, Sigma_c_n_time, Sigma_c_n_freq, ispin)
3068 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
3069 REAL(kind=dp), DIMENSION(:, :, :) :: sigma_c_n_time, sigma_c_n_freq
3070 INTEGER :: ispin
3071
3072 CHARACTER(LEN=*), PARAMETER :: routinen = 'time_to_freq'
3073
3074 INTEGER :: handle, i_t, j_w, n_occ
3075 REAL(kind=dp) :: freq_j, time_i, w_cos_ij, w_sin_ij
3076 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :) :: sigma_c_n_cos_time, sigma_c_n_sin_time
3077
3078 CALL timeset(routinen, handle)
3079
3080 ALLOCATE (sigma_c_n_cos_time(bs_env%n_ao, bs_env%num_time_freq_points))
3081 ALLOCATE (sigma_c_n_sin_time(bs_env%n_ao, bs_env%num_time_freq_points))
3082
3083 sigma_c_n_cos_time(:, :) = 0.5_dp*(sigma_c_n_time(:, :, 1) + sigma_c_n_time(:, :, 2))
3084 sigma_c_n_sin_time(:, :) = 0.5_dp*(sigma_c_n_time(:, :, 1) - sigma_c_n_time(:, :, 2))
3085
3086 sigma_c_n_freq(:, :, :) = 0.0_dp
3087
3088 DO i_t = 1, bs_env%num_time_freq_points
3089
3090 DO j_w = 1, bs_env%num_time_freq_points
3091
3092 freq_j = bs_env%imag_freq_points(j_w)
3093 time_i = bs_env%imag_time_points(i_t)
3094 ! integration weights for cosine and sine transform
3095 w_cos_ij = bs_env%weights_cos_t_to_w(j_w, i_t)*cos(freq_j*time_i)
3096 w_sin_ij = bs_env%weights_sin_t_to_w(j_w, i_t)*sin(freq_j*time_i)
3097
3098 ! 1. Re(Σ^c_nn(k_i,iω)) from cosine transform
3099 sigma_c_n_freq(:, j_w, 1) = sigma_c_n_freq(:, j_w, 1) + &
3100 w_cos_ij*sigma_c_n_cos_time(:, i_t)
3101
3102 ! 2. Im(Σ^c_nn(k_i,iω)) from sine transform
3103 sigma_c_n_freq(:, j_w, 2) = sigma_c_n_freq(:, j_w, 2) + &
3104 w_sin_ij*sigma_c_n_sin_time(:, i_t)
3105
3106 END DO
3107
3108 END DO
3109
3110 ! for occupied levels, we need the correlation self-energy for negative omega.
3111 ! Therefore, weight_sin should be computed with -omega, which results in an
3112 ! additional minus for the imaginary part:
3113 n_occ = bs_env%n_occ(ispin)
3114 sigma_c_n_freq(1:n_occ, :, 2) = -sigma_c_n_freq(1:n_occ, :, 2)
3115
3116 CALL timestop(handle)
3117
3118 END SUBROUTINE time_to_freq
3119
3120! **************************************************************************************************
3121!> \brief ...
3122!> \param bs_env ...
3123!> \param Sigma_c_ikp_n_freq ...
3124!> \param Sigma_x_ikp_n ...
3125!> \param V_xc_ikp_n ...
3126!> \param eigenval_scf ...
3127!> \param ikp ...
3128!> \param ispin ...
3129! **************************************************************************************************
3130 SUBROUTINE analyt_conti_and_print(bs_env, Sigma_c_ikp_n_freq, Sigma_x_ikp_n, V_xc_ikp_n, &
3131 eigenval_scf, ikp, ispin)
3132
3133 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
3134 REAL(kind=dp), DIMENSION(:, :, :) :: sigma_c_ikp_n_freq
3135 REAL(kind=dp), DIMENSION(:) :: sigma_x_ikp_n, v_xc_ikp_n, eigenval_scf
3136 INTEGER :: ikp, ispin
3137
3138 CHARACTER(LEN=*), PARAMETER :: routinen = 'analyt_conti_and_print'
3139
3140 CHARACTER(len=3) :: occ_vir
3141 CHARACTER(len=default_string_length) :: fname
3142 INTEGER :: handle, i_mo, ikp_for_print, iunit, &
3143 n_mo, nkp
3144 LOGICAL :: is_bandstruc_kpoint, print_dos_kpoints, &
3145 print_ikp
3146 REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: dummy, sigma_c_ikp_n_qp
3147
3148 CALL timeset(routinen, handle)
3149
3150 n_mo = bs_env%n_ao
3151 ALLOCATE (dummy(n_mo), sigma_c_ikp_n_qp(n_mo))
3152 sigma_c_ikp_n_qp(:) = 0.0_dp
3153
3154 DO i_mo = 1, n_mo
3155
3156 ! parallelization
3157 IF (modulo(i_mo, bs_env%para_env%num_pe) /= bs_env%para_env%mepos) cycle
3158
3159 CALL continuation_pade(sigma_c_ikp_n_qp, &
3160 bs_env%imag_freq_points_fit, dummy, dummy, &
3161 sigma_c_ikp_n_freq(:, 1:bs_env%num_freq_points_fit, 1)*z_one + &
3162 sigma_c_ikp_n_freq(:, 1:bs_env%num_freq_points_fit, 2)*gaussi, &
3163 sigma_x_ikp_n(:) - v_xc_ikp_n(:), &
3164 eigenval_scf(:), eigenval_scf(:), &
3165 bs_env%do_hedin_shift, &
3166 i_mo, bs_env%n_occ(ispin), bs_env%n_vir(ispin), &
3167 bs_env%nparam_pade, bs_env%num_freq_points_fit, &
3168 ri_rpa_g0w0_crossing_newton, bs_env%n_occ(ispin), &
3169 0.0_dp, .true., .false., 1, e_fermi_ext=bs_env%e_fermi(ispin))
3170 END DO
3171
3172 CALL bs_env%para_env%sum(sigma_c_ikp_n_qp)
3173
3174 CALL correct_obvious_fitting_fails(sigma_c_ikp_n_qp, ispin, bs_env)
3175
3176 bs_env%eigenval_G0W0(:, ikp, ispin) = eigenval_scf(:) + &
3177 sigma_c_ikp_n_qp(:) + &
3178 sigma_x_ikp_n(:) - &
3179 v_xc_ikp_n(:)
3180
3181 bs_env%eigenval_HF(:, ikp, ispin) = eigenval_scf(:) + sigma_x_ikp_n(:) - v_xc_ikp_n(:)
3182
3183 ! only print eigenvalues of DOS k-points in case no bandstructure path has been given
3184 print_dos_kpoints = (bs_env%nkp_only_bs .LE. 0)
3185 ! in kpoints_DOS, the last nkp_only_bs are bandstructure k-points
3186 is_bandstruc_kpoint = (ikp > bs_env%nkp_only_DOS)
3187 print_ikp = print_dos_kpoints .OR. is_bandstruc_kpoint
3188
3189 IF (bs_env%para_env%is_source() .AND. print_ikp) THEN
3190
3191 IF (print_dos_kpoints) THEN
3192 nkp = bs_env%nkp_only_DOS
3193 ikp_for_print = ikp
3194 ELSE
3195 nkp = bs_env%nkp_only_bs
3196 ikp_for_print = ikp - bs_env%nkp_only_DOS
3197 END IF
3198
3199 fname = "bandstructure_SCF_and_G0W0"
3200
3201 IF (ikp_for_print == 1) THEN
3202 CALL open_file(trim(fname), unit_number=iunit, file_status="REPLACE", &
3203 file_action="WRITE")
3204 ELSE
3205 CALL open_file(trim(fname), unit_number=iunit, file_status="OLD", &
3206 file_action="WRITE", file_position="APPEND")
3207 END IF
3208
3209 WRITE (iunit, "(A)") " "
3210 WRITE (iunit, "(A10,I7,A25,3F10.4)") "kpoint: ", ikp_for_print, "coordinate: ", &
3211 bs_env%kpoints_DOS%xkp(:, ikp)
3212 WRITE (iunit, "(A)") " "
3213 WRITE (iunit, "(A5,A12,3A17,A16,A18)") "n", "k", ϵ"_nk^DFT (eV)", Σ"^c_nk (eV)", &
3214 Σ"^x_nk (eV)", "v_nk^xc (eV)", ϵ"_nk^G0W0 (eV)"
3215 WRITE (iunit, "(A)") " "
3216
3217 DO i_mo = 1, n_mo
3218 IF (i_mo .LE. bs_env%n_occ(ispin)) occ_vir = 'occ'
3219 IF (i_mo > bs_env%n_occ(ispin)) occ_vir = 'vir'
3220 WRITE (iunit, "(I5,3A,I5,4F16.3,F17.3)") i_mo, ' (', occ_vir, ') ', ikp_for_print, &
3221 eigenval_scf(i_mo)*evolt, &
3222 sigma_c_ikp_n_qp(i_mo)*evolt, &
3223 sigma_x_ikp_n(i_mo)*evolt, &
3224 v_xc_ikp_n(i_mo)*evolt, &
3225 bs_env%eigenval_G0W0(i_mo, ikp, ispin)*evolt
3226 END DO
3227
3228 WRITE (iunit, "(A)") " "
3229
3230 CALL close_file(iunit)
3231
3232 END IF
3233
3234 CALL timestop(handle)
3235
3236 END SUBROUTINE analyt_conti_and_print
3237
3238! **************************************************************************************************
3239!> \brief ...
3240!> \param Sigma_c_ikp_n_qp ...
3241!> \param ispin ...
3242!> \param bs_env ...
3243! **************************************************************************************************
3244 SUBROUTINE correct_obvious_fitting_fails(Sigma_c_ikp_n_qp, ispin, bs_env)
3245 REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: sigma_c_ikp_n_qp
3246 INTEGER :: ispin
3247 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
3248
3249 CHARACTER(LEN=*), PARAMETER :: routinen = 'correct_obvious_fitting_fails'
3250
3251 INTEGER :: handle, homo, i_mo, j_mo, &
3252 n_levels_scissor, n_mo
3253 LOGICAL :: is_occ, is_vir
3254 REAL(kind=dp) :: sum_sigma_c
3255
3256 CALL timeset(routinen, handle)
3257
3258 n_mo = bs_env%n_ao
3259 homo = bs_env%n_occ(ispin)
3260
3261 DO i_mo = 1, n_mo
3262
3263 ! if |𝚺^c| > 13 eV, we use a scissors shift
3264 IF (abs(sigma_c_ikp_n_qp(i_mo)) > 13.0_dp/evolt) THEN
3265
3266 is_occ = (i_mo .LE. homo)
3267 is_vir = (i_mo > homo)
3268
3269 n_levels_scissor = 0
3270 sum_sigma_c = 0.0_dp
3271
3272 ! compute scissor
3273 DO j_mo = 1, n_mo
3274
3275 ! only compute scissor from other GW levels close in energy
3276 IF (is_occ .AND. j_mo > homo) cycle
3277 IF (is_vir .AND. j_mo .LE. homo) cycle
3278 IF (abs(i_mo - j_mo) > 10) cycle
3279 IF (i_mo == j_mo) cycle
3280
3281 n_levels_scissor = n_levels_scissor + 1
3282 sum_sigma_c = sum_sigma_c + sigma_c_ikp_n_qp(j_mo)
3283
3284 END DO
3285
3286 ! overwrite the self-energy with scissor shift
3287 sigma_c_ikp_n_qp(i_mo) = sum_sigma_c/real(n_levels_scissor, kind=dp)
3288
3289 END IF
3290
3291 END DO ! i_mo
3292
3293 CALL timestop(handle)
3294
3295 END SUBROUTINE correct_obvious_fitting_fails
3296
3297END MODULE gw_utils
static GRID_HOST_DEVICE int modulo(int a, int m)
Equivalent of Fortran's MODULO, which always return a positive number. https://gcc....
struct tensor_ tensor
Define the atomic kind types and their sub types.
subroutine, public get_atomic_kind_set(atomic_kind_set, atom_of_kind, kind_of, natom_of_kind, maxatom, natom, nshell, fist_potential_present, shell_present, shell_adiabatic, shell_check_distance, damping_present)
Get attributes of an atomic kind set.
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)
...
collects all references to literature in CP2K as new algorithms / method are included from literature...
integer, save, public graml2024
Handles all functions related to the CELL.
Definition cell_types.F:15
methods related to the blacs parallel environment
subroutine, public cp_blacs_env_release(blacs_env)
releases the given blacs_env
subroutine, public cp_blacs_env_create(blacs_env, para_env, blacs_grid_layout, blacs_repeatable, row_major, grid_2d)
allocates and initializes a type that represent a blacs context
Represents a complex full matrix distributed on many processors.
subroutine, public cp_cfm_create(matrix, matrix_struct, name)
Creates a new full matrix with the given structure.
subroutine, public cp_cfm_release(matrix)
Releases a full matrix.
subroutine, public cp_cfm_to_fm(msource, mtargetr, mtargeti)
Copy real and imaginary parts of a complex full matrix into separate real-value full matrices.
Defines control structures, which contain the parameters and the settings for the DFT-based calculati...
subroutine, public dbcsr_distribution_release(dist)
...
subroutine, public dbcsr_set(matrix, alpha)
...
subroutine, public dbcsr_release(matrix)
...
DBCSR operations in CP2K.
subroutine, public cp_dbcsr_dist2d_to_dist(dist2d, dist)
Creates a DBCSR distribution from a distribution_2d.
subroutine, public copy_dbcsr_to_fm(matrix, fm)
Copy a DBCSR matrix to a BLACS matrix.
subroutine, public copy_fm_to_dbcsr(fm, matrix, keep_sparsity)
Copy a BLACS matrix to a dbcsr matrix.
Utility routines to open and close files. Tracking of preconnections.
Definition cp_files.F:16
subroutine, public open_file(file_name, file_status, file_form, file_action, file_position, file_pad, unit_number, debug, skip_get_unit_number, file_access)
Opens the requested file using a free unit number.
Definition cp_files.F:308
subroutine, public close_file(unit_number, file_status, keep_preconnection)
Close an open file given by its logical unit number. Optionally, keep the file and unit preconnected.
Definition cp_files.F:119
basic linear algebra operations for full matrices
subroutine, public cp_fm_scale_and_add(alpha, matrix_a, beta, matrix_b)
calc A <- alpha*A + beta*B optimized for alpha == 1.0 (just add beta*B) and beta == 0....
represent the structure of a full matrix
subroutine, public cp_fm_struct_create(fmstruct, para_env, context, nrow_global, ncol_global, nrow_block, ncol_block, descriptor, first_p_pos, local_leading_dimension, template_fmstruct, square_blocks, force_block)
allocates and initializes a full matrix structure
subroutine, public cp_fm_struct_release(fmstruct)
releases a full matrix structure
represent a full matrix distributed on many processors
Definition cp_fm_types.F:15
subroutine, public cp_fm_get_diag(matrix, diag)
returns the diagonal elements of a fm
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...
character(len=default_path_length) function, public cp_print_key_generate_filename(logger, print_key, middle_name, extension, my_local)
Utility function that returns a unit number to write the print key. Might open a file with a unique f...
This is the start of a dbt_api, all publically needed functions are exported here....
Definition dbt_api.F:17
stores a mapping of 2D info (e.g. matrix) on a 2D processor distribution (i.e. blacs grid) where cpus...
subroutine, public fm_to_local_array(fm_s, array_s, weight, add)
...
Utility method to build 3-center integrals for small cell GW.
subroutine, public build_3c_integral_block(int_3c, qs_env, potential_parameter, basis_j, basis_k, basis_i, cell_j, cell_k, cell_i, atom_j, atom_k, atom_i, j_bf_start_from_atom, k_bf_start_from_atom, i_bf_start_from_atom)
...
subroutine, public trafo_rs_to_ikp(array_rs, array_kp, index_to_cell, xkp)
...
subroutine, public get_v_tr_r(v_tr_r, pot_type, regularization_ri, bs_env, qs_env)
...
Definition gw_utils.F:2931
subroutine, public time_to_freq(bs_env, sigma_c_n_time, sigma_c_n_freq, ispin)
...
Definition gw_utils.F:3068
subroutine, public de_init_bs_env(bs_env)
...
Definition gw_utils.F:237
subroutine, public compute_xkp(xkp, ikp_start, ikp_end, grid)
...
Definition gw_utils.F:624
subroutine, public analyt_conti_and_print(bs_env, sigma_c_ikp_n_freq, sigma_x_ikp_n, v_xc_ikp_n, eigenval_scf, ikp, ispin)
...
Definition gw_utils.F:3132
subroutine, public create_and_init_bs_env_for_gw(qs_env, bs_env, bs_sec)
...
Definition gw_utils.F:151
subroutine, public add_r(cell_1, cell_2, index_to_cell, cell_1_plus_2, cell_found, cell_to_index, i_cell_1_plus_2)
...
Definition gw_utils.F:2648
subroutine, public kpoint_init_cell_index_simple(kpoints, qs_env)
...
Definition gw_utils.F:594
subroutine, public get_i_j_atoms(atoms_i, atoms_j, n_atom_i, n_atom_j, color_sub, bs_env)
...
Definition gw_utils.F:1411
subroutine, public power(matrix, exponent, eps, cond_nr, min_ev, max_ev)
...
Definition gw_utils.F:3019
subroutine, public is_cell_in_index_to_cell(cell, index_to_cell, cell_found)
...
Definition gw_utils.F:2687
collects all constants needed in input so that they can be used without circular dependencies
integer, parameter, public do_potential_truncated
integer, parameter, public rtp_method_bse
integer, parameter, public small_cell_full_kp
integer, parameter, public large_cell_gamma
integer, parameter, public xc_none
integer, parameter, public ri_rpa_g0w0_crossing_newton
objects that represent the structure of input sections and the data contained in an input section
subroutine, public section_vals_val_set(section_vals, keyword_name, i_rep_section, i_rep_val, val, l_val, i_val, r_val, c_val, l_vals_ptr, i_vals_ptr, r_vals_ptr, c_vals_ptr)
sets the requested value
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_get(section_vals, ref_count, n_repetition, n_subs_vals_rep, section, explicit)
returns various attributes about the section_vals
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 int_8
Definition kinds.F:54
integer, parameter, public dp
Definition kinds.F:34
integer, parameter, public default_string_length
Definition kinds.F:57
Routines needed for kpoint calculation.
subroutine, public kpoint_init_cell_index(kpoint, sab_nl, para_env, dft_control)
Generates the mapping of cell indices and linear RS index CELL (0,0,0) is always mapped to index 1.
Types and basic routines needed for a kpoint calculation.
subroutine, public kpoint_create(kpoint)
Create a kpoint environment.
subroutine, public get_kpoint_info(kpoint, kp_scheme, nkp_grid, kp_shift, symmetry, verbose, full_grid, use_real_wfn, eps_geo, parallel_group_size, kp_range, nkp, xkp, wkp, para_env, blacs_env_all, para_env_kp, para_env_inter_kp, blacs_env, kp_env, kp_aux_env, mpools, iogrp, nkp_groups, kp_dist, cell_to_index, index_to_cell, sab_nl, sab_nl_nosym)
Retrieve information from a kpoint environment.
2- and 3-center electron repulsion integral routines based on libint2 Currently available operators: ...
Interface to the Libint-Library or a c++ wrapper.
subroutine, public cp_libint_static_cleanup()
subroutine, public cp_libint_static_init()
Machine interface based on Fortran 2003 and POSIX.
Definition machine.F:17
subroutine, public m_memory(mem)
Returns the total amount of memory [bytes] in use, if known, zero otherwise.
Definition machine.F:440
real(kind=dp) function, public m_walltime()
returns time from a real-time clock, protected against rolling early/easily
Definition machine.F:147
Definition of mathematical constants and functions.
complex(kind=dp), parameter, public z_one
complex(kind=dp), parameter, public gaussi
complex(kind=dp), parameter, public z_zero
Collection of simple mathematical functions and subroutines.
Definition mathlib.F:15
subroutine, public diag_complex(matrix, eigenvectors, eigenvalues)
Diagonalizes a local complex Hermitian matrix using LAPACK. Based on cp_cfm_heevd.
Definition mathlib.F:1743
elemental integer function, public gcd(a, b)
computes the greatest common divisor of two number
Definition mathlib.F:1280
Interface to the message passing library MPI.
Routines to calculate the minimax coefficients in order to approximate 1/x as a sum over exponential ...
subroutine, public get_exp_minimax_coeff_gw(k, e_range, aw)
...
Routines to calculate the minimax coefficients in order to approximate 1/x as a sum over exponential ...
Definition minimax_exp.F:29
subroutine, public get_exp_minimax_coeff(k, rc, aw, mm_error, which_coeffs)
Get best minimax approximation for given input parameters. Automatically chooses the most exact set o...
Routines to calculate the minimax coefficients for approximating 1/x as 1/x ~ 1/pi SUM_{i}^{K} w_i x^...
Definition minimax_rpa.F:14
subroutine, public get_rpa_minimax_coeff_larger_grid(k, e_range, aw)
...
subroutine, public get_rpa_minimax_coeff(k, e_range, aw, ierr, print_warning)
The a_i and w_i coefficient are stored in aw such that the first 1:K elements correspond to a_i and t...
Definition minimax_rpa.F:41
Calls routines to get RI integrals and calculate total energies.
Definition mp2_gpw.F:14
subroutine, public create_mat_munu(mat_munu, qs_env, eps_grid, blacs_env_sub, do_ri_aux_basis, do_mixed_basis, group_size_prim, do_alloc_blocks_from_nbl, do_kpoints, sab_orb_sub, dbcsr_sym_type)
Encapsulate the building of dbcsr_matrix mat_munu.
Definition mp2_gpw.F:990
Routines to calculate frequency and time grids (integration points and weights) for correlation metho...
Definition mp2_grids.F:14
subroutine, public get_l_sq_wghts_cos_tf_w_to_t(num_integ_points, tau_tj, weights_cos_tf_w_to_t, omega_tj, e_min, e_max, max_error, num_points_per_magnitude, regularization)
...
Definition mp2_grids.F:1244
subroutine, public get_l_sq_wghts_cos_tf_t_to_w(num_integ_points, tau_tj, weights_cos_tf_t_to_w, omega_tj, e_min, e_max, max_error, num_points_per_magnitude, regularization)
Calculate integration weights for the tau grid (in dependency of the omega node)
Definition mp2_grids.F:745
subroutine, public get_l_sq_wghts_sin_tf_t_to_w(num_integ_points, tau_tj, weights_sin_tf_t_to_w, omega_tj, e_min, e_max, max_error, num_points_per_magnitude, regularization)
Calculate integration weights for the tau grid (in dependency of the omega node)
Definition mp2_grids.F:881
Framework for 2c-integrals for RI.
Definition mp2_ri_2c.F:14
subroutine, public trunc_coulomb_for_exchange(qs_env, trunc_coulomb, rel_cutoff_trunc_coulomb_ri_x, cell_grid, do_bvk_cell)
...
Definition mp2_ri_2c.F:1613
basic linear algebra operations for full matrixes
Define methods related to particle_type.
subroutine, public get_particle_set(particle_set, qs_kind_set, first_sgf, last_sgf, nsgf, nmao, basis)
Get the components of a particle set.
Define the data structure for the particle information.
Definition of physical constants:
Definition physcon.F:68
real(kind=dp), parameter, public evolt
Definition physcon.F:183
real(kind=dp), parameter, public angstrom
Definition physcon.F:144
subroutine, public rsmat_to_kp(mat_rs, ispin, xkp, cell_to_index_scf, sab_nl, bs_env, cfm_kp, imag_rs_mat)
...
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.
subroutine, public qs_env_part_release(qs_env)
releases part of the given qs_env in order to save memory
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.
Calculate the interaction radii for the operator matrix calculation.
subroutine, public init_interaction_radii_orb_basis(orb_basis_set, eps_pgf_orb, eps_pgf_short)
...
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.
routines that build the Kohn-Sham matrix (i.e calculate the coulomb and xc parts
subroutine, public qs_ks_build_kohn_sham_matrix(qs_env, calculate_forces, just_energy, print_active, ext_ks_matrix)
routine where the real calculations are made: the KS matrix is calculated
Define the neighbor list data types and the corresponding functionality.
subroutine, public release_neighbor_list_sets(nlists)
releases an array of neighbor_list_sets
Utility methods to build 3-center integral tensors of various types.
subroutine, public distribution_3d_create(dist_3d, dist1, dist2, dist3, nkind, particle_set, mp_comm_3d, own_comm)
Create a 3d distribution.
subroutine, public create_2c_tensor(t2c, dist_1, dist_2, pgrid, sizes_1, sizes_2, order, name)
...
subroutine, public create_3c_tensor(t3c, dist_1, dist_2, dist_3, pgrid, sizes_1, sizes_2, sizes_3, map1, map2, name)
...
Utility methods to build 3-center integral tensors of various types.
Definition qs_tensors.F:11
subroutine, public build_2c_integrals(t2c, filter_eps, qs_env, nl_2c, basis_i, basis_j, potential_parameter, do_kpoints, do_hfx_kpoints, ext_kpoints, regularization_ri)
...
subroutine, public build_2c_neighbor_lists(ij_list, basis_i, basis_j, potential_parameter, name, qs_env, sym_ij, molecular, dist_2d, pot_to_rad)
Build 2-center neighborlists adapted to different operators This mainly wraps build_neighbor_lists fo...
Definition qs_tensors.F:143
subroutine, public build_3c_integrals(t3c, filter_eps, qs_env, nl_3c, basis_i, basis_j, basis_k, potential_parameter, int_eps, op_pos, do_kpoints, do_hfx_kpoints, desymmetrize, cell_sym, bounds_i, bounds_j, bounds_k, ri_range, img_to_ri_cell, cell_to_index_ext)
Build 3-center integral tensor.
subroutine, public neighbor_list_3c_destroy(ijk_list)
Destroy 3c neighborlist.
Definition qs_tensors.F:383
subroutine, public get_tensor_occupancy(tensor, nze, occ)
...
subroutine, public build_3c_neighbor_lists(ijk_list, basis_i, basis_j, basis_k, dist_3d, potential_parameter, name, qs_env, sym_ij, sym_jk, sym_ik, molecular, op_pos, own_dist)
Build a 3-center neighbor list.
Definition qs_tensors.F:282
Routines for GW, continuous development [Jan Wilhelm].
Definition rpa_gw.F:14
subroutine, public continuation_pade(vec_gw_energ, vec_omega_fit_gw, z_value, m_value, vec_sigma_c_gw, vec_sigma_x_minus_vxc_gw, eigenval, eigenval_scf, do_hedin_shift, n_level_gw, gw_corr_lev_occ, gw_corr_lev_vir, nparam_pade, num_fit_points, crossing_search, homo, fermi_level_offset, do_gw_im_time, print_self_energy, count_ev_sc_gw, vec_gw_dos, dos_lower_bound, dos_precision, ndos, min_level_self_energy, max_level_self_energy, dos_eta, dos_min, dos_max, e_fermi_ext)
perform analytic continuation with pade approximation
Definition rpa_gw.F:4314
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...
Represent a complex full matrix.
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...
distributes pairs on a 2d grid of processors
Contains information about kpoints.
stores all the informations relevant to an mpi environment
Provides all information about a quickstep kind.