Line data Source code
1 : !--------------------------------------------------------------------------------------------------!
2 : ! CP2K: A general program to perform molecular dynamics simulations !
3 : ! Copyright 2000-2026 CP2K developers group <https://cp2k.org> !
4 : ! !
5 : ! SPDX-License-Identifier: GPL-2.0-or-later !
6 : !--------------------------------------------------------------------------------------------------!
7 :
8 : ! **************************************************************************************************
9 : !> \brief Coulomb matrices and screened interactions for imaginary-time GW.
10 : ! **************************************************************************************************
11 : MODULE gw_compute_V_and_W
12 : USE atomic_kind_types, ONLY: atomic_kind_type
13 : USE cell_types, ONLY: cell_type
14 : USE constants_operator, ONLY: operator_coulomb
15 : USE cp_blacs_env, ONLY: cp_blacs_env_type
16 : USE cp_cfm_basic_linalg, ONLY: cp_cfm_add_on_diag,&
17 : cp_cfm_uplo_to_full
18 : USE cp_cfm_cholesky, ONLY: cp_cfm_cholesky_decompose,&
19 : cp_cfm_cholesky_invert
20 : USE cp_cfm_diag, ONLY: cp_cfm_power
21 : USE cp_cfm_types, ONLY: cp_cfm_create,&
22 : cp_cfm_get_info,&
23 : cp_cfm_release,&
24 : cp_cfm_to_cfm,&
25 : cp_cfm_type
26 : USE cp_dbcsr_api, ONLY: &
27 : dbcsr_add, dbcsr_create, dbcsr_deallocate_matrix, dbcsr_distribution_release, &
28 : dbcsr_distribution_type, dbcsr_p_type, dbcsr_release, dbcsr_set, dbcsr_type, &
29 : dbcsr_type_no_symmetry
30 : USE cp_dbcsr_contrib, ONLY: dbcsr_reserve_all_blocks
31 : USE cp_dbcsr_operations, ONLY: copy_dbcsr_to_fm,&
32 : cp_dbcsr_dist2d_to_dist,&
33 : dbcsr_deallocate_matrix_set
34 : USE cp_files, ONLY: close_file,&
35 : open_file
36 : USE cp_fm_basic_linalg, ONLY: cp_fm_add_on_diag,&
37 : cp_fm_scale_and_add,&
38 : cp_fm_syrk,&
39 : cp_fm_triangular_multiply,&
40 : cp_fm_uplo_to_full
41 : USE cp_fm_cholesky, ONLY: cp_fm_cholesky_decompose
42 : USE cp_fm_diag, ONLY: cp_fm_power
43 : USE cp_fm_redistribution, ONLY: cp_fm_to_replicated_array
44 : USE cp_fm_types, ONLY: cp_fm_create,&
45 : cp_fm_get_info,&
46 : cp_fm_read_unformatted,&
47 : cp_fm_release,&
48 : cp_fm_set_all,&
49 : cp_fm_to_fm,&
50 : cp_fm_type,&
51 : cp_fm_write_unformatted
52 : USE cp_log_handling, ONLY: cp_get_default_logger,&
53 : cp_logger_type
54 : USE cp_output_handling, ONLY: cp_p_file,&
55 : cp_print_key_should_output,&
56 : cp_print_key_unit_nr
57 : USE distribution_2d_types, ONLY: distribution_2d_type
58 : USE gw_utils_fm, ONLY: cfm_contract_ABA,&
59 : fm_contract_ABA,&
60 : fm_sqrt
61 : USE input_constants, ONLY: rtp_method_bse,&
62 : rtp_method_bse_linearized
63 : USE input_section_types, ONLY: section_vals_type
64 : USE kinds, ONLY: default_path_length,&
65 : dp
66 : USE kpoint_coulomb_2c, ONLY: build_2c_coulomb_matrix_kp
67 : USE libint_2c_3c, ONLY: libint_potential_type
68 : USE machine, ONLY: m_walltime
69 : USE mathconstants, ONLY: z_one,&
70 : z_zero
71 : USE mp2_ri_2c, ONLY: RI_2c_integral_mat_kp
72 : USE parallel_gemm_api, ONLY: parallel_gemm
73 : USE particle_methods, ONLY: get_particle_set
74 : USE particle_types, ONLY: particle_type
75 : USE post_scf_bandstructure_types, ONLY: post_scf_bandstructure_type
76 : USE post_scf_bandstructure_utils, ONLY: MIC_contribution_from_ikp,&
77 : cfm_ikp_from_fm_Gamma
78 : USE qs_environment_types, ONLY: get_qs_env,&
79 : qs_environment_type
80 : USE qs_kind_types, ONLY: qs_kind_type
81 : USE qs_neighbor_list_types, ONLY: neighbor_list_set_p_type,&
82 : release_neighbor_list_sets
83 : USE qs_tensors, ONLY: build_2c_integrals,&
84 : build_2c_neighbor_lists
85 : USE rpa_gw_kpoints_util, ONLY: cfm_screened_interaction_from_eps_cholesky
86 : #include "./base/base_uses.f90"
87 :
88 : IMPLICIT NONE
89 : PRIVATE
90 : CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'gw_compute_V_and_W'
91 : PUBLIC :: compute_W, &
92 : get_W_MIC, &
93 : compute_V_k_by_lattice_sum, &
94 : compute_MinvVsqrt_Vsqrt, &
95 : compute_fm_W_MIC_freq_j_from_chi, &
96 : apply_extrapol_factor, &
97 : fm_read, &
98 : fm_write, &
99 : get_V_tr_R
100 :
101 : CONTAINS
102 :
103 : ! **************************************************************************************************
104 : !> \brief Computes the screened Coulomb interaction on the imaginary-time grid, entirely in the
105 : !> RI auxiliary (PQ) basis:
106 : !> χ_PQ(iω) = Σ_τ w(ω,τ) cos(ωτ) χ_PQ(iτ) (cosine transform)
107 : !> V = B^T B, A = M^-1 B^T (Coulomb and RI metric factors)
108 : !> ε(iω) = Id + A^T χ(iω) A (dielectric function)
109 : !> W(iω) = A ( ε^-1(iω) - Id ) A^T (metric-dressed correlation part)
110 : !> W(iτ) = Σ_ω w̃(τ,ω) cos(ωτ) W(iω) (back transform)
111 : !> The RI metric is folded in before the back transform. V is the bare Coulomb matrix.
112 : !> \param bs_env ...
113 : !> \param qs_env ...
114 : !> \param mat_chi_Gamma_tau ...
115 : !> \param fm_W_time ...
116 : ! **************************************************************************************************
117 160 : SUBROUTINE compute_W(bs_env, qs_env, mat_chi_Gamma_tau, fm_W_time)
118 : TYPE(post_scf_bandstructure_type), POINTER :: bs_env
119 : TYPE(qs_environment_type), POINTER :: qs_env
120 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: mat_chi_Gamma_tau
121 : TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:) :: fm_W_time
122 :
123 : CHARACTER(LEN=*), PARAMETER :: routineN = 'compute_W'
124 :
125 : INTEGER :: handle, i_t, j_w
126 : REAL(KIND=dp) :: t1
127 : TYPE(cp_fm_type) :: fm_coulomb_factor, &
128 : fm_Minv_coulomb_factor, fm_Minv_V_Minv
129 :
130 40 : CALL timeset(routineN, handle)
131 :
132 40 : t1 = m_walltime()
133 :
134 40 : CALL create_fm_W_MIC_time(bs_env, fm_W_time)
135 :
136 : ! 1. Allocate V and M matrices
137 40 : CALL cp_fm_create(fm_Minv_V_Minv, bs_env%fm_RI_RI%matrix_struct)
138 40 : CALL cp_fm_create(fm_coulomb_factor, bs_env%fm_RI_RI%matrix_struct)
139 40 : CALL cp_fm_create(fm_Minv_coulomb_factor, bs_env%fm_RI_RI%matrix_struct)
140 :
141 : ! Compute V = B^T B and A = M^-1 B^T.
142 40 : CALL compute_coulomb_factors(bs_env, qs_env, fm_Minv_V_Minv, fm_coulomb_factor, fm_Minv_coulomb_factor)
143 :
144 : ! Reuse the Coulomb buffer for M^-1 V M^-1 = A A^T.
145 40 : CALL cp_fm_syrk('U', 'N', bs_env%n_RI, 1.0_dp, fm_Minv_coulomb_factor, 1, 1, 0.0_dp, fm_Minv_V_Minv)
146 : ! The Coulomb factor is no longer needed; reuse it as workspace to complete the lower triangle.
147 40 : CALL cp_fm_uplo_to_full(fm_Minv_V_Minv, fm_coulomb_factor)
148 40 : CALL cp_fm_release(fm_coulomb_factor)
149 :
150 : ! 2. Loop over frequencies
151 590 : DO j_w = 1, bs_env%num_time_freq_points
152 : ! Fourier transformation of χ_PQ(iτ) to χ_PQ(iω_j)
153 550 : CALL compute_fm_chi_Gamma_freq(bs_env, bs_env%fm_chi_Gamma_freq, j_w, mat_chi_Gamma_tau)
154 :
155 : ! ε(iω_j) = Id + A^T χ(iω_j) A; W(iω_j) = A (ε^-1(iω_j)-Id) A^T.
156 : CALL compute_fm_W_freq(bs_env, bs_env%fm_chi_Gamma_freq, fm_Minv_V_Minv, &
157 550 : fm_Minv_coulomb_factor, bs_env%fm_W_MIC_freq)
158 :
159 : ! Fourier transform from W_PQ^MIC(iω_j) to W_PQ^MIC(iτ)
160 590 : CALL Fourier_transform_w_to_t(bs_env, fm_W_time, bs_env%fm_W_MIC_freq, j_w)
161 : END DO
162 :
163 40 : IF (bs_env%unit_nr > 0) THEN
164 : WRITE (bs_env%unit_nr, '(T2,A,T58,A,F7.1,A)') &
165 20 : 'Computed W(iτ),', ' Execution time', m_walltime() - t1, ' s'
166 : END IF
167 :
168 40 : CALL dbcsr_deallocate_matrix_set(mat_chi_Gamma_tau)
169 :
170 : ! Cleanup
171 40 : CALL cp_fm_release(fm_Minv_V_Minv)
172 40 : CALL cp_fm_release(fm_Minv_coulomb_factor)
173 :
174 : ! Marek : Fourier transform W^MIC(itau) back to get it at a specific im.frequency point - iomega = 0
175 40 : IF (bs_env%rtp_method == rtp_method_bse) THEN
176 14 : t1 = m_walltime()
177 14 : CALL cp_fm_create(bs_env%fm_W_MIC_freq_zero, bs_env%fm_W_MIC_freq%matrix_struct)
178 : ! Set to zero
179 14 : CALL cp_fm_set_all(bs_env%fm_W_MIC_freq_zero, 0.0_dp)
180 : ! Sum over all times
181 294 : DO i_t = 1, bs_env%num_time_freq_points
182 : ! Add the relevant structure with correct weight
183 : CALL cp_fm_scale_and_add(1.0_dp, bs_env%fm_W_MIC_freq_zero, &
184 294 : bs_env%time_frequency_grid%time_weights_at_zero_frequency(i_t), fm_W_time(i_t))
185 : END DO
186 : ! Done, save to file
187 14 : CALL fm_write(bs_env%fm_W_MIC_freq_zero, 0, "W_freq_rtp", qs_env)
188 : ! Report calculation
189 14 : IF (bs_env%unit_nr > 0) THEN
190 : WRITE (bs_env%unit_nr, '(T2,A,T57,A,F7.1,A)') &
191 7 : 'Computed W(0),', ' Execution time', m_walltime() - t1, ' s'
192 : END IF
193 : END IF
194 :
195 40 : IF (bs_env%unit_nr > 0) WRITE (bs_env%unit_nr, '(A)') ' '
196 :
197 40 : CALL timestop(handle)
198 :
199 40 : END SUBROUTINE compute_W
200 :
201 : ! **************************************************************************************************
202 : !> \brief ...
203 : !> \param bs_env ...
204 : !> \param qs_env ...
205 : !> \param mat_chi_Gamma_tau ...
206 : !> \param fm_W_MIC_time ...
207 : ! **************************************************************************************************
208 74 : SUBROUTINE get_W_MIC(bs_env, qs_env, mat_chi_Gamma_tau, fm_W_MIC_time)
209 : TYPE(post_scf_bandstructure_type), POINTER :: bs_env
210 : TYPE(qs_environment_type), POINTER :: qs_env
211 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: mat_chi_Gamma_tau
212 : TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:) :: fm_W_MIC_time
213 :
214 : CHARACTER(LEN=*), PARAMETER :: routineN = 'get_W_MIC'
215 :
216 : INTEGER :: handle
217 :
218 74 : CALL timeset(routineN, handle)
219 :
220 74 : IF (bs_env%all_W_exist) THEN
221 0 : CALL read_W_MIC_time(bs_env, mat_chi_Gamma_tau, fm_W_MIC_time)
222 : ELSE
223 74 : CALL compute_W_MIC(bs_env, qs_env, mat_chi_Gamma_tau, fm_W_MIC_time)
224 : END IF
225 :
226 74 : CALL timestop(handle)
227 :
228 74 : END SUBROUTINE get_W_MIC
229 :
230 : ! **************************************************************************************************
231 : !> \brief ...
232 : !> \param bs_env ...
233 : !> \param qs_env ...
234 : !> \param mat_chi_Gamma_tau ...
235 : !> \param fm_W_MIC_time ...
236 : ! **************************************************************************************************
237 74 : SUBROUTINE compute_W_MIC(bs_env, qs_env, mat_chi_Gamma_tau, fm_W_MIC_time)
238 : TYPE(post_scf_bandstructure_type), POINTER :: bs_env
239 : TYPE(qs_environment_type), POINTER :: qs_env
240 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: mat_chi_Gamma_tau
241 : TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:) :: fm_W_MIC_time
242 :
243 : CHARACTER(LEN=*), PARAMETER :: routineN = 'compute_W_MIC'
244 :
245 : INTEGER :: handle, i_t, ikp, ikp_batch, &
246 : ikp_in_batch, j_w
247 : REAL(KIND=dp) :: t1
248 : TYPE(cp_cfm_type) :: cfm_M_inv_V_sqrt_ikp, cfm_V_sqrt_ikp
249 74 : TYPE(cp_cfm_type), ALLOCATABLE, DIMENSION(:) :: cfm_V_kp
250 :
251 74 : CALL timeset(routineN, handle)
252 :
253 74 : CALL create_fm_W_MIC_time(bs_env, fm_W_MIC_time)
254 :
255 208 : DO ikp_batch = 1, bs_env%num_chi_eps_W_batches
256 :
257 134 : t1 = m_walltime()
258 :
259 : ! Compute V_PQ(k) = sum_R e^(ikR) <phi_P, cell 0 | 1/r | phi_Q, cell R>
260 134 : CALL compute_V_k_by_lattice_sum(bs_env, qs_env, cfm_V_kp, ikp_batch)
261 :
262 670 : DO ikp_in_batch = 1, bs_env%nkp_chi_eps_W_batch
263 :
264 536 : ikp = (ikp_batch - 1)*bs_env%nkp_chi_eps_W_batch + ikp_in_batch
265 :
266 536 : IF (ikp > bs_env%nkp_chi_eps_W_orig_plus_extra) THEN
267 : CYCLE
268 : END IF
269 :
270 : CALL compute_MinvVsqrt_Vsqrt(bs_env, qs_env, cfm_V_kp, &
271 324 : cfm_V_sqrt_ikp, cfm_M_inv_V_sqrt_ikp, ikp)
272 :
273 324 : CALL bs_env%para_env%sync()
274 324 : CALL cp_cfm_release(cfm_V_kp(ikp))
275 :
276 3922 : DO j_w = 1, bs_env%num_time_freq_points
277 :
278 : ! check if we need this (ikp, ω_j) combination for approximate k-point extrapolation
279 3464 : IF (bs_env%approx_kp_extrapol .AND. j_w > 1 .AND. &
280 : ikp > bs_env%nkp_chi_eps_W_orig) CYCLE
281 :
282 : CALL compute_fm_W_MIC_freq_j(bs_env, qs_env, bs_env%fm_W_MIC_freq, j_w, ikp, &
283 : mat_chi_Gamma_tau, cfm_M_inv_V_sqrt_ikp, &
284 3140 : cfm_V_sqrt_ikp)
285 :
286 : ! Fourier trafo from W_PQ^MIC(iω_j) to W_PQ^MIC(iτ)
287 4000 : CALL Fourier_transform_w_to_t(bs_env, fm_W_MIC_time, bs_env%fm_W_MIC_freq, j_w)
288 :
289 : END DO ! ω_j
290 :
291 : END DO ! ikp_in_batch
292 :
293 134 : DEALLOCATE (cfm_V_kp)
294 :
295 208 : IF (bs_env%unit_nr > 0) THEN
296 : WRITE (bs_env%unit_nr, '(T2,A,I12,A,I3,A,F10.1,A)') &
297 67 : 'Computed W(iτ,k) for k-point batch', &
298 67 : ikp_batch, ' /', bs_env%num_chi_eps_W_batches, &
299 134 : ', Execution time', m_walltime() - t1, ' s'
300 : END IF
301 :
302 : END DO ! ikp_batch
303 :
304 74 : IF (bs_env%approx_kp_extrapol) THEN
305 2 : CALL apply_extrapol_factor(bs_env, fm_W_MIC_time)
306 : END IF
307 :
308 : ! M^-1(k=0) W^MIC(iτ) M^-1(k=0) -> fm_W_MIC_time
309 74 : CALL fm_contract_ABA(bs_env%fm_Minv_Gamma, fm_W_MIC_time)
310 :
311 1438 : DO i_t = 1, bs_env%num_time_freq_points
312 1438 : CALL fm_write(fm_W_MIC_time(i_t), i_t, bs_env%W_time_name, qs_env)
313 : END DO
314 :
315 74 : CALL cp_cfm_release(cfm_M_inv_V_sqrt_ikp)
316 74 : CALL cp_cfm_release(cfm_V_sqrt_ikp)
317 74 : CALL dbcsr_deallocate_matrix_set(mat_chi_Gamma_tau)
318 :
319 : ! W^MIC(iω=0) from W^MIC(iτ) for the post-GW consumers; the file is the RT-BSE restart's
320 74 : IF (bs_env%rtp_method == rtp_method_bse .OR. &
321 : bs_env%rtp_method == rtp_method_bse_linearized) THEN
322 58 : CALL sum_W_MIC_freq_zero(bs_env, fm_W_MIC_time)
323 58 : CALL fm_write(bs_env%fm_W_MIC_freq_zero, 0, "W_freq_rtp", qs_env)
324 16 : ELSE IF (bs_env%keep_W_freq_zero) THEN
325 6 : CALL sum_W_MIC_freq_zero(bs_env, fm_W_MIC_time)
326 : END IF
327 :
328 74 : IF (bs_env%unit_nr > 0) WRITE (bs_env%unit_nr, '(A)') ' '
329 :
330 74 : CALL timestop(handle)
331 :
332 148 : END SUBROUTINE compute_W_MIC
333 :
334 : ! **************************************************************************************************
335 : !> \brief ...
336 : !> \param bs_env ...
337 : !> \param qs_env ...
338 : !> \param cfm_V_kp ...
339 : !> \param ikp_batch ...
340 : ! **************************************************************************************************
341 188 : SUBROUTINE compute_V_k_by_lattice_sum(bs_env, qs_env, cfm_V_kp, ikp_batch)
342 : TYPE(post_scf_bandstructure_type), POINTER :: bs_env
343 : TYPE(qs_environment_type), POINTER :: qs_env
344 : TYPE(cp_cfm_type), ALLOCATABLE, DIMENSION(:) :: cfm_V_kp
345 : INTEGER :: ikp_batch
346 :
347 : CHARACTER(LEN=*), PARAMETER :: routineN = 'compute_V_k_by_lattice_sum'
348 :
349 : INTEGER :: handle, ikp, ikp_end, ikp_start, &
350 : nkp_chi_eps_W_batch, re_im
351 188 : TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set
352 : TYPE(cell_type), POINTER :: cell
353 : TYPE(cp_fm_type) :: fm_V_kp_work
354 188 : TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: mat_V_kp
355 188 : TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
356 188 : TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
357 :
358 188 : CALL timeset(routineN, handle)
359 :
360 188 : nkp_chi_eps_W_batch = bs_env%nkp_chi_eps_W_batch
361 :
362 188 : ikp_start = (ikp_batch - 1)*bs_env%nkp_chi_eps_W_batch + 1
363 188 : ikp_end = MIN(ikp_batch*bs_env%nkp_chi_eps_W_batch, bs_env%kpoints_chi_eps_W%nkp)
364 :
365 188 : NULLIFY (mat_V_kp)
366 2188 : ALLOCATE (mat_V_kp(ikp_start:ikp_end, 2))
367 :
368 564 : DO re_im = 1, 2
369 1624 : DO ikp = ikp_start, ikp_end
370 1060 : NULLIFY (mat_V_kp(ikp, re_im)%matrix)
371 1060 : ALLOCATE (mat_V_kp(ikp, re_im)%matrix)
372 1060 : CALL dbcsr_create(mat_V_kp(ikp, re_im)%matrix, template=bs_env%mat_RI_RI%matrix)
373 1060 : CALL dbcsr_reserve_all_blocks(mat_V_kp(ikp, re_im)%matrix)
374 1436 : CALL dbcsr_set(mat_V_kp(ikp, re_im)%matrix, 0.0_dp)
375 : END DO ! ikp
376 : END DO ! re_im
377 :
378 : CALL get_qs_env(qs_env=qs_env, &
379 : particle_set=particle_set, &
380 : cell=cell, &
381 : qs_kind_set=qs_kind_set, &
382 188 : atomic_kind_set=atomic_kind_set)
383 :
384 188 : IF (ikp_end <= bs_env%nkp_chi_eps_W_orig) THEN
385 :
386 : ! 1. 2c Coulomb integrals for the first "original" k-point grid
387 384 : bs_env%kpoints_chi_eps_W%nkp_grid = bs_env%nkp_grid_chi_eps_W_orig
388 :
389 92 : ELSE IF (ikp_start > bs_env%nkp_chi_eps_W_orig .AND. &
390 : ikp_end <= bs_env%nkp_chi_eps_W_orig_plus_extra) THEN
391 :
392 : ! 2. 2c Coulomb integrals for the second "extrapolation" k-point grid
393 368 : bs_env%kpoints_chi_eps_W%nkp_grid = bs_env%nkp_grid_chi_eps_W_extra
394 :
395 : ELSE
396 :
397 0 : CPABORT("Error with k-point parallelization.")
398 :
399 : END IF
400 :
401 : CALL build_2c_coulomb_matrix_kp(mat_V_kp, &
402 : bs_env%kpoints_chi_eps_W, &
403 : basis_type="RI_AUX", &
404 : cell=cell, &
405 : particle_set=particle_set, &
406 : qs_kind_set=qs_kind_set, &
407 : atomic_kind_set=atomic_kind_set, &
408 : size_lattice_sum=bs_env%size_lattice_sum_V, &
409 : operator_type=operator_coulomb, &
410 : ikp_start=ikp_start, &
411 188 : ikp_end=ikp_end)
412 :
413 752 : bs_env%kpoints_chi_eps_W%nkp_grid = bs_env%nkp_grid_chi_eps_W_orig
414 :
415 1094 : ALLOCATE (cfm_V_kp(ikp_start:ikp_end))
416 188 : CALL cp_fm_create(fm_V_kp_work, bs_env%fm_RI_RI%matrix_struct)
417 718 : DO ikp = ikp_start, ikp_end
418 530 : CALL cp_cfm_create(cfm_V_kp(ikp), bs_env%fm_RI_RI%matrix_struct)
419 530 : CALL cp_fm_set_all(fm_V_kp_work, 0.0_dp)
420 530 : CALL copy_dbcsr_to_fm(mat_V_kp(ikp, 1)%matrix, fm_V_kp_work)
421 89500 : cfm_V_kp(ikp)%local_data = CMPLX(fm_V_kp_work%local_data, 0.0_dp, KIND=dp)
422 :
423 530 : CALL cp_fm_set_all(fm_V_kp_work, 0.0_dp)
424 530 : CALL copy_dbcsr_to_fm(mat_V_kp(ikp, 2)%matrix, fm_V_kp_work)
425 : cfm_V_kp(ikp)%local_data = CMPLX(REAL(cfm_V_kp(ikp)%local_data, KIND=dp), &
426 89688 : fm_V_kp_work%local_data, KIND=dp)
427 : END DO
428 188 : CALL cp_fm_release(fm_V_kp_work)
429 188 : CALL dbcsr_deallocate_matrix_set(mat_V_kp)
430 :
431 188 : CALL timestop(handle)
432 :
433 376 : END SUBROUTINE compute_V_k_by_lattice_sum
434 :
435 : ! **************************************************************************************************
436 : !> \brief ...
437 : !> \param bs_env ...
438 : !> \param qs_env ...
439 : !> \param cfm_V_kp ...
440 : !> \param cfm_V_sqrt_ikp ...
441 : !> \param cfm_M_inv_V_sqrt_ikp ...
442 : !> \param ikp ...
443 : ! **************************************************************************************************
444 530 : SUBROUTINE compute_MinvVsqrt_Vsqrt(bs_env, qs_env, cfm_V_kp, cfm_V_sqrt_ikp, &
445 : cfm_M_inv_V_sqrt_ikp, ikp)
446 : TYPE(post_scf_bandstructure_type), POINTER :: bs_env
447 : TYPE(qs_environment_type), POINTER :: qs_env
448 : TYPE(cp_cfm_type), ALLOCATABLE, DIMENSION(:) :: cfm_V_kp
449 : TYPE(cp_cfm_type) :: cfm_V_sqrt_ikp, cfm_M_inv_V_sqrt_ikp
450 : INTEGER :: ikp
451 :
452 : CHARACTER(LEN=*), PARAMETER :: routineN = 'compute_MinvVsqrt_Vsqrt'
453 :
454 : INTEGER :: handle, info, n_RI
455 : TYPE(cp_cfm_type) :: cfm_M_inv_ikp, cfm_work
456 530 : TYPE(cp_cfm_type), ALLOCATABLE, DIMENSION(:) :: cfm_M_ikp
457 :
458 530 : CALL timeset(routineN, handle)
459 :
460 530 : n_RI = bs_env%n_RI
461 :
462 : ! get here M(k) and write it to cfm_M_ikp
463 : CALL RI_2c_integral_mat_kp(qs_env, cfm_M_ikp, cfm_V_kp(ikp)%matrix_struct, n_RI, bs_env%ri_metric, &
464 : bs_env%kpoints_chi_eps_W, regularization_RI=bs_env%regularization_RI, &
465 530 : ikp_ext=ikp, do_build_cell_index=(ikp == 1))
466 :
467 530 : IF (ikp == 1) THEN
468 82 : CALL cp_cfm_create(cfm_V_sqrt_ikp, cfm_V_kp(ikp)%matrix_struct)
469 82 : CALL cp_cfm_create(cfm_M_inv_V_sqrt_ikp, cfm_V_kp(ikp)%matrix_struct)
470 : END IF
471 530 : CALL cp_cfm_create(cfm_M_inv_ikp, cfm_V_kp(ikp)%matrix_struct)
472 :
473 530 : CALL cp_cfm_to_cfm(cfm_M_ikp(1), cfm_M_inv_ikp)
474 530 : CALL cp_cfm_to_cfm(cfm_V_kp(ikp), cfm_V_sqrt_ikp)
475 :
476 530 : CALL cp_cfm_release(cfm_M_ikp(1))
477 530 : DEALLOCATE (cfm_M_ikp)
478 :
479 530 : CALL cp_cfm_create(cfm_work, cfm_V_kp(ikp)%matrix_struct)
480 :
481 : ! M(k) -> M^-1(k)
482 530 : CALL cp_cfm_to_cfm(cfm_M_inv_ikp, cfm_work)
483 530 : CALL cp_cfm_cholesky_decompose(matrix=cfm_M_inv_ikp, n=n_RI, info_out=info)
484 530 : IF (info == 0) THEN
485 : ! successful Cholesky decomposition
486 530 : CALL cp_cfm_cholesky_invert(cfm_M_inv_ikp)
487 : ! symmetrize the result
488 530 : CALL cp_cfm_uplo_to_full(cfm_M_inv_ikp)
489 : ELSE
490 : ! Cholesky decomposition not successful: use expensive diagonalization
491 0 : CALL cp_cfm_power(cfm_work, threshold=bs_env%eps_eigval_mat_RI, exponent=-1.0_dp)
492 0 : CALL cp_cfm_to_cfm(cfm_work, cfm_M_inv_ikp)
493 : END IF
494 :
495 : ! V(k) -> L(k) with L^H(k)*L(k) = V(k) [L(k) can be just considered to be V^0.5(k)]
496 530 : CALL cp_cfm_to_cfm(cfm_V_sqrt_ikp, cfm_work)
497 530 : CALL cp_cfm_cholesky_decompose(matrix=cfm_V_sqrt_ikp, n=n_RI, info_out=info)
498 530 : IF (info == 0) THEN
499 : ! successful Cholesky decomposition
500 530 : CALL clean_lower_part(cfm_V_sqrt_ikp)
501 : ELSE
502 : ! Cholesky decomposition not successful: use expensive diagonalization
503 0 : CALL cp_cfm_power(cfm_work, threshold=0.0_dp, exponent=0.5_dp)
504 0 : CALL cp_cfm_to_cfm(cfm_work, cfm_V_sqrt_ikp)
505 : END IF
506 530 : CALL cp_cfm_release(cfm_work)
507 :
508 : ! get M^-1(k)*V^0.5(k)
509 : CALL parallel_gemm("N", "C", n_RI, n_RI, n_RI, z_one, cfm_M_inv_ikp, cfm_V_sqrt_ikp, &
510 530 : z_zero, cfm_M_inv_V_sqrt_ikp)
511 :
512 530 : CALL cp_cfm_release(cfm_M_inv_ikp)
513 :
514 530 : CALL timestop(handle)
515 :
516 1060 : END SUBROUTINE compute_MinvVsqrt_Vsqrt
517 :
518 : ! **************************************************************************************************
519 : !> \brief Compute the screened interaction for one frequency and k-point.
520 : !> \param bs_env band-structure environment
521 : !> \param cfm_chi_eps_W_ikp_freq_j input chi; overwritten by W
522 : !> \param cfm_V_sqrt_ikp square root of the Coulomb matrix
523 : !> \param cfm_M_inv_V_sqrt_ikp metric-weighted Coulomb factor
524 : ! **************************************************************************************************
525 6692 : SUBROUTINE compute_cfm_W_ikp_freq_j(bs_env, cfm_chi_eps_W_ikp_freq_j, cfm_V_sqrt_ikp, &
526 : cfm_M_inv_V_sqrt_ikp)
527 : TYPE(post_scf_bandstructure_type), POINTER :: bs_env
528 : TYPE(cp_cfm_type), INTENT(INOUT) :: cfm_chi_eps_W_ikp_freq_j
529 : TYPE(cp_cfm_type), INTENT(IN) :: cfm_V_sqrt_ikp, cfm_M_inv_V_sqrt_ikp
530 :
531 : CHARACTER(LEN=*), PARAMETER :: routineN = 'compute_cfm_W_ikp_freq_j'
532 :
533 : INTEGER :: handle, info
534 :
535 3346 : CALL timeset(routineN, handle)
536 :
537 : ! 1. epsilon(iw,k) = Id - V^0.5(k)*M^-1(k)*chi(iw,k)*M^-1(k)*V^0.5(k)
538 :
539 : ! 1. a) Form V^0.5(k)*M^-1(k)*chi(iw,k)*M^-1(k)*V^0.5(k).
540 3346 : CALL cfm_contract_ABA(cfm_M_inv_V_sqrt_ikp, cfm_chi_eps_W_ikp_freq_j)
541 :
542 : ! 1. b) Add the identity matrix.
543 3346 : CALL cp_cfm_add_on_diag(cfm_chi_eps_W_ikp_freq_j, z_one)
544 :
545 : ! 2. W(iw,k) = V^0.5(k)*(epsilon^-1(iw,k)-Id)*V^0.5(k)
546 :
547 : ! 2. a) Cholesky-factorize epsilon before inversion.
548 3346 : CALL cp_cfm_cholesky_decompose(matrix=cfm_chi_eps_W_ikp_freq_j, n=bs_env%n_RI, info_out=info)
549 3346 : CPASSERT(info == 0)
550 :
551 : ! 2. b) Invert epsilon, subtract Id, then contract with V^0.5 on both sides.
552 3346 : CALL cfm_screened_interaction_from_eps_cholesky(cfm_chi_eps_W_ikp_freq_j, cfm_V_sqrt_ikp)
553 :
554 3346 : CALL timestop(handle)
555 :
556 3346 : END SUBROUTINE compute_cfm_W_ikp_freq_j
557 :
558 : ! **************************************************************************************************
559 : !> \brief ...
560 : !> \param bs_env ...
561 : !> \param mat_chi_Gamma_tau ...
562 : !> \param fm_W_MIC_time ...
563 : ! **************************************************************************************************
564 0 : SUBROUTINE read_W_MIC_time(bs_env, mat_chi_Gamma_tau, fm_W_MIC_time)
565 : TYPE(post_scf_bandstructure_type), POINTER :: bs_env
566 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: mat_chi_Gamma_tau
567 : TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:) :: fm_W_MIC_time
568 :
569 : CHARACTER(LEN=*), PARAMETER :: routineN = 'read_W_MIC_time'
570 :
571 : INTEGER :: handle, i_t
572 : REAL(KIND=dp) :: t1
573 :
574 0 : CALL timeset(routineN, handle)
575 :
576 0 : CALL dbcsr_deallocate_matrix_set(mat_chi_Gamma_tau)
577 0 : CALL create_fm_W_MIC_time(bs_env, fm_W_MIC_time)
578 :
579 0 : DO i_t = 1, bs_env%num_time_freq_points
580 :
581 0 : t1 = m_walltime()
582 :
583 0 : CALL fm_read(fm_W_MIC_time(i_t), bs_env, bs_env%W_time_name, i_t)
584 :
585 0 : IF (bs_env%unit_nr > 0) THEN
586 : WRITE (bs_env%unit_nr, '(T2,A,I5,A,I3,A,F10.1,A)') &
587 0 : 'Read W^MIC(iτ) from file for time point ', i_t, ' /', bs_env%num_time_freq_points, &
588 0 : ', Execution time', m_walltime() - t1, ' s'
589 : END IF
590 :
591 : END DO
592 :
593 0 : IF (bs_env%unit_nr > 0) WRITE (bs_env%unit_nr, '(A)') ' '
594 :
595 : ! W^MIC(iω=0) for the post-GW consumers, built here because fm_W_MIC_time does not outlive
596 : ! the W stage: RT-BSE reads its own restart file, PROPERTIES%BSE sums the W(iτ) just read.
597 0 : IF (bs_env%rtp_method == rtp_method_bse .OR. &
598 : bs_env%rtp_method == rtp_method_bse_linearized) THEN
599 0 : CALL cp_fm_create(bs_env%fm_W_MIC_freq_zero, bs_env%fm_W_MIC_freq%matrix_struct)
600 0 : t1 = m_walltime()
601 0 : CALL fm_read(bs_env%fm_W_MIC_freq_zero, bs_env, "W_freq_rtp", 0)
602 0 : IF (bs_env%unit_nr > 0) THEN
603 : WRITE (bs_env%unit_nr, '(T2,A,I3,A,I3,A,F10.1,A)') &
604 0 : 'Read W^MIC(f=0) from file for freq. point ', 1, ' /', 1, &
605 0 : ', Execution time', m_walltime() - t1, ' s'
606 : END IF
607 0 : ELSE IF (bs_env%keep_W_freq_zero) THEN
608 : ! no RTP file in a LRBSE-only run: W(iτ) was just read from the W_time files
609 0 : CALL sum_W_MIC_freq_zero(bs_env, fm_W_MIC_time)
610 : END IF
611 :
612 0 : CALL timestop(handle)
613 :
614 0 : END SUBROUTINE read_W_MIC_time
615 :
616 : ! **************************************************************************************************
617 : !> \brief ...
618 : !> \param bs_env ...
619 : !> \param qs_env ...
620 : !> \param fm_W_MIC_freq_j ...
621 : !> \param j_w ...
622 : !> \param ikp ...
623 : !> \param mat_chi_Gamma_tau ...
624 : !> \param cfm_M_inv_V_sqrt_ikp ...
625 : !> \param cfm_V_sqrt_ikp ...
626 : ! **************************************************************************************************
627 3140 : SUBROUTINE compute_fm_W_MIC_freq_j(bs_env, qs_env, fm_W_MIC_freq_j, j_w, ikp, mat_chi_Gamma_tau, &
628 : cfm_M_inv_V_sqrt_ikp, cfm_V_sqrt_ikp)
629 : TYPE(post_scf_bandstructure_type), POINTER :: bs_env
630 : TYPE(qs_environment_type), POINTER :: qs_env
631 : TYPE(cp_fm_type) :: fm_W_MIC_freq_j
632 : INTEGER :: j_w, ikp
633 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: mat_chi_Gamma_tau
634 : TYPE(cp_cfm_type) :: cfm_M_inv_V_sqrt_ikp, cfm_V_sqrt_ikp
635 :
636 : CHARACTER(LEN=*), PARAMETER :: routineN = 'compute_fm_W_MIC_freq_j'
637 :
638 : INTEGER :: handle
639 :
640 3140 : CALL timeset(routineN, handle)
641 :
642 : ! 1. Fourier transformation of χ_PQ(iτ,k=0) to χ_PQ(iω_j,k=0)
643 3140 : CALL compute_fm_chi_Gamma_freq(bs_env, bs_env%fm_chi_Gamma_freq, j_w, mat_chi_Gamma_tau)
644 :
645 : ! 2. χ_PQ(iω_j,k=0) -> W_PQ^MIC(iω_j)
646 : CALL compute_fm_W_MIC_freq_j_from_chi(bs_env, qs_env, fm_W_MIC_freq_j, j_w, ikp, &
647 3140 : cfm_M_inv_V_sqrt_ikp, cfm_V_sqrt_ikp)
648 :
649 3140 : CALL timestop(handle)
650 :
651 3140 : END SUBROUTINE compute_fm_W_MIC_freq_j
652 :
653 : ! **************************************************************************************************
654 : !> \brief W_PQ^MIC(iω_j) from χ_PQ(iω_j,k=0) in bs_env%fm_chi_Gamma_freq
655 : !> \param bs_env ...
656 : !> \param qs_env ...
657 : !> \param fm_W_MIC_freq_j ...
658 : !> \param j_w ...
659 : !> \param ikp ...
660 : !> \param cfm_M_inv_V_sqrt_ikp ...
661 : !> \param cfm_V_sqrt_ikp ...
662 : ! **************************************************************************************************
663 3346 : SUBROUTINE compute_fm_W_MIC_freq_j_from_chi(bs_env, qs_env, fm_W_MIC_freq_j, j_w, ikp, &
664 : cfm_M_inv_V_sqrt_ikp, cfm_V_sqrt_ikp)
665 : TYPE(post_scf_bandstructure_type), POINTER :: bs_env
666 : TYPE(qs_environment_type), POINTER :: qs_env
667 : TYPE(cp_fm_type) :: fm_W_MIC_freq_j
668 : INTEGER :: j_w, ikp
669 : TYPE(cp_cfm_type) :: cfm_M_inv_V_sqrt_ikp, cfm_V_sqrt_ikp
670 :
671 : CHARACTER(LEN=*), PARAMETER :: routineN = 'compute_fm_W_MIC_freq_j_from_chi'
672 :
673 : INTEGER :: handle
674 : TYPE(cp_cfm_type) :: cfm_chi_eps_W_ikp_freq_j
675 :
676 3346 : CALL timeset(routineN, handle)
677 :
678 3346 : CALL cp_fm_set_all(fm_W_MIC_freq_j, 0.0_dp)
679 :
680 : ! 1. Get χ_PQ(iω_j,k_i) from χ_PQ(iω_j,k=0) using the minimum image convention
681 : CALL cfm_ikp_from_fm_Gamma(cfm_chi_eps_W_ikp_freq_j, bs_env%fm_chi_Gamma_freq, &
682 3346 : ikp, qs_env, bs_env%kpoints_chi_eps_W, "RI_AUX")
683 :
684 : ! 2. Remove all negative eigenvalues from χ_PQ(iω_j,k_i)
685 3346 : CALL cp_cfm_power(cfm_chi_eps_W_ikp_freq_j, threshold=0.0_dp, exponent=1.0_dp)
686 :
687 : ! 3. ε(iω_j,k_i) = Id - V^0.5(k_i)*M^-1(k_i)*χ(iω_j,k_i)*M^-1(k_i)*V^0.5(k_i)
688 : CALL compute_cfm_W_ikp_freq_j(bs_env, cfm_chi_eps_W_ikp_freq_j, cfm_V_sqrt_ikp, &
689 3346 : cfm_M_inv_V_sqrt_ikp)
690 :
691 : ! 4. k-point integration W_PQ(iω_j, k_i) to W_PQ^MIC(iω_j)
692 3346 : SELECT CASE (bs_env%approx_kp_extrapol)
693 : CASE (.FALSE.)
694 : ! default: standard k-point extrapolation
695 : CALL MIC_contribution_from_ikp(bs_env, qs_env, fm_W_MIC_freq_j, &
696 : cfm_chi_eps_W_ikp_freq_j, ikp, &
697 3346 : bs_env%kpoints_chi_eps_W, "RI_AUX")
698 : CASE (.TRUE.)
699 : ! for approximate kpoint extrapolation: get W_PQ^MIC(iω_1) with and without k-point
700 : ! extrapolation to compute the extrapolation factor f_PQ for every PQ-matrix element,
701 : ! f_PQ = (W_PQ^MIC(iω_1) with extrapolation) / (W_PQ^MIC(iω_1) without extrapolation)
702 :
703 : ! for ω_1, we compute the k-point extrapolated result using all k-points
704 196 : IF (j_w == 1) THEN
705 :
706 : ! k-point extrapolated
707 : CALL MIC_contribution_from_ikp(bs_env, qs_env, bs_env%fm_W_MIC_freq_1_extra, &
708 : cfm_chi_eps_W_ikp_freq_j, ikp, &
709 : bs_env%kpoints_chi_eps_W, &
710 52 : "RI_AUX")
711 : ! non-kpoint extrapolated
712 52 : IF (ikp <= bs_env%nkp_chi_eps_W_orig) THEN
713 : CALL MIC_contribution_from_ikp(bs_env, qs_env, bs_env%fm_W_MIC_freq_1_no_extra, &
714 : cfm_chi_eps_W_ikp_freq_j, ikp, &
715 : bs_env%kpoints_chi_eps_W, &
716 16 : "RI_AUX", wkp_ext=bs_env%wkp_orig)
717 : END IF
718 :
719 : END IF
720 :
721 : ! for all ω_j, we need to compute W^MIC without k-point extrpolation
722 196 : IF (ikp <= bs_env%nkp_chi_eps_W_orig) THEN
723 : CALL MIC_contribution_from_ikp(bs_env, qs_env, fm_W_MIC_freq_j, &
724 : cfm_chi_eps_W_ikp_freq_j, &
725 : ikp, bs_env%kpoints_chi_eps_W, "RI_AUX", &
726 160 : wkp_ext=bs_env%wkp_orig)
727 : END IF
728 : END SELECT
729 :
730 3346 : CALL cp_cfm_release(cfm_chi_eps_W_ikp_freq_j)
731 :
732 3346 : CALL timestop(handle)
733 :
734 3346 : END SUBROUTINE compute_fm_W_MIC_freq_j_from_chi
735 :
736 : ! **************************************************************************************************
737 : !> \brief ...
738 : !> \param cfm_mat ...
739 : ! **************************************************************************************************
740 1060 : SUBROUTINE clean_lower_part(cfm_mat)
741 : TYPE(cp_cfm_type) :: cfm_mat
742 :
743 : CHARACTER(LEN=*), PARAMETER :: routineN = 'clean_lower_part'
744 :
745 : INTEGER :: handle, i_row, j_col, j_global, &
746 : ncol_local, nrow_local
747 530 : INTEGER, DIMENSION(:), POINTER :: col_indices, row_indices
748 :
749 530 : CALL timeset(routineN, handle)
750 :
751 : CALL cp_cfm_get_info(matrix=cfm_mat, &
752 : nrow_local=nrow_local, ncol_local=ncol_local, &
753 530 : row_indices=row_indices, col_indices=col_indices)
754 :
755 6646 : DO j_col = 1, ncol_local
756 6116 : j_global = col_indices(j_col)
757 89500 : DO i_row = 1, nrow_local
758 88970 : IF (j_global < row_indices(i_row)) cfm_mat%local_data(i_row, j_col) = z_zero
759 : END DO
760 : END DO
761 :
762 530 : CALL timestop(handle)
763 :
764 530 : END SUBROUTINE clean_lower_part
765 :
766 : ! **************************************************************************************************
767 : !> \brief ...
768 : !> \param bs_env ...
769 : !> \param fm_W_MIC_time ...
770 : ! **************************************************************************************************
771 4 : SUBROUTINE apply_extrapol_factor(bs_env, fm_W_MIC_time)
772 : TYPE(post_scf_bandstructure_type), POINTER :: bs_env
773 : TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:) :: fm_W_MIC_time
774 :
775 : CHARACTER(LEN=*), PARAMETER :: routineN = 'apply_extrapol_factor'
776 : REAL(KIND=dp), PARAMETER :: eps_W_no_extra_1 = 1.0E-13_dp
777 :
778 : INTEGER :: handle, i, i_t, j, ncol_local, nrow_local
779 : REAL(KIND=dp) :: extrapol_factor, W_extra_1, W_no_extra_1
780 :
781 2 : CALL timeset(routineN, handle)
782 :
783 2 : CALL cp_fm_get_info(matrix=fm_W_MIC_time(1), nrow_local=nrow_local, ncol_local=ncol_local)
784 :
785 22 : DO i_t = 1, SIZE(fm_W_MIC_time)
786 122 : DO j = 1, ncol_local
787 370 : DO i = 1, nrow_local
788 :
789 250 : W_extra_1 = bs_env%fm_W_MIC_freq_1_extra%local_data(i, j)
790 250 : W_no_extra_1 = bs_env%fm_W_MIC_freq_1_no_extra%local_data(i, j)
791 :
792 250 : IF (ABS(W_no_extra_1) > eps_W_no_extra_1) THEN
793 190 : extrapol_factor = ABS(W_extra_1/W_no_extra_1)
794 : ELSE
795 : extrapol_factor = 1.0_dp
796 : END IF
797 :
798 : ! reset extrapolation factor if it is very large
799 190 : IF (extrapol_factor > 10.0_dp) extrapol_factor = 1.0_dp
800 :
801 : fm_W_MIC_time(i_t)%local_data(i, j) = fm_W_MIC_time(i_t)%local_data(i, j) &
802 350 : *extrapol_factor
803 : END DO
804 : END DO
805 : END DO
806 :
807 2 : CALL timestop(handle)
808 :
809 2 : END SUBROUTINE apply_extrapol_factor
810 :
811 : ! **************************************************************************************************
812 : !> \brief Computes V, its factor B with V = B^T B, and A = M^-1 B^T.
813 : !> The Coulomb matrix V is constructed by the RI-RS k-point path. The inverse metric
814 : !> M^-1(k=0) is precomputed once in gw_utils and stored in bs_env.
815 : !> \param bs_env ...
816 : !> \param qs_env ...
817 : !> \param fm_V Coulomb matrix V(k=0)
818 : !> \param fm_coulomb_factor upper Cholesky factor B, or symmetric square root if Cholesky fails
819 : !> \param fm_Minv_coulomb_factor product A = M^-1(k=0) B^T
820 : ! **************************************************************************************************
821 40 : SUBROUTINE compute_coulomb_factors(bs_env, qs_env, fm_V, fm_coulomb_factor, fm_Minv_coulomb_factor)
822 : TYPE(post_scf_bandstructure_type), POINTER :: bs_env
823 : TYPE(qs_environment_type), POINTER :: qs_env
824 : TYPE(cp_fm_type), INTENT(INOUT) :: fm_V, fm_coulomb_factor, &
825 : fm_Minv_coulomb_factor
826 :
827 : CHARACTER(LEN=*), PARAMETER :: routineN = 'compute_coulomb_factors'
828 :
829 : INTEGER :: handle
830 40 : TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set
831 : TYPE(cell_type), POINTER :: cell
832 40 : TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: mat_V_kp
833 40 : TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
834 40 : TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
835 :
836 40 : CALL timeset(routineN, handle)
837 :
838 40 : IF (bs_env%auto_ri%enabled) THEN
839 : ! -------------------------------------------------------------------
840 : ! 1a. The optimized AB functions span two atoms, so their previously transformed
841 : ! Coulomb matrix cannot be rebuilt by the atom-local k-point integral routine.
842 : ! -------------------------------------------------------------------
843 4 : CALL cp_fm_to_fm(bs_env%auto_ri%V_pq, fm_V)
844 : ELSE
845 : ! -------------------------------------------------------------------
846 : ! 1b. Build Coulomb Matrix V(k=0) using the kp-routine but only for ikp=1.
847 : ! -------------------------------------------------------------------
848 : CALL get_qs_env(qs_env=qs_env, particle_set=particle_set, cell=cell, &
849 36 : qs_kind_set=qs_kind_set)
850 36 : atomic_kind_set => bs_env%ri_rs%atomic_kind_set
851 :
852 180 : ALLOCATE (mat_V_kp(1:1, 1:2))
853 36 : NULLIFY (mat_V_kp(1, 1)%matrix, mat_V_kp(1, 2)%matrix)
854 36 : ALLOCATE (mat_V_kp(1, 1)%matrix, mat_V_kp(1, 2)%matrix)
855 36 : CALL dbcsr_create(mat_V_kp(1, 1)%matrix, template=bs_env%mat_RI_RI%matrix)
856 36 : CALL dbcsr_reserve_all_blocks(mat_V_kp(1, 1)%matrix)
857 36 : CALL dbcsr_set(mat_V_kp(1, 1)%matrix, 0.0_dp)
858 36 : CALL dbcsr_create(mat_V_kp(1, 2)%matrix, template=bs_env%mat_RI_RI%matrix)
859 36 : CALL dbcsr_reserve_all_blocks(mat_V_kp(1, 2)%matrix)
860 : ! The dummy imaginary part is required only by the k-point routine interface.
861 36 : CALL dbcsr_set(mat_V_kp(1, 2)%matrix, 0.0_dp)
862 :
863 144 : bs_env%kpoints_chi_eps_W%nkp_grid = bs_env%nkp_grid_chi_eps_W_orig
864 : CALL build_2c_coulomb_matrix_kp(mat_V_kp, bs_env%kpoints_chi_eps_W, "RI_AUX", cell, &
865 : particle_set, qs_kind_set, atomic_kind_set, &
866 36 : bs_env%size_lattice_sum_V, operator_coulomb, 1, 1)
867 36 : CALL copy_dbcsr_to_fm(mat_V_kp(1, 1)%matrix, fm_V)
868 :
869 36 : CALL dbcsr_deallocate_matrix(mat_V_kp(1, 1)%matrix)
870 36 : CALL dbcsr_deallocate_matrix(mat_V_kp(1, 2)%matrix)
871 36 : DEALLOCATE (mat_V_kp)
872 : END IF
873 :
874 : ! -----------------------------------------------------------------------
875 : ! 2. V -> B, with V = B^T B.
876 : ! -----------------------------------------------------------------------
877 40 : CALL fm_sqrt(fm_V, fm_coulomb_factor, bs_env%eps_eigval_mat_RI, bs_env%unit_nr)
878 :
879 : ! -----------------------------------------------------------------------
880 : ! 3. A = M^-1(k=0) B^T.
881 : ! -----------------------------------------------------------------------
882 : CALL parallel_gemm("N", "T", bs_env%n_RI, bs_env%n_RI, bs_env%n_RI, 1.0_dp, &
883 40 : bs_env%fm_Minv_Gamma, fm_coulomb_factor, 0.0_dp, fm_Minv_coulomb_factor)
884 :
885 40 : CALL timestop(handle)
886 :
887 40 : END SUBROUTINE compute_coulomb_factors
888 :
889 : ! **************************************************************************************************
890 : !> \brief Computes the metric-dressed screened interaction at one imaginary frequency.
891 : !> With V = B^T B and A = M^-1 B^T, form ε = Id + A^T χ A.
892 : !> For ε = U^T U, solve Z U = A, then W = Z Z^T - A A^T.
893 : !> If Cholesky fails, use the same eigenvalue cutoff as the inverse path:
894 : !> Z = A ε^(-1/2), with discarded eigenmodes set to zero.
895 : !> \param bs_env ...
896 : !> \param fm_chi_freq_j ...
897 : !> \param fm_Minv_V_Minv full symmetric matrix M^-1 V M^-1 = A A^T
898 : !> \param fm_Minv_coulomb_factor RI metric and Coulomb factor A = M^-1 B^T
899 : !> \param fm_W_freq_j full symmetric metric-dressed correlation interaction W
900 : ! **************************************************************************************************
901 2200 : SUBROUTINE compute_fm_W_freq(bs_env, fm_chi_freq_j, fm_Minv_V_Minv, fm_Minv_coulomb_factor, fm_W_freq_j)
902 : TYPE(post_scf_bandstructure_type), POINTER :: bs_env
903 : TYPE(cp_fm_type), INTENT(IN) :: fm_chi_freq_j, fm_Minv_V_Minv, &
904 : fm_Minv_coulomb_factor
905 : TYPE(cp_fm_type), INTENT(INOUT) :: fm_W_freq_j
906 :
907 : CHARACTER(LEN=*), PARAMETER :: routineN = 'compute_fm_W_freq'
908 :
909 : INTEGER :: handle, info, n_dependent, n_RI
910 : TYPE(cp_fm_type) :: fm_eps_freq_j, fm_work
911 :
912 550 : CALL timeset(routineN, handle)
913 :
914 550 : n_RI = bs_env%n_RI
915 :
916 550 : CALL cp_fm_create(fm_eps_freq_j, fm_chi_freq_j%matrix_struct)
917 550 : CALL cp_fm_create(fm_work, fm_chi_freq_j%matrix_struct)
918 :
919 : ! -----------------------------------------------------------------------
920 : ! 1. ε(iω_j) = Id + A^T χ(iω_j) A, where A = M^-1 B^T and V = B^T B.
921 : ! -----------------------------------------------------------------------
922 : ! work = χ(iω_j) A
923 : CALL parallel_gemm('N', 'N', n_RI, n_RI, n_RI, 1.0_dp, &
924 550 : fm_chi_freq_j, fm_Minv_coulomb_factor, 0.0_dp, fm_work)
925 :
926 : ! eps_work = A^T work
927 : CALL parallel_gemm('T', 'N', n_RI, n_RI, n_RI, 1.0_dp, &
928 550 : fm_Minv_coulomb_factor, fm_work, 0.0_dp, fm_eps_freq_j)
929 :
930 : ! Add the identity without changing the sign convention of χ.
931 550 : CALL cp_fm_add_on_diag(fm_eps_freq_j, 1.0_dp)
932 :
933 : ! Force perfect symmetry before Cholesky to avoid info != 0 due to GEMM noise
934 550 : CALL cp_fm_uplo_to_full(fm_eps_freq_j, fm_work)
935 :
936 : ! -----------------------------------------------------------------------
937 : ! 2. W(iω_j) = A (ε^-1(iω_j) - Id) A^T = Z Z^T - A A^T.
938 : ! -----------------------------------------------------------------------
939 :
940 : ! Preserve ε because a failed Cholesky decomposition overwrites it.
941 550 : CALL cp_fm_to_fm(fm_eps_freq_j, fm_work)
942 550 : CALL cp_fm_cholesky_decompose(fm_eps_freq_j, info_out=info)
943 550 : IF (info == 0) THEN
944 : ! Z = A U^-1, so Z Z^T = A ε^-1 A^T. No explicit inverse is needed.
945 550 : CALL cp_fm_to_fm(fm_Minv_coulomb_factor, fm_work)
946 550 : CALL cp_fm_triangular_multiply(fm_eps_freq_j, fm_work, side='R', invert_tr=.TRUE.)
947 : ELSE
948 0 : CALL cp_fm_to_fm(fm_work, fm_eps_freq_j)
949 0 : CALL cp_fm_power(fm_eps_freq_j, fm_work, -0.5_dp, bs_env%eps_eigval_mat_RI, n_dependent)
950 : CALL parallel_gemm('N', 'N', n_RI, n_RI, n_RI, 1.0_dp, &
951 0 : fm_Minv_coulomb_factor, fm_eps_freq_j, 0.0_dp, fm_work)
952 0 : IF (bs_env%unit_nr > 0) THEN
953 : WRITE (bs_env%unit_nr, '(T2,A)') &
954 0 : 'Cholesky decomposition failed; screening computed by diagonalization.'
955 0 : WRITE (bs_env%unit_nr, '(T2,A,T72,I9)') 'Discarded eigenmodes:', n_dependent
956 : END IF
957 : END IF
958 :
959 550 : CALL cp_fm_to_fm(fm_Minv_V_Minv, fm_W_freq_j)
960 550 : CALL cp_fm_syrk('U', 'N', n_RI, 1.0_dp, fm_work, 1, 1, -1.0_dp, fm_W_freq_j)
961 550 : CALL cp_fm_uplo_to_full(fm_W_freq_j, fm_work)
962 :
963 : ! Cleanup
964 550 : CALL cp_fm_release(fm_work)
965 550 : CALL cp_fm_release(fm_eps_freq_j)
966 :
967 550 : CALL timestop(handle)
968 :
969 550 : END SUBROUTINE compute_fm_W_freq
970 :
971 : ! **************************************************************************************************
972 : !> \brief ...
973 : !> \param fm ...
974 : !> \param bs_env ...
975 : !> \param mat_name ...
976 : !> \param idx ...
977 : ! **************************************************************************************************
978 248 : SUBROUTINE fm_read(fm, bs_env, mat_name, idx)
979 : TYPE(cp_fm_type) :: fm
980 : TYPE(post_scf_bandstructure_type), POINTER :: bs_env
981 : CHARACTER(LEN=*) :: mat_name
982 : INTEGER :: idx
983 :
984 : CHARACTER(LEN=*), PARAMETER :: routineN = 'fm_read'
985 :
986 : CHARACTER(LEN=default_path_length) :: f_chi
987 : INTEGER :: handle, unit_nr
988 :
989 248 : CALL timeset(routineN, handle)
990 :
991 248 : unit_nr = -1
992 248 : IF (bs_env%para_env%is_source()) THEN
993 :
994 124 : IF (idx < 10) THEN
995 58 : WRITE (f_chi, '(3A,I1,A)') TRIM(bs_env%prefix), TRIM(mat_name), "_0", idx, ".matrix"
996 66 : ELSE IF (idx < 100) THEN
997 66 : WRITE (f_chi, '(3A,I2,A)') TRIM(bs_env%prefix), TRIM(mat_name), "_", idx, ".matrix"
998 : ELSE
999 0 : CPABORT('Please implement more than 99 time/frequency points.')
1000 : END IF
1001 :
1002 : CALL open_file(file_name=TRIM(f_chi), file_action="READ", file_form="UNFORMATTED", &
1003 124 : file_position="REWIND", file_status="OLD", unit_number=unit_nr)
1004 :
1005 : END IF
1006 :
1007 248 : CALL cp_fm_read_unformatted(fm, unit_nr)
1008 :
1009 248 : IF (bs_env%para_env%is_source()) CALL close_file(unit_number=unit_nr)
1010 :
1011 248 : CALL timestop(handle)
1012 :
1013 248 : END SUBROUTINE fm_read
1014 :
1015 : ! **************************************************************************************************
1016 : !> \brief Write a GW restart matrix when requested by the print key.
1017 : !> \param fm Matrix to write, or reusable conversion buffer when matrix is supplied.
1018 : !> \param matrix_index ...
1019 : !> \param matrix_name ...
1020 : !> \param qs_env ...
1021 : !> \param matrix Optional DBCSR source, converted to fm only when output is enabled.
1022 : ! **************************************************************************************************
1023 5834 : SUBROUTINE fm_write(fm, matrix_index, matrix_name, qs_env, matrix)
1024 : TYPE(cp_fm_type) :: fm
1025 : INTEGER :: matrix_index
1026 : CHARACTER(LEN=*) :: matrix_name
1027 : TYPE(qs_environment_type), POINTER :: qs_env
1028 : TYPE(dbcsr_type), INTENT(IN), OPTIONAL :: matrix
1029 :
1030 : CHARACTER(LEN=*), PARAMETER :: key = 'PROPERTIES%BANDSTRUCTURE%GW%PRINT%RESTART', &
1031 : routineN = 'fm_write'
1032 :
1033 : CHARACTER(LEN=default_path_length) :: filename
1034 : INTEGER :: handle, unit_nr
1035 : TYPE(cp_logger_type), POINTER :: logger
1036 : TYPE(section_vals_type), POINTER :: input
1037 :
1038 5834 : CALL timeset(routineN, handle)
1039 :
1040 5834 : CALL get_qs_env(qs_env, input=input)
1041 :
1042 5834 : logger => cp_get_default_logger()
1043 :
1044 5834 : IF (BTEST(cp_print_key_should_output(logger%iter_info, input, key), cp_p_file)) THEN
1045 :
1046 1148 : IF (PRESENT(matrix)) THEN
1047 814 : CALL cp_fm_set_all(fm, 0.0_dp)
1048 814 : CALL copy_dbcsr_to_fm(matrix, fm)
1049 : END IF
1050 :
1051 1148 : IF (matrix_index < 10) THEN
1052 568 : WRITE (filename, '(3A,I1)') "RESTART_", matrix_name, "_0", matrix_index
1053 580 : ELSE IF (matrix_index < 100) THEN
1054 580 : WRITE (filename, '(3A,I2)') "RESTART_", matrix_name, "_", matrix_index
1055 : ELSE
1056 0 : CPABORT('Please implement more than 99 time/frequency points.')
1057 : END IF
1058 :
1059 : unit_nr = cp_print_key_unit_nr(logger, input, key, extension=".matrix", &
1060 : file_form="UNFORMATTED", middle_name=TRIM(filename), &
1061 1148 : file_position="REWIND", file_action="WRITE")
1062 :
1063 1148 : CALL cp_fm_write_unformatted(fm, unit_nr)
1064 1148 : IF (unit_nr > 0) THEN
1065 574 : CALL close_file(unit_nr)
1066 : END IF
1067 : END IF
1068 :
1069 5834 : CALL timestop(handle)
1070 :
1071 5834 : END SUBROUTINE fm_write
1072 :
1073 : ! **************************************************************************************************
1074 : !> \brief ...
1075 : !> \param bs_env ...
1076 : !> \param fm_chi_Gamma_freq ...
1077 : !> \param j_w ...
1078 : !> \param mat_chi_Gamma_tau ...
1079 : ! **************************************************************************************************
1080 3690 : SUBROUTINE compute_fm_chi_Gamma_freq(bs_env, fm_chi_Gamma_freq, j_w, mat_chi_Gamma_tau)
1081 : TYPE(post_scf_bandstructure_type), POINTER :: bs_env
1082 : TYPE(cp_fm_type) :: fm_chi_Gamma_freq
1083 : INTEGER :: j_w
1084 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: mat_chi_Gamma_tau
1085 :
1086 : CHARACTER(LEN=*), PARAMETER :: routineN = 'compute_fm_chi_Gamma_freq'
1087 :
1088 : INTEGER :: handle, i_t
1089 : REAL(KIND=dp) :: weight_ij
1090 :
1091 3690 : CALL timeset(routineN, handle)
1092 :
1093 3690 : CALL dbcsr_set(bs_env%mat_RI_RI%matrix, 0.0_dp)
1094 :
1095 53844 : DO i_t = 1, bs_env%num_time_freq_points
1096 :
1097 50154 : weight_ij = bs_env%time_frequency_grid%cosine_time_to_frequency(j_w, i_t)
1098 :
1099 : ! Fourier transform
1100 : CALL dbcsr_add(bs_env%mat_RI_RI%matrix, mat_chi_Gamma_tau(i_t)%matrix, &
1101 53844 : 1.0_dp, weight_ij)
1102 :
1103 : END DO
1104 :
1105 3690 : CALL copy_dbcsr_to_fm(bs_env%mat_RI_RI%matrix, fm_chi_Gamma_freq)
1106 :
1107 3690 : CALL timestop(handle)
1108 :
1109 3690 : END SUBROUTINE compute_fm_chi_Gamma_freq
1110 :
1111 : ! **************************************************************************************************
1112 : !> \brief W^MIC_PQ(iω=0) = sum_j w_j W^MIC_PQ(iτ_j) with the time weights w_j of the grid at zero
1113 : !> frequency, into bs_env%fm_W_MIC_freq_zero
1114 : !> \param bs_env time grid and its weights; receives fm_W_MIC_freq_zero
1115 : !> \param fm_W_MIC_time W^MIC_PQ(iτ_j) for every time point j
1116 : ! **************************************************************************************************
1117 64 : SUBROUTINE sum_W_MIC_freq_zero(bs_env, fm_W_MIC_time)
1118 : TYPE(post_scf_bandstructure_type), POINTER :: bs_env
1119 : TYPE(cp_fm_type), DIMENSION(:) :: fm_W_MIC_time
1120 :
1121 : CHARACTER(LEN=*), PARAMETER :: routineN = 'sum_W_MIC_freq_zero'
1122 :
1123 : INTEGER :: handle, i_t
1124 : REAL(KIND=dp) :: t_start
1125 :
1126 64 : CALL timeset(routineN, handle)
1127 :
1128 64 : t_start = m_walltime()
1129 64 : CALL cp_fm_create(bs_env%fm_W_MIC_freq_zero, bs_env%fm_W_MIC_freq%matrix_struct)
1130 64 : CALL cp_fm_set_all(bs_env%fm_W_MIC_freq_zero, 0.0_dp)
1131 1344 : DO i_t = 1, bs_env%num_time_freq_points
1132 : CALL cp_fm_scale_and_add(1.0_dp, bs_env%fm_W_MIC_freq_zero, &
1133 : bs_env%time_frequency_grid%time_weights_at_zero_frequency(i_t), &
1134 1344 : fm_W_MIC_time(i_t))
1135 : END DO
1136 64 : IF (bs_env%unit_nr > 0) THEN
1137 : WRITE (bs_env%unit_nr, '(T2,A,I11,A,I3,A,F10.1,A)') &
1138 32 : 'Computed W(ω=0,k) for k-point batch', &
1139 32 : 1, ' /', 1, &
1140 64 : ', Execution time', m_walltime() - t_start, ' s'
1141 : END IF
1142 :
1143 64 : CALL timestop(handle)
1144 :
1145 64 : END SUBROUTINE sum_W_MIC_freq_zero
1146 :
1147 : ! **************************************************************************************************
1148 : !> \brief ...
1149 : !> \param bs_env ...
1150 : !> \param fm_W_MIC_time ...
1151 : ! **************************************************************************************************
1152 114 : SUBROUTINE create_fm_W_MIC_time(bs_env, fm_W_MIC_time)
1153 : TYPE(post_scf_bandstructure_type), POINTER :: bs_env
1154 : TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:) :: fm_W_MIC_time
1155 :
1156 : CHARACTER(LEN=*), PARAMETER :: routineN = 'create_fm_W_MIC_time'
1157 :
1158 : INTEGER :: handle, i_t
1159 :
1160 114 : CALL timeset(routineN, handle)
1161 :
1162 2256 : ALLOCATE (fm_W_MIC_time(bs_env%num_time_freq_points))
1163 2028 : DO i_t = 1, bs_env%num_time_freq_points
1164 2028 : CALL cp_fm_create(fm_W_MIC_time(i_t), bs_env%fm_RI_RI%matrix_struct, set_zero=.TRUE.)
1165 : END DO
1166 :
1167 114 : CALL timestop(handle)
1168 :
1169 114 : END SUBROUTINE create_fm_W_MIC_time
1170 :
1171 : ! **************************************************************************************************
1172 : !> \brief ...
1173 : !> \param bs_env ...
1174 : !> \param fm_W_MIC_time ...
1175 : !> \param fm_W_MIC_freq_j ...
1176 : !> \param j_w ...
1177 : ! **************************************************************************************************
1178 3690 : SUBROUTINE Fourier_transform_w_to_t(bs_env, fm_W_MIC_time, fm_W_MIC_freq_j, j_w)
1179 : TYPE(post_scf_bandstructure_type), POINTER :: bs_env
1180 : TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:) :: fm_W_MIC_time
1181 : TYPE(cp_fm_type) :: fm_W_MIC_freq_j
1182 : INTEGER :: j_w
1183 :
1184 : CHARACTER(LEN=*), PARAMETER :: routineN = 'Fourier_transform_w_to_t'
1185 :
1186 : INTEGER :: handle, i_t
1187 : REAL(KIND=dp) :: weight_ij
1188 :
1189 3690 : CALL timeset(routineN, handle)
1190 :
1191 53844 : DO i_t = 1, bs_env%num_time_freq_points
1192 :
1193 50154 : weight_ij = bs_env%time_frequency_grid%cosine_frequency_to_time(i_t, j_w)
1194 :
1195 : ! actual Fourier transform
1196 : CALL cp_fm_scale_and_add(alpha=1.0_dp, matrix_a=fm_W_MIC_time(i_t), &
1197 53844 : beta=weight_ij, matrix_b=fm_W_MIC_freq_j)
1198 :
1199 : END DO
1200 :
1201 3690 : CALL timestop(handle)
1202 :
1203 3690 : END SUBROUTINE Fourier_transform_w_to_t
1204 :
1205 : ! **************************************************************************************************
1206 : !> \brief ...
1207 : !> \param V_tr_R ...
1208 : !> \param pot_type ...
1209 : !> \param regularization_RI ...
1210 : !> \param bs_env ...
1211 : !> \param qs_env ...
1212 : ! **************************************************************************************************
1213 168 : SUBROUTINE get_V_tr_R(V_tr_R, pot_type, regularization_RI, bs_env, qs_env)
1214 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :) :: V_tr_R
1215 : TYPE(libint_potential_type) :: pot_type
1216 : REAL(KIND=dp) :: regularization_RI
1217 : TYPE(post_scf_bandstructure_type), POINTER :: bs_env
1218 : TYPE(qs_environment_type), POINTER :: qs_env
1219 :
1220 : CHARACTER(LEN=*), PARAMETER :: routineN = 'get_V_tr_R'
1221 :
1222 : INTEGER :: handle, img, nimages_scf_desymm
1223 : INTEGER, ALLOCATABLE, DIMENSION(:) :: sizes_RI
1224 168 : INTEGER, DIMENSION(:), POINTER :: col_bsize, row_bsize
1225 : TYPE(cp_blacs_env_type), POINTER :: blacs_env
1226 168 : TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:) :: fm_V_tr_R
1227 : TYPE(dbcsr_distribution_type) :: dbcsr_dist
1228 168 : TYPE(dbcsr_type), ALLOCATABLE, DIMENSION(:) :: mat_V_tr_R
1229 : TYPE(distribution_2d_type), POINTER :: dist_2d
1230 : TYPE(neighbor_list_set_p_type), DIMENSION(:), &
1231 168 : POINTER :: sab_RI
1232 168 : TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
1233 168 : TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
1234 :
1235 168 : CALL timeset(routineN, handle)
1236 :
1237 168 : NULLIFY (sab_RI, dist_2d)
1238 :
1239 : CALL get_qs_env(qs_env=qs_env, &
1240 : blacs_env=blacs_env, &
1241 : distribution_2d=dist_2d, &
1242 : qs_kind_set=qs_kind_set, &
1243 168 : particle_set=particle_set)
1244 :
1245 504 : ALLOCATE (sizes_RI(bs_env%n_atom))
1246 168 : CALL get_particle_set(particle_set, qs_kind_set, nsgf=sizes_RI, basis=bs_env%basis_set_RI)
1247 : CALL build_2c_neighbor_lists(sab_RI, bs_env%basis_set_RI, bs_env%basis_set_RI, &
1248 : pot_type, "2c_nl_RI", qs_env, sym_ij=.FALSE., &
1249 168 : dist_2d=dist_2d)
1250 168 : CALL cp_dbcsr_dist2d_to_dist(dist_2d, dbcsr_dist)
1251 504 : ALLOCATE (row_bsize(SIZE(sizes_RI)))
1252 336 : ALLOCATE (col_bsize(SIZE(sizes_RI)))
1253 644 : row_bsize(:) = sizes_RI
1254 644 : col_bsize(:) = sizes_RI
1255 :
1256 168 : nimages_scf_desymm = bs_env%nimages_scf_desymm
1257 2016 : ALLOCATE (mat_V_tr_R(nimages_scf_desymm))
1258 : CALL dbcsr_create(mat_V_tr_R(1), "(RI|RI)", dbcsr_dist, dbcsr_type_no_symmetry, &
1259 168 : row_bsize, col_bsize)
1260 168 : DEALLOCATE (row_bsize, col_bsize)
1261 :
1262 1512 : DO img = 2, nimages_scf_desymm
1263 1512 : CALL dbcsr_create(mat_V_tr_R(img), template=mat_V_tr_R(1))
1264 : END DO
1265 :
1266 : CALL build_2c_integrals(mat_V_tr_R, 0.0_dp, qs_env, sab_RI, bs_env%basis_set_RI, &
1267 : bs_env%basis_set_RI, pot_type, do_kpoints=.TRUE., &
1268 : ext_kpoints=bs_env%kpoints_scf_desymm, &
1269 168 : regularization_RI=regularization_RI)
1270 :
1271 2016 : ALLOCATE (fm_V_tr_R(nimages_scf_desymm))
1272 1680 : DO img = 1, nimages_scf_desymm
1273 1512 : CALL cp_fm_create(fm_V_tr_R(img), bs_env%fm_RI_RI%matrix_struct)
1274 1512 : CALL copy_dbcsr_to_fm(mat_V_tr_R(img), fm_V_tr_R(img))
1275 1680 : CALL dbcsr_release(mat_V_tr_R(img))
1276 : END DO
1277 :
1278 168 : IF (.NOT. ALLOCATED(V_tr_R)) THEN
1279 840 : ALLOCATE (V_tr_R(bs_env%n_RI, bs_env%n_RI, nimages_scf_desymm))
1280 : END IF
1281 :
1282 168 : CALL cp_fm_to_replicated_array(fm_V_tr_R, V_tr_R)
1283 :
1284 168 : CALL cp_fm_release(fm_V_tr_R)
1285 168 : CALL dbcsr_distribution_release(dbcsr_dist)
1286 168 : CALL release_neighbor_list_sets(sab_RI)
1287 :
1288 168 : CALL timestop(handle)
1289 :
1290 504 : END SUBROUTINE get_V_tr_R
1291 :
1292 : END MODULE gw_compute_V_and_W
|