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