Line data Source code
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 Routines from paper [Graml2024]
10 : !> \author Jan Wilhelm
11 : !> \date 07.2023
12 : ! **************************************************************************************************
13 : MODULE gw_large_cell_gamma
14 : USE atomic_kind_types, ONLY: atomic_kind_type
15 : USE bibliography, ONLY: Graml2024,&
16 : cite_reference
17 : USE cell_types, ONLY: cell_type,&
18 : get_cell,&
19 : pbc
20 : USE constants_operator, ONLY: operator_coulomb
21 : USE cp_cfm_basic_linalg, ONLY: cp_cfm_uplo_to_full
22 : USE cp_cfm_cholesky, ONLY: cp_cfm_cholesky_decompose,&
23 : cp_cfm_cholesky_invert
24 : USE cp_cfm_diag, ONLY: cp_cfm_geeig
25 : USE cp_cfm_types, ONLY: cp_cfm_create,&
26 : cp_cfm_get_info,&
27 : cp_cfm_release,&
28 : cp_cfm_to_cfm,&
29 : cp_cfm_to_fm,&
30 : cp_cfm_type,&
31 : cp_fm_to_cfm
32 : USE cp_dbcsr_api, ONLY: &
33 : dbcsr_add, dbcsr_copy, dbcsr_create, dbcsr_deallocate_matrix, dbcsr_get_block_p, &
34 : dbcsr_iterator_blocks_left, dbcsr_iterator_next_block, dbcsr_iterator_start, &
35 : dbcsr_iterator_stop, dbcsr_iterator_type, dbcsr_p_type, dbcsr_release, dbcsr_set, &
36 : dbcsr_type
37 : USE cp_dbcsr_contrib, ONLY: dbcsr_reserve_all_blocks
38 : USE cp_dbcsr_operations, ONLY: copy_dbcsr_to_fm,&
39 : copy_fm_to_dbcsr,&
40 : dbcsr_deallocate_matrix_set
41 : USE cp_files, ONLY: close_file,&
42 : open_file
43 : USE cp_fm_basic_linalg, ONLY: cp_fm_scale_and_add
44 : USE cp_fm_diag, ONLY: cp_fm_power
45 : USE cp_fm_types, ONLY: &
46 : cp_fm_create, cp_fm_get_diag, cp_fm_get_info, cp_fm_read_unformatted, cp_fm_release, &
47 : cp_fm_set_all, cp_fm_to_fm, cp_fm_type, cp_fm_write_unformatted
48 : USE cp_log_handling, ONLY: cp_get_default_logger,&
49 : cp_logger_type
50 : USE cp_output_handling, ONLY: cp_p_file,&
51 : cp_print_key_should_output,&
52 : cp_print_key_unit_nr
53 : USE dbt_api, ONLY: dbt_clear,&
54 : dbt_contract,&
55 : dbt_copy,&
56 : dbt_create,&
57 : dbt_destroy,&
58 : dbt_type
59 : USE gw_communication, ONLY: fm_to_local_tensor,&
60 : local_dbt_to_global_mat
61 : USE gw_utils, ONLY: analyt_conti_and_print,&
62 : de_init_bs_env,&
63 : time_to_freq
64 : USE input_constants, ONLY: rtp_method_bse
65 : USE input_section_types, ONLY: section_vals_type
66 : USE kinds, ONLY: default_string_length,&
67 : dp,&
68 : int_8
69 : USE kpoint_coulomb_2c, ONLY: build_2c_coulomb_matrix_kp
70 : USE kpoint_types, ONLY: kpoint_type
71 : USE machine, ONLY: m_walltime
72 : USE mathconstants, ONLY: twopi,&
73 : z_one,&
74 : z_zero
75 : USE message_passing, ONLY: mp_file_delete
76 : USE mp2_ri_2c, ONLY: RI_2c_integral_mat
77 : USE parallel_gemm_api, ONLY: parallel_gemm
78 : USE particle_types, ONLY: particle_type
79 : USE post_scf_bandstructure_types, ONLY: post_scf_bandstructure_type
80 : USE post_scf_bandstructure_utils, ONLY: MIC_contribution_from_ikp,&
81 : cfm_ikp_from_fm_Gamma,&
82 : get_all_VBM_CBM_bandgaps
83 : USE qs_environment_types, ONLY: get_qs_env,&
84 : qs_environment_type
85 : USE qs_kind_types, ONLY: qs_kind_type
86 : USE qs_tensors, ONLY: build_3c_integrals
87 : USE rpa_gw_kpoints_util, ONLY: cp_cfm_power
88 : #include "./base/base_uses.f90"
89 :
90 : IMPLICIT NONE
91 :
92 : PRIVATE
93 :
94 : CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'gw_large_cell_gamma'
95 :
96 : PUBLIC :: gw_calc_large_cell_Gamma, &
97 : compute_3c_integrals
98 :
99 : CONTAINS
100 :
101 : ! **************************************************************************************************
102 : !> \brief Perform GW band structure calculation
103 : !> \param qs_env ...
104 : !> \param bs_env ...
105 : !> \par History
106 : !> * 07.2023 created [Jan Wilhelm]
107 : ! **************************************************************************************************
108 22 : SUBROUTINE gw_calc_large_cell_Gamma(qs_env, bs_env)
109 : TYPE(qs_environment_type), POINTER :: qs_env
110 : TYPE(post_scf_bandstructure_type), POINTER :: bs_env
111 :
112 : CHARACTER(LEN=*), PARAMETER :: routineN = 'gw_calc_large_cell_Gamma'
113 :
114 : INTEGER :: handle
115 22 : TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:) :: fm_Sigma_x_Gamma, fm_W_MIC_time
116 22 : TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:, :, :) :: fm_Sigma_c_Gamma_time
117 :
118 22 : CALL timeset(routineN, handle)
119 :
120 22 : CALL cite_reference(Graml2024)
121 :
122 : ! G^occ_µλ(i|τ|,k=0) = sum_n^occ C_µn(k=0) e^(-|(ϵ_nk=0-ϵ_F)τ|) C_λn(k=0)
123 : ! G^vir_µλ(i|τ|,k=0) = sum_n^vir C_µn(k=0) e^(-|(ϵ_nk=0-ϵ_F)τ|) C_λn(k=0)
124 : ! χ_PQ(iτ,k=0) = sum_λν [sum_µ (µν|P) G^occ_µλ(i|τ|)] [sum_σ (σλ|Q) G^vir_σν(i|τ|)]
125 22 : CALL get_mat_chi_Gamma_tau(bs_env, qs_env, bs_env%mat_chi_Gamma_tau)
126 :
127 : ! χ_PQ(iτ,k=0) -> χ_PQ(iω,k) -> ε_PQ(iω,k) -> W_PQ(iω,k) -> W^MIC_PQ(iτ) -> M^-1*W^MIC*M^-1
128 22 : CALL get_W_MIC(bs_env, qs_env, bs_env%mat_chi_Gamma_tau, fm_W_MIC_time)
129 :
130 : ! D_µν = sum_n^occ C_µn(k=0) C_νn(k=0), V^trunc_PQ = sum_cell_R <phi_P,0|V^trunc|phi_Q,R>
131 : ! Σ^x_λσ(k=0) = sum_νQ [sum_P (νσ|P) V^trunc_PQ] [sum_µ (λµ|Q) D_µν)]
132 22 : CALL get_Sigma_x(bs_env, qs_env, fm_Sigma_x_Gamma)
133 :
134 : ! Σ^c_λσ(iτ,k=0) = sum_νQ [sum_P (νσ|P) W^MIC_PQ(iτ)] [sum_µ (λµ|Q) G^occ_µν(i|τ|)], τ < 0
135 : ! Σ^c_λσ(iτ,k=0) = sum_νQ [sum_P (νσ|P) W^MIC_PQ(iτ)] [sum_µ (λµ|Q) G^vir_µν(i|τ|)], τ > 0
136 22 : CALL get_Sigma_c(bs_env, qs_env, fm_W_MIC_time, fm_Sigma_c_Gamma_time)
137 :
138 : ! Σ^c_λσ(iτ,k=0) -> Σ^c_nn(ϵ,k); ϵ_nk^GW = ϵ_nk^DFT + Σ^c_nn(ϵ,k) + Σ^x_nn(k) - v^xc_nn(k)
139 22 : CALL compute_QP_energies(bs_env, qs_env, fm_Sigma_x_Gamma, fm_Sigma_c_Gamma_time)
140 :
141 22 : CALL de_init_bs_env(bs_env)
142 :
143 22 : CALL timestop(handle)
144 :
145 22 : END SUBROUTINE gw_calc_large_cell_Gamma
146 :
147 : ! **************************************************************************************************
148 : !> \brief ...
149 : !> \param bs_env ...
150 : !> \param qs_env ...
151 : !> \param mat_chi_Gamma_tau ...
152 : ! **************************************************************************************************
153 22 : SUBROUTINE get_mat_chi_Gamma_tau(bs_env, qs_env, mat_chi_Gamma_tau)
154 : TYPE(post_scf_bandstructure_type), POINTER :: bs_env
155 : TYPE(qs_environment_type), POINTER :: qs_env
156 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: mat_chi_Gamma_tau
157 :
158 : CHARACTER(LEN=*), PARAMETER :: routineN = 'get_mat_chi_Gamma_tau'
159 :
160 : INTEGER :: handle, i_intval_idx, i_t, inner_loop_atoms_interval_index, ispin, j_intval_idx
161 : INTEGER, DIMENSION(2) :: i_atoms, IL_atoms, j_atoms
162 : LOGICAL :: dist_too_long_i, dist_too_long_j
163 : REAL(KIND=dp) :: t1, tau
164 550 : TYPE(dbt_type) :: t_2c_Gocc, t_2c_Gvir, t_3c_for_Gocc, &
165 374 : t_3c_for_Gvir, t_3c_x_Gocc, &
166 374 : t_3c_x_Gocc_2, t_3c_x_Gvir, &
167 198 : t_3c_x_Gvir_2
168 :
169 22 : CALL timeset(routineN, handle)
170 :
171 346 : DO i_t = 1, bs_env%num_time_freq_points
172 :
173 324 : t1 = m_walltime()
174 :
175 324 : IF (bs_env%read_chi(i_t)) THEN
176 :
177 0 : CALL fm_read(bs_env%fm_RI_RI, bs_env, bs_env%chi_name, i_t)
178 :
179 : CALL copy_fm_to_dbcsr(bs_env%fm_RI_RI, mat_chi_Gamma_tau(i_t)%matrix, &
180 0 : keep_sparsity=.FALSE.)
181 :
182 0 : IF (bs_env%unit_nr > 0) THEN
183 : WRITE (bs_env%unit_nr, '(T2,A,I5,A,I3,A,F7.1,A)') &
184 0 : 'Read χ(iτ,k=0) from file for time point ', i_t, ' /', &
185 0 : bs_env%num_time_freq_points, &
186 0 : ', Execution time', m_walltime() - t1, ' s'
187 : END IF
188 :
189 : CYCLE
190 :
191 : END IF
192 :
193 324 : IF (.NOT. bs_env%calc_chi(i_t)) CYCLE
194 :
195 : CALL create_tensors_chi(t_2c_Gocc, t_2c_Gvir, t_3c_for_Gocc, t_3c_for_Gvir, &
196 224 : t_3c_x_Gocc, t_3c_x_Gvir, t_3c_x_Gocc_2, t_3c_x_Gvir_2, bs_env)
197 :
198 : ! 1. compute G^occ and G^vir
199 : ! Background: G^σ(iτ) = G^occ,σ(iτ) * Θ(-τ) + G^vir,σ(iτ) * Θ(τ), σ ∈ {↑,↓}
200 : ! G^occ,σ_µλ(i|τ|,k=0) = sum_n^occ C^σ_µn(k=0) e^(-|(ϵ^σ_nk=0-ϵ_F)τ|) C^σ_λn(k=0)
201 : ! G^vir,σ_µλ(i|τ|,k=0) = sum_n^vir C^σ_µn(k=0) e^(-|(ϵ^σ_nk=0-ϵ_F)τ|) C^σ_λn(k=0)
202 224 : tau = bs_env%imag_time_points(i_t)
203 :
204 468 : DO ispin = 1, bs_env%n_spin
205 244 : CALL G_occ_vir(bs_env, tau, bs_env%fm_Gocc, ispin, occ=.TRUE., vir=.FALSE.)
206 244 : CALL G_occ_vir(bs_env, tau, bs_env%fm_Gvir, ispin, occ=.FALSE., vir=.TRUE.)
207 :
208 : CALL fm_to_local_tensor(bs_env%fm_Gocc, bs_env%mat_ao_ao%matrix, &
209 : bs_env%mat_ao_ao_tensor%matrix, t_2c_Gocc, bs_env, &
210 244 : bs_env%atoms_j_t_group)
211 : CALL fm_to_local_tensor(bs_env%fm_Gvir, bs_env%mat_ao_ao%matrix, &
212 : bs_env%mat_ao_ao_tensor%matrix, t_2c_Gvir, bs_env, &
213 244 : bs_env%atoms_i_t_group)
214 :
215 : ! every group has its own range of i_atoms and j_atoms; only deal with a
216 : ! limited number of i_atom-j_atom pairs simultaneously in a group to save memory
217 712 : DO i_intval_idx = 1, bs_env%n_intervals_i
218 732 : DO j_intval_idx = 1, bs_env%n_intervals_j
219 732 : i_atoms = bs_env%i_atom_intervals(1:2, i_intval_idx)
220 732 : j_atoms = bs_env%j_atom_intervals(1:2, j_intval_idx)
221 :
222 488 : DO inner_loop_atoms_interval_index = 1, bs_env%n_intervals_inner_loop_atoms
223 :
224 732 : IL_atoms = bs_env%inner_loop_atom_intervals(1:2, inner_loop_atoms_interval_index)
225 :
226 244 : CALL check_dist(i_atoms, IL_atoms, qs_env, bs_env, dist_too_long_i)
227 244 : CALL check_dist(j_atoms, IL_atoms, qs_env, bs_env, dist_too_long_j)
228 244 : IF (dist_too_long_i .OR. dist_too_long_j) CYCLE
229 :
230 : ! 2. compute 3-center integrals (µν|P) ("|": truncated Coulomb operator)
231 244 : CALL compute_3c_integrals(qs_env, bs_env, t_3c_for_Gocc, i_atoms, IL_atoms)
232 :
233 : ! 3. tensor operation M_λνP(iτ) = sum_µ (µν|P) G^occ_µλ(i|τ|,k=0)
234 : CALL G_times_3c(t_3c_for_Gocc, t_2c_Gocc, t_3c_x_Gocc, bs_env, &
235 244 : j_atoms, i_atoms, IL_atoms)
236 :
237 : ! 4. compute 3-center integrals (σλ|Q) ("|": truncated Coulomb operator)
238 244 : CALL compute_3c_integrals(qs_env, bs_env, t_3c_for_Gvir, j_atoms, IL_atoms)
239 :
240 : ! 5. tensor operation N_νλQ(iτ) = sum_σ (σλ|Q) G^vir_σν(i|τ|,k=0)
241 : CALL G_times_3c(t_3c_for_Gvir, t_2c_Gvir, t_3c_x_Gvir, bs_env, &
242 488 : i_atoms, j_atoms, IL_atoms)
243 :
244 : END DO ! IL_atoms
245 :
246 : ! 6. reorder tensors
247 244 : CALL dbt_copy(t_3c_x_Gocc, t_3c_x_Gocc_2, move_data=.TRUE., order=[1, 3, 2])
248 244 : CALL dbt_copy(t_3c_x_Gvir, t_3c_x_Gvir_2, move_data=.TRUE.)
249 :
250 : ! 7. tensor operation χ_PQ(iτ,k=0) = sum_λν M_λνP(iτ) N_νλQ(iτ),
251 : CALL dbt_contract(alpha=bs_env%spin_degeneracy, &
252 : tensor_1=t_3c_x_Gocc_2, tensor_2=t_3c_x_Gvir_2, &
253 : beta=1.0_dp, tensor_3=bs_env%t_chi, &
254 : contract_1=[2, 3], notcontract_1=[1], map_1=[1], &
255 : contract_2=[2, 3], notcontract_2=[1], map_2=[2], &
256 488 : filter_eps=bs_env%eps_filter, move_data=.TRUE.)
257 :
258 : END DO ! j_atoms
259 : END DO ! i_atoms
260 : END DO ! ispin
261 :
262 : ! 8. communicate data of χ_PQ(iτ,k=0) in tensor bs_env%t_chi (which local in the
263 : ! subgroup) to the global dbcsr matrix mat_chi_Gamma_tau (which stores
264 : ! χ_PQ(iτ,k=0) for all time points)
265 : CALL local_dbt_to_global_mat(bs_env%t_chi, bs_env%mat_RI_RI_tensor%matrix, &
266 224 : mat_chi_Gamma_tau(i_t)%matrix, bs_env%para_env)
267 :
268 : CALL write_matrix(mat_chi_Gamma_tau(i_t)%matrix, i_t, bs_env%chi_name, &
269 224 : bs_env%fm_RI_RI, qs_env)
270 :
271 : CALL destroy_tensors_chi(t_2c_Gocc, t_2c_Gvir, t_3c_for_Gocc, t_3c_for_Gvir, &
272 224 : t_3c_x_Gocc, t_3c_x_Gvir, t_3c_x_Gocc_2, t_3c_x_Gvir_2)
273 :
274 246 : IF (bs_env%unit_nr > 0) THEN
275 : WRITE (bs_env%unit_nr, '(T2,A,I13,A,I3,A,F7.1,A)') &
276 112 : 'Computed χ(iτ,k=0) for time point', i_t, ' /', bs_env%num_time_freq_points, &
277 224 : ', Execution time', m_walltime() - t1, ' s'
278 : END IF
279 :
280 : END DO ! i_t
281 :
282 22 : IF (bs_env%unit_nr > 0) WRITE (bs_env%unit_nr, '(A)') ' '
283 :
284 22 : CALL timestop(handle)
285 :
286 22 : END SUBROUTINE get_mat_chi_Gamma_tau
287 :
288 : ! **************************************************************************************************
289 : !> \brief ...
290 : !> \param fm ...
291 : !> \param bs_env ...
292 : !> \param mat_name ...
293 : !> \param idx ...
294 : ! **************************************************************************************************
295 352 : SUBROUTINE fm_read(fm, bs_env, mat_name, idx)
296 : TYPE(cp_fm_type) :: fm
297 : TYPE(post_scf_bandstructure_type), POINTER :: bs_env
298 : CHARACTER(LEN=*) :: mat_name
299 : INTEGER :: idx
300 :
301 : CHARACTER(LEN=*), PARAMETER :: routineN = 'fm_read'
302 :
303 : CHARACTER(LEN=default_string_length) :: f_chi
304 : INTEGER :: handle, unit_nr
305 :
306 352 : CALL timeset(routineN, handle)
307 :
308 352 : unit_nr = -1
309 352 : IF (bs_env%para_env%is_source()) THEN
310 :
311 176 : IF (idx < 10) THEN
312 87 : WRITE (f_chi, '(3A,I1,A)') TRIM(bs_env%prefix), TRIM(mat_name), "_0", idx, ".matrix"
313 89 : ELSE IF (idx < 100) THEN
314 89 : WRITE (f_chi, '(3A,I2,A)') TRIM(bs_env%prefix), TRIM(mat_name), "_", idx, ".matrix"
315 : ELSE
316 0 : CPABORT('Please implement more than 99 time/frequency points.')
317 : END IF
318 :
319 : CALL open_file(file_name=TRIM(f_chi), file_action="READ", file_form="UNFORMATTED", &
320 176 : file_position="REWIND", file_status="OLD", unit_number=unit_nr)
321 :
322 : END IF
323 :
324 352 : CALL cp_fm_read_unformatted(fm, unit_nr)
325 :
326 352 : IF (bs_env%para_env%is_source()) CALL close_file(unit_number=unit_nr)
327 :
328 352 : CALL timestop(handle)
329 :
330 352 : END SUBROUTINE fm_read
331 :
332 : ! **************************************************************************************************
333 : !> \brief ...
334 : !> \param t_2c_Gocc ...
335 : !> \param t_2c_Gvir ...
336 : !> \param t_3c_for_Gocc ...
337 : !> \param t_3c_for_Gvir ...
338 : !> \param t_3c_x_Gocc ...
339 : !> \param t_3c_x_Gvir ...
340 : !> \param t_3c_x_Gocc_2 ...
341 : !> \param t_3c_x_Gvir_2 ...
342 : !> \param bs_env ...
343 : ! **************************************************************************************************
344 224 : SUBROUTINE create_tensors_chi(t_2c_Gocc, t_2c_Gvir, t_3c_for_Gocc, t_3c_for_Gvir, &
345 : t_3c_x_Gocc, t_3c_x_Gvir, t_3c_x_Gocc_2, t_3c_x_Gvir_2, bs_env)
346 :
347 : TYPE(dbt_type) :: t_2c_Gocc, t_2c_Gvir, t_3c_for_Gocc, &
348 : t_3c_for_Gvir, t_3c_x_Gocc, &
349 : t_3c_x_Gvir, t_3c_x_Gocc_2, &
350 : t_3c_x_Gvir_2
351 : TYPE(post_scf_bandstructure_type), POINTER :: bs_env
352 :
353 : CHARACTER(LEN=*), PARAMETER :: routineN = 'create_tensors_chi'
354 :
355 : INTEGER :: handle
356 :
357 224 : CALL timeset(routineN, handle)
358 :
359 224 : CALL dbt_create(bs_env%t_G, t_2c_Gocc)
360 224 : CALL dbt_create(bs_env%t_G, t_2c_Gvir)
361 224 : CALL dbt_create(bs_env%t_RI_AO__AO, t_3c_for_Gocc)
362 224 : CALL dbt_create(bs_env%t_RI_AO__AO, t_3c_for_Gvir)
363 224 : CALL dbt_create(bs_env%t_RI_AO__AO, t_3c_x_Gocc)
364 224 : CALL dbt_create(bs_env%t_RI_AO__AO, t_3c_x_Gvir)
365 224 : CALL dbt_create(bs_env%t_RI__AO_AO, t_3c_x_Gocc_2)
366 224 : CALL dbt_create(bs_env%t_RI__AO_AO, t_3c_x_Gvir_2)
367 :
368 224 : CALL timestop(handle)
369 :
370 224 : END SUBROUTINE create_tensors_chi
371 :
372 : ! **************************************************************************************************
373 : !> \brief ...
374 : !> \param t_2c_Gocc ...
375 : !> \param t_2c_Gvir ...
376 : !> \param t_3c_for_Gocc ...
377 : !> \param t_3c_for_Gvir ...
378 : !> \param t_3c_x_Gocc ...
379 : !> \param t_3c_x_Gvir ...
380 : !> \param t_3c_x_Gocc_2 ...
381 : !> \param t_3c_x_Gvir_2 ...
382 : ! **************************************************************************************************
383 224 : SUBROUTINE destroy_tensors_chi(t_2c_Gocc, t_2c_Gvir, t_3c_for_Gocc, t_3c_for_Gvir, &
384 : t_3c_x_Gocc, t_3c_x_Gvir, t_3c_x_Gocc_2, t_3c_x_Gvir_2)
385 : TYPE(dbt_type) :: t_2c_Gocc, t_2c_Gvir, t_3c_for_Gocc, &
386 : t_3c_for_Gvir, t_3c_x_Gocc, &
387 : t_3c_x_Gvir, t_3c_x_Gocc_2, &
388 : t_3c_x_Gvir_2
389 :
390 : CHARACTER(LEN=*), PARAMETER :: routineN = 'destroy_tensors_chi'
391 :
392 : INTEGER :: handle
393 :
394 224 : CALL timeset(routineN, handle)
395 :
396 224 : CALL dbt_destroy(t_2c_Gocc)
397 224 : CALL dbt_destroy(t_2c_Gvir)
398 224 : CALL dbt_destroy(t_3c_for_Gocc)
399 224 : CALL dbt_destroy(t_3c_for_Gvir)
400 224 : CALL dbt_destroy(t_3c_x_Gocc)
401 224 : CALL dbt_destroy(t_3c_x_Gvir)
402 224 : CALL dbt_destroy(t_3c_x_Gocc_2)
403 224 : CALL dbt_destroy(t_3c_x_Gvir_2)
404 :
405 224 : CALL timestop(handle)
406 :
407 224 : END SUBROUTINE destroy_tensors_chi
408 :
409 : ! **************************************************************************************************
410 : !> \brief ...
411 : !> \param matrix ...
412 : !> \param matrix_index ...
413 : !> \param matrix_name ...
414 : !> \param fm ...
415 : !> \param qs_env ...
416 : ! **************************************************************************************************
417 730 : SUBROUTINE write_matrix(matrix, matrix_index, matrix_name, fm, qs_env)
418 : TYPE(dbcsr_type) :: matrix
419 : INTEGER :: matrix_index
420 : CHARACTER(LEN=*) :: matrix_name
421 : TYPE(cp_fm_type), INTENT(IN), POINTER :: fm
422 : TYPE(qs_environment_type), POINTER :: qs_env
423 :
424 : CHARACTER(LEN=*), PARAMETER :: routineN = 'write_matrix'
425 :
426 : INTEGER :: handle
427 :
428 730 : CALL timeset(routineN, handle)
429 :
430 730 : CALL cp_fm_set_all(fm, 0.0_dp)
431 :
432 730 : CALL copy_dbcsr_to_fm(matrix, fm)
433 :
434 730 : CALL fm_write(fm, matrix_index, matrix_name, qs_env)
435 :
436 730 : CALL timestop(handle)
437 :
438 730 : END SUBROUTINE write_matrix
439 :
440 : ! **************************************************************************************************
441 : !> \brief ...
442 : !> \param fm ...
443 : !> \param matrix_index ...
444 : !> \param matrix_name ...
445 : !> \param qs_env ...
446 : ! **************************************************************************************************
447 962 : SUBROUTINE fm_write(fm, matrix_index, matrix_name, qs_env)
448 : TYPE(cp_fm_type) :: fm
449 : INTEGER :: matrix_index
450 : CHARACTER(LEN=*) :: matrix_name
451 : TYPE(qs_environment_type), POINTER :: qs_env
452 :
453 : CHARACTER(LEN=*), PARAMETER :: key = 'PROPERTIES%BANDSTRUCTURE%GW%PRINT%RESTART', &
454 : routineN = 'fm_write'
455 :
456 : CHARACTER(LEN=default_string_length) :: filename
457 : INTEGER :: handle, unit_nr
458 : TYPE(cp_logger_type), POINTER :: logger
459 : TYPE(section_vals_type), POINTER :: input
460 :
461 962 : CALL timeset(routineN, handle)
462 :
463 962 : CALL get_qs_env(qs_env, input=input)
464 :
465 962 : logger => cp_get_default_logger()
466 :
467 962 : IF (BTEST(cp_print_key_should_output(logger%iter_info, input, key), cp_p_file)) THEN
468 :
469 780 : IF (matrix_index < 10) THEN
470 380 : WRITE (filename, '(3A,I1)') "RESTART_", matrix_name, "_0", matrix_index
471 400 : ELSE IF (matrix_index < 100) THEN
472 400 : WRITE (filename, '(3A,I2)') "RESTART_", matrix_name, "_", matrix_index
473 : ELSE
474 0 : CPABORT('Please implement more than 99 time/frequency points.')
475 : END IF
476 :
477 : unit_nr = cp_print_key_unit_nr(logger, input, key, extension=".matrix", &
478 : file_form="UNFORMATTED", middle_name=TRIM(filename), &
479 780 : file_position="REWIND", file_action="WRITE")
480 :
481 780 : CALL cp_fm_write_unformatted(fm, unit_nr)
482 780 : IF (unit_nr > 0) THEN
483 390 : CALL close_file(unit_nr)
484 : END IF
485 : END IF
486 :
487 962 : CALL timestop(handle)
488 :
489 962 : END SUBROUTINE fm_write
490 :
491 : ! **************************************************************************************************
492 : !> \brief ...
493 : !> \param bs_env ...
494 : !> \param tau ...
495 : !> \param fm_G_Gamma ...
496 : !> \param ispin ...
497 : !> \param occ ...
498 : !> \param vir ...
499 : ! **************************************************************************************************
500 1988 : SUBROUTINE G_occ_vir(bs_env, tau, fm_G_Gamma, ispin, occ, vir)
501 : TYPE(post_scf_bandstructure_type), POINTER :: bs_env
502 : REAL(KIND=dp) :: tau
503 : TYPE(cp_fm_type) :: fm_G_Gamma
504 : INTEGER :: ispin
505 : LOGICAL :: occ, vir
506 :
507 : CHARACTER(LEN=*), PARAMETER :: routineN = 'G_occ_vir'
508 :
509 : INTEGER :: handle, homo, i_row_local, j_col, &
510 : j_col_local, n_mo, ncol_local, &
511 : nrow_local
512 994 : INTEGER, DIMENSION(:), POINTER :: col_indices
513 : REAL(KIND=dp) :: tau_E
514 :
515 994 : CALL timeset(routineN, handle)
516 :
517 994 : CPASSERT(occ .NEQV. vir)
518 :
519 : CALL cp_fm_get_info(matrix=bs_env%fm_work_mo(1), &
520 : nrow_local=nrow_local, &
521 : ncol_local=ncol_local, &
522 994 : col_indices=col_indices)
523 :
524 994 : n_mo = bs_env%n_ao
525 994 : homo = bs_env%n_occ(ispin)
526 :
527 994 : CALL cp_fm_to_fm(bs_env%fm_mo_coeff_Gamma(ispin), bs_env%fm_work_mo(1))
528 :
529 3899 : DO i_row_local = 1, nrow_local
530 41608 : DO j_col_local = 1, ncol_local
531 :
532 37709 : j_col = col_indices(j_col_local)
533 :
534 37709 : tau_E = ABS(tau*0.5_dp*(bs_env%eigenval_scf_Gamma(j_col, ispin) - bs_env%e_fermi(ispin)))
535 :
536 37709 : IF (tau_E < bs_env%stabilize_exp) THEN
537 : bs_env%fm_work_mo(1)%local_data(i_row_local, j_col_local) = &
538 36917 : bs_env%fm_work_mo(1)%local_data(i_row_local, j_col_local)*EXP(-tau_E)
539 : ELSE
540 792 : bs_env%fm_work_mo(1)%local_data(i_row_local, j_col_local) = 0.0_dp
541 : END IF
542 :
543 40614 : IF ((occ .AND. j_col > homo) .OR. (vir .AND. j_col <= homo)) THEN
544 19222 : bs_env%fm_work_mo(1)%local_data(i_row_local, j_col_local) = 0.0_dp
545 : END IF
546 :
547 : END DO
548 : END DO
549 :
550 : CALL parallel_gemm(transa="N", transb="T", m=n_mo, n=n_mo, k=n_mo, alpha=1.0_dp, &
551 : matrix_a=bs_env%fm_work_mo(1), matrix_b=bs_env%fm_work_mo(1), &
552 994 : beta=0.0_dp, matrix_c=fm_G_Gamma)
553 :
554 994 : CALL timestop(handle)
555 :
556 994 : END SUBROUTINE G_occ_vir
557 :
558 : ! **************************************************************************************************
559 : !> \brief ...
560 : !> \param qs_env ...
561 : !> \param bs_env ...
562 : !> \param t_3c ...
563 : !> \param atoms_AO_1 ...
564 : !> \param atoms_AO_2 ...
565 : !> \param atoms_RI ...
566 : ! **************************************************************************************************
567 1214 : SUBROUTINE compute_3c_integrals(qs_env, bs_env, t_3c, atoms_AO_1, atoms_AO_2, atoms_RI)
568 : TYPE(qs_environment_type), POINTER :: qs_env
569 : TYPE(post_scf_bandstructure_type), POINTER :: bs_env
570 : TYPE(dbt_type) :: t_3c
571 : INTEGER, DIMENSION(2), OPTIONAL :: atoms_AO_1, atoms_AO_2, atoms_RI
572 :
573 : CHARACTER(LEN=*), PARAMETER :: routineN = 'compute_3c_integrals'
574 :
575 : INTEGER :: handle
576 : INTEGER, DIMENSION(2) :: my_atoms_AO_1, my_atoms_AO_2, my_atoms_RI
577 1214 : TYPE(dbt_type), ALLOCATABLE, DIMENSION(:, :) :: t_3c_array
578 :
579 1214 : CALL timeset(routineN, handle)
580 :
581 : ! free memory (not clear whether memory has been freed previously)
582 1214 : CALL dbt_clear(t_3c)
583 :
584 13354 : ALLOCATE (t_3c_array(1, 1))
585 1214 : CALL dbt_create(t_3c, t_3c_array(1, 1))
586 :
587 1214 : IF (PRESENT(atoms_AO_1)) THEN
588 : my_atoms_AO_1 = atoms_AO_1
589 : ELSE
590 1446 : my_atoms_AO_1 = [1, bs_env%n_atom]
591 : END IF
592 1214 : IF (PRESENT(atoms_AO_2)) THEN
593 : my_atoms_AO_2 = atoms_AO_2
594 : ELSE
595 768 : my_atoms_AO_2 = [1, bs_env%n_atom]
596 : END IF
597 1214 : IF (PRESENT(atoms_RI)) THEN
598 : my_atoms_RI = atoms_RI
599 : ELSE
600 1500 : my_atoms_RI = [1, bs_env%n_atom]
601 : END IF
602 :
603 : CALL build_3c_integrals(t_3c_array, &
604 : bs_env%eps_filter, &
605 : qs_env, &
606 : bs_env%nl_3c, &
607 : int_eps=bs_env%eps_filter, &
608 : basis_i=bs_env%basis_set_RI, &
609 : basis_j=bs_env%basis_set_AO, &
610 : basis_k=bs_env%basis_set_AO, &
611 : potential_parameter=bs_env%ri_metric, &
612 : bounds_i=atoms_RI, &
613 : bounds_j=atoms_AO_1, &
614 : bounds_k=atoms_AO_2, &
615 1214 : desymmetrize=.FALSE.)
616 :
617 1214 : CALL dbt_copy(t_3c_array(1, 1), t_3c, move_data=.TRUE.)
618 :
619 1214 : CALL dbt_destroy(t_3c_array(1, 1))
620 2428 : DEALLOCATE (t_3c_array)
621 :
622 1214 : CALL timestop(handle)
623 :
624 2428 : END SUBROUTINE compute_3c_integrals
625 :
626 : ! **************************************************************************************************
627 : !> \brief ...
628 : !> \param t_3c_for_G ...
629 : !> \param t_G ...
630 : !> \param t_M ...
631 : !> \param bs_env ...
632 : !> \param atoms_AO_1 ...
633 : !> \param atoms_AO_2 ...
634 : !> \param atoms_IL ...
635 : ! **************************************************************************************************
636 488 : SUBROUTINE G_times_3c(t_3c_for_G, t_G, t_M, bs_env, atoms_AO_1, atoms_AO_2, atoms_IL)
637 : TYPE(dbt_type) :: t_3c_for_G, t_G, t_M
638 : TYPE(post_scf_bandstructure_type), POINTER :: bs_env
639 : INTEGER, DIMENSION(2) :: atoms_AO_1, atoms_AO_2, atoms_IL
640 :
641 : CHARACTER(LEN=*), PARAMETER :: routineN = 'G_times_3c'
642 :
643 : INTEGER :: handle
644 : INTEGER, DIMENSION(2) :: bounds_IL, bounds_l
645 : INTEGER, DIMENSION(2, 2) :: bounds_k
646 :
647 488 : CALL timeset(routineN, handle)
648 :
649 : ! JW bounds_IL and bounds_k do not safe any operations, but maybe communication
650 : ! maybe remove "bounds_1=bounds_IL, &" and "bounds_2=bounds_k, &" later and
651 : ! check whether performance improves
652 :
653 : bounds_IL(1:2) = [bs_env%i_ao_start_from_atom(atoms_IL(1)), &
654 1464 : bs_env%i_ao_end_from_atom(atoms_IL(2))]
655 1464 : bounds_k(1:2, 1) = [1, bs_env%n_RI]
656 : bounds_k(1:2, 2) = [bs_env%i_ao_start_from_atom(atoms_AO_2(1)), &
657 1464 : bs_env%i_ao_end_from_atom(atoms_AO_2(2))]
658 : bounds_l(1:2) = [bs_env%i_ao_start_from_atom(atoms_AO_1(1)), &
659 1464 : bs_env%i_ao_end_from_atom(atoms_AO_1(2))]
660 :
661 : CALL dbt_contract(alpha=1.0_dp, &
662 : tensor_1=t_3c_for_G, &
663 : tensor_2=t_G, &
664 : beta=1.0_dp, &
665 : tensor_3=t_M, &
666 : contract_1=[3], notcontract_1=[1, 2], map_1=[1, 2], &
667 : contract_2=[2], notcontract_2=[1], map_2=[3], &
668 : bounds_1=bounds_IL, &
669 : bounds_2=bounds_k, &
670 : bounds_3=bounds_l, &
671 488 : filter_eps=bs_env%eps_filter)
672 :
673 488 : CALL dbt_clear(t_3c_for_G)
674 :
675 488 : CALL timestop(handle)
676 :
677 488 : END SUBROUTINE G_times_3c
678 :
679 : ! **************************************************************************************************
680 : !> \brief ...
681 : !> \param atoms_1 ...
682 : !> \param atoms_2 ...
683 : !> \param qs_env ...
684 : !> \param bs_env ...
685 : !> \param dist_too_long ...
686 : ! **************************************************************************************************
687 488 : SUBROUTINE check_dist(atoms_1, atoms_2, qs_env, bs_env, dist_too_long)
688 : INTEGER, DIMENSION(2) :: atoms_1, atoms_2
689 : TYPE(qs_environment_type), POINTER :: qs_env
690 : TYPE(post_scf_bandstructure_type), POINTER :: bs_env
691 : LOGICAL :: dist_too_long
692 :
693 : CHARACTER(LEN=*), PARAMETER :: routineN = 'check_dist'
694 :
695 : INTEGER :: atom_1, atom_2, handle
696 : REAL(dp) :: abs_rab, min_dist_AO_atoms
697 : REAL(KIND=dp), DIMENSION(3) :: rab
698 : TYPE(cell_type), POINTER :: cell
699 488 : TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
700 :
701 488 : CALL timeset(routineN, handle)
702 :
703 488 : CALL get_qs_env(qs_env, cell=cell, particle_set=particle_set)
704 :
705 488 : min_dist_AO_atoms = 1.0E5_dp
706 1512 : DO atom_1 = atoms_1(1), atoms_1(2)
707 3704 : DO atom_2 = atoms_2(1), atoms_2(2)
708 :
709 2192 : rab = pbc(particle_set(atom_1)%r(1:3), particle_set(atom_2)%r(1:3), cell)
710 :
711 2192 : abs_rab = SQRT(rab(1)**2 + rab(2)**2 + rab(3)**2)
712 :
713 3216 : min_dist_AO_atoms = MIN(min_dist_AO_atoms, abs_rab)
714 :
715 : END DO
716 : END DO
717 :
718 488 : dist_too_long = (min_dist_AO_atoms > bs_env%max_dist_AO_atoms)
719 :
720 488 : CALL timestop(handle)
721 :
722 488 : END SUBROUTINE check_dist
723 :
724 : ! **************************************************************************************************
725 : !> \brief ...
726 : !> \param bs_env ...
727 : !> \param qs_env ...
728 : !> \param mat_chi_Gamma_tau ...
729 : !> \param fm_W_MIC_time ...
730 : ! **************************************************************************************************
731 22 : SUBROUTINE get_W_MIC(bs_env, qs_env, mat_chi_Gamma_tau, fm_W_MIC_time)
732 : TYPE(post_scf_bandstructure_type), POINTER :: bs_env
733 : TYPE(qs_environment_type), POINTER :: qs_env
734 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: mat_chi_Gamma_tau
735 : TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:) :: fm_W_MIC_time
736 :
737 : CHARACTER(LEN=*), PARAMETER :: routineN = 'get_W_MIC'
738 :
739 : INTEGER :: handle
740 :
741 22 : CALL timeset(routineN, handle)
742 :
743 22 : IF (bs_env%all_W_exist) THEN
744 6 : CALL read_W_MIC_time(bs_env, mat_chi_Gamma_tau, fm_W_MIC_time)
745 : ELSE
746 16 : CALL compute_W_MIC(bs_env, qs_env, mat_chi_Gamma_tau, fm_W_MIC_time)
747 : END IF
748 :
749 22 : CALL timestop(handle)
750 :
751 22 : END SUBROUTINE get_W_MIC
752 :
753 : ! **************************************************************************************************
754 : !> \brief ...
755 : !> \param bs_env ...
756 : !> \param qs_env ...
757 : !> \param fm_V_kp ...
758 : !> \param ikp_batch ...
759 : ! **************************************************************************************************
760 64 : SUBROUTINE compute_V_k_by_lattice_sum(bs_env, qs_env, fm_V_kp, ikp_batch)
761 : TYPE(post_scf_bandstructure_type), POINTER :: bs_env
762 : TYPE(qs_environment_type), POINTER :: qs_env
763 : TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:, :) :: fm_V_kp
764 : INTEGER :: ikp_batch
765 :
766 : CHARACTER(LEN=*), PARAMETER :: routineN = 'compute_V_k_by_lattice_sum'
767 :
768 : INTEGER :: handle, ikp, ikp_end, ikp_start, &
769 : nkp_chi_eps_W_batch, re_im
770 64 : TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set
771 : TYPE(cell_type), POINTER :: cell
772 64 : TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: mat_V_kp
773 64 : TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
774 64 : TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
775 :
776 64 : CALL timeset(routineN, handle)
777 :
778 64 : nkp_chi_eps_W_batch = bs_env%nkp_chi_eps_W_batch
779 :
780 64 : ikp_start = (ikp_batch - 1)*bs_env%nkp_chi_eps_W_batch + 1
781 64 : ikp_end = MIN(ikp_batch*bs_env%nkp_chi_eps_W_batch, bs_env%kpoints_chi_eps_W%nkp)
782 :
783 64 : NULLIFY (mat_V_kp)
784 816 : ALLOCATE (mat_V_kp(ikp_start:ikp_end, 2))
785 :
786 192 : DO re_im = 1, 2
787 624 : DO ikp = ikp_start, ikp_end
788 432 : NULLIFY (mat_V_kp(ikp, re_im)%matrix)
789 432 : ALLOCATE (mat_V_kp(ikp, re_im)%matrix)
790 432 : CALL dbcsr_create(mat_V_kp(ikp, re_im)%matrix, template=bs_env%mat_RI_RI%matrix)
791 432 : CALL dbcsr_reserve_all_blocks(mat_V_kp(ikp, re_im)%matrix)
792 560 : CALL dbcsr_set(mat_V_kp(ikp, re_im)%matrix, 0.0_dp)
793 : END DO ! ikp
794 : END DO ! re_im
795 :
796 : CALL get_qs_env(qs_env=qs_env, &
797 : particle_set=particle_set, &
798 : cell=cell, &
799 : qs_kind_set=qs_kind_set, &
800 64 : atomic_kind_set=atomic_kind_set)
801 :
802 64 : IF (ikp_end <= bs_env%nkp_chi_eps_W_orig) THEN
803 :
804 : ! 1. 2c Coulomb integrals for the first "original" k-point grid
805 96 : bs_env%kpoints_chi_eps_W%nkp_grid = bs_env%nkp_grid_chi_eps_W_orig
806 :
807 40 : ELSE IF (ikp_start > bs_env%nkp_chi_eps_W_orig .AND. &
808 : ikp_end <= bs_env%nkp_chi_eps_W_orig_plus_extra) THEN
809 :
810 : ! 2. 2c Coulomb integrals for the second "extrapolation" k-point grid
811 160 : bs_env%kpoints_chi_eps_W%nkp_grid = bs_env%nkp_grid_chi_eps_W_extra
812 :
813 : ELSE
814 :
815 0 : CPABORT("Error with k-point parallelization.")
816 :
817 : END IF
818 :
819 : CALL build_2c_coulomb_matrix_kp(mat_V_kp, &
820 : bs_env%kpoints_chi_eps_W, &
821 : basis_type="RI_AUX", &
822 : cell=cell, &
823 : particle_set=particle_set, &
824 : qs_kind_set=qs_kind_set, &
825 : atomic_kind_set=atomic_kind_set, &
826 : size_lattice_sum=bs_env%size_lattice_sum_V, &
827 : operator_type=operator_coulomb, &
828 : ikp_start=ikp_start, &
829 64 : ikp_end=ikp_end)
830 :
831 256 : bs_env%kpoints_chi_eps_W%nkp_grid = bs_env%nkp_grid_chi_eps_W_orig
832 :
833 816 : ALLOCATE (fm_V_kp(ikp_start:ikp_end, 2))
834 192 : DO re_im = 1, 2
835 624 : DO ikp = ikp_start, ikp_end
836 432 : CALL cp_fm_create(fm_V_kp(ikp, re_im), bs_env%fm_RI_RI%matrix_struct)
837 432 : CALL copy_dbcsr_to_fm(mat_V_kp(ikp, re_im)%matrix, fm_V_kp(ikp, re_im))
838 560 : CALL dbcsr_deallocate_matrix(mat_V_kp(ikp, re_im)%matrix)
839 : END DO
840 : END DO
841 64 : DEALLOCATE (mat_V_kp)
842 :
843 64 : CALL timestop(handle)
844 :
845 64 : END SUBROUTINE compute_V_k_by_lattice_sum
846 :
847 : ! **************************************************************************************************
848 : !> \brief ...
849 : !> \param bs_env ...
850 : !> \param qs_env ...
851 : !> \param fm_V_kp ...
852 : !> \param cfm_V_sqrt_ikp ...
853 : !> \param cfm_M_inv_V_sqrt_ikp ...
854 : !> \param ikp ...
855 : ! **************************************************************************************************
856 216 : SUBROUTINE compute_MinvVsqrt_Vsqrt(bs_env, qs_env, fm_V_kp, cfm_V_sqrt_ikp, &
857 : cfm_M_inv_V_sqrt_ikp, ikp)
858 : TYPE(post_scf_bandstructure_type), POINTER :: bs_env
859 : TYPE(qs_environment_type), POINTER :: qs_env
860 : TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:, :) :: fm_V_kp
861 : TYPE(cp_cfm_type) :: cfm_V_sqrt_ikp, cfm_M_inv_V_sqrt_ikp
862 : INTEGER :: ikp
863 :
864 : CHARACTER(LEN=*), PARAMETER :: routineN = 'compute_MinvVsqrt_Vsqrt'
865 :
866 : INTEGER :: handle, info, n_RI
867 : TYPE(cp_cfm_type) :: cfm_M_inv_ikp, cfm_work
868 216 : TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:, :) :: fm_M_ikp
869 :
870 216 : CALL timeset(routineN, handle)
871 :
872 216 : n_RI = bs_env%n_RI
873 :
874 : ! get here M(k) and write it to fm_M_ikp
875 : CALL RI_2c_integral_mat(qs_env, fm_M_ikp, fm_V_kp(ikp, 1), &
876 : n_RI, bs_env%ri_metric, do_kpoints=.TRUE., &
877 : kpoints=bs_env%kpoints_chi_eps_W, &
878 : regularization_RI=bs_env%regularization_RI, ikp_ext=ikp, &
879 216 : do_build_cell_index=(ikp == 1))
880 :
881 216 : IF (ikp == 1) THEN
882 16 : CALL cp_cfm_create(cfm_V_sqrt_ikp, fm_V_kp(ikp, 1)%matrix_struct)
883 16 : CALL cp_cfm_create(cfm_M_inv_V_sqrt_ikp, fm_V_kp(ikp, 1)%matrix_struct)
884 : END IF
885 216 : CALL cp_cfm_create(cfm_M_inv_ikp, fm_V_kp(ikp, 1)%matrix_struct)
886 :
887 216 : CALL cp_fm_to_cfm(fm_M_ikp(1, 1), fm_M_ikp(1, 2), cfm_M_inv_ikp)
888 216 : CALL cp_fm_to_cfm(fm_V_kp(ikp, 1), fm_V_kp(ikp, 2), cfm_V_sqrt_ikp)
889 :
890 216 : CALL cp_fm_release(fm_M_ikp)
891 :
892 216 : CALL cp_cfm_create(cfm_work, fm_V_kp(ikp, 1)%matrix_struct)
893 :
894 : ! M(k) -> M^-1(k)
895 216 : CALL cp_cfm_to_cfm(cfm_M_inv_ikp, cfm_work)
896 216 : CALL cp_cfm_cholesky_decompose(matrix=cfm_M_inv_ikp, n=n_RI, info_out=info)
897 216 : IF (info == 0) THEN
898 : ! successful Cholesky decomposition
899 216 : CALL cp_cfm_cholesky_invert(cfm_M_inv_ikp)
900 : ! symmetrize the result
901 216 : CALL cp_cfm_uplo_to_full(cfm_M_inv_ikp)
902 : ELSE
903 : ! Cholesky decomposition not successful: use expensive diagonalization
904 0 : CALL cp_cfm_power(cfm_work, threshold=bs_env%eps_eigval_mat_RI, exponent=-1.0_dp)
905 0 : CALL cp_cfm_to_cfm(cfm_work, cfm_M_inv_ikp)
906 : END IF
907 :
908 : ! V(k) -> L(k) with L^H(k)*L(k) = V(k) [L(k) can be just considered to be V^0.5(k)]
909 216 : CALL cp_cfm_to_cfm(cfm_V_sqrt_ikp, cfm_work)
910 216 : CALL cp_cfm_cholesky_decompose(matrix=cfm_V_sqrt_ikp, n=n_RI, info_out=info)
911 216 : IF (info == 0) THEN
912 : ! successful Cholesky decomposition
913 216 : CALL clean_lower_part(cfm_V_sqrt_ikp)
914 : ELSE
915 : ! Cholesky decomposition not successful: use expensive diagonalization
916 0 : CALL cp_cfm_power(cfm_work, threshold=0.0_dp, exponent=0.5_dp)
917 0 : CALL cp_cfm_to_cfm(cfm_work, cfm_V_sqrt_ikp)
918 : END IF
919 216 : CALL cp_cfm_release(cfm_work)
920 :
921 : ! get M^-1(k)*V^0.5(k)
922 : CALL parallel_gemm("N", "C", n_RI, n_RI, n_RI, z_one, cfm_M_inv_ikp, cfm_V_sqrt_ikp, &
923 216 : z_zero, cfm_M_inv_V_sqrt_ikp)
924 :
925 216 : CALL cp_cfm_release(cfm_M_inv_ikp)
926 :
927 216 : CALL timestop(handle)
928 :
929 432 : END SUBROUTINE compute_MinvVsqrt_Vsqrt
930 :
931 : ! **************************************************************************************************
932 : !> \brief ...
933 : !> \param bs_env ...
934 : !> \param mat_chi_Gamma_tau ...
935 : !> \param fm_W_MIC_time ...
936 : ! **************************************************************************************************
937 6 : SUBROUTINE read_W_MIC_time(bs_env, mat_chi_Gamma_tau, fm_W_MIC_time)
938 : TYPE(post_scf_bandstructure_type), POINTER :: bs_env
939 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: mat_chi_Gamma_tau
940 : TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:) :: fm_W_MIC_time
941 :
942 : CHARACTER(LEN=*), PARAMETER :: routineN = 'read_W_MIC_time'
943 :
944 : INTEGER :: handle, i_t
945 : REAL(KIND=dp) :: t1
946 :
947 6 : CALL timeset(routineN, handle)
948 :
949 6 : CALL dbcsr_deallocate_matrix_set(mat_chi_Gamma_tau)
950 6 : CALL create_fm_W_MIC_time(bs_env, fm_W_MIC_time)
951 :
952 106 : DO i_t = 1, bs_env%num_time_freq_points
953 :
954 100 : t1 = m_walltime()
955 :
956 100 : CALL fm_read(fm_W_MIC_time(i_t), bs_env, bs_env%W_time_name, i_t)
957 :
958 106 : IF (bs_env%unit_nr > 0) THEN
959 : WRITE (bs_env%unit_nr, '(T2,A,I5,A,I3,A,F7.1,A)') &
960 50 : 'Read W^MIC(iτ) from file for time point ', i_t, ' /', bs_env%num_time_freq_points, &
961 100 : ', Execution time', m_walltime() - t1, ' s'
962 : END IF
963 :
964 : END DO
965 :
966 6 : IF (bs_env%unit_nr > 0) WRITE (bs_env%unit_nr, '(A)') ' '
967 :
968 : ! Marek : Reading of the W(w=0) potential for RTP
969 : ! TODO : is the condition bs_env%all_W_exist sufficient for reading?
970 6 : IF (bs_env%rtp_method == rtp_method_bse) THEN
971 4 : CALL cp_fm_create(bs_env%fm_W_MIC_freq_zero, bs_env%fm_W_MIC_freq%matrix_struct)
972 4 : t1 = m_walltime()
973 4 : CALL fm_read(bs_env%fm_W_MIC_freq_zero, bs_env, "W_freq_rtp", 0)
974 4 : IF (bs_env%unit_nr > 0) THEN
975 : WRITE (bs_env%unit_nr, '(T2,A,I3,A,I3,A,F7.1,A)') &
976 2 : 'Read W^MIC(f=0) from file for freq. point ', 1, ' /', 1, &
977 4 : ', Execution time', m_walltime() - t1, ' s'
978 : END IF
979 : END IF
980 :
981 6 : CALL timestop(handle)
982 :
983 6 : END SUBROUTINE read_W_MIC_time
984 :
985 : ! **************************************************************************************************
986 : !> \brief ...
987 : !> \param bs_env ...
988 : !> \param qs_env ...
989 : !> \param mat_chi_Gamma_tau ...
990 : !> \param fm_W_MIC_time ...
991 : ! **************************************************************************************************
992 16 : SUBROUTINE compute_W_MIC(bs_env, qs_env, mat_chi_Gamma_tau, fm_W_MIC_time)
993 : TYPE(post_scf_bandstructure_type), POINTER :: bs_env
994 : TYPE(qs_environment_type), POINTER :: qs_env
995 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: mat_chi_Gamma_tau
996 : TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:) :: fm_W_MIC_time
997 :
998 : CHARACTER(LEN=*), PARAMETER :: routineN = 'compute_W_MIC'
999 :
1000 : INTEGER :: handle, i_t, ikp, ikp_batch, &
1001 : ikp_in_batch, j_w
1002 : REAL(KIND=dp) :: t1
1003 : TYPE(cp_cfm_type) :: cfm_M_inv_V_sqrt_ikp, cfm_V_sqrt_ikp
1004 16 : TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:, :) :: fm_V_kp
1005 :
1006 16 : CALL timeset(routineN, handle)
1007 :
1008 16 : CALL create_fm_W_MIC_time(bs_env, fm_W_MIC_time)
1009 :
1010 80 : DO ikp_batch = 1, bs_env%num_chi_eps_W_batches
1011 :
1012 64 : t1 = m_walltime()
1013 :
1014 : ! Compute V_PQ(k) = sum_R e^(ikR) <phi_P, cell 0 | 1/r | phi_Q, cell R>
1015 64 : CALL compute_V_k_by_lattice_sum(bs_env, qs_env, fm_V_kp, ikp_batch)
1016 :
1017 320 : DO ikp_in_batch = 1, bs_env%nkp_chi_eps_W_batch
1018 :
1019 256 : ikp = (ikp_batch - 1)*bs_env%nkp_chi_eps_W_batch + ikp_in_batch
1020 :
1021 256 : IF (ikp > bs_env%nkp_chi_eps_W_orig_plus_extra) CYCLE
1022 :
1023 : CALL compute_MinvVsqrt_Vsqrt(bs_env, qs_env, fm_V_kp, &
1024 216 : cfm_V_sqrt_ikp, cfm_M_inv_V_sqrt_ikp, ikp)
1025 :
1026 216 : CALL bs_env%para_env%sync()
1027 216 : CALL cp_fm_release(fm_V_kp(ikp, 1))
1028 216 : CALL cp_fm_release(fm_V_kp(ikp, 2))
1029 :
1030 2104 : DO j_w = 1, bs_env%num_time_freq_points
1031 :
1032 : ! check if we need this (ikp, ω_j) combination for approximate k-point extrapolation
1033 1824 : IF (bs_env%approx_kp_extrapol .AND. j_w > 1 .AND. &
1034 : ikp > bs_env%nkp_chi_eps_W_orig) CYCLE
1035 :
1036 : CALL compute_fm_W_MIC_freq_j(bs_env, qs_env, bs_env%fm_W_MIC_freq, j_w, ikp, &
1037 : mat_chi_Gamma_tau, cfm_M_inv_V_sqrt_ikp, &
1038 1500 : cfm_V_sqrt_ikp)
1039 :
1040 : ! Fourier trafo from W_PQ^MIC(iω_j) to W_PQ^MIC(iτ)
1041 2080 : CALL Fourier_transform_w_to_t(bs_env, fm_W_MIC_time, bs_env%fm_W_MIC_freq, j_w)
1042 :
1043 : END DO ! ω_j
1044 :
1045 : END DO ! ikp_in_batch
1046 :
1047 64 : DEALLOCATE (fm_V_kp)
1048 :
1049 80 : IF (bs_env%unit_nr > 0) THEN
1050 : WRITE (bs_env%unit_nr, '(T2,A,I12,A,I3,A,F7.1,A)') &
1051 32 : 'Computed W(iτ,k) for k-point batch', &
1052 32 : ikp_batch, ' /', bs_env%num_chi_eps_W_batches, &
1053 64 : ', Execution time', m_walltime() - t1, ' s'
1054 : END IF
1055 :
1056 : END DO ! ikp_batch
1057 :
1058 16 : IF (bs_env%approx_kp_extrapol) THEN
1059 2 : CALL apply_extrapol_factor(bs_env, fm_W_MIC_time)
1060 : END IF
1061 :
1062 : ! M^-1(k=0)*W^MIC(iτ)*M^-1(k=0)
1063 16 : CALL multiply_fm_W_MIC_time_with_Minv_Gamma(bs_env, qs_env, fm_W_MIC_time)
1064 :
1065 240 : DO i_t = 1, bs_env%num_time_freq_points
1066 240 : CALL fm_write(fm_W_MIC_time(i_t), i_t, bs_env%W_time_name, qs_env)
1067 : END DO
1068 :
1069 16 : CALL cp_cfm_release(cfm_M_inv_V_sqrt_ikp)
1070 16 : CALL cp_cfm_release(cfm_V_sqrt_ikp)
1071 16 : CALL dbcsr_deallocate_matrix_set(mat_chi_Gamma_tau)
1072 :
1073 : ! Marek : Fourier transform W^MIC(itau) back to get it at a specific im.frequency point - iomega = 0
1074 16 : IF (bs_env%rtp_method == rtp_method_bse) THEN
1075 8 : t1 = m_walltime()
1076 8 : CALL cp_fm_create(bs_env%fm_W_MIC_freq_zero, bs_env%fm_W_MIC_freq%matrix_struct)
1077 : ! Set to zero
1078 8 : CALL cp_fm_set_all(bs_env%fm_W_MIC_freq_zero, 0.0_dp)
1079 : ! Sum over all times
1080 168 : DO i_t = 1, bs_env%num_time_freq_points
1081 : ! Add the relevant structure with correct weight
1082 : CALL cp_fm_scale_and_add(1.0_dp, bs_env%fm_W_MIC_freq_zero, &
1083 168 : bs_env%imag_time_weights_freq_zero(i_t), fm_W_MIC_time(i_t))
1084 : END DO
1085 : ! Done, save to file
1086 8 : CALL fm_write(bs_env%fm_W_MIC_freq_zero, 0, "W_freq_rtp", qs_env)
1087 : ! Report calculation
1088 8 : IF (bs_env%unit_nr > 0) THEN
1089 : WRITE (bs_env%unit_nr, '(T2,A,I11,A,I3,A,F7.1,A)') &
1090 4 : 'Computed W(f=0,k) for k-point batch', &
1091 4 : 1, ' /', 1, &
1092 8 : ', Execution time', m_walltime() - t1, ' s'
1093 : END IF
1094 : END IF
1095 :
1096 16 : IF (bs_env%unit_nr > 0) WRITE (bs_env%unit_nr, '(A)') ' '
1097 :
1098 16 : CALL timestop(handle)
1099 :
1100 32 : END SUBROUTINE compute_W_MIC
1101 :
1102 : ! **************************************************************************************************
1103 : !> \brief ...
1104 : !> \param bs_env ...
1105 : !> \param qs_env ...
1106 : !> \param fm_W_MIC_freq_j ...
1107 : !> \param j_w ...
1108 : !> \param ikp ...
1109 : !> \param mat_chi_Gamma_tau ...
1110 : !> \param cfm_M_inv_V_sqrt_ikp ...
1111 : !> \param cfm_V_sqrt_ikp ...
1112 : ! **************************************************************************************************
1113 1500 : SUBROUTINE compute_fm_W_MIC_freq_j(bs_env, qs_env, fm_W_MIC_freq_j, j_w, ikp, mat_chi_Gamma_tau, &
1114 : cfm_M_inv_V_sqrt_ikp, cfm_V_sqrt_ikp)
1115 : TYPE(post_scf_bandstructure_type), POINTER :: bs_env
1116 : TYPE(qs_environment_type), POINTER :: qs_env
1117 : TYPE(cp_fm_type) :: fm_W_MIC_freq_j
1118 : INTEGER :: j_w, ikp
1119 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: mat_chi_Gamma_tau
1120 : TYPE(cp_cfm_type) :: cfm_M_inv_V_sqrt_ikp, cfm_V_sqrt_ikp
1121 :
1122 : CHARACTER(LEN=*), PARAMETER :: routineN = 'compute_fm_W_MIC_freq_j'
1123 :
1124 : INTEGER :: handle
1125 : TYPE(cp_cfm_type) :: cfm_chi_ikp_freq_j, cfm_W_ikp_freq_j
1126 :
1127 1500 : CALL timeset(routineN, handle)
1128 :
1129 : ! 1. Fourier transformation of χ_PQ(iτ,k=0) to χ_PQ(iω_j,k=0)
1130 1500 : CALL compute_fm_chi_Gamma_freq(bs_env, bs_env%fm_chi_Gamma_freq, j_w, mat_chi_Gamma_tau)
1131 :
1132 1500 : CALL cp_fm_set_all(fm_W_MIC_freq_j, 0.0_dp)
1133 :
1134 : ! 2. Get χ_PQ(iω_j,k_i) from χ_PQ(iω_j,k=0) using the minimum image convention
1135 : CALL cfm_ikp_from_fm_Gamma(cfm_chi_ikp_freq_j, bs_env%fm_chi_Gamma_freq, &
1136 1500 : ikp, qs_env, bs_env%kpoints_chi_eps_W, "RI_AUX")
1137 :
1138 : ! 3. Remove all negative eigenvalues from χ_PQ(iω_j,k_i)
1139 1500 : CALL cp_cfm_power(cfm_chi_ikp_freq_j, threshold=0.0_dp, exponent=1.0_dp)
1140 :
1141 : ! 4. ε(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)
1142 : ! W(iω_j,k_i) = V^0.5(k_i)*(ε^-1(iω_j,k_i)-Id)*V^0.5(k_i)
1143 : CALL compute_cfm_W_ikp_freq_j(bs_env, cfm_chi_ikp_freq_j, cfm_V_sqrt_ikp, &
1144 1500 : cfm_M_inv_V_sqrt_ikp, cfm_W_ikp_freq_j)
1145 :
1146 : ! 5. k-point integration W_PQ(iω_j, k_i) to W_PQ^MIC(iω_j)
1147 1500 : SELECT CASE (bs_env%approx_kp_extrapol)
1148 : CASE (.FALSE.)
1149 : ! default: standard k-point extrapolation
1150 : CALL MIC_contribution_from_ikp(bs_env, qs_env, fm_W_MIC_freq_j, cfm_W_ikp_freq_j, ikp, &
1151 1500 : bs_env%kpoints_chi_eps_W, "RI_AUX")
1152 : CASE (.TRUE.)
1153 : ! for approximate kpoint extrapolation: get W_PQ^MIC(iω_1) with and without k-point
1154 : ! extrapolation to compute the extrapolation factor f_PQ for every PQ-matrix element,
1155 : ! f_PQ = (W_PQ^MIC(iω_1) with extrapolation) / (W_PQ^MIC(iω_1) without extrapolation)
1156 :
1157 : ! for ω_1, we compute the k-point extrapolated result using all k-points
1158 196 : IF (j_w == 1) THEN
1159 :
1160 : ! k-point extrapolated
1161 : CALL MIC_contribution_from_ikp(bs_env, qs_env, bs_env%fm_W_MIC_freq_1_extra, &
1162 : cfm_W_ikp_freq_j, ikp, bs_env%kpoints_chi_eps_W, &
1163 52 : "RI_AUX")
1164 : ! non-kpoint extrapolated
1165 52 : IF (ikp <= bs_env%nkp_chi_eps_W_orig) THEN
1166 : CALL MIC_contribution_from_ikp(bs_env, qs_env, bs_env%fm_W_MIC_freq_1_no_extra, &
1167 : cfm_W_ikp_freq_j, ikp, bs_env%kpoints_chi_eps_W, &
1168 16 : "RI_AUX", wkp_ext=bs_env%wkp_orig)
1169 : END IF
1170 :
1171 : END IF
1172 :
1173 : ! for all ω_j, we need to compute W^MIC without k-point extrpolation
1174 196 : IF (ikp <= bs_env%nkp_chi_eps_W_orig) THEN
1175 : CALL MIC_contribution_from_ikp(bs_env, qs_env, fm_W_MIC_freq_j, cfm_W_ikp_freq_j, &
1176 : ikp, bs_env%kpoints_chi_eps_W, "RI_AUX", &
1177 160 : wkp_ext=bs_env%wkp_orig)
1178 : END IF
1179 : END SELECT
1180 :
1181 1500 : CALL cp_cfm_release(cfm_W_ikp_freq_j)
1182 :
1183 1500 : CALL timestop(handle)
1184 :
1185 1500 : END SUBROUTINE compute_fm_W_MIC_freq_j
1186 :
1187 : ! **************************************************************************************************
1188 : !> \brief ...
1189 : !> \param cfm_mat ...
1190 : ! **************************************************************************************************
1191 432 : SUBROUTINE clean_lower_part(cfm_mat)
1192 : TYPE(cp_cfm_type) :: cfm_mat
1193 :
1194 : CHARACTER(LEN=*), PARAMETER :: routineN = 'clean_lower_part'
1195 :
1196 : INTEGER :: handle, i_row, j_col, j_global, &
1197 : ncol_local, nrow_local
1198 216 : INTEGER, DIMENSION(:), POINTER :: col_indices, row_indices
1199 :
1200 216 : CALL timeset(routineN, handle)
1201 :
1202 : CALL cp_cfm_get_info(matrix=cfm_mat, &
1203 : nrow_local=nrow_local, ncol_local=ncol_local, &
1204 216 : row_indices=row_indices, col_indices=col_indices)
1205 :
1206 1744 : DO j_col = 1, ncol_local
1207 1528 : j_global = col_indices(j_col)
1208 8308 : DO i_row = 1, nrow_local
1209 8092 : IF (j_global < row_indices(i_row)) cfm_mat%local_data(i_row, j_col) = z_zero
1210 : END DO
1211 : END DO
1212 :
1213 216 : CALL timestop(handle)
1214 :
1215 216 : END SUBROUTINE clean_lower_part
1216 :
1217 : ! **************************************************************************************************
1218 : !> \brief ...
1219 : !> \param bs_env ...
1220 : !> \param fm_W_MIC_time ...
1221 : ! **************************************************************************************************
1222 4 : SUBROUTINE apply_extrapol_factor(bs_env, fm_W_MIC_time)
1223 : TYPE(post_scf_bandstructure_type), POINTER :: bs_env
1224 : TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:) :: fm_W_MIC_time
1225 :
1226 : CHARACTER(LEN=*), PARAMETER :: routineN = 'apply_extrapol_factor'
1227 :
1228 : INTEGER :: handle, i, i_t, j, ncol_local, nrow_local
1229 : REAL(KIND=dp) :: extrapol_factor, W_extra_1, W_no_extra_1
1230 :
1231 2 : CALL timeset(routineN, handle)
1232 :
1233 2 : CALL cp_fm_get_info(matrix=fm_W_MIC_time(1), nrow_local=nrow_local, ncol_local=ncol_local)
1234 :
1235 22 : DO i_t = 1, bs_env%num_time_freq_points
1236 122 : DO j = 1, ncol_local
1237 370 : DO i = 1, nrow_local
1238 :
1239 250 : W_extra_1 = bs_env%fm_W_MIC_freq_1_extra%local_data(i, j)
1240 250 : W_no_extra_1 = bs_env%fm_W_MIC_freq_1_no_extra%local_data(i, j)
1241 :
1242 250 : IF (ABS(W_no_extra_1) > 1.0E-13) THEN
1243 190 : extrapol_factor = ABS(W_extra_1/W_no_extra_1)
1244 : ELSE
1245 : extrapol_factor = 1.0_dp
1246 : END IF
1247 :
1248 : ! reset extrapolation factor if it is very large
1249 190 : IF (extrapol_factor > 10.0_dp) extrapol_factor = 1.0_dp
1250 :
1251 : fm_W_MIC_time(i_t)%local_data(i, j) = fm_W_MIC_time(i_t)%local_data(i, j) &
1252 350 : *extrapol_factor
1253 : END DO
1254 : END DO
1255 : END DO
1256 :
1257 2 : CALL timestop(handle)
1258 :
1259 2 : END SUBROUTINE apply_extrapol_factor
1260 :
1261 : ! **************************************************************************************************
1262 : !> \brief ...
1263 : !> \param bs_env ...
1264 : !> \param fm_chi_Gamma_freq ...
1265 : !> \param j_w ...
1266 : !> \param mat_chi_Gamma_tau ...
1267 : ! **************************************************************************************************
1268 1500 : SUBROUTINE compute_fm_chi_Gamma_freq(bs_env, fm_chi_Gamma_freq, j_w, mat_chi_Gamma_tau)
1269 : TYPE(post_scf_bandstructure_type), POINTER :: bs_env
1270 : TYPE(cp_fm_type) :: fm_chi_Gamma_freq
1271 : INTEGER :: j_w
1272 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: mat_chi_Gamma_tau
1273 :
1274 : CHARACTER(LEN=*), PARAMETER :: routineN = 'compute_fm_chi_Gamma_freq'
1275 :
1276 : INTEGER :: handle, i_t
1277 : REAL(KIND=dp) :: freq_j, time_i, weight_ij
1278 :
1279 1500 : CALL timeset(routineN, handle)
1280 :
1281 1500 : CALL dbcsr_set(bs_env%mat_RI_RI%matrix, 0.0_dp)
1282 :
1283 1500 : freq_j = bs_env%imag_freq_points(j_w)
1284 :
1285 15604 : DO i_t = 1, bs_env%num_time_freq_points
1286 :
1287 14104 : time_i = bs_env%imag_time_points(i_t)
1288 14104 : weight_ij = bs_env%weights_cos_t_to_w(j_w, i_t)
1289 :
1290 : ! actual Fourier transform
1291 : CALL dbcsr_add(bs_env%mat_RI_RI%matrix, mat_chi_Gamma_tau(i_t)%matrix, &
1292 15604 : 1.0_dp, COS(time_i*freq_j)*weight_ij)
1293 :
1294 : END DO
1295 :
1296 1500 : CALL copy_dbcsr_to_fm(bs_env%mat_RI_RI%matrix, fm_chi_Gamma_freq)
1297 :
1298 1500 : CALL timestop(handle)
1299 :
1300 1500 : END SUBROUTINE compute_fm_chi_Gamma_freq
1301 :
1302 : ! **************************************************************************************************
1303 : !> \brief ...
1304 : !> \param mat_ikp_re ...
1305 : !> \param mat_ikp_im ...
1306 : !> \param mat_Gamma ...
1307 : !> \param kpoints ...
1308 : !> \param ikp ...
1309 : !> \param qs_env ...
1310 : ! **************************************************************************************************
1311 0 : SUBROUTINE mat_ikp_from_mat_Gamma(mat_ikp_re, mat_ikp_im, mat_Gamma, kpoints, ikp, qs_env)
1312 : TYPE(dbcsr_type) :: mat_ikp_re, mat_ikp_im, mat_Gamma
1313 : TYPE(kpoint_type), POINTER :: kpoints
1314 : INTEGER :: ikp
1315 : TYPE(qs_environment_type), POINTER :: qs_env
1316 :
1317 : CHARACTER(LEN=*), PARAMETER :: routineN = 'mat_ikp_from_mat_Gamma'
1318 :
1319 : INTEGER :: col, handle, i_cell, j_cell, num_cells, &
1320 : row
1321 0 : INTEGER, DIMENSION(:, :), POINTER :: index_to_cell
1322 : LOGICAL :: f, i_cell_is_the_minimum_image_cell
1323 : REAL(KIND=dp) :: abs_rab_cell_i, abs_rab_cell_j, arg
1324 : REAL(KIND=dp), DIMENSION(3) :: cell_vector, cell_vector_j, rab_cell_i, &
1325 : rab_cell_j
1326 : REAL(KIND=dp), DIMENSION(3, 3) :: hmat
1327 0 : REAL(KIND=dp), DIMENSION(:, :), POINTER :: block_im, block_re, data_block
1328 : TYPE(cell_type), POINTER :: cell
1329 : TYPE(dbcsr_iterator_type) :: iter
1330 0 : TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
1331 :
1332 0 : CALL timeset(routineN, handle)
1333 :
1334 : ! get the same blocks in mat_ikp_re and mat_ikp_im as in mat_Gamma
1335 0 : CALL dbcsr_copy(mat_ikp_re, mat_Gamma)
1336 0 : CALL dbcsr_copy(mat_ikp_im, mat_Gamma)
1337 0 : CALL dbcsr_set(mat_ikp_re, 0.0_dp)
1338 0 : CALL dbcsr_set(mat_ikp_im, 0.0_dp)
1339 :
1340 0 : NULLIFY (cell, particle_set)
1341 0 : CALL get_qs_env(qs_env, cell=cell, particle_set=particle_set)
1342 0 : CALL get_cell(cell=cell, h=hmat)
1343 :
1344 0 : index_to_cell => kpoints%index_to_cell
1345 :
1346 0 : num_cells = SIZE(index_to_cell, 2)
1347 :
1348 0 : DO i_cell = 1, num_cells
1349 :
1350 0 : CALL dbcsr_iterator_start(iter, mat_Gamma)
1351 0 : DO WHILE (dbcsr_iterator_blocks_left(iter))
1352 0 : CALL dbcsr_iterator_next_block(iter, row, col, data_block)
1353 :
1354 0 : cell_vector(1:3) = MATMUL(hmat, REAL(index_to_cell(1:3, i_cell), dp))
1355 :
1356 : rab_cell_i(1:3) = pbc(particle_set(row)%r(1:3), cell) - &
1357 0 : (pbc(particle_set(col)%r(1:3), cell) + cell_vector(1:3))
1358 0 : abs_rab_cell_i = SQRT(rab_cell_i(1)**2 + rab_cell_i(2)**2 + rab_cell_i(3)**2)
1359 :
1360 : ! minimum image convention
1361 0 : i_cell_is_the_minimum_image_cell = .TRUE.
1362 0 : DO j_cell = 1, num_cells
1363 0 : cell_vector_j(1:3) = MATMUL(hmat, REAL(index_to_cell(1:3, j_cell), dp))
1364 : rab_cell_j(1:3) = pbc(particle_set(row)%r(1:3), cell) - &
1365 0 : (pbc(particle_set(col)%r(1:3), cell) + cell_vector_j(1:3))
1366 0 : abs_rab_cell_j = SQRT(rab_cell_j(1)**2 + rab_cell_j(2)**2 + rab_cell_j(3)**2)
1367 :
1368 0 : IF (abs_rab_cell_i > abs_rab_cell_j + 1.0E-6_dp) THEN
1369 0 : i_cell_is_the_minimum_image_cell = .FALSE.
1370 : END IF
1371 : END DO
1372 :
1373 0 : IF (i_cell_is_the_minimum_image_cell) THEN
1374 0 : NULLIFY (block_re, block_im)
1375 0 : CALL dbcsr_get_block_p(matrix=mat_ikp_re, row=row, col=col, block=block_re, found=f)
1376 0 : CALL dbcsr_get_block_p(matrix=mat_ikp_im, row=row, col=col, block=block_im, found=f)
1377 0 : CPASSERT(ALL(ABS(block_re) < 1.0E-10_dp))
1378 0 : CPASSERT(ALL(ABS(block_im) < 1.0E-10_dp))
1379 :
1380 : arg = REAL(index_to_cell(1, i_cell), dp)*kpoints%xkp(1, ikp) + &
1381 : REAL(index_to_cell(2, i_cell), dp)*kpoints%xkp(2, ikp) + &
1382 0 : REAL(index_to_cell(3, i_cell), dp)*kpoints%xkp(3, ikp)
1383 :
1384 0 : block_re(:, :) = COS(twopi*arg)*data_block(:, :)
1385 0 : block_im(:, :) = SIN(twopi*arg)*data_block(:, :)
1386 : END IF
1387 :
1388 : END DO
1389 0 : CALL dbcsr_iterator_stop(iter)
1390 :
1391 : END DO
1392 :
1393 0 : CALL timestop(handle)
1394 :
1395 0 : END SUBROUTINE mat_ikp_from_mat_Gamma
1396 :
1397 : ! **************************************************************************************************
1398 : !> \brief ...
1399 : !> \param bs_env ...
1400 : !> \param cfm_chi_ikp_freq_j ...
1401 : !> \param cfm_V_sqrt_ikp ...
1402 : !> \param cfm_M_inv_V_sqrt_ikp ...
1403 : !> \param cfm_W_ikp_freq_j ...
1404 : ! **************************************************************************************************
1405 7500 : SUBROUTINE compute_cfm_W_ikp_freq_j(bs_env, cfm_chi_ikp_freq_j, cfm_V_sqrt_ikp, &
1406 : cfm_M_inv_V_sqrt_ikp, cfm_W_ikp_freq_j)
1407 :
1408 : TYPE(post_scf_bandstructure_type), POINTER :: bs_env
1409 : TYPE(cp_cfm_type) :: cfm_chi_ikp_freq_j, cfm_V_sqrt_ikp, &
1410 : cfm_M_inv_V_sqrt_ikp, cfm_W_ikp_freq_j
1411 :
1412 : CHARACTER(LEN=*), PARAMETER :: routineN = 'compute_cfm_W_ikp_freq_j'
1413 :
1414 : INTEGER :: handle, info, n_RI
1415 : TYPE(cp_cfm_type) :: cfm_eps_ikp_freq_j, cfm_work
1416 :
1417 1500 : CALL timeset(routineN, handle)
1418 :
1419 1500 : CALL cp_cfm_create(cfm_work, cfm_chi_ikp_freq_j%matrix_struct)
1420 1500 : n_RI = bs_env%n_RI
1421 :
1422 : ! 1. ε(iω_j,k) = Id - V^0.5(k)*M^-1(k)*χ(iω_j,k)*M^-1(k)*V^0.5(k)
1423 :
1424 : ! 1. a) work = χ(iω_j,k)*M^-1(k)*V^0.5(k)
1425 : CALL parallel_gemm('N', 'N', n_RI, n_RI, n_RI, z_one, &
1426 1500 : cfm_chi_ikp_freq_j, cfm_M_inv_V_sqrt_ikp, z_zero, cfm_work)
1427 1500 : CALL cp_cfm_release(cfm_chi_ikp_freq_j)
1428 :
1429 : ! 1. b) eps_work = V^0.5(k)*M^-1(k)*work
1430 1500 : CALL cp_cfm_create(cfm_eps_ikp_freq_j, cfm_work%matrix_struct)
1431 : CALL parallel_gemm('C', 'N', n_RI, n_RI, n_RI, z_one, &
1432 1500 : cfm_M_inv_V_sqrt_ikp, cfm_work, z_zero, cfm_eps_ikp_freq_j)
1433 :
1434 : ! 1. c) ε(iω_j,k) = eps_work - Id
1435 1500 : CALL cfm_add_on_diag(cfm_eps_ikp_freq_j, z_one)
1436 :
1437 : ! 2. W(iω_j,k) = V^0.5(k)*(ε^-1(iω_j,k)-Id)*V^0.5(k)
1438 :
1439 : ! 2. a) Cholesky decomposition of ε(iω_j,k) as preparation for inversion
1440 1500 : CALL cp_cfm_cholesky_decompose(matrix=cfm_eps_ikp_freq_j, n=n_RI, info_out=info)
1441 1500 : CPASSERT(info == 0)
1442 :
1443 : ! 2. b) Inversion of ε(iω_j,k) using its Cholesky decomposition
1444 1500 : CALL cp_cfm_cholesky_invert(cfm_eps_ikp_freq_j)
1445 1500 : CALL cp_cfm_uplo_to_full(cfm_eps_ikp_freq_j)
1446 :
1447 : ! 2. c) ε^-1(iω_j,k)-Id
1448 1500 : CALL cfm_add_on_diag(cfm_eps_ikp_freq_j, -z_one)
1449 :
1450 : ! 2. d) work = (ε^-1(iω_j,k)-Id)*V^0.5(k)
1451 : CALL parallel_gemm('N', 'N', n_RI, n_RI, n_RI, z_one, cfm_eps_ikp_freq_j, cfm_V_sqrt_ikp, &
1452 1500 : z_zero, cfm_work)
1453 :
1454 : ! 2. e) W(iw,k) = V^0.5(k)*work
1455 1500 : CALL cp_cfm_create(cfm_W_ikp_freq_j, cfm_work%matrix_struct)
1456 : CALL parallel_gemm('C', 'N', n_RI, n_RI, n_RI, z_one, cfm_V_sqrt_ikp, cfm_work, &
1457 1500 : z_zero, cfm_W_ikp_freq_j)
1458 :
1459 1500 : CALL cp_cfm_release(cfm_work)
1460 1500 : CALL cp_cfm_release(cfm_eps_ikp_freq_j)
1461 :
1462 1500 : CALL timestop(handle)
1463 :
1464 1500 : END SUBROUTINE compute_cfm_W_ikp_freq_j
1465 :
1466 : ! **************************************************************************************************
1467 : !> \brief ...
1468 : !> \param cfm ...
1469 : !> \param alpha ...
1470 : ! **************************************************************************************************
1471 6000 : SUBROUTINE cfm_add_on_diag(cfm, alpha)
1472 :
1473 : TYPE(cp_cfm_type) :: cfm
1474 : COMPLEX(KIND=dp) :: alpha
1475 :
1476 : CHARACTER(LEN=*), PARAMETER :: routineN = 'cfm_add_on_diag'
1477 :
1478 : INTEGER :: handle, i_row, j_col, j_global, &
1479 : ncol_local, nrow_local
1480 3000 : INTEGER, DIMENSION(:), POINTER :: col_indices, row_indices
1481 :
1482 3000 : CALL timeset(routineN, handle)
1483 :
1484 : CALL cp_cfm_get_info(matrix=cfm, &
1485 : nrow_local=nrow_local, &
1486 : ncol_local=ncol_local, &
1487 : row_indices=row_indices, &
1488 3000 : col_indices=col_indices)
1489 :
1490 : ! add 1 on the diagonal
1491 27184 : DO j_col = 1, ncol_local
1492 24184 : j_global = col_indices(j_col)
1493 162460 : DO i_row = 1, nrow_local
1494 159460 : IF (j_global == row_indices(i_row)) THEN
1495 12092 : cfm%local_data(i_row, j_col) = cfm%local_data(i_row, j_col) + alpha
1496 : END IF
1497 : END DO
1498 : END DO
1499 :
1500 3000 : CALL timestop(handle)
1501 :
1502 3000 : END SUBROUTINE cfm_add_on_diag
1503 :
1504 : ! **************************************************************************************************
1505 : !> \brief ...
1506 : !> \param bs_env ...
1507 : !> \param fm_W_MIC_time ...
1508 : ! **************************************************************************************************
1509 22 : SUBROUTINE create_fm_W_MIC_time(bs_env, fm_W_MIC_time)
1510 : TYPE(post_scf_bandstructure_type), POINTER :: bs_env
1511 : TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:) :: fm_W_MIC_time
1512 :
1513 : CHARACTER(LEN=*), PARAMETER :: routineN = 'create_fm_W_MIC_time'
1514 :
1515 : INTEGER :: handle, i_t
1516 :
1517 22 : CALL timeset(routineN, handle)
1518 :
1519 390 : ALLOCATE (fm_W_MIC_time(bs_env%num_time_freq_points))
1520 346 : DO i_t = 1, bs_env%num_time_freq_points
1521 346 : CALL cp_fm_create(fm_W_MIC_time(i_t), bs_env%fm_RI_RI%matrix_struct, set_zero=.TRUE.)
1522 : END DO
1523 :
1524 22 : CALL timestop(handle)
1525 :
1526 22 : END SUBROUTINE create_fm_W_MIC_time
1527 :
1528 : ! **************************************************************************************************
1529 : !> \brief ...
1530 : !> \param bs_env ...
1531 : !> \param fm_W_MIC_time ...
1532 : !> \param fm_W_MIC_freq_j ...
1533 : !> \param j_w ...
1534 : ! **************************************************************************************************
1535 1500 : SUBROUTINE Fourier_transform_w_to_t(bs_env, fm_W_MIC_time, fm_W_MIC_freq_j, j_w)
1536 : TYPE(post_scf_bandstructure_type), POINTER :: bs_env
1537 : TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:) :: fm_W_MIC_time
1538 : TYPE(cp_fm_type) :: fm_W_MIC_freq_j
1539 : INTEGER :: j_w
1540 :
1541 : CHARACTER(LEN=*), PARAMETER :: routineN = 'Fourier_transform_w_to_t'
1542 :
1543 : INTEGER :: handle, i_t
1544 : REAL(KIND=dp) :: freq_j, time_i, weight_ij
1545 :
1546 1500 : CALL timeset(routineN, handle)
1547 :
1548 1500 : freq_j = bs_env%imag_freq_points(j_w)
1549 :
1550 15604 : DO i_t = 1, bs_env%num_time_freq_points
1551 :
1552 14104 : time_i = bs_env%imag_time_points(i_t)
1553 14104 : weight_ij = bs_env%weights_cos_w_to_t(i_t, j_w)
1554 :
1555 : ! actual Fourier transform
1556 : CALL cp_fm_scale_and_add(alpha=1.0_dp, matrix_a=fm_W_MIC_time(i_t), &
1557 15604 : beta=weight_ij*COS(time_i*freq_j), matrix_b=fm_W_MIC_freq_j)
1558 :
1559 : END DO
1560 :
1561 1500 : CALL timestop(handle)
1562 :
1563 1500 : END SUBROUTINE Fourier_transform_w_to_t
1564 :
1565 : ! **************************************************************************************************
1566 : !> \brief ...
1567 : !> \param bs_env ...
1568 : !> \param qs_env ...
1569 : !> \param fm_W_MIC_time ...
1570 : ! **************************************************************************************************
1571 32 : SUBROUTINE multiply_fm_W_MIC_time_with_Minv_Gamma(bs_env, qs_env, fm_W_MIC_time)
1572 : TYPE(post_scf_bandstructure_type), POINTER :: bs_env
1573 : TYPE(qs_environment_type), POINTER :: qs_env
1574 : TYPE(cp_fm_type), DIMENSION(:) :: fm_W_MIC_time
1575 :
1576 : CHARACTER(LEN=*), PARAMETER :: routineN = 'multiply_fm_W_MIC_time_with_Minv_Gamma'
1577 :
1578 : INTEGER :: handle, i_t, n_RI, ndep
1579 : TYPE(cp_fm_type) :: fm_work
1580 32 : TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:, :) :: fm_Minv_Gamma
1581 :
1582 32 : CALL timeset(routineN, handle)
1583 :
1584 32 : n_RI = bs_env%n_RI
1585 :
1586 32 : CALL cp_fm_create(fm_work, fm_W_MIC_time(1)%matrix_struct)
1587 :
1588 : ! compute Gamma-only RI-metric matrix M(k=0); no regularization
1589 : CALL RI_2c_integral_mat(qs_env, fm_Minv_Gamma, fm_W_MIC_time(1), n_RI, &
1590 32 : bs_env%ri_metric, do_kpoints=.FALSE.)
1591 :
1592 32 : CALL cp_fm_power(fm_Minv_Gamma(1, 1), fm_work, -1.0_dp, 0.0_dp, ndep)
1593 :
1594 : ! M^-1(k=0)*W^MIC(iτ)*M^-1(k=0)
1595 272 : DO i_t = 1, SIZE(fm_W_MIC_time)
1596 :
1597 : CALL parallel_gemm('N', 'N', n_RI, n_RI, n_RI, 1.0_dp, fm_Minv_Gamma(1, 1), &
1598 240 : fm_W_MIC_time(i_t), 0.0_dp, fm_work)
1599 :
1600 : CALL parallel_gemm('N', 'N', n_RI, n_RI, n_RI, 1.0_dp, fm_work, &
1601 272 : fm_Minv_Gamma(1, 1), 0.0_dp, fm_W_MIC_time(i_t))
1602 :
1603 : END DO
1604 :
1605 32 : CALL cp_fm_release(fm_work)
1606 32 : CALL cp_fm_release(fm_Minv_Gamma)
1607 :
1608 32 : CALL timestop(handle)
1609 :
1610 64 : END SUBROUTINE multiply_fm_W_MIC_time_with_Minv_Gamma
1611 :
1612 : ! **************************************************************************************************
1613 : !> \brief ...
1614 : !> \param bs_env ...
1615 : !> \param qs_env ...
1616 : !> \param fm_Sigma_x_Gamma ...
1617 : ! **************************************************************************************************
1618 22 : SUBROUTINE get_Sigma_x(bs_env, qs_env, fm_Sigma_x_Gamma)
1619 : TYPE(post_scf_bandstructure_type), POINTER :: bs_env
1620 : TYPE(qs_environment_type), POINTER :: qs_env
1621 : TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:) :: fm_Sigma_x_Gamma
1622 :
1623 : CHARACTER(LEN=*), PARAMETER :: routineN = 'get_Sigma_x'
1624 :
1625 : INTEGER :: handle, ispin
1626 :
1627 22 : CALL timeset(routineN, handle)
1628 :
1629 92 : ALLOCATE (fm_Sigma_x_Gamma(bs_env%n_spin))
1630 48 : DO ispin = 1, bs_env%n_spin
1631 48 : CALL cp_fm_create(fm_Sigma_x_Gamma(ispin), bs_env%fm_s_Gamma%matrix_struct)
1632 : END DO
1633 :
1634 22 : IF (bs_env%Sigma_x_exists) THEN
1635 14 : DO ispin = 1, bs_env%n_spin
1636 14 : CALL fm_read(fm_Sigma_x_Gamma(ispin), bs_env, bs_env%Sigma_x_name, ispin)
1637 : END DO
1638 : ELSE
1639 16 : CALL compute_Sigma_x(bs_env, qs_env, fm_Sigma_x_Gamma)
1640 : END IF
1641 :
1642 22 : CALL timestop(handle)
1643 :
1644 22 : END SUBROUTINE get_Sigma_x
1645 :
1646 : ! **************************************************************************************************
1647 : !> \brief ...
1648 : !> \param bs_env ...
1649 : !> \param qs_env ...
1650 : !> \param fm_Sigma_x_Gamma ...
1651 : ! **************************************************************************************************
1652 16 : SUBROUTINE compute_Sigma_x(bs_env, qs_env, fm_Sigma_x_Gamma)
1653 : TYPE(post_scf_bandstructure_type), POINTER :: bs_env
1654 : TYPE(qs_environment_type), POINTER :: qs_env
1655 : TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:) :: fm_Sigma_x_Gamma
1656 :
1657 : CHARACTER(LEN=*), PARAMETER :: routineN = 'compute_Sigma_x'
1658 :
1659 : INTEGER :: handle, i_intval_idx, ispin, j_intval_idx
1660 : INTEGER, DIMENSION(2) :: i_atoms, j_atoms
1661 : REAL(KIND=dp) :: t1
1662 16 : TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:, :) :: fm_Vtr_Gamma
1663 : TYPE(dbcsr_type) :: mat_Sigma_x_Gamma
1664 528 : TYPE(dbt_type) :: t_2c_D, t_2c_Sigma_x, t_2c_V, t_3c_x_V
1665 :
1666 16 : CALL timeset(routineN, handle)
1667 :
1668 16 : t1 = m_walltime()
1669 :
1670 16 : CALL dbt_create(bs_env%t_G, t_2c_D)
1671 16 : CALL dbt_create(bs_env%t_W, t_2c_V)
1672 16 : CALL dbt_create(bs_env%t_G, t_2c_Sigma_x)
1673 16 : CALL dbt_create(bs_env%t_RI_AO__AO, t_3c_x_V)
1674 16 : CALL dbcsr_create(mat_Sigma_x_Gamma, template=bs_env%mat_ao_ao%matrix)
1675 :
1676 : ! 1. Compute truncated Coulomb operator matrix V^tr(k=0) (cutoff rad: cellsize/2)
1677 : CALL RI_2c_integral_mat(qs_env, fm_Vtr_Gamma, bs_env%fm_RI_RI, bs_env%n_RI, &
1678 16 : bs_env%trunc_coulomb, do_kpoints=.FALSE.)
1679 :
1680 : ! 2. Compute M^-1(k=0) and get M^-1(k=0)*V^tr(k=0)*M^-1(k=0)
1681 16 : CALL multiply_fm_W_MIC_time_with_Minv_Gamma(bs_env, qs_env, fm_Vtr_Gamma(:, 1))
1682 :
1683 34 : DO ispin = 1, bs_env%n_spin
1684 :
1685 : ! 3. Compute density matrix D_µν
1686 18 : CALL G_occ_vir(bs_env, 0.0_dp, bs_env%fm_work_mo(2), ispin, occ=.TRUE., vir=.FALSE.)
1687 :
1688 : CALL fm_to_local_tensor(bs_env%fm_work_mo(2), bs_env%mat_ao_ao%matrix, &
1689 : bs_env%mat_ao_ao_tensor%matrix, t_2c_D, bs_env, &
1690 18 : bs_env%atoms_i_t_group)
1691 :
1692 : CALL fm_to_local_tensor(fm_Vtr_Gamma(1, 1), bs_env%mat_RI_RI%matrix, &
1693 : bs_env%mat_RI_RI_tensor%matrix, t_2c_V, bs_env, &
1694 18 : bs_env%atoms_j_t_group)
1695 :
1696 : ! every group has its own range of i_atoms and j_atoms; only deal with a
1697 : ! limited number of i_atom-j_atom pairs simultaneously in a group to save memory
1698 36 : DO i_intval_idx = 1, bs_env%n_intervals_i
1699 54 : DO j_intval_idx = 1, bs_env%n_intervals_j
1700 54 : i_atoms = bs_env%i_atom_intervals(1:2, i_intval_idx)
1701 54 : j_atoms = bs_env%j_atom_intervals(1:2, j_intval_idx)
1702 :
1703 : ! 4. compute 3-center integrals (µν|P) ("|": truncated Coulomb operator)
1704 : ! 5. M_νσQ(iτ) = sum_P (νσ|P) (M^-1(k=0)*V^tr(k=0)*M^-1(k=0))_PQ(iτ)
1705 18 : CALL compute_3c_and_contract_W(qs_env, bs_env, i_atoms, j_atoms, t_3c_x_V, t_2c_V)
1706 :
1707 : ! 6. tensor operations with D and computation of Σ^x
1708 : ! Σ^x_λσ(k=0) = sum_νQ M_νσQ(iτ) sum_µ (λµ|Q) D_µν
1709 : CALL contract_to_Sigma(t_2c_D, t_3c_x_V, t_2c_Sigma_x, i_atoms, j_atoms, &
1710 36 : qs_env, bs_env, occ=.TRUE., vir=.FALSE., clear_W=.TRUE.)
1711 :
1712 : END DO ! j_atoms
1713 : END DO ! i_atoms
1714 :
1715 : CALL local_dbt_to_global_mat(t_2c_Sigma_x, bs_env%mat_ao_ao_tensor%matrix, &
1716 18 : mat_Sigma_x_Gamma, bs_env%para_env)
1717 :
1718 : CALL write_matrix(mat_Sigma_x_Gamma, ispin, bs_env%Sigma_x_name, &
1719 18 : bs_env%fm_work_mo(1), qs_env)
1720 :
1721 34 : CALL copy_dbcsr_to_fm(mat_Sigma_x_Gamma, fm_Sigma_x_Gamma(ispin))
1722 :
1723 : END DO ! ispin
1724 :
1725 16 : IF (bs_env%unit_nr > 0) THEN
1726 : WRITE (bs_env%unit_nr, '(T2,A,T58,A,F7.1,A)') &
1727 8 : 'Computed Σ^x(k=0),', ' Execution time', m_walltime() - t1, ' s'
1728 8 : WRITE (bs_env%unit_nr, '(A)') ' '
1729 : END IF
1730 :
1731 16 : CALL dbcsr_release(mat_Sigma_x_Gamma)
1732 16 : CALL dbt_destroy(t_2c_D)
1733 16 : CALL dbt_destroy(t_2c_V)
1734 16 : CALL dbt_destroy(t_2c_Sigma_x)
1735 16 : CALL dbt_destroy(t_3c_x_V)
1736 16 : CALL cp_fm_release(fm_Vtr_Gamma)
1737 :
1738 16 : CALL timestop(handle)
1739 :
1740 32 : END SUBROUTINE compute_Sigma_x
1741 :
1742 : ! **************************************************************************************************
1743 : !> \brief ...
1744 : !> \param bs_env ...
1745 : !> \param qs_env ...
1746 : !> \param fm_W_MIC_time ...
1747 : !> \param fm_Sigma_c_Gamma_time ...
1748 : ! **************************************************************************************************
1749 22 : SUBROUTINE get_Sigma_c(bs_env, qs_env, fm_W_MIC_time, fm_Sigma_c_Gamma_time)
1750 : TYPE(post_scf_bandstructure_type), POINTER :: bs_env
1751 : TYPE(qs_environment_type), POINTER :: qs_env
1752 : TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:) :: fm_W_MIC_time
1753 : TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:, :, :) :: fm_Sigma_c_Gamma_time
1754 :
1755 : CHARACTER(LEN=*), PARAMETER :: routineN = 'get_Sigma_c'
1756 :
1757 : INTEGER :: handle, i_intval_idx, i_t, ispin, &
1758 : j_intval_idx, read_write_index
1759 : INTEGER, DIMENSION(2) :: i_atoms, j_atoms
1760 : REAL(KIND=dp) :: t1, tau
1761 22 : TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: mat_Sigma_neg_tau, mat_Sigma_pos_tau
1762 374 : TYPE(dbt_type) :: t_2c_Gocc, t_2c_Gvir, &
1763 198 : t_2c_Sigma_neg_tau, &
1764 550 : t_2c_Sigma_pos_tau, t_2c_W, t_3c_x_W
1765 :
1766 22 : CALL timeset(routineN, handle)
1767 :
1768 : CALL create_mat_for_Sigma_c(bs_env, t_2c_Gocc, t_2c_Gvir, t_2c_W, t_2c_Sigma_neg_tau, &
1769 : t_2c_Sigma_pos_tau, t_3c_x_W, &
1770 22 : mat_Sigma_neg_tau, mat_Sigma_pos_tau)
1771 :
1772 346 : DO i_t = 1, bs_env%num_time_freq_points
1773 :
1774 710 : DO ispin = 1, bs_env%n_spin
1775 :
1776 364 : t1 = m_walltime()
1777 :
1778 364 : read_write_index = i_t + (ispin - 1)*bs_env%num_time_freq_points
1779 :
1780 : ! read self-energy from restart
1781 364 : IF (bs_env%Sigma_c_exists(i_t, ispin)) THEN
1782 120 : CALL fm_read(bs_env%fm_work_mo(1), bs_env, bs_env%Sigma_p_name, read_write_index)
1783 : CALL copy_fm_to_dbcsr(bs_env%fm_work_mo(1), mat_Sigma_pos_tau(i_t, ispin)%matrix, &
1784 120 : keep_sparsity=.FALSE.)
1785 120 : CALL fm_read(bs_env%fm_work_mo(1), bs_env, bs_env%Sigma_n_name, read_write_index)
1786 : CALL copy_fm_to_dbcsr(bs_env%fm_work_mo(1), mat_Sigma_neg_tau(i_t, ispin)%matrix, &
1787 120 : keep_sparsity=.FALSE.)
1788 120 : IF (bs_env%unit_nr > 0) THEN
1789 60 : WRITE (bs_env%unit_nr, '(T2,2A,I3,A,I3,A,F7.1,A)') 'Read Σ^c(iτ,k=0) ', &
1790 60 : 'from file for time point ', i_t, ' /', bs_env%num_time_freq_points, &
1791 120 : ', Execution time', m_walltime() - t1, ' s'
1792 : END IF
1793 :
1794 : CYCLE
1795 :
1796 : END IF
1797 :
1798 244 : tau = bs_env%imag_time_points(i_t)
1799 :
1800 244 : CALL G_occ_vir(bs_env, tau, bs_env%fm_Gocc, ispin, occ=.TRUE., vir=.FALSE.)
1801 244 : CALL G_occ_vir(bs_env, tau, bs_env%fm_Gvir, ispin, occ=.FALSE., vir=.TRUE.)
1802 :
1803 : ! fm G^occ, G^vir and W to local tensor
1804 : CALL fm_to_local_tensor(bs_env%fm_Gocc, bs_env%mat_ao_ao%matrix, &
1805 : bs_env%mat_ao_ao_tensor%matrix, t_2c_Gocc, bs_env, &
1806 244 : bs_env%atoms_i_t_group)
1807 : CALL fm_to_local_tensor(bs_env%fm_Gvir, bs_env%mat_ao_ao%matrix, &
1808 : bs_env%mat_ao_ao_tensor%matrix, t_2c_Gvir, bs_env, &
1809 244 : bs_env%atoms_i_t_group)
1810 : CALL fm_to_local_tensor(fm_W_MIC_time(i_t), bs_env%mat_RI_RI%matrix, &
1811 : bs_env%mat_RI_RI_tensor%matrix, t_2c_W, bs_env, &
1812 244 : bs_env%atoms_j_t_group)
1813 :
1814 : ! every group has its own range of i_atoms and j_atoms; only deal with a
1815 : ! limited number of i_atom-j_atom pairs simultaneously in a group to save memory
1816 488 : DO i_intval_idx = 1, bs_env%n_intervals_i
1817 732 : DO j_intval_idx = 1, bs_env%n_intervals_j
1818 732 : i_atoms = bs_env%i_atom_intervals(1:2, i_intval_idx)
1819 732 : j_atoms = bs_env%j_atom_intervals(1:2, j_intval_idx)
1820 :
1821 244 : IF (bs_env%skip_Sigma_occ(i_intval_idx, j_intval_idx) .AND. &
1822 : bs_env%skip_Sigma_vir(i_intval_idx, j_intval_idx)) CYCLE
1823 :
1824 : ! 1. compute 3-center integrals (µν|P) ("|": truncated Coulomb operator)
1825 : ! 2. tensor operation M_νσQ(iτ) = sum_P (νσ|P) W^MIC_PQ(iτ)
1826 226 : CALL compute_3c_and_contract_W(qs_env, bs_env, i_atoms, j_atoms, t_3c_x_W, t_2c_W)
1827 :
1828 : ! 3. Σ_λσ(iτ,k=0) = sum_νQ M_νσQ(iτ) sum_µ (λµ|Q) G^occ_µν(i|τ|) for τ < 0
1829 : ! (recall M_νσQ(iτ) = M_νσQ(-iτ) because W^MIC_PQ(iτ) = W^MIC_PQ(-iτ) )
1830 : CALL contract_to_Sigma(t_2c_Gocc, t_3c_x_W, t_2c_Sigma_neg_tau, i_atoms, j_atoms, &
1831 : qs_env, bs_env, occ=.TRUE., vir=.FALSE., clear_W=.FALSE., &
1832 226 : can_skip=bs_env%skip_Sigma_occ(i_intval_idx, j_intval_idx))
1833 :
1834 : ! Σ_λσ(iτ,k=0) = sum_νQ M_νσQ(iτ) sum_µ (λµ|Q) G^vir_µν(i|τ|) for τ > 0
1835 : CALL contract_to_Sigma(t_2c_Gvir, t_3c_x_W, t_2c_Sigma_pos_tau, i_atoms, j_atoms, &
1836 : qs_env, bs_env, occ=.FALSE., vir=.TRUE., clear_W=.TRUE., &
1837 488 : can_skip=bs_env%skip_Sigma_vir(i_intval_idx, j_intval_idx))
1838 :
1839 : END DO ! j_atoms
1840 : END DO ! i_atoms
1841 :
1842 : ! 4. communicate data tensor t_2c_Sigma (which is local in the subgroup)
1843 : ! to the global dbcsr matrix mat_Sigma_pos/neg_tau (which stores Σ for all iτ)
1844 : CALL local_dbt_to_global_mat(t_2c_Sigma_neg_tau, bs_env%mat_ao_ao_tensor%matrix, &
1845 244 : mat_Sigma_neg_tau(i_t, ispin)%matrix, bs_env%para_env)
1846 : CALL local_dbt_to_global_mat(t_2c_Sigma_pos_tau, bs_env%mat_ao_ao_tensor%matrix, &
1847 244 : mat_Sigma_pos_tau(i_t, ispin)%matrix, bs_env%para_env)
1848 :
1849 : CALL write_matrix(mat_Sigma_pos_tau(i_t, ispin)%matrix, read_write_index, &
1850 244 : bs_env%Sigma_p_name, bs_env%fm_work_mo(1), qs_env)
1851 : CALL write_matrix(mat_Sigma_neg_tau(i_t, ispin)%matrix, read_write_index, &
1852 244 : bs_env%Sigma_n_name, bs_env%fm_work_mo(1), qs_env)
1853 :
1854 568 : IF (bs_env%unit_nr > 0) THEN
1855 : WRITE (bs_env%unit_nr, '(T2,A,I10,A,I3,A,F7.1,A)') &
1856 122 : 'Computed Σ^c(iτ,k=0) for time point ', i_t, ' /', bs_env%num_time_freq_points, &
1857 244 : ', Execution time', m_walltime() - t1, ' s'
1858 : END IF
1859 :
1860 : END DO ! ispin
1861 :
1862 : END DO ! i_t
1863 :
1864 22 : IF (bs_env%unit_nr > 0) WRITE (bs_env%unit_nr, '(A)') ' '
1865 :
1866 : CALL fill_fm_Sigma_c_Gamma_time(fm_Sigma_c_Gamma_time, bs_env, &
1867 22 : mat_Sigma_pos_tau, mat_Sigma_neg_tau)
1868 :
1869 22 : CALL print_skipping(bs_env)
1870 :
1871 : CALL destroy_mat_Sigma_c(t_2c_Gocc, t_2c_Gvir, t_2c_W, t_2c_Sigma_neg_tau, &
1872 : t_2c_Sigma_pos_tau, t_3c_x_W, fm_W_MIC_time, &
1873 22 : mat_Sigma_neg_tau, mat_Sigma_pos_tau)
1874 :
1875 22 : CALL delete_unnecessary_files(bs_env)
1876 :
1877 22 : CALL timestop(handle)
1878 :
1879 44 : END SUBROUTINE get_Sigma_c
1880 :
1881 : ! **************************************************************************************************
1882 : !> \brief ...
1883 : !> \param bs_env ...
1884 : !> \param t_2c_Gocc ...
1885 : !> \param t_2c_Gvir ...
1886 : !> \param t_2c_W ...
1887 : !> \param t_2c_Sigma_neg_tau ...
1888 : !> \param t_2c_Sigma_pos_tau ...
1889 : !> \param t_3c_x_W ...
1890 : !> \param mat_Sigma_neg_tau ...
1891 : !> \param mat_Sigma_pos_tau ...
1892 : ! **************************************************************************************************
1893 22 : SUBROUTINE create_mat_for_Sigma_c(bs_env, t_2c_Gocc, t_2c_Gvir, t_2c_W, t_2c_Sigma_neg_tau, &
1894 : t_2c_Sigma_pos_tau, t_3c_x_W, &
1895 : mat_Sigma_neg_tau, mat_Sigma_pos_tau)
1896 :
1897 : TYPE(post_scf_bandstructure_type), POINTER :: bs_env
1898 : TYPE(dbt_type) :: t_2c_Gocc, t_2c_Gvir, t_2c_W, &
1899 : t_2c_Sigma_neg_tau, &
1900 : t_2c_Sigma_pos_tau, t_3c_x_W
1901 : TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: mat_Sigma_neg_tau, mat_Sigma_pos_tau
1902 :
1903 : CHARACTER(LEN=*), PARAMETER :: routineN = 'create_mat_for_Sigma_c'
1904 :
1905 : INTEGER :: handle, i_t, ispin
1906 :
1907 22 : CALL timeset(routineN, handle)
1908 :
1909 22 : CALL dbt_create(bs_env%t_G, t_2c_Gocc)
1910 22 : CALL dbt_create(bs_env%t_G, t_2c_Gvir)
1911 22 : CALL dbt_create(bs_env%t_W, t_2c_W)
1912 22 : CALL dbt_create(bs_env%t_G, t_2c_Sigma_neg_tau)
1913 22 : CALL dbt_create(bs_env%t_G, t_2c_Sigma_pos_tau)
1914 22 : CALL dbt_create(bs_env%t_RI_AO__AO, t_3c_x_W)
1915 :
1916 22 : NULLIFY (mat_Sigma_neg_tau, mat_Sigma_pos_tau)
1917 478 : ALLOCATE (mat_Sigma_neg_tau(bs_env%num_time_freq_points, bs_env%n_spin))
1918 478 : ALLOCATE (mat_Sigma_pos_tau(bs_env%num_time_freq_points, bs_env%n_spin))
1919 :
1920 48 : DO ispin = 1, bs_env%n_spin
1921 412 : DO i_t = 1, bs_env%num_time_freq_points
1922 364 : ALLOCATE (mat_Sigma_neg_tau(i_t, ispin)%matrix)
1923 364 : ALLOCATE (mat_Sigma_pos_tau(i_t, ispin)%matrix)
1924 364 : CALL dbcsr_create(mat_Sigma_neg_tau(i_t, ispin)%matrix, template=bs_env%mat_ao_ao%matrix)
1925 390 : CALL dbcsr_create(mat_Sigma_pos_tau(i_t, ispin)%matrix, template=bs_env%mat_ao_ao%matrix)
1926 : END DO
1927 : END DO
1928 :
1929 22 : CALL timestop(handle)
1930 :
1931 22 : END SUBROUTINE create_mat_for_Sigma_c
1932 :
1933 : ! **************************************************************************************************
1934 : !> \brief ...
1935 : !> \param qs_env ...
1936 : !> \param bs_env ...
1937 : !> \param i_atoms ...
1938 : !> \param j_atoms ...
1939 : !> \param t_3c_x_W ...
1940 : !> \param t_2c_W ...
1941 : ! **************************************************************************************************
1942 244 : SUBROUTINE compute_3c_and_contract_W(qs_env, bs_env, i_atoms, j_atoms, t_3c_x_W, t_2c_W)
1943 :
1944 : TYPE(qs_environment_type), POINTER :: qs_env
1945 : TYPE(post_scf_bandstructure_type), POINTER :: bs_env
1946 : INTEGER, DIMENSION(2) :: i_atoms, j_atoms
1947 : TYPE(dbt_type) :: t_3c_x_W, t_2c_W
1948 :
1949 : CHARACTER(LEN=*), PARAMETER :: routineN = 'compute_3c_and_contract_W'
1950 :
1951 : INTEGER :: handle, RI_intval_idx
1952 : INTEGER, DIMENSION(2) :: bounds_j, RI_atoms
1953 4148 : TYPE(dbt_type) :: t_3c_for_W, t_3c_x_W_tmp
1954 :
1955 244 : CALL timeset(routineN, handle)
1956 :
1957 244 : CALL dbt_create(bs_env%t_RI__AO_AO, t_3c_x_W_tmp)
1958 244 : CALL dbt_create(bs_env%t_RI__AO_AO, t_3c_for_W)
1959 :
1960 : bounds_j(1:2) = [bs_env%i_RI_start_from_atom(j_atoms(1)), &
1961 732 : bs_env%i_RI_end_from_atom(j_atoms(2))]
1962 :
1963 488 : DO RI_intval_idx = 1, bs_env%n_intervals_inner_loop_atoms
1964 732 : RI_atoms = bs_env%inner_loop_atom_intervals(1:2, RI_intval_idx)
1965 :
1966 : ! 1. compute 3-center integrals (µν|P) ("|": truncated Coulomb operator)
1967 : CALL compute_3c_integrals(qs_env, bs_env, t_3c_for_W, &
1968 244 : atoms_AO_1=i_atoms, atoms_RI=RI_atoms)
1969 :
1970 : ! 2. tensor operation M_νσQ(iτ) = sum_P (νσ|P) W^MIC_PQ(iτ)
1971 : CALL dbt_contract(alpha=1.0_dp, &
1972 : tensor_1=t_2c_W, &
1973 : tensor_2=t_3c_for_W, &
1974 : beta=1.0_dp, &
1975 : tensor_3=t_3c_x_W_tmp, &
1976 : contract_1=[2], notcontract_1=[1], map_1=[1], &
1977 : contract_2=[1], notcontract_2=[2, 3], map_2=[2, 3], &
1978 : bounds_2=bounds_j, &
1979 488 : filter_eps=bs_env%eps_filter)
1980 :
1981 : END DO ! RI_atoms
1982 :
1983 : ! 3. reorder tensor
1984 244 : CALL dbt_copy(t_3c_x_W_tmp, t_3c_x_W, order=[1, 2, 3], move_data=.TRUE.)
1985 :
1986 244 : CALL dbt_destroy(t_3c_x_W_tmp)
1987 244 : CALL dbt_destroy(t_3c_for_W)
1988 :
1989 244 : CALL timestop(handle)
1990 :
1991 244 : END SUBROUTINE compute_3c_and_contract_W
1992 :
1993 : ! **************************************************************************************************
1994 : !> \brief ...
1995 : !> \param t_2c_G ...
1996 : !> \param t_3c_x_W ...
1997 : !> \param t_2c_Sigma ...
1998 : !> \param i_atoms ...
1999 : !> \param j_atoms ...
2000 : !> \param qs_env ...
2001 : !> \param bs_env ...
2002 : !> \param occ ...
2003 : !> \param vir ...
2004 : !> \param clear_W ...
2005 : !> \param can_skip ...
2006 : ! **************************************************************************************************
2007 470 : SUBROUTINE contract_to_Sigma(t_2c_G, t_3c_x_W, t_2c_Sigma, i_atoms, j_atoms, qs_env, bs_env, &
2008 : occ, vir, clear_W, can_skip)
2009 : TYPE(dbt_type) :: t_2c_G, t_3c_x_W, t_2c_Sigma
2010 : INTEGER, DIMENSION(2) :: i_atoms, j_atoms
2011 : TYPE(qs_environment_type), POINTER :: qs_env
2012 : TYPE(post_scf_bandstructure_type), POINTER :: bs_env
2013 : LOGICAL :: occ, vir, clear_W
2014 : LOGICAL, OPTIONAL :: can_skip
2015 :
2016 : CHARACTER(LEN=*), PARAMETER :: routineN = 'contract_to_Sigma'
2017 :
2018 : INTEGER :: handle, inner_loop_atoms_interval_index
2019 : INTEGER(KIND=int_8) :: flop
2020 : INTEGER, DIMENSION(2) :: bounds_i, IL_atoms
2021 : REAL(KIND=dp) :: sign_Sigma
2022 11750 : TYPE(dbt_type) :: t_3c_for_G, t_3c_x_G, t_3c_x_G_2
2023 :
2024 470 : CALL timeset(routineN, handle)
2025 :
2026 470 : CPASSERT(occ .EQV. (.NOT. vir))
2027 470 : IF (occ) sign_Sigma = -1.0_dp
2028 470 : IF (vir) sign_Sigma = 1.0_dp
2029 :
2030 470 : CALL dbt_create(bs_env%t_RI_AO__AO, t_3c_for_G)
2031 470 : CALL dbt_create(bs_env%t_RI_AO__AO, t_3c_x_G)
2032 470 : CALL dbt_create(bs_env%t_RI_AO__AO, t_3c_x_G_2)
2033 :
2034 : bounds_i(1:2) = [bs_env%i_ao_start_from_atom(i_atoms(1)), &
2035 1410 : bs_env%i_ao_end_from_atom(i_atoms(2))]
2036 :
2037 940 : DO inner_loop_atoms_interval_index = 1, bs_env%n_intervals_inner_loop_atoms
2038 1410 : IL_atoms = bs_env%inner_loop_atom_intervals(1:2, inner_loop_atoms_interval_index)
2039 :
2040 : CALL compute_3c_integrals(qs_env, bs_env, t_3c_for_G, &
2041 470 : atoms_RI=j_atoms, atoms_AO_2=IL_atoms)
2042 :
2043 : CALL dbt_contract(alpha=1.0_dp, &
2044 : tensor_1=t_2c_G, &
2045 : tensor_2=t_3c_for_G, &
2046 : beta=1.0_dp, &
2047 : tensor_3=t_3c_x_G, &
2048 : contract_1=[2], notcontract_1=[1], map_1=[3], &
2049 : contract_2=[3], notcontract_2=[1, 2], map_2=[1, 2], &
2050 : bounds_2=bounds_i, &
2051 940 : filter_eps=bs_env%eps_filter)
2052 :
2053 : END DO ! IL_atoms
2054 :
2055 470 : CALL dbt_copy(t_3c_x_G, t_3c_x_G_2, order=[1, 3, 2], move_data=.TRUE.)
2056 :
2057 : CALL dbt_contract(alpha=sign_Sigma, &
2058 : tensor_1=t_3c_x_W, &
2059 : tensor_2=t_3c_x_G_2, &
2060 : beta=1.0_dp, &
2061 : tensor_3=t_2c_Sigma, &
2062 : contract_1=[1, 2], notcontract_1=[3], map_1=[1], &
2063 : contract_2=[1, 2], notcontract_2=[3], map_2=[2], &
2064 470 : filter_eps=bs_env%eps_filter, move_data=clear_W, flop=flop)
2065 :
2066 470 : IF (PRESENT(can_skip)) THEN
2067 452 : IF (flop == 0_int_8) can_skip = .TRUE.
2068 : END IF
2069 :
2070 470 : CALL dbt_destroy(t_3c_for_G)
2071 470 : CALL dbt_destroy(t_3c_x_G)
2072 470 : CALL dbt_destroy(t_3c_x_G_2)
2073 :
2074 470 : CALL timestop(handle)
2075 :
2076 470 : END SUBROUTINE contract_to_Sigma
2077 :
2078 : ! **************************************************************************************************
2079 : !> \brief ...
2080 : !> \param fm_Sigma_c_Gamma_time ...
2081 : !> \param bs_env ...
2082 : !> \param mat_Sigma_pos_tau ...
2083 : !> \param mat_Sigma_neg_tau ...
2084 : ! **************************************************************************************************
2085 22 : SUBROUTINE fill_fm_Sigma_c_Gamma_time(fm_Sigma_c_Gamma_time, bs_env, &
2086 : mat_Sigma_pos_tau, mat_Sigma_neg_tau)
2087 :
2088 : TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:, :, :) :: fm_Sigma_c_Gamma_time
2089 : TYPE(post_scf_bandstructure_type), POINTER :: bs_env
2090 : TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: mat_Sigma_pos_tau, mat_Sigma_neg_tau
2091 :
2092 : CHARACTER(LEN=*), PARAMETER :: routineN = 'fill_fm_Sigma_c_Gamma_time'
2093 :
2094 : INTEGER :: handle, i_t, ispin, pos_neg
2095 :
2096 22 : CALL timeset(routineN, handle)
2097 :
2098 894 : ALLOCATE (fm_Sigma_c_Gamma_time(bs_env%num_time_freq_points, 2, bs_env%n_spin))
2099 48 : DO ispin = 1, bs_env%n_spin
2100 412 : DO i_t = 1, bs_env%num_time_freq_points
2101 1092 : DO pos_neg = 1, 2
2102 : CALL cp_fm_create(fm_Sigma_c_Gamma_time(i_t, pos_neg, ispin), &
2103 1092 : bs_env%fm_s_Gamma%matrix_struct)
2104 : END DO
2105 : CALL copy_dbcsr_to_fm(mat_Sigma_pos_tau(i_t, ispin)%matrix, &
2106 364 : fm_Sigma_c_Gamma_time(i_t, 1, ispin))
2107 : CALL copy_dbcsr_to_fm(mat_Sigma_neg_tau(i_t, ispin)%matrix, &
2108 390 : fm_Sigma_c_Gamma_time(i_t, 2, ispin))
2109 : END DO
2110 : END DO
2111 :
2112 22 : CALL timestop(handle)
2113 :
2114 22 : END SUBROUTINE fill_fm_Sigma_c_Gamma_time
2115 :
2116 : ! **************************************************************************************************
2117 : !> \brief ...
2118 : !> \param bs_env ...
2119 : ! **************************************************************************************************
2120 22 : SUBROUTINE print_skipping(bs_env)
2121 :
2122 : TYPE(post_scf_bandstructure_type), POINTER :: bs_env
2123 :
2124 : CHARACTER(LEN=*), PARAMETER :: routineN = 'print_skipping'
2125 :
2126 : INTEGER :: handle, i_intval_idx, j_intval_idx, &
2127 : n_skip
2128 :
2129 22 : CALL timeset(routineN, handle)
2130 :
2131 22 : n_skip = 0
2132 :
2133 44 : DO i_intval_idx = 1, bs_env%n_intervals_i
2134 66 : DO j_intval_idx = 1, bs_env%n_intervals_j
2135 22 : IF (bs_env%skip_Sigma_occ(i_intval_idx, j_intval_idx) .AND. &
2136 22 : bs_env%skip_Sigma_vir(i_intval_idx, j_intval_idx)) THEN
2137 2 : n_skip = n_skip + 1
2138 : END IF
2139 : END DO
2140 : END DO
2141 :
2142 22 : IF (bs_env%unit_nr > 0) THEN
2143 : WRITE (bs_env%unit_nr, '(T2,A,T74,F7.1,A)') &
2144 11 : 'Sparsity of Σ^c(iτ,k=0): Percentage of skipped atom pairs:', &
2145 22 : REAL(100*n_skip, KIND=dp)/REAL(i_intval_idx*j_intval_idx, KIND=dp), ' %'
2146 : END IF
2147 :
2148 22 : CALL timestop(handle)
2149 :
2150 22 : END SUBROUTINE print_skipping
2151 :
2152 : ! **************************************************************************************************
2153 : !> \brief ...
2154 : !> \param t_2c_Gocc ...
2155 : !> \param t_2c_Gvir ...
2156 : !> \param t_2c_W ...
2157 : !> \param t_2c_Sigma_neg_tau ...
2158 : !> \param t_2c_Sigma_pos_tau ...
2159 : !> \param t_3c_x_W ...
2160 : !> \param fm_W_MIC_time ...
2161 : !> \param mat_Sigma_neg_tau ...
2162 : !> \param mat_Sigma_pos_tau ...
2163 : ! **************************************************************************************************
2164 22 : SUBROUTINE destroy_mat_Sigma_c(t_2c_Gocc, t_2c_Gvir, t_2c_W, t_2c_Sigma_neg_tau, &
2165 : t_2c_Sigma_pos_tau, t_3c_x_W, fm_W_MIC_time, &
2166 : mat_Sigma_neg_tau, mat_Sigma_pos_tau)
2167 :
2168 : TYPE(dbt_type) :: t_2c_Gocc, t_2c_Gvir, t_2c_W, &
2169 : t_2c_Sigma_neg_tau, &
2170 : t_2c_Sigma_pos_tau, t_3c_x_W
2171 : TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:) :: fm_W_MIC_time
2172 : TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: mat_Sigma_neg_tau, mat_Sigma_pos_tau
2173 :
2174 : CHARACTER(LEN=*), PARAMETER :: routineN = 'destroy_mat_Sigma_c'
2175 :
2176 : INTEGER :: handle
2177 :
2178 22 : CALL timeset(routineN, handle)
2179 :
2180 22 : CALL dbt_destroy(t_2c_Gocc)
2181 22 : CALL dbt_destroy(t_2c_Gvir)
2182 22 : CALL dbt_destroy(t_2c_W)
2183 22 : CALL dbt_destroy(t_2c_Sigma_neg_tau)
2184 22 : CALL dbt_destroy(t_2c_Sigma_pos_tau)
2185 22 : CALL dbt_destroy(t_3c_x_W)
2186 22 : CALL cp_fm_release(fm_W_MIC_time)
2187 22 : CALL dbcsr_deallocate_matrix_set(mat_Sigma_neg_tau)
2188 22 : CALL dbcsr_deallocate_matrix_set(mat_Sigma_pos_tau)
2189 :
2190 22 : CALL timestop(handle)
2191 :
2192 22 : END SUBROUTINE destroy_mat_Sigma_c
2193 :
2194 : ! **************************************************************************************************
2195 : !> \brief ...
2196 : !> \param bs_env ...
2197 : ! **************************************************************************************************
2198 22 : SUBROUTINE delete_unnecessary_files(bs_env)
2199 : TYPE(post_scf_bandstructure_type), POINTER :: bs_env
2200 :
2201 : CHARACTER(LEN=*), PARAMETER :: routineN = 'delete_unnecessary_files'
2202 :
2203 : CHARACTER(LEN=default_string_length) :: f_chi, f_W_t, prefix
2204 : INTEGER :: handle, i_t
2205 :
2206 22 : CALL timeset(routineN, handle)
2207 :
2208 22 : prefix = bs_env%prefix
2209 :
2210 346 : DO i_t = 1, bs_env%num_time_freq_points
2211 :
2212 324 : IF (i_t < 10) THEN
2213 186 : WRITE (f_chi, '(3A,I1,A)') TRIM(prefix), bs_env%chi_name, "_00", i_t, ".matrix"
2214 186 : WRITE (f_W_t, '(3A,I1,A)') TRIM(prefix), bs_env%W_time_name, "_00", i_t, ".matrix"
2215 138 : ELSE IF (i_t < 100) THEN
2216 138 : WRITE (f_chi, '(3A,I2,A)') TRIM(prefix), bs_env%chi_name, "_0", i_t, ".matrix"
2217 138 : WRITE (f_W_t, '(3A,I2,A)') TRIM(prefix), bs_env%W_time_name, "_0", i_t, ".matrix"
2218 : ELSE
2219 0 : CPABORT('Please implement more than 99 time/frequency points.')
2220 : END IF
2221 :
2222 324 : CALL safe_delete(f_chi, bs_env)
2223 346 : CALL safe_delete(f_W_t, bs_env)
2224 :
2225 : END DO
2226 :
2227 22 : CALL timestop(handle)
2228 :
2229 22 : END SUBROUTINE delete_unnecessary_files
2230 :
2231 : ! **************************************************************************************************
2232 : !> \brief ...
2233 : !> \param filename ...
2234 : !> \param bs_env ...
2235 : ! **************************************************************************************************
2236 648 : SUBROUTINE safe_delete(filename, bs_env)
2237 : CHARACTER(LEN=*) :: filename
2238 : TYPE(post_scf_bandstructure_type), POINTER :: bs_env
2239 :
2240 : CHARACTER(LEN=*), PARAMETER :: routineN = 'safe_delete'
2241 :
2242 : INTEGER :: handle
2243 : LOGICAL :: file_exists
2244 :
2245 648 : CALL timeset(routineN, handle)
2246 :
2247 648 : IF (bs_env%para_env%mepos == 0) THEN
2248 :
2249 324 : INQUIRE (file=TRIM(filename), exist=file_exists)
2250 324 : IF (file_exists) CALL mp_file_delete(TRIM(filename))
2251 :
2252 : END IF
2253 :
2254 648 : CALL timestop(handle)
2255 :
2256 648 : END SUBROUTINE safe_delete
2257 :
2258 : ! **************************************************************************************************
2259 : !> \brief ...
2260 : !> \param bs_env ...
2261 : !> \param qs_env ...
2262 : !> \param fm_Sigma_x_Gamma ...
2263 : !> \param fm_Sigma_c_Gamma_time ...
2264 : ! **************************************************************************************************
2265 22 : SUBROUTINE compute_QP_energies(bs_env, qs_env, fm_Sigma_x_Gamma, fm_Sigma_c_Gamma_time)
2266 :
2267 : TYPE(post_scf_bandstructure_type), POINTER :: bs_env
2268 : TYPE(qs_environment_type), POINTER :: qs_env
2269 : TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:) :: fm_Sigma_x_Gamma
2270 : TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:, :, :) :: fm_Sigma_c_Gamma_time
2271 :
2272 : CHARACTER(LEN=*), PARAMETER :: routineN = 'compute_QP_energies'
2273 :
2274 : INTEGER :: handle, ikp, ispin, j_t
2275 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:) :: Sigma_x_ikp_n, V_xc_ikp_n
2276 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :) :: Sigma_c_ikp_n_freq, Sigma_c_ikp_n_time
2277 : TYPE(cp_cfm_type) :: cfm_ks_ikp, cfm_mos_ikp, cfm_s_ikp, &
2278 : cfm_Sigma_x_ikp, cfm_work_ikp
2279 :
2280 22 : CALL timeset(routineN, handle)
2281 :
2282 22 : CALL cp_cfm_create(cfm_mos_ikp, bs_env%fm_s_Gamma%matrix_struct)
2283 22 : CALL cp_cfm_create(cfm_work_ikp, bs_env%fm_s_Gamma%matrix_struct)
2284 : ! JW TODO: fully distribute these arrays at given time; also eigenvalues in bs_env
2285 110 : ALLOCATE (V_xc_ikp_n(bs_env%n_ao), Sigma_x_ikp_n(bs_env%n_ao))
2286 110 : ALLOCATE (Sigma_c_ikp_n_time(bs_env%n_ao, bs_env%num_time_freq_points, 2))
2287 88 : ALLOCATE (Sigma_c_ikp_n_freq(bs_env%n_ao, bs_env%num_time_freq_points, 2))
2288 :
2289 48 : DO ispin = 1, bs_env%n_spin
2290 :
2291 86 : DO ikp = 1, bs_env%nkp_bs_and_DOS
2292 :
2293 : ! 1. get H^KS_µν(k_i) from H^KS_µν(k=0)
2294 : CALL cfm_ikp_from_fm_Gamma(cfm_ks_ikp, bs_env%fm_ks_Gamma(ispin), &
2295 38 : ikp, qs_env, bs_env%kpoints_DOS, "ORB")
2296 :
2297 : ! 2. get S_µν(k_i) from S_µν(k=0)
2298 : CALL cfm_ikp_from_fm_Gamma(cfm_s_ikp, bs_env%fm_s_Gamma, &
2299 38 : ikp, qs_env, bs_env%kpoints_DOS, "ORB")
2300 :
2301 : ! 3. Diagonalize (Roothaan-Hall): H_KS(k_i)*C(k_i) = S(k_i)*C(k_i)*ϵ(k_i)
2302 : CALL cp_cfm_geeig(cfm_ks_ikp, cfm_s_ikp, cfm_mos_ikp, &
2303 38 : bs_env%eigenval_scf(:, ikp, ispin), cfm_work_ikp)
2304 :
2305 : ! 4. V^xc_µν(k=0) -> V^xc_µν(k_i) -> V^xc_nn(k_i)
2306 : CALL to_ikp_and_mo(V_xc_ikp_n, bs_env%fm_V_xc_Gamma(ispin), &
2307 38 : ikp, qs_env, bs_env, cfm_mos_ikp)
2308 :
2309 : ! 5. Σ^x_µν(k=0) -> Σ^x_µν(k_i) -> Σ^x_nn(k_i)
2310 : CALL to_ikp_and_mo(Sigma_x_ikp_n, fm_Sigma_x_Gamma(ispin), &
2311 38 : ikp, qs_env, bs_env, cfm_mos_ikp)
2312 :
2313 : ! 6. Σ^c_µν(k=0,+/-i|τ_j|) -> Σ^c_µν(k_i,+/-i|τ_j|) -> Σ^c_nn(k_i,+/-i|τ_j|)
2314 506 : DO j_t = 1, bs_env%num_time_freq_points
2315 : CALL to_ikp_and_mo(Sigma_c_ikp_n_time(:, j_t, 1), &
2316 : fm_Sigma_c_Gamma_time(j_t, 1, ispin), &
2317 468 : ikp, qs_env, bs_env, cfm_mos_ikp)
2318 : CALL to_ikp_and_mo(Sigma_c_ikp_n_time(:, j_t, 2), &
2319 : fm_Sigma_c_Gamma_time(j_t, 2, ispin), &
2320 506 : ikp, qs_env, bs_env, cfm_mos_ikp)
2321 : END DO
2322 :
2323 : ! 7. Σ^c_nn(k_i,iτ) -> Σ^c_nn(k_i,iω)
2324 38 : CALL time_to_freq(bs_env, Sigma_c_ikp_n_time, Sigma_c_ikp_n_freq, ispin)
2325 :
2326 : ! 8. Analytic continuation Σ^c_nn(k_i,iω) -> Σ^c_nn(k_i,ϵ) and
2327 : ! ϵ_nk_i^GW = ϵ_nk_i^DFT + Σ^c_nn(k_i,ϵ) + Σ^x_nn(k_i) - v^xc_nn(k_i)
2328 : CALL analyt_conti_and_print(bs_env, Sigma_c_ikp_n_freq, Sigma_x_ikp_n, V_xc_ikp_n, &
2329 64 : bs_env%eigenval_scf(:, ikp, ispin), ikp, ispin)
2330 :
2331 : END DO ! ikp_DOS
2332 :
2333 : END DO ! ispin
2334 :
2335 22 : CALL get_all_VBM_CBM_bandgaps(bs_env)
2336 :
2337 22 : CALL cp_fm_release(fm_Sigma_x_Gamma)
2338 22 : CALL cp_fm_release(fm_Sigma_c_Gamma_time)
2339 22 : CALL cp_cfm_release(cfm_ks_ikp)
2340 22 : CALL cp_cfm_release(cfm_s_ikp)
2341 22 : CALL cp_cfm_release(cfm_mos_ikp)
2342 22 : CALL cp_cfm_release(cfm_work_ikp)
2343 22 : CALL cp_cfm_release(cfm_Sigma_x_ikp)
2344 :
2345 22 : CALL timestop(handle)
2346 :
2347 44 : END SUBROUTINE compute_QP_energies
2348 :
2349 : ! **************************************************************************************************
2350 : !> \brief ...
2351 : !> \param array_ikp_n ...
2352 : !> \param fm_Gamma ...
2353 : !> \param ikp ...
2354 : !> \param qs_env ...
2355 : !> \param bs_env ...
2356 : !> \param cfm_mos_ikp ...
2357 : ! **************************************************************************************************
2358 1012 : SUBROUTINE to_ikp_and_mo(array_ikp_n, fm_Gamma, ikp, qs_env, bs_env, cfm_mos_ikp)
2359 :
2360 : REAL(KIND=dp), DIMENSION(:) :: array_ikp_n
2361 : TYPE(cp_fm_type) :: fm_Gamma
2362 : INTEGER :: ikp
2363 : TYPE(qs_environment_type), POINTER :: qs_env
2364 : TYPE(post_scf_bandstructure_type), POINTER :: bs_env
2365 : TYPE(cp_cfm_type) :: cfm_mos_ikp
2366 :
2367 : CHARACTER(LEN=*), PARAMETER :: routineN = 'to_ikp_and_mo'
2368 :
2369 : INTEGER :: handle
2370 : TYPE(cp_fm_type) :: fm_ikp_mo_re
2371 :
2372 1012 : CALL timeset(routineN, handle)
2373 :
2374 1012 : CALL cp_fm_create(fm_ikp_mo_re, fm_Gamma%matrix_struct)
2375 :
2376 1012 : CALL fm_Gamma_ao_to_cfm_ikp_mo(fm_Gamma, fm_ikp_mo_re, ikp, qs_env, bs_env, cfm_mos_ikp)
2377 :
2378 1012 : CALL cp_fm_get_diag(fm_ikp_mo_re, array_ikp_n)
2379 :
2380 1012 : CALL cp_fm_release(fm_ikp_mo_re)
2381 :
2382 1012 : CALL timestop(handle)
2383 :
2384 1012 : END SUBROUTINE to_ikp_and_mo
2385 :
2386 : ! **************************************************************************************************
2387 : !> \brief ...
2388 : !> \param fm_Gamma ...
2389 : !> \param fm_ikp_mo_re ...
2390 : !> \param ikp ...
2391 : !> \param qs_env ...
2392 : !> \param bs_env ...
2393 : !> \param cfm_mos_ikp ...
2394 : ! **************************************************************************************************
2395 4048 : SUBROUTINE fm_Gamma_ao_to_cfm_ikp_mo(fm_Gamma, fm_ikp_mo_re, ikp, qs_env, bs_env, cfm_mos_ikp)
2396 : TYPE(cp_fm_type) :: fm_Gamma, fm_ikp_mo_re
2397 : INTEGER :: ikp
2398 : TYPE(qs_environment_type), POINTER :: qs_env
2399 : TYPE(post_scf_bandstructure_type), POINTER :: bs_env
2400 : TYPE(cp_cfm_type) :: cfm_mos_ikp
2401 :
2402 : CHARACTER(LEN=*), PARAMETER :: routineN = 'fm_Gamma_ao_to_cfm_ikp_mo'
2403 :
2404 : INTEGER :: handle, nmo
2405 : TYPE(cp_cfm_type) :: cfm_ikp_ao, cfm_ikp_mo, cfm_tmp
2406 :
2407 1012 : CALL timeset(routineN, handle)
2408 :
2409 1012 : CALL cp_cfm_create(cfm_ikp_ao, fm_Gamma%matrix_struct)
2410 1012 : CALL cp_cfm_create(cfm_ikp_mo, fm_Gamma%matrix_struct)
2411 1012 : CALL cp_cfm_create(cfm_tmp, fm_Gamma%matrix_struct)
2412 :
2413 : ! get cfm_µν(k_i) from fm_µν(k=0)
2414 1012 : CALL cfm_ikp_from_fm_Gamma(cfm_ikp_ao, fm_Gamma, ikp, qs_env, bs_env%kpoints_DOS, "ORB")
2415 :
2416 1012 : nmo = bs_env%n_ao
2417 1012 : CALL parallel_gemm('N', 'N', nmo, nmo, nmo, z_one, cfm_ikp_ao, cfm_mos_ikp, z_zero, cfm_tmp)
2418 1012 : CALL parallel_gemm('C', 'N', nmo, nmo, nmo, z_one, cfm_mos_ikp, cfm_tmp, z_zero, cfm_ikp_mo)
2419 :
2420 1012 : CALL cp_cfm_to_fm(cfm_ikp_mo, fm_ikp_mo_re)
2421 :
2422 1012 : CALL cp_cfm_release(cfm_ikp_mo)
2423 1012 : CALL cp_cfm_release(cfm_ikp_ao)
2424 1012 : CALL cp_cfm_release(cfm_tmp)
2425 :
2426 1012 : CALL timestop(handle)
2427 :
2428 1012 : END SUBROUTINE fm_Gamma_ao_to_cfm_ikp_mo
2429 :
2430 : END MODULE gw_large_cell_gamma
|