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 Iterative routines for GW + Bethe-Salpeter for computing electronic excitations
10 : !> \par History
11 : !> 04.2017 created [Jan Wilhelm]
12 : !> 11.2023 Davidson solver implemented [Maximilian Graml]
13 : ! **************************************************************************************************
14 : MODULE bse_iterative
15 : USE cp_fm_types, ONLY: cp_fm_get_info,&
16 : cp_fm_type
17 : USE group_dist_types, ONLY: get_group_dist,&
18 : group_dist_d1_type
19 : USE input_constants, ONLY: bse_singlet,&
20 : bse_triplet
21 : USE kinds, ONLY: dp
22 : USE message_passing, ONLY: mp_para_env_type,&
23 : mp_request_type
24 : USE mp2_types, ONLY: integ_mat_buffer_type,&
25 : mp2_type
26 : USE physcon, ONLY: evolt
27 : USE rpa_communication, ONLY: communicate_buffer
28 : #include "./base/base_uses.f90"
29 :
30 : IMPLICIT NONE
31 :
32 : PRIVATE
33 :
34 : CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'bse_iterative'
35 :
36 : PUBLIC :: fill_local_3c_arrays, do_subspace_iterations
37 :
38 : CONTAINS
39 :
40 : ! **************************************************************************************************
41 : !> \brief ...
42 : !> \param B_bar_ijQ_bse_local ...
43 : !> \param B_abQ_bse_local ...
44 : !> \param B_bar_iaQ_bse_local ...
45 : !> \param B_iaQ_bse_local ...
46 : !> \param homo ...
47 : !> \param virtual ...
48 : !> \param bse_spin_config ...
49 : !> \param unit_nr ...
50 : !> \param Eigenval ...
51 : !> \param para_env ...
52 : !> \param mp2_env ...
53 : ! **************************************************************************************************
54 0 : SUBROUTINE do_subspace_iterations(B_bar_ijQ_bse_local, B_abQ_bse_local, B_bar_iaQ_bse_local, &
55 : B_iaQ_bse_local, homo, virtual, bse_spin_config, unit_nr, &
56 0 : Eigenval, para_env, mp2_env)
57 :
58 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :) :: B_bar_ijQ_bse_local, B_abQ_bse_local, &
59 : B_bar_iaQ_bse_local, B_iaQ_bse_local
60 : INTEGER :: homo, virtual, bse_spin_config, unit_nr
61 : REAL(KIND=dp), DIMENSION(:) :: Eigenval
62 : TYPE(mp_para_env_type), INTENT(IN) :: para_env
63 : TYPE(mp2_type) :: mp2_env
64 :
65 : CHARACTER(LEN=*), PARAMETER :: routineN = 'do_subspace_iterations'
66 :
67 : CHARACTER(LEN=10) :: bse_davidson_abort_cond_string, &
68 : success_abort_string
69 : INTEGER :: bse_davidson_abort_cond, davidson_converged, fac_max_z_space, handle, i_iter, &
70 : j_print, local_RI_size, num_add_start_z_space, num_davidson_iter, num_en_unconverged, &
71 : num_exact_en_unconverged, num_exc_en, num_max_z_space, num_new_t, num_res_unconverged, &
72 : num_Z_vectors, num_Z_vectors_init
73 : LOGICAL :: bse_full_diag_debug
74 : REAL(kind=dp) :: eps_exc_en, eps_res, max_en_diff, &
75 : max_res_norm, z_space_energy_cutoff
76 0 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:) :: En_diffs, En_diffs_exact, Full_exc_spectrum, &
77 0 : Res_norms, Subspace_full_eigenval, Subspace_new_eigenval, Subspace_prev_eigenval
78 0 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: AZ_reshaped, M_ia_tmp, M_ji_tmp, RI_vector, &
79 0 : Subspace_new_eigenvec, Subspace_residuals_reshaped, Z_vectors_reshaped
80 0 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :) :: AZ, BZ, Subspace_add_dir, &
81 0 : Subspace_ritzvec, W_vectors, Z_vectors
82 :
83 0 : CALL timeset(routineN, handle)
84 :
85 : !MG to del
86 : !Debug flag for exact diagonalization (only using lapack!!!)
87 0 : bse_full_diag_debug = .TRUE.
88 0 : num_en_unconverged = -1
89 0 : num_res_unconverged = -1
90 0 : num_exact_en_unconverged = -1
91 :
92 0 : bse_davidson_abort_cond = mp2_env%ri_g0w0%davidson_abort_cond
93 0 : num_exc_en = mp2_env%ri_g0w0%num_exc_en
94 0 : num_add_start_z_space = mp2_env%ri_g0w0%num_add_start_z_space
95 0 : fac_max_z_space = mp2_env%ri_g0w0%fac_max_z_space
96 0 : num_new_t = mp2_env%ri_g0w0%num_new_t
97 0 : num_davidson_iter = mp2_env%ri_g0w0%num_davidson_iter
98 0 : eps_res = mp2_env%ri_g0w0%eps_res
99 0 : eps_exc_en = mp2_env%ri_g0w0%eps_exc_en
100 0 : z_space_energy_cutoff = mp2_env%ri_g0w0%z_space_energy_cutoff
101 :
102 0 : num_Z_vectors_init = num_exc_en + num_add_start_z_space
103 :
104 0 : IF (unit_nr > 0) THEN
105 0 : WRITE (unit_nr, *) "bse_spin_config", bse_spin_config
106 0 : WRITE (unit_nr, *) "num_exc_en", num_exc_en
107 0 : WRITE (unit_nr, *) "num_add_start_z_space", num_add_start_z_space
108 0 : WRITE (unit_nr, *) "num_Z_vectors_init", num_Z_vectors_init
109 0 : WRITE (unit_nr, *) "fac_max_z_space", fac_max_z_space
110 0 : WRITE (unit_nr, *) "num_new_t", num_new_t
111 0 : WRITE (unit_nr, *) "eps_res", eps_res
112 0 : WRITE (unit_nr, *) "num_davidson_iter", num_davidson_iter
113 0 : WRITE (unit_nr, *) "eps_exc_en", eps_exc_en
114 0 : WRITE (unit_nr, *) "bse_davidson_abort_cond", bse_davidson_abort_cond
115 0 : WRITE (unit_nr, *) "z_space_energy_cutoff", z_space_energy_cutoff
116 0 : WRITE (unit_nr, *) "Printing B_bar_iaQ_bse_local of shape", SHAPE(B_bar_iaQ_bse_local)
117 : END IF
118 :
119 0 : local_RI_size = SIZE(B_iaQ_bse_local, 3)
120 :
121 0 : num_Z_vectors = num_Z_vectors_init
122 0 : num_max_z_space = num_Z_vectors_init*fac_max_z_space
123 :
124 : !Check input parameters and correct them if necessary
125 0 : IF (num_new_t > num_Z_vectors_init) THEN
126 0 : num_new_t = num_Z_vectors_init
127 0 : IF (unit_nr > 0) THEN
128 : CALL cp_warn(__LOCATION__, "Number of added directions has to be smaller/equals than "// &
129 0 : "initial dimension. Corrected num_new_t accordingly.")
130 : END IF
131 : END IF
132 0 : IF (unit_nr > 0) THEN
133 0 : WRITE (unit_nr, *) "Between BSE correction Warnings"
134 : END IF
135 : !If initial number is too big, already the first iteration causes trouble in LAPACK diagonal. (DORGQR)
136 0 : IF (2*num_Z_vectors_init > homo*virtual) THEN
137 : CALL cp_abort(__LOCATION__, "Initial dimension was too large and could not be corrected. "// &
138 0 : "Choose another num_exc_en and num_add_start_z_space or adapt your basis set.")
139 : END IF
140 0 : IF (num_max_z_space .GE. homo*virtual) THEN
141 0 : fac_max_z_space = homo*virtual/num_Z_vectors_init
142 0 : num_max_z_space = num_Z_vectors_init*fac_max_z_space
143 :
144 0 : IF (fac_max_z_space == 0) THEN
145 : CALL cp_abort(__LOCATION__, "Maximal dimension was too large and could not be corrected. "// &
146 0 : "Choose another fac_max_z_space and num_Z_vectors_init or adapt your basis set.")
147 : ELSE
148 0 : IF (unit_nr > 0) THEN
149 : CALL cp_warn(__LOCATION__, "Maximal dimension of Z space has to be smaller than homo*virtual. "// &
150 0 : "Corrected fac_max_z_space accordingly.")
151 : END IF
152 : END IF
153 : END IF
154 :
155 0 : DO i_iter = 1, num_davidson_iter
156 0 : IF (unit_nr > 0) THEN
157 0 : WRITE (unit_nr, *) "Allocating Z_vec,AZ,BZ with dimensions (homo,virt,num_Z)", homo, virtual, num_Z_vectors
158 0 : WRITE (unit_nr, *) 'ProcNr', para_env%mepos, 'you really enter here for i_iter', i_iter
159 : END IF
160 0 : ALLOCATE (Z_vectors(homo, virtual, num_Z_vectors))
161 0 : Z_vectors = 0.0_dp
162 :
163 : !Dellocation procedures are a bit intricate, W_/Z_vectors and eigenvalues are needed for the next iteration,
164 : ! therefore we have to deallocate them separately from the other quantities
165 0 : IF (i_iter == 1) THEN
166 0 : CALL initial_guess_Z_vectors(Z_vectors, Eigenval, num_Z_vectors, homo, virtual)
167 0 : ALLOCATE (Subspace_prev_eigenval(num_exc_en))
168 0 : Subspace_prev_eigenval = 0.0_dp
169 : ELSE
170 0 : Z_vectors(:, :, :) = W_vectors(:, :, :)
171 0 : DEALLOCATE (W_vectors)
172 : END IF
173 0 : IF (unit_nr > 0) THEN
174 0 : WRITE (unit_nr, *) 'ProcNr', para_env%mepos, "Allocated/rewritten Z arrays"
175 : END IF
176 :
177 : CALL create_bse_work_arrays(AZ, Z_vectors_reshaped, AZ_reshaped, BZ, M_ia_tmp, M_ji_tmp, &
178 : RI_vector, Subspace_new_eigenval, Subspace_full_eigenval, Subspace_new_eigenvec, &
179 : Subspace_residuals_reshaped, Subspace_ritzvec, Subspace_add_dir, W_vectors, &
180 0 : homo, virtual, num_Z_vectors, local_RI_size, num_new_t)
181 0 : IF (unit_nr > 0) THEN
182 0 : WRITE (unit_nr, *) 'ProcNr', para_env%mepos, "Allocated Work arrays"
183 : END IF
184 :
185 : CALL compute_AZ(AZ, Z_vectors, B_iaQ_bse_local, B_bar_ijQ_bse_local, B_abQ_bse_local, &
186 : M_ia_tmp, RI_vector, Eigenval, homo, virtual, num_Z_vectors, local_RI_size, &
187 : para_env, bse_spin_config, z_space_energy_cutoff, i_iter, bse_full_diag_debug, &
188 0 : Full_exc_spectrum, unit_nr)
189 :
190 : !MG: functionality of BZ not checked (issue with fm_mat_Q_static_bse_gemm in rpa_util needs to be checked!)
191 : !CALL compute_BZ(BZ, Z_vectors, B_iaQ_bse_local, B_bar_iaQ_bse_local, &
192 : ! M_ji_tmp, homo, virtual, num_Z_vectors, local_RI_size, &
193 : ! para_env)
194 :
195 0 : IF (unit_nr > 0) THEN
196 0 : WRITE (unit_nr, *) 'ProcNr', para_env%mepos, "Computed AZ"
197 : END IF
198 :
199 : !MG to check: Reshaping correct?
200 0 : AZ_reshaped(:, :) = RESHAPE(AZ, (/homo*virtual, num_Z_vectors/))
201 0 : Z_vectors_reshaped(:, :) = RESHAPE(Z_vectors, (/homo*virtual, num_Z_vectors/))
202 :
203 : ! Diagonalize M and extract smallest eigenvalues/corresponding eigenvector
204 : CALL compute_diagonalize_ZAZ(AZ_reshaped, Z_vectors_reshaped, num_Z_vectors, Subspace_new_eigenval, &
205 0 : Subspace_new_eigenvec, num_new_t, Subspace_full_eigenval, para_env, unit_nr)
206 0 : IF (unit_nr > 0) THEN
207 0 : WRITE (unit_nr, *) "Eigenval (eV) in iter=", i_iter, " is:", Subspace_new_eigenval(:6)*evolt
208 : END IF
209 :
210 : ! Threshold in energies
211 : CALL check_en_convergence(Subspace_full_eigenval, Subspace_prev_eigenval, eps_exc_en, num_en_unconverged, &
212 0 : num_exc_en, max_en_diff, En_diffs)
213 0 : IF (unit_nr > 0) THEN
214 0 : WRITE (unit_nr, *) "Largest change of desired exc ens =", max_en_diff
215 : END IF
216 : ! Compute residuals
217 : CALL compute_residuals(AZ_reshaped, Z_vectors_reshaped, Subspace_new_eigenval, Subspace_new_eigenvec, &
218 0 : Subspace_residuals_reshaped, homo, virtual, num_new_t, num_Z_vectors, Subspace_ritzvec)
219 :
220 : !Abort, if residuals are small enough w.r.t threshold
221 : CALL check_res_convergence(Subspace_residuals_reshaped, num_new_t, eps_res, num_res_unconverged, &
222 0 : i_iter, max_res_norm, unit_nr, Res_norms)
223 :
224 0 : davidson_converged = -1
225 0 : IF (num_res_unconverged == 0 .AND. bse_davidson_abort_cond /= 0) THEN
226 0 : davidson_converged = 1
227 0 : success_abort_string = "RESIDUALS"
228 0 : ELSE IF (num_en_unconverged == 0 .AND. (bse_davidson_abort_cond /= 1)) THEN
229 0 : davidson_converged = 1
230 0 : success_abort_string = "ENERGIES"
231 0 : ELSE IF (i_iter == num_davidson_iter) THEN
232 0 : davidson_converged = -100
233 0 : success_abort_string = "-----"
234 : ELSE
235 : davidson_converged = -1
236 : END IF
237 :
238 0 : IF (bse_davidson_abort_cond == 0) THEN
239 0 : bse_davidson_abort_cond_string = "ENERGY"
240 0 : ELSE IF (bse_davidson_abort_cond == 1) THEN
241 0 : bse_davidson_abort_cond_string = "RESIDUAL"
242 : ELSE
243 0 : bse_davidson_abort_cond_string = "EITHER"
244 : END IF
245 :
246 0 : IF (davidson_converged == 1) THEN
247 : CALL success_message(Subspace_full_eigenval, num_new_t, eps_res, num_res_unconverged, &
248 : bse_spin_config, unit_nr, num_exc_en, num_Z_vectors_init, &
249 : num_davidson_iter, i_iter, num_Z_vectors, num_max_z_space, max_res_norm, &
250 : max_en_diff, num_en_unconverged, bse_davidson_abort_cond_string, &
251 0 : eps_exc_en, success_abort_string, z_space_energy_cutoff)
252 :
253 : !Deallocate matrices, which are otherwise not cleared due to exiting the loop
254 0 : DEALLOCATE (AZ, BZ, &
255 0 : Z_vectors, M_ia_tmp, M_ji_tmp, RI_vector, Subspace_prev_eigenval, &
256 0 : Subspace_new_eigenval, Subspace_new_eigenvec, Subspace_residuals_reshaped, &
257 0 : Subspace_add_dir, AZ_reshaped, Z_vectors_reshaped, Subspace_ritzvec, Subspace_full_eigenval)
258 :
259 0 : EXIT
260 0 : ELSE IF (davidson_converged < -1) THEN
261 : CALL print_davidson_parameter(i_iter, num_davidson_iter, num_Z_vectors, num_res_unconverged, max_res_norm, &
262 : eps_res, num_en_unconverged, max_en_diff, eps_exc_en, num_exc_en, &
263 : num_Z_vectors_init, num_max_z_space, num_new_t, unit_nr, &
264 0 : success_abort_string, bse_davidson_abort_cond_string, z_space_energy_cutoff)
265 :
266 : CALL cp_abort(__LOCATION__, "BSE/TDA-Davidson did not converge using "// &
267 0 : bse_davidson_abort_cond_string//" threshold condition!")
268 : END IF
269 :
270 : ! Calculate and add next orthonormal vector and update num_Z_vectors
271 : CALL compute_new_directions(homo, virtual, Subspace_residuals_reshaped, Subspace_new_eigenval, Eigenval, &
272 0 : num_new_t, Subspace_add_dir)
273 :
274 : !If exact-diag: compute difference to exact eigenvalues
275 : IF (bse_full_diag_debug) THEN
276 0 : ALLOCATE (En_diffs_exact(num_exc_en))
277 0 : num_exact_en_unconverged = 0
278 0 : DO j_print = 1, num_exc_en
279 0 : En_diffs_exact(j_print) = ABS(Subspace_full_eigenval(j_print) - Full_exc_spectrum(j_print))
280 0 : IF (En_diffs_exact(j_print) > eps_exc_en) num_exact_en_unconverged = num_exact_en_unconverged + 1
281 : END DO
282 : END IF
283 :
284 : !Check dimensions and orthonormalize vector system, depending on dimensionality
285 : CALL check_Z_space_dimension(W_vectors, Z_vectors, Subspace_add_dir, Subspace_ritzvec, &
286 0 : num_Z_vectors, num_new_t, num_max_z_space, homo, virtual, i_iter, unit_nr)
287 :
288 : !Copy eigenvalues for threshold
289 0 : Subspace_prev_eigenval(:) = Subspace_full_eigenval(:num_exc_en)
290 :
291 0 : DEALLOCATE (AZ, & !BZ,
292 0 : Z_vectors, M_ia_tmp, M_ji_tmp, RI_vector, &
293 0 : Subspace_new_eigenval, Subspace_new_eigenvec, Subspace_residuals_reshaped, &
294 0 : Subspace_add_dir, AZ_reshaped, Z_vectors_reshaped, Subspace_ritzvec, Subspace_full_eigenval, &
295 0 : Res_norms, En_diffs)
296 :
297 : IF (bse_full_diag_debug) THEN
298 0 : DEALLOCATE (En_diffs_exact)
299 : END IF
300 :
301 : !Orthonorm:
302 0 : CALL orthonormalize_W(W_vectors, num_Z_vectors, homo, virtual)
303 :
304 : END DO
305 :
306 0 : CALL timestop(handle)
307 :
308 0 : END SUBROUTINE
309 :
310 : ! **************************************************************************************************
311 : !> \brief ...
312 : !> \param W_vectors ...
313 : !> \param Z_vectors ...
314 : !> \param Subspace_add_dir ...
315 : !> \param Subspace_ritzvec ...
316 : !> \param num_Z_vectors ...
317 : !> \param num_new_t ...
318 : !> \param num_max_z_space ...
319 : !> \param homo ...
320 : !> \param virtual ...
321 : !> \param i_iter ...
322 : !> \param unit_nr ...
323 : ! **************************************************************************************************
324 0 : SUBROUTINE check_Z_space_dimension(W_vectors, Z_vectors, Subspace_add_dir, Subspace_ritzvec, &
325 : num_Z_vectors, num_new_t, num_max_z_space, homo, virtual, i_iter, unit_nr)
326 :
327 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :) :: W_vectors, Z_vectors, Subspace_add_dir, &
328 : Subspace_ritzvec
329 : INTEGER :: num_Z_vectors, num_new_t, &
330 : num_max_z_space, homo, virtual, &
331 : i_iter, unit_nr
332 :
333 : CHARACTER(LEN=*), PARAMETER :: routineN = 'check_Z_space_dimension'
334 :
335 : INTEGER :: handle
336 :
337 0 : CALL timeset(routineN, handle)
338 :
339 0 : IF (num_Z_vectors + num_new_t .LE. num_max_z_space) THEN
340 0 : W_vectors(:, :, :num_Z_vectors) = Z_vectors(:, :, :)
341 0 : W_vectors(:, :, num_Z_vectors + 1:) = Subspace_add_dir
342 0 : num_Z_vectors = num_Z_vectors + num_new_t
343 : ELSE
344 0 : IF (unit_nr > 0) THEN
345 0 : WRITE (unit_nr, *) "Resetting dimension in i_iter=", i_iter
346 : END IF
347 0 : DEALLOCATE (W_vectors)
348 0 : ALLOCATE (W_vectors(homo, virtual, 2*num_new_t))
349 0 : W_vectors(:, :, :num_new_t) = Subspace_ritzvec(:, :, :)
350 0 : W_vectors(:, :, num_new_t + 1:) = Subspace_add_dir
351 0 : num_Z_vectors = 2*num_new_t
352 : END IF
353 :
354 0 : CALL timestop(handle)
355 :
356 0 : END SUBROUTINE
357 :
358 : ! **************************************************************************************************
359 : !> \brief ...
360 : !> \param AZ ...
361 : !> \param Z_vectors_reshaped ...
362 : !> \param AZ_reshaped ...
363 : !> \param BZ ...
364 : !> \param M_ia_tmp ...
365 : !> \param M_ji_tmp ...
366 : !> \param RI_vector ...
367 : !> \param Subspace_new_eigenval ...
368 : !> \param Subspace_full_eigenval ...
369 : !> \param Subspace_new_eigenvec ...
370 : !> \param Subspace_residuals_reshaped ...
371 : !> \param Subspace_ritzvec ...
372 : !> \param Subspace_add_dir ...
373 : !> \param W_vectors ...
374 : !> \param homo ...
375 : !> \param virtual ...
376 : !> \param num_Z_vectors ...
377 : !> \param local_RI_size ...
378 : !> \param num_new_t ...
379 : ! **************************************************************************************************
380 0 : SUBROUTINE create_bse_work_arrays(AZ, Z_vectors_reshaped, AZ_reshaped, BZ, M_ia_tmp, M_ji_tmp, &
381 : RI_vector, Subspace_new_eigenval, Subspace_full_eigenval, Subspace_new_eigenvec, &
382 : Subspace_residuals_reshaped, Subspace_ritzvec, Subspace_add_dir, W_vectors, &
383 : homo, virtual, num_Z_vectors, local_RI_size, num_new_t)
384 :
385 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :) :: AZ
386 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: Z_vectors_reshaped, AZ_reshaped
387 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :) :: BZ
388 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: M_ia_tmp, M_ji_tmp, RI_vector
389 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:) :: Subspace_new_eigenval, &
390 : Subspace_full_eigenval
391 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: Subspace_new_eigenvec, &
392 : Subspace_residuals_reshaped
393 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :) :: Subspace_ritzvec, Subspace_add_dir, &
394 : W_vectors
395 : INTEGER :: homo, virtual, num_Z_vectors, &
396 : local_RI_size, num_new_t
397 :
398 : CHARACTER(LEN=*), PARAMETER :: routineN = 'create_bse_work_arrays'
399 :
400 : INTEGER :: handle
401 :
402 0 : CALL timeset(routineN, handle)
403 :
404 0 : ALLOCATE (AZ(homo, virtual, num_Z_vectors))
405 0 : AZ = 0.0_dp
406 :
407 0 : ALLOCATE (Z_vectors_reshaped(homo*virtual, num_Z_vectors))
408 0 : Z_vectors_reshaped = 0.0_dp
409 :
410 0 : ALLOCATE (AZ_reshaped(homo*virtual, num_Z_vectors))
411 0 : AZ_reshaped = 0.0_dp
412 :
413 0 : ALLOCATE (BZ(homo, virtual, num_Z_vectors))
414 0 : BZ = 0.0_dp
415 :
416 0 : ALLOCATE (M_ia_tmp(homo, virtual))
417 0 : M_ia_tmp = 0.0_dp
418 :
419 0 : ALLOCATE (M_ji_tmp(homo, homo))
420 0 : M_ji_tmp = 0.0_dp
421 :
422 0 : ALLOCATE (RI_vector(local_RI_size, num_Z_vectors))
423 0 : RI_vector = 0.0_dp
424 :
425 0 : ALLOCATE (Subspace_new_eigenval(num_new_t))
426 0 : Subspace_new_eigenval = 0.0_dp
427 :
428 0 : ALLOCATE (Subspace_full_eigenval(num_Z_vectors))
429 0 : Subspace_full_eigenval = 0.0_dp
430 :
431 0 : ALLOCATE (Subspace_new_eigenvec(num_Z_vectors, num_new_t))
432 0 : Subspace_new_eigenvec = 0.0_dp
433 :
434 0 : ALLOCATE (subspace_residuals_reshaped(homo*virtual, num_new_t))
435 0 : subspace_residuals_reshaped = 0.0_dp
436 :
437 0 : ALLOCATE (Subspace_ritzvec(homo, virtual, num_new_t))
438 0 : Subspace_ritzvec = 0.0_dp
439 :
440 0 : ALLOCATE (Subspace_add_dir(homo, virtual, num_new_t))
441 0 : Subspace_add_dir = 0.0_dp
442 :
443 0 : ALLOCATE (W_vectors(homo, virtual, num_Z_vectors + num_new_t))
444 0 : W_vectors = 0.0_dp
445 :
446 0 : CALL timestop(handle)
447 :
448 0 : END SUBROUTINE
449 :
450 : ! **************************************************************************************************
451 : !> \brief ...
452 : !> \param Subspace_full_eigenval ...
453 : !> \param num_new_t ...
454 : !> \param eps_res ...
455 : !> \param num_res_unconverged ...
456 : !> \param bse_spin_config ...
457 : !> \param unit_nr ...
458 : !> \param num_exc_en ...
459 : !> \param num_Z_vectors_init ...
460 : !> \param num_davidson_iter ...
461 : !> \param i_iter ...
462 : !> \param num_Z_vectors ...
463 : !> \param num_max_z_space ...
464 : !> \param max_res_norm ...
465 : !> \param max_en_diff ...
466 : !> \param num_en_unconverged ...
467 : !> \param bse_davidson_abort_cond_string ...
468 : !> \param eps_exc_en ...
469 : !> \param success_abort_string ...
470 : !> \param z_space_energy_cutoff ...
471 : ! **************************************************************************************************
472 0 : SUBROUTINE success_message(Subspace_full_eigenval, num_new_t, eps_res, num_res_unconverged, &
473 : bse_spin_config, unit_nr, num_exc_en, num_Z_vectors_init, &
474 : num_davidson_iter, i_iter, num_Z_vectors, num_max_z_space, max_res_norm, &
475 : max_en_diff, num_en_unconverged, bse_davidson_abort_cond_string, &
476 : eps_exc_en, success_abort_string, z_space_energy_cutoff)
477 :
478 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:) :: Subspace_full_eigenval
479 : INTEGER :: num_new_t
480 : REAL(KIND=dp) :: eps_res
481 : INTEGER :: num_res_unconverged, bse_spin_config, unit_nr, num_exc_en, num_Z_vectors_init, &
482 : num_davidson_iter, i_iter, num_Z_vectors, num_max_z_space
483 : REAL(KIND=dp) :: max_res_norm, max_en_diff
484 : INTEGER :: num_en_unconverged
485 : CHARACTER(LEN=10) :: bse_davidson_abort_cond_string
486 : REAL(KIND=dp) :: eps_exc_en
487 : CHARACTER(LEN=10) :: success_abort_string
488 : REAL(KIND=dp) :: z_space_energy_cutoff
489 :
490 : CHARACTER(LEN=*), PARAMETER :: routineN = 'success_message'
491 :
492 : CHARACTER(LEN=10) :: multiplet
493 : INTEGER :: handle, i
494 : REAL(KIND=dp) :: alpha
495 :
496 0 : CALL timeset(routineN, handle)
497 :
498 : !Prepare variables for printing
499 0 : SELECT CASE (bse_spin_config)
500 : CASE (bse_singlet)
501 0 : alpha = 2.0_dp
502 0 : multiplet = "Singlet"
503 : CASE (bse_triplet)
504 0 : alpha = 0.0_dp
505 0 : multiplet = "Triplet"
506 : END SELECT
507 :
508 0 : IF (unit_nr > 0) THEN
509 0 : WRITE (unit_nr, *) ' '
510 0 : WRITE (unit_nr, '(T3,A)') '******************************************************************************'
511 0 : WRITE (unit_nr, '(T3,A)') '** **'
512 0 : WRITE (unit_nr, '(T3,A)') '** BSE-TDA EXCITONIC ENERGIES **'
513 0 : WRITE (unit_nr, '(T3,A)') '** **'
514 0 : WRITE (unit_nr, '(T3,A)') '******************************************************************************'
515 0 : WRITE (unit_nr, '(T3,A)') ' '
516 0 : WRITE (unit_nr, '(T3,A)') ' '
517 0 : WRITE (unit_nr, '(T3,A)') ' The excitation energies are calculated by iteratively diagonalizing: '
518 0 : WRITE (unit_nr, '(T3,A)') ' '
519 0 : WRITE (unit_nr, '(T3,A)') ' A_iajb = (E_a-E_i) delta_ij delta_ab + alpha * v_iajb - W_ijab '
520 0 : WRITE (unit_nr, '(T3,A)') ' '
521 : WRITE (unit_nr, '(T3,A48,A7,A12,F3.1)') &
522 0 : ' The spin-dependent factor for the requested ', multiplet, " is alpha = ", alpha
523 0 : WRITE (unit_nr, '(T3,A)') ' '
524 : WRITE (unit_nr, '(T3,A16,T50,A22)') &
525 0 : ' Excitonic level', 'Excitation energy (eV)'
526 : !prints actual energies values
527 0 : DO i = 1, num_exc_en
528 0 : WRITE (unit_nr, '(T3,I16,T50,F22.3)') i, Subspace_full_eigenval(i)*evolt
529 : END DO
530 :
531 0 : WRITE (unit_nr, '(T3,A)') ' '
532 :
533 : !prints parameters of Davidson algorithm
534 : CALL print_davidson_parameter(i_iter, num_davidson_iter, num_Z_vectors, num_res_unconverged, max_res_norm, &
535 : eps_res, num_en_unconverged, max_en_diff, eps_exc_en, num_exc_en, &
536 : num_Z_vectors_init, num_max_z_space, num_new_t, unit_nr, &
537 0 : success_abort_string, bse_davidson_abort_cond_string, z_space_energy_cutoff)
538 :
539 : !Insert warning if energies are not converged (could probably be the case if one uses residual threshold)
540 0 : IF (num_en_unconverged > 0) THEN
541 0 : WRITE (unit_nr, '(T3,A)') '!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!'
542 0 : WRITE (unit_nr, '(T3,A2,T79,A2)') '!!', "!!"
543 0 : WRITE (unit_nr, '(T3,A2,T8,A65,T79,A2)') '!!', "THERE ARE UNCONVERGED ENERGIES PRINTED OUT, SOMETHING WENT WRONG!", "!!"
544 0 : WRITE (unit_nr, '(T3,A2,T79,A2)') '!!', "!!"
545 0 : WRITE (unit_nr, '(T3,A)') '!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!'
546 : END IF
547 : END IF
548 :
549 0 : CALL timestop(handle)
550 :
551 0 : END SUBROUTINE
552 :
553 : ! **************************************************************************************************
554 : !> \brief ...
555 : !> \param i_iter ...
556 : !> \param num_davidson_iter ...
557 : !> \param num_Z_vectors ...
558 : !> \param num_res_unconverged ...
559 : !> \param max_res_norm ...
560 : !> \param eps_res ...
561 : !> \param num_en_unconverged ...
562 : !> \param max_en_diff ...
563 : !> \param eps_exc_en ...
564 : !> \param num_exc_en ...
565 : !> \param num_Z_vectors_init ...
566 : !> \param num_max_z_space ...
567 : !> \param num_new_t ...
568 : !> \param unit_nr ...
569 : !> \param success_abort_string ...
570 : !> \param bse_davidson_abort_cond_string ...
571 : !> \param z_space_energy_cutoff ...
572 : ! **************************************************************************************************
573 0 : SUBROUTINE print_davidson_parameter(i_iter, num_davidson_iter, num_Z_vectors, num_res_unconverged, max_res_norm, &
574 : eps_res, num_en_unconverged, max_en_diff, eps_exc_en, num_exc_en, &
575 : num_Z_vectors_init, num_max_z_space, num_new_t, unit_nr, &
576 : success_abort_string, bse_davidson_abort_cond_string, z_space_energy_cutoff)
577 :
578 : INTEGER :: i_iter, num_davidson_iter, &
579 : num_Z_vectors, num_res_unconverged
580 : REAL(KIND=dp) :: max_res_norm, eps_res
581 : INTEGER :: num_en_unconverged
582 : REAL(KIND=dp) :: max_en_diff, eps_exc_en
583 : INTEGER :: num_exc_en, num_Z_vectors_init, &
584 : num_max_z_space, num_new_t, unit_nr
585 : CHARACTER(LEN=10) :: success_abort_string, &
586 : bse_davidson_abort_cond_string
587 : REAL(KIND=dp) :: z_space_energy_cutoff
588 :
589 : CHARACTER(LEN=*), PARAMETER :: routineN = 'print_davidson_parameter'
590 :
591 : INTEGER :: handle
592 :
593 0 : CALL timeset(routineN, handle)
594 :
595 0 : WRITE (unit_nr, '(T3,A)') '******************************************************************************'
596 : WRITE (unit_nr, '(T3,A2,T15,A49,T79,A2)') &
597 0 : '**', "Parameters of the BSE-Davidson solver:", "**"
598 : WRITE (unit_nr, '(T3,A2,T79,A2)') &
599 0 : '**', "**"
600 : WRITE (unit_nr, '(T3,A2,T79,A2)') &
601 0 : '**', "**"
602 : WRITE (unit_nr, '(T3,A2,T10,A16,I5,A12,I5,A8,T79,A2)') &
603 0 : '**', "Converged after ", i_iter, " of maximal ", num_davidson_iter, " cycles,", "**"
604 : WRITE (unit_nr, '(T3,A2,T20,A11,A9,A7,A8,A20,T79,A2)') &
605 0 : '**', "because of ", success_abort_string, " using ", &
606 0 : bse_davidson_abort_cond_string, " threshold condition", "**"
607 : WRITE (unit_nr, '(T3,A2,T79,A2)') &
608 0 : '**', "**"
609 : WRITE (unit_nr, '(T3,A2,T10,A32,T65,I11,T79,A2)') &
610 0 : '**', "The Z space has at the end dim. ", num_Z_vectors, "**"
611 : WRITE (unit_nr, '(T3,A2,T10,A45,T65,I11,T79,A2)') &
612 0 : '**', "Number of unconverged residuals in subspace: ", num_res_unconverged, "**"
613 : WRITE (unit_nr, '(T3,A2,T10,A35,T65,E11.4,T79,A2)') &
614 0 : '**', "largest unconverged residual (eV): ", max_res_norm*evolt, "**"
615 : WRITE (unit_nr, '(T3,A2,T10,A45,T65,E11.4,T79,A2)') &
616 0 : '**', "threshold for convergence of residuals (eV): ", eps_res*evolt, "**"
617 : WRITE (unit_nr, '(T3,A2,T10,A45,T65,I11,T79,A2)') &
618 0 : '**', "Number of desired, but unconverged energies: ", num_en_unconverged, "**"
619 : WRITE (unit_nr, '(T3,A2,T10,A44,T65,E11.4,T79,A2)') &
620 0 : '**', "largest unconverged energy difference (eV): ", max_en_diff*evolt, "**"
621 : WRITE (unit_nr, '(T3,A2,T10,A44,T65,E11.4,T79,A2)') &
622 0 : '**', "threshold for convergence of energies (eV): ", eps_exc_en*evolt, "**"
623 : WRITE (unit_nr, '(T3,A2,T10,A40,T65,I11,T79,A2)') &
624 0 : '**', "number of computed excitation energies: ", num_exc_en, "**"
625 :
626 0 : IF (z_space_energy_cutoff > 0) THEN
627 : WRITE (unit_nr, '(T3,A2,T10,A37,T65,E11.4,T79,A2)') &
628 0 : '**', "cutoff for excitation energies (eV): ", z_space_energy_cutoff*evolt, "**"
629 : END IF
630 :
631 : WRITE (unit_nr, '(T3,A2,T10,A36,T65,I11,T79,A2)') &
632 0 : '**', "number of Z space at the beginning: ", num_Z_vectors_init, "**"
633 : WRITE (unit_nr, '(T3,A2,T10,A30,T65,I11,T79,A2)') &
634 0 : '**', "maximal dimension of Z space: ", num_max_z_space, "**"
635 : WRITE (unit_nr, '(T3,A2,T10,A31,T65,I11,T79,A2)') &
636 0 : '**', "added directions per iteration: ", num_new_t, "**"
637 : WRITE (unit_nr, '(T3,A2,T79,A2)') &
638 0 : '**', "**"
639 : WRITE (unit_nr, '(T3,A2,T79,A2)') &
640 0 : '**', "**"
641 0 : WRITE (unit_nr, '(T3,A)') '******************************************************************************'
642 0 : WRITE (unit_nr, '(T3,A)') ' '
643 :
644 0 : CALL timestop(handle)
645 :
646 0 : END SUBROUTINE
647 :
648 : ! **************************************************************************************************
649 : !> \brief ...
650 : !> \param Subspace_full_eigenval ...
651 : !> \param Subspace_prev_eigenval ...
652 : !> \param eps_exc_en ...
653 : !> \param num_en_unconverged ...
654 : !> \param num_exc_en ...
655 : !> \param max_en_diff ...
656 : !> \param En_diffs ...
657 : ! **************************************************************************************************
658 0 : SUBROUTINE check_en_convergence(Subspace_full_eigenval, Subspace_prev_eigenval, eps_exc_en, num_en_unconverged, &
659 : num_exc_en, max_en_diff, En_diffs)
660 :
661 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:) :: Subspace_full_eigenval, &
662 : Subspace_prev_eigenval
663 : REAL(KIND=dp) :: eps_exc_en
664 : INTEGER :: num_en_unconverged, num_exc_en
665 : REAL(KIND=dp) :: max_en_diff
666 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:) :: En_diffs
667 :
668 : CHARACTER(LEN=*), PARAMETER :: routineN = 'check_en_convergence'
669 :
670 : INTEGER :: handle, mu_l
671 :
672 0 : CALL timeset(routineN, handle)
673 :
674 0 : num_en_unconverged = 0
675 0 : ALLOCATE (En_diffs(num_exc_en))
676 0 : DO mu_l = 1, num_exc_en
677 0 : En_diffs(mu_l) = ABS(Subspace_full_eigenval(mu_l) - Subspace_prev_eigenval(mu_l))
678 0 : IF (En_diffs(mu_l) > eps_exc_en) num_en_unconverged = num_en_unconverged + 1
679 : END DO
680 0 : max_en_diff = MAXVAL(En_diffs)
681 :
682 0 : CALL timestop(handle)
683 :
684 0 : END SUBROUTINE
685 :
686 : ! **************************************************************************************************
687 : !> \brief ...
688 : !> \param Subspace_residuals_reshaped ...
689 : !> \param num_new_t ...
690 : !> \param eps_res ...
691 : !> \param num_res_unconverged ...
692 : !> \param i_iter ...
693 : !> \param max_res_norm ...
694 : !> \param unit_nr ...
695 : !> \param Res_norms ...
696 : ! **************************************************************************************************
697 0 : SUBROUTINE check_res_convergence(Subspace_residuals_reshaped, num_new_t, eps_res, num_res_unconverged, &
698 : i_iter, max_res_norm, unit_nr, Res_norms)
699 :
700 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: Subspace_residuals_reshaped
701 : INTEGER :: num_new_t
702 : REAL(KIND=dp) :: eps_res
703 : INTEGER :: num_res_unconverged, i_iter
704 : REAL(KIND=dp) :: max_res_norm
705 : INTEGER :: unit_nr
706 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:) :: Res_norms
707 :
708 : CHARACTER(LEN=*), PARAMETER :: routineN = 'check_res_convergence'
709 :
710 : INTEGER :: handle, mu_l
711 :
712 0 : CALL timeset(routineN, handle)
713 :
714 0 : num_res_unconverged = 0
715 0 : ALLOCATE (Res_norms(num_new_t))
716 0 : DO mu_l = 1, num_new_t
717 0 : Res_norms(mu_l) = NORM2(Subspace_residuals_reshaped(:, mu_l))
718 0 : IF (Res_norms(mu_l) > eps_res) THEN
719 0 : num_res_unconverged = num_res_unconverged + 1
720 0 : IF (unit_nr > 0) THEN
721 0 : WRITE (unit_nr, *) "Unconverged res in i_iter=", i_iter, "is:", Res_norms(mu_l)
722 : END IF
723 : END IF
724 : END DO
725 0 : max_res_norm = MAXVAL(Res_norms)
726 0 : IF (unit_nr > 0) THEN
727 0 : WRITE (unit_nr, *) "Maximal unconverged res (of ", num_res_unconverged, &
728 0 : " unconverged res in this step) in i_iter=", i_iter, "is:", max_res_norm
729 : END IF
730 :
731 0 : CALL timestop(handle)
732 :
733 0 : END SUBROUTINE
734 :
735 : ! **************************************************************************************************
736 : !> \brief ...
737 : !> \param W_vectors ...
738 : !> \param num_Z_vectors ...
739 : !> \param homo ...
740 : !> \param virtual ...
741 : ! **************************************************************************************************
742 0 : SUBROUTINE orthonormalize_W(W_vectors, num_Z_vectors, homo, virtual)
743 :
744 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :) :: W_vectors
745 : INTEGER :: num_Z_vectors, homo, virtual
746 :
747 : CHARACTER(LEN=*), PARAMETER :: routineN = 'orthonormalize_W'
748 :
749 : INTEGER :: handle, info_dor, info_orth, LWORK_dor, &
750 : LWORK_W
751 0 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:) :: Tau_W, WORK_W, WORK_W_dor
752 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: W_vectors_reshaped
753 :
754 0 : CALL timeset(routineN, handle)
755 :
756 0 : ALLOCATE (W_vectors_reshaped(homo*virtual, num_Z_vectors))
757 0 : W_vectors_reshaped(:, :) = RESHAPE(W_vectors, (/homo*virtual, num_Z_vectors/))
758 :
759 0 : ALLOCATE (Tau_W(MIN(homo*virtual, num_Z_vectors)))
760 0 : Tau_W = 0.0_dp
761 :
762 0 : ALLOCATE (WORK_W(1))
763 0 : WORK_W = 0.0_dp
764 :
765 0 : ALLOCATE (WORK_W_dor(1))
766 0 : WORK_W_dor = 0.0_dp
767 :
768 0 : CALL DGEQRF(homo*virtual, num_Z_vectors, W_vectors_reshaped, homo*virtual, Tau_W, WORK_W, -1, info_orth)
769 0 : LWORK_W = INT(WORK_W(1))
770 0 : DEALLOCATE (WORK_W)
771 0 : ALLOCATE (WORK_W(LWORK_W))
772 0 : WORK_W = 0.0_dp
773 0 : CALL DGEQRF(homo*virtual, num_Z_vectors, W_vectors_reshaped, homo*virtual, Tau_W, WORK_W, LWORK_W, info_orth)
774 0 : IF (info_orth /= 0) THEN
775 0 : CPABORT("QR Decomp Step 1 doesnt work")
776 : END IF
777 : CALL DORGQR(homo*virtual, num_Z_vectors, MIN(homo*virtual, num_Z_vectors), W_vectors_reshaped, homo*virtual, &
778 0 : Tau_W, WORK_W_dor, -1, info_dor)
779 0 : LWORK_dor = INT(WORK_W_dor(1))
780 0 : DEALLOCATE (WORK_W_dor)
781 0 : ALLOCATE (WORK_W_dor(LWORK_dor))
782 0 : WORK_W_dor = 0.0_dp
783 : CALL DORGQR(homo*virtual, num_Z_vectors, MIN(homo*virtual, num_Z_vectors), W_vectors_reshaped, homo*virtual, &
784 0 : Tau_W, WORK_W_dor, LWORK_dor, info_dor)
785 0 : IF (info_orth /= 0) THEN
786 0 : CPABORT("QR Decomp Step 2 doesnt work")
787 : END IF
788 :
789 0 : W_vectors(:, :, :) = RESHAPE(W_vectors_reshaped, (/homo, virtual, num_Z_vectors/))
790 :
791 0 : DEALLOCATE (WORK_W, WORK_W_dor, Tau_W, W_vectors_reshaped)
792 :
793 0 : CALL timestop(handle)
794 :
795 0 : END SUBROUTINE
796 :
797 : ! **************************************************************************************************
798 : !> \brief ...
799 : !> \param homo ...
800 : !> \param virtual ...
801 : !> \param Subspace_residuals_reshaped ...
802 : !> \param Subspace_new_eigenval ...
803 : !> \param Eigenval ...
804 : !> \param num_new_t ...
805 : !> \param Subspace_add_dir ...
806 : ! **************************************************************************************************
807 0 : SUBROUTINE compute_new_directions(homo, virtual, Subspace_residuals_reshaped, Subspace_new_eigenval, Eigenval, &
808 : num_new_t, Subspace_add_dir)
809 :
810 : INTEGER :: homo, virtual
811 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: Subspace_residuals_reshaped
812 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:) :: Subspace_new_eigenval
813 : REAL(KIND=dp), DIMENSION(:) :: Eigenval
814 : INTEGER :: num_new_t
815 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :) :: Subspace_add_dir
816 :
817 : CHARACTER(LEN=*), PARAMETER :: routineN = 'compute_new_directions'
818 :
819 : INTEGER :: a_virt, handle, i_occ, mu_subspace, &
820 : prec_neg
821 : REAL(KIND=dp) :: prec_scalar
822 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: Subspace_add_dir_reshaped
823 :
824 0 : CALL timeset(routineN, handle)
825 :
826 0 : ALLOCATE (Subspace_add_dir_reshaped(homo*virtual, num_new_t))
827 :
828 0 : prec_neg = 0
829 0 : DO mu_subspace = 1, num_new_t
830 0 : DO i_occ = 1, homo
831 0 : DO a_virt = 1, virtual
832 : !MG to check: Indexorder and range of indices
833 0 : prec_scalar = -1/(Subspace_new_eigenval(mu_subspace) - (Eigenval(a_virt + homo) - Eigenval(i_occ)))
834 : IF (prec_scalar < 0) THEN
835 0 : prec_neg = prec_neg + 1
836 : !prec_scalar = - prec_scalar
837 : END IF
838 : Subspace_add_dir_reshaped((i_occ - 1)*virtual + a_virt, mu_subspace) = prec_scalar* &
839 0 : Subspace_residuals_reshaped((i_occ - 1)*virtual + a_virt, mu_subspace)
840 : END DO
841 : END DO
842 : END DO
843 :
844 0 : Subspace_add_dir(:, :, :) = RESHAPE(Subspace_add_dir_reshaped, (/homo, virtual, num_new_t/))
845 :
846 0 : DEALLOCATE (Subspace_add_dir_reshaped)
847 0 : CALL timestop(handle)
848 :
849 0 : END SUBROUTINE
850 :
851 : ! **************************************************************************************************
852 : !> \brief ...
853 : !> \param AZ_reshaped ...
854 : !> \param Z_vectors_reshaped ...
855 : !> \param Subspace_new_eigenval ...
856 : !> \param Subspace_new_eigenvec ...
857 : !> \param Subspace_residuals_reshaped ...
858 : !> \param homo ...
859 : !> \param virtual ...
860 : !> \param num_new_t ...
861 : !> \param num_Z_vectors ...
862 : !> \param Subspace_ritzvec ...
863 : ! **************************************************************************************************
864 0 : SUBROUTINE compute_residuals(AZ_reshaped, Z_vectors_reshaped, Subspace_new_eigenval, Subspace_new_eigenvec, &
865 : Subspace_residuals_reshaped, homo, virtual, num_new_t, num_Z_vectors, Subspace_ritzvec)
866 :
867 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: AZ_reshaped, Z_vectors_reshaped
868 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:) :: Subspace_new_eigenval
869 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: Subspace_new_eigenvec, &
870 : Subspace_residuals_reshaped
871 : INTEGER :: homo, virtual, num_new_t, num_Z_vectors
872 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :) :: Subspace_ritzvec
873 :
874 : CHARACTER(LEN=*), PARAMETER :: routineN = 'compute_residuals'
875 :
876 : INTEGER :: handle, mu_subspace
877 0 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: Subspace_res_A, Subspace_res_ev
878 :
879 0 : CALL timeset(routineN, handle)
880 :
881 0 : ALLOCATE (Subspace_res_ev(homo*virtual, num_new_t))
882 0 : Subspace_res_ev = 0.0_dp
883 :
884 0 : ALLOCATE (Subspace_res_A(homo*virtual, num_new_t))
885 0 : Subspace_res_A = 0.0_dp
886 :
887 : !Compute all residuals in one loop, iterating over number of new/added t per iteration
888 0 : DO mu_subspace = 1, num_new_t
889 :
890 : CALL DGEMM("N", "N", homo*virtual, 1, num_Z_vectors, 1.0_dp, Z_vectors_reshaped, homo*virtual, &
891 0 : Subspace_new_eigenvec(:, mu_subspace), num_Z_vectors, 0.0_dp, Subspace_res_ev(:, mu_subspace), homo*virtual)
892 :
893 : CALL DGEMM("N", "N", homo*virtual, 1, num_Z_vectors, 1.0_dp, AZ_reshaped, homo*virtual, &
894 0 : Subspace_new_eigenvec(:, mu_subspace), num_Z_vectors, 0.0_dp, Subspace_res_A(:, mu_subspace), homo*virtual)
895 :
896 : Subspace_residuals_reshaped(:, mu_subspace) = Subspace_new_eigenval(mu_subspace)*Subspace_res_ev(:, mu_subspace) &
897 0 : - Subspace_res_A(:, mu_subspace)
898 :
899 : END DO
900 0 : Subspace_ritzvec(:, :, :) = RESHAPE(Subspace_res_ev, (/homo, virtual, num_new_t/))
901 0 : DEALLOCATE (Subspace_res_ev, Subspace_res_A)
902 :
903 0 : CALL timestop(handle)
904 :
905 0 : END SUBROUTINE
906 :
907 : ! **************************************************************************************************
908 : !> \brief ...
909 : !> \param AZ_reshaped ...
910 : !> \param Z_vectors_reshaped ...
911 : !> \param num_Z_vectors ...
912 : !> \param Subspace_new_eigenval ...
913 : !> \param Subspace_new_eigenvec ...
914 : !> \param num_new_t ...
915 : !> \param Subspace_full_eigenval ...
916 : !> \param para_env ...
917 : !> \param unit_nr ...
918 : ! **************************************************************************************************
919 0 : SUBROUTINE compute_diagonalize_ZAZ(AZ_reshaped, Z_vectors_reshaped, num_Z_vectors, Subspace_new_eigenval, &
920 : Subspace_new_eigenvec, num_new_t, Subspace_full_eigenval, para_env, unit_nr)
921 :
922 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: AZ_reshaped, Z_vectors_reshaped
923 : INTEGER, INTENT(in) :: num_Z_vectors
924 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:) :: Subspace_new_eigenval
925 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: Subspace_new_eigenvec
926 : INTEGER, INTENT(in) :: num_new_t
927 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:) :: Subspace_full_eigenval
928 : TYPE(mp_para_env_type), INTENT(IN) :: para_env
929 : INTEGER, INTENT(in) :: unit_nr
930 :
931 : CHARACTER(LEN=*), PARAMETER :: routineN = 'compute_diagonalize_ZAZ'
932 :
933 : INTEGER :: handle, i_Z_vector, j_Z_vector, LWORK, &
934 : ZAZ_diag_info
935 0 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:) :: WORK
936 0 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: ZAZ
937 :
938 0 : CALL timeset(routineN, handle)
939 :
940 0 : ALLOCATE (ZAZ(num_Z_vectors, num_Z_vectors))
941 0 : ZAZ(:, :) = 0.0_dp
942 :
943 : !Flatten AZ and Z matrices of a certain j_Z_vector w.r.t. occ and virt indices
944 : !Multiply for each j_Z_vec and write into matrix of dim (num_Z_vec, num_Z_vec)
945 0 : DO i_Z_vector = 1, num_Z_vectors
946 0 : DO j_Z_vector = 1, num_Z_vectors
947 0 : ZAZ(j_Z_vector, i_Z_vector) = DOT_PRODUCT(Z_vectors_reshaped(:, j_Z_vector), AZ_reshaped(:, i_Z_vector))
948 : END DO
949 : END DO
950 0 : IF (unit_nr > 0) THEN
951 0 : WRITE (unit_nr, *) 'ProcNr', para_env%mepos, "Before Diag"
952 : END IF
953 :
954 : !MG to do: Check for symmetry of ZAZ!
955 0 : ALLOCATE (WORK(1))
956 0 : WORK = 0.0_dp
957 0 : CALL DSYEV("V", "U", num_Z_vectors, ZAZ, num_Z_vectors, Subspace_full_eigenval, WORK, -1, ZAZ_diag_info)
958 0 : LWORK = INT(WORK(1))
959 0 : DEALLOCATE (WORK)
960 0 : ALLOCATE (WORK(LWORK))
961 0 : WORK = 0.0_dp
962 : !MG to check: Usage of symmetric routine okay? (Correct LWORK?)
963 0 : CALL DSYEV("V", "U", num_Z_vectors, ZAZ, num_Z_vectors, Subspace_full_eigenval, WORK, LWORK, ZAZ_diag_info)
964 :
965 0 : IF (ZAZ_diag_info /= 0) THEN
966 0 : CPABORT("ZAZ could not be diagonalized successfully.")
967 : END IF
968 :
969 0 : IF (unit_nr > 0) THEN
970 0 : WRITE (unit_nr, *) 'ProcNr', para_env%mepos, "After Diag"
971 : END IF
972 :
973 0 : Subspace_new_eigenval(1:num_new_t) = Subspace_full_eigenval(1:num_new_t)
974 0 : Subspace_new_eigenvec(:, 1:num_new_t) = ZAZ(:, 1:num_new_t)
975 0 : DEALLOCATE (WORK)
976 0 : DEALLOCATE (ZAZ)
977 :
978 0 : CALL timestop(handle)
979 :
980 0 : END SUBROUTINE
981 :
982 : ! **************************************************************************************************
983 : !> \brief ...
984 : !> \param BZ ...
985 : !> \param Z_vectors ...
986 : !> \param B_iaQ_bse_local ...
987 : !> \param B_bar_iaQ_bse_local ...
988 : !> \param M_ji_tmp ...
989 : !> \param homo ...
990 : !> \param virtual ...
991 : !> \param num_Z_vectors ...
992 : !> \param local_RI_size ...
993 : !> \param para_env ...
994 : ! **************************************************************************************************
995 0 : SUBROUTINE compute_BZ(BZ, Z_vectors, B_iaQ_bse_local, B_bar_iaQ_bse_local, &
996 0 : M_ji_tmp, homo, virtual, num_Z_vectors, local_RI_size, para_env)
997 :
998 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :) :: BZ, Z_vectors, B_iaQ_bse_local, &
999 : B_bar_iaQ_bse_local
1000 : REAL(KIND=dp), DIMENSION(:, :) :: M_ji_tmp
1001 : INTEGER :: homo, virtual, num_Z_vectors, &
1002 : local_RI_size
1003 : TYPE(mp_para_env_type), INTENT(IN) :: para_env
1004 :
1005 : INTEGER :: i_Z_vector, LLL
1006 :
1007 0 : BZ(:, :, :) = 0.0_dp
1008 :
1009 : !CALL compute_v_ia_jb_part(BZ, Z_vectors, B_iaQ_bse_local, RI_vector, local_RI_size, &
1010 : ! num_Z_vectors, homo, virtual)
1011 :
1012 0 : DO i_Z_vector = 1, num_Z_vectors
1013 :
1014 0 : DO LLL = 1, local_RI_size
1015 :
1016 : ! M_ji^P = sum_b Z_jb*B_bi^P
1017 : CALL DGEMM("N", "T", homo, homo, virtual, 1.0_dp, Z_vectors(:, :, i_Z_vector), homo, &
1018 0 : B_iaQ_bse_local(:, :, LLL), homo, 0.0_dp, M_ji_tmp, homo)
1019 : ! (BZ)_ia = sum_jP M_ij^P*B^bar_ja^P
1020 : CALL DGEMM("T", "N", homo, virtual, homo, 1.0_dp, M_ji_tmp, homo, &
1021 0 : B_bar_iaQ_bse_local, homo, 1.0_dp, BZ(:, :, i_Z_vector), homo)
1022 :
1023 : END DO
1024 :
1025 : END DO
1026 :
1027 : ! we make the sum to sum over all RI basis functions
1028 0 : CALL para_env%sum(BZ)
1029 :
1030 0 : END SUBROUTINE
1031 :
1032 : ! **************************************************************************************************
1033 : !> \brief ...
1034 : !> \param AZ ...
1035 : !> \param Z_vectors ...
1036 : !> \param B_iaQ_bse_local ...
1037 : !> \param B_bar_ijQ_bse_local ...
1038 : !> \param B_abQ_bse_local ...
1039 : !> \param M_ia_tmp ...
1040 : !> \param RI_vector ...
1041 : !> \param Eigenval ...
1042 : !> \param homo ...
1043 : !> \param virtual ...
1044 : !> \param num_Z_vectors ...
1045 : !> \param local_RI_size ...
1046 : !> \param para_env ...
1047 : !> \param bse_spin_config ...
1048 : !> \param z_space_energy_cutoff ...
1049 : !> \param i_iter ...
1050 : !> \param bse_full_diag_debug ...
1051 : !> \param Full_exc_spectrum ...
1052 : !> \param unit_nr ...
1053 : ! **************************************************************************************************
1054 0 : SUBROUTINE compute_AZ(AZ, Z_vectors, B_iaQ_bse_local, B_bar_ijQ_bse_local, B_abQ_bse_local, M_ia_tmp, &
1055 0 : RI_vector, Eigenval, homo, virtual, num_Z_vectors, local_RI_size, &
1056 : para_env, bse_spin_config, z_space_energy_cutoff, i_iter, bse_full_diag_debug, &
1057 : Full_exc_spectrum, unit_nr)
1058 :
1059 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :) :: AZ, Z_vectors, B_iaQ_bse_local, &
1060 : B_bar_ijQ_bse_local, B_abQ_bse_local
1061 : REAL(KIND=dp), DIMENSION(:, :) :: M_ia_tmp, RI_vector
1062 : REAL(KIND=dp), DIMENSION(:) :: Eigenval
1063 : INTEGER :: homo, virtual, num_Z_vectors, &
1064 : local_RI_size
1065 : TYPE(mp_para_env_type), INTENT(IN) :: para_env
1066 : INTEGER :: bse_spin_config
1067 : REAL(KIND=dp) :: z_space_energy_cutoff
1068 : INTEGER :: i_iter
1069 : LOGICAL :: bse_full_diag_debug
1070 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:) :: Full_exc_spectrum
1071 : INTEGER :: unit_nr
1072 :
1073 : CHARACTER(LEN=*), PARAMETER :: routineN = 'compute_AZ'
1074 :
1075 : INTEGER :: a, a_virt, b, diag_info, handle, i, &
1076 : i_occ, i_Z_vector, j, LLL, LWORK, m, n
1077 : REAL(KIND=dp) :: eigen_diff
1078 0 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:) :: WORK
1079 0 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: A_full_reshaped
1080 0 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :, :) :: A_full, v_iajb, W_ijab
1081 :
1082 0 : CALL timeset(routineN, handle)
1083 0 : AZ(:, :, :) = 0.0_dp
1084 :
1085 0 : IF (i_iter == 1 .AND. bse_full_diag_debug) THEN
1086 0 : ALLOCATE (W_ijab(homo, homo, virtual, virtual))
1087 0 : ALLOCATE (A_full(homo, virtual, homo, virtual))
1088 0 : ALLOCATE (A_full_reshaped(homo*virtual, homo*virtual))
1089 0 : ALLOCATE (Full_exc_spectrum(homo*virtual))
1090 0 : W_ijab = 0.0_dp
1091 0 : A_full = 0.0_dp
1092 0 : A_full_reshaped = 0.0_dp
1093 0 : Full_exc_spectrum = 0.0_dp
1094 : END IF
1095 :
1096 : CALL compute_v_ia_jb_part(AZ, Z_vectors, B_iaQ_bse_local, RI_vector, local_RI_size, &
1097 : num_Z_vectors, homo, virtual, bse_spin_config, v_iajb, bse_full_diag_debug, i_iter, &
1098 0 : para_env)
1099 :
1100 0 : DO i_Z_vector = 1, num_Z_vectors
1101 :
1102 0 : DO LLL = 1, local_RI_size
1103 :
1104 : ! M_ja^P = sum_b Z_jb*B_ba^P
1105 : CALL DGEMM("N", "N", homo, virtual, virtual, 1.0_dp, Z_vectors(:, :, i_Z_vector), homo, &
1106 0 : B_abQ_bse_local(:, :, LLL), virtual, 0.0_dp, M_ia_tmp, homo)
1107 :
1108 : ! (AZ)_ia = sum_jP B_bar_ij^P*M_ja^P
1109 : CALL DGEMM("N", "N", homo, virtual, homo, -1.0_dp, B_bar_ijQ_bse_local(:, :, LLL), homo, &
1110 0 : M_ia_tmp, homo, 1.0_dp, AZ(:, :, i_Z_vector), homo)
1111 :
1112 : END DO
1113 : END DO
1114 :
1115 0 : IF (i_iter == 1 .AND. bse_full_diag_debug) THEN
1116 0 : W_ijab = 0.0_dp
1117 : !Create screened 4c integrals for check
1118 0 : DO LLL = 1, local_RI_size
1119 0 : DO i = 1, homo
1120 0 : DO j = 1, homo
1121 0 : DO a = 1, virtual
1122 0 : DO b = 1, virtual
1123 0 : W_ijab(i, j, a, b) = W_ijab(i, j, a, b) + B_bar_ijQ_bse_local(i, j, LLL)*B_abQ_bse_local(a, b, LLL)
1124 : END DO
1125 : END DO
1126 : END DO
1127 : END DO
1128 : END DO
1129 : ! we make the mp_sum to sum over all RI basis functions
1130 0 : CALL para_env%sum(W_ijab)
1131 : END IF
1132 :
1133 : ! we make the mp_sum to sum over all RI basis functions
1134 0 : CALL para_env%sum(AZ)
1135 :
1136 : ! add (e_a-e_i)*Z_ia
1137 0 : DO i_occ = 1, homo
1138 0 : DO a_virt = 1, virtual
1139 :
1140 0 : eigen_diff = Eigenval(a_virt + homo) - Eigenval(i_occ)
1141 0 : IF (unit_nr > 0 .AND. i_iter == 1) THEN
1142 0 : WRITE (unit_nr, *) "Ediff at (i_occ,a_virt)=", i_occ, a_virt, " is: ", eigen_diff
1143 : END IF
1144 :
1145 0 : AZ(i_occ, a_virt, :) = AZ(i_occ, a_virt, :) + Z_vectors(i_occ, a_virt, :)*eigen_diff
1146 :
1147 : END DO
1148 : END DO
1149 :
1150 : !cut off contributions, which are too high in the excitation spectrum
1151 0 : IF (z_space_energy_cutoff > 0) THEN
1152 0 : DO i_occ = 1, homo
1153 0 : DO a_virt = 1, virtual
1154 :
1155 0 : IF (Eigenval(a_virt + homo) > z_space_energy_cutoff .OR. -Eigenval(i_occ) > z_space_energy_cutoff) THEN
1156 0 : AZ(i_occ, a_virt, :) = 0
1157 : END IF
1158 :
1159 : END DO
1160 : END DO
1161 : END IF
1162 :
1163 : !Debugging purposes: full diagonalization of A
1164 0 : IF (i_iter == 1 .AND. bse_full_diag_debug) THEN
1165 0 : n = 0
1166 0 : DO i = 1, homo
1167 0 : DO a = 1, virtual
1168 0 : n = n + 1
1169 0 : m = 0
1170 0 : DO j = 1, homo
1171 0 : DO b = 1, virtual
1172 0 : m = m + 1
1173 0 : IF (a == b .AND. i == j) THEN
1174 0 : eigen_diff = Eigenval(a + homo) - Eigenval(i)
1175 : ELSE
1176 0 : eigen_diff = 0
1177 : END IF
1178 0 : A_full_reshaped(n, m) = eigen_diff + 2*v_iajb(i, a, j, b) - W_ijab(i, j, a, b)
1179 0 : A_full(i, a, j, b) = eigen_diff + 2*v_iajb(i, a, j, b) - W_ijab(i, j, a, b)
1180 : END DO
1181 : END DO
1182 : END DO
1183 : END DO
1184 :
1185 : !MG to do: Check for symmetry of ZAZ!
1186 0 : ALLOCATE (WORK(1))
1187 0 : WORK = 0.0_dp
1188 0 : CALL DSYEV("N", "U", homo*virtual, A_full_reshaped, homo*virtual, Full_exc_spectrum, WORK, -1, diag_info)
1189 0 : LWORK = INT(WORK(1))
1190 0 : DEALLOCATE (WORK)
1191 0 : ALLOCATE (WORK(LWORK))
1192 0 : WORK = 0.0_dp
1193 : !MG to check: Usage of symmetric routine okay? (Correct LWORK?)
1194 0 : CALL DSYEV("N", "U", homo*virtual, A_full_reshaped, homo*virtual, Full_exc_spectrum, WORK, LWORK, diag_info)
1195 :
1196 0 : DEALLOCATE (WORK)
1197 :
1198 0 : DEALLOCATE (W_ijab, v_iajb, A_full, A_full_reshaped)
1199 : END IF
1200 :
1201 0 : CALL timestop(handle)
1202 :
1203 0 : END SUBROUTINE
1204 :
1205 : ! **************************************************************************************************
1206 : !> \brief ...
1207 : !> \param AZ ...
1208 : !> \param Z_vectors ...
1209 : !> \param B_iaQ_bse_local ...
1210 : !> \param RI_vector ...
1211 : !> \param local_RI_size ...
1212 : !> \param num_Z_vectors ...
1213 : !> \param homo ...
1214 : !> \param virtual ...
1215 : !> \param bse_spin_config ...
1216 : !> \param v_iajb ...
1217 : !> \param bse_full_diag_debug ...
1218 : !> \param i_iter ...
1219 : !> \param para_env ...
1220 : ! **************************************************************************************************
1221 0 : SUBROUTINE compute_v_ia_jb_part(AZ, Z_vectors, B_iaQ_bse_local, RI_vector, local_RI_size, &
1222 : num_Z_vectors, homo, virtual, bse_spin_config, v_iajb, bse_full_diag_debug, i_iter, &
1223 : para_env)
1224 :
1225 : REAL(KIND=dp), DIMENSION(:, :, :), INTENT(INOUT) :: AZ, Z_vectors, B_iaQ_bse_local
1226 : REAL(KIND=dp), DIMENSION(:, :), INTENT(INOUT) :: RI_vector
1227 : INTEGER, INTENT(IN) :: local_RI_size, num_Z_vectors, homo, &
1228 : virtual, bse_spin_config
1229 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :, :) :: v_iajb
1230 : LOGICAL :: bse_full_diag_debug
1231 : INTEGER, INTENT(IN) :: i_iter
1232 : TYPE(mp_para_env_type), INTENT(IN) :: para_env
1233 :
1234 : CHARACTER(LEN=*), PARAMETER :: routineN = 'compute_v_ia_jb_part'
1235 :
1236 : INTEGER :: a, a_virt, b, handle, i, i_occ, &
1237 : i_Z_vector, j, LLL
1238 : REAL(KIND=dp) :: alpha
1239 :
1240 : !debugging:
1241 :
1242 0 : CALL timeset(routineN, handle)
1243 :
1244 : !Determines factor of exchange term, depending on requested spin configuration (cf. input_constants.F)
1245 0 : SELECT CASE (bse_spin_config)
1246 : CASE (bse_singlet)
1247 0 : alpha = 2.0_dp
1248 : CASE (bse_triplet)
1249 0 : alpha = 0.0_dp
1250 : END SELECT
1251 :
1252 0 : RI_vector = 0.0_dp
1253 :
1254 : ! v_P = sum_jb B_jb^P Z_jb
1255 0 : DO LLL = 1, local_RI_size
1256 0 : DO i_Z_vector = 1, num_Z_vectors
1257 0 : DO i_occ = 1, homo
1258 0 : DO a_virt = 1, virtual
1259 :
1260 : RI_vector(LLL, i_Z_vector) = RI_vector(LLL, i_Z_vector) + &
1261 : Z_vectors(i_occ, a_virt, i_Z_vector)* &
1262 0 : B_iaQ_bse_local(i_occ, a_virt, LLL)
1263 :
1264 : END DO
1265 : END DO
1266 : END DO
1267 : END DO
1268 :
1269 : ! AZ = sum_P B_ia^P*v_P + ...
1270 0 : DO LLL = 1, local_RI_size
1271 0 : DO i_Z_vector = 1, num_Z_vectors
1272 0 : DO i_occ = 1, homo
1273 0 : DO a_virt = 1, virtual
1274 : !MG to check: Minus sign at v oder W? Factor for triplet/singlet
1275 : AZ(i_occ, a_virt, i_Z_vector) = AZ(i_occ, a_virt, i_Z_vector) + &
1276 : alpha*RI_vector(LLL, i_Z_vector)* &
1277 0 : B_iaQ_bse_local(i_occ, a_virt, LLL)
1278 :
1279 : END DO
1280 : END DO
1281 : END DO
1282 : END DO
1283 0 : IF (i_iter == 1 .AND. bse_full_diag_debug) THEN
1284 0 : ALLOCATE (v_iajb(homo, virtual, homo, virtual))
1285 0 : v_iajb = 0.0_dp
1286 : !Create unscreened 4c integrals for check
1287 0 : DO LLL = 1, local_RI_size
1288 0 : DO i = 1, homo
1289 0 : DO j = 1, homo
1290 0 : DO a = 1, virtual
1291 0 : DO b = 1, virtual
1292 0 : v_iajb(i, a, j, b) = v_iajb(i, a, j, b) + B_iaQ_bse_local(i, a, LLL)*B_iaQ_bse_local(j, b, LLL)
1293 : END DO
1294 : END DO
1295 : END DO
1296 : END DO
1297 : END DO
1298 : ! we make the mp_sum to sum over all RI basis functions
1299 0 : CALL para_env%sum(v_iajb)
1300 : END IF
1301 :
1302 0 : CALL timestop(handle)
1303 :
1304 0 : END SUBROUTINE
1305 :
1306 : ! **************************************************************************************************
1307 : !> \brief ...Eigenval
1308 : !> \param Z_vectors ...
1309 : !> \param Eigenval ...
1310 : !> \param num_Z_vectors ...
1311 : !> \param homo ...
1312 : !> \param virtual ...
1313 : ! **************************************************************************************************
1314 0 : SUBROUTINE initial_guess_Z_vectors(Z_vectors, Eigenval, num_Z_vectors, homo, virtual)
1315 :
1316 : REAL(KIND=dp), DIMENSION(:, :, :), INTENT(INOUT) :: Z_vectors
1317 : REAL(KIND=dp), DIMENSION(:), INTENT(IN) :: Eigenval
1318 : INTEGER, INTENT(IN) :: num_Z_vectors, homo, virtual
1319 :
1320 : CHARACTER(LEN=*), PARAMETER :: routineN = 'initial_guess_Z_vectors'
1321 :
1322 : INTEGER :: a_virt, handle, i_occ, i_Z_vector, &
1323 : min_loc(2)
1324 0 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: eigen_diff_ia
1325 :
1326 0 : CALL timeset(routineN, handle)
1327 :
1328 0 : ALLOCATE (eigen_diff_ia(homo, virtual))
1329 :
1330 0 : DO i_occ = 1, homo
1331 0 : DO a_virt = 1, virtual
1332 0 : eigen_diff_ia(i_occ, a_virt) = Eigenval(a_virt + homo) - Eigenval(i_occ)
1333 : END DO
1334 : END DO
1335 :
1336 0 : DO i_Z_vector = 1, num_Z_vectors
1337 :
1338 0 : min_loc = MINLOC(eigen_diff_ia)
1339 :
1340 0 : Z_vectors(min_loc(1), min_loc(2), i_Z_vector) = 1.0_dp
1341 :
1342 0 : eigen_diff_ia(min_loc(1), min_loc(2)) = 1.0E20_dp
1343 :
1344 : END DO
1345 :
1346 0 : DEALLOCATE (eigen_diff_ia)
1347 :
1348 0 : CALL timestop(handle)
1349 :
1350 0 : END SUBROUTINE
1351 :
1352 : ! **************************************************************************************************
1353 : !> \brief ...
1354 : !> \param fm_mat_S_ab_bse ...
1355 : !> \param fm_mat_S ...
1356 : !> \param fm_mat_S_bar_ia_bse ...
1357 : !> \param fm_mat_S_bar_ij_bse ...
1358 : !> \param B_bar_ijQ_bse_local ...
1359 : !> \param B_abQ_bse_local ...
1360 : !> \param B_bar_iaQ_bse_local ...
1361 : !> \param B_iaQ_bse_local ...
1362 : !> \param dimen_RI ...
1363 : !> \param homo ...
1364 : !> \param virtual ...
1365 : !> \param gd_array ...
1366 : !> \param color_sub ...
1367 : !> \param para_env ...
1368 : ! **************************************************************************************************
1369 0 : SUBROUTINE fill_local_3c_arrays(fm_mat_S_ab_bse, fm_mat_S, &
1370 : fm_mat_S_bar_ia_bse, fm_mat_S_bar_ij_bse, &
1371 : B_bar_ijQ_bse_local, B_abQ_bse_local, B_bar_iaQ_bse_local, &
1372 : B_iaQ_bse_local, dimen_RI, homo, virtual, &
1373 : gd_array, color_sub, para_env)
1374 :
1375 : TYPE(cp_fm_type), INTENT(IN) :: fm_mat_S_ab_bse, fm_mat_S, &
1376 : fm_mat_S_bar_ia_bse, &
1377 : fm_mat_S_bar_ij_bse
1378 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :), &
1379 : INTENT(OUT) :: B_bar_ijQ_bse_local, B_abQ_bse_local, &
1380 : B_bar_iaQ_bse_local, B_iaQ_bse_local
1381 : INTEGER, INTENT(IN) :: dimen_RI, homo, virtual
1382 : TYPE(group_dist_d1_type), INTENT(IN) :: gd_array
1383 : INTEGER, INTENT(IN) :: color_sub
1384 : TYPE(mp_para_env_type), INTENT(IN) :: para_env
1385 :
1386 : CHARACTER(LEN=*), PARAMETER :: routineN = 'fill_local_3c_arrays'
1387 :
1388 : INTEGER :: handle
1389 :
1390 0 : CALL timeset(routineN, handle)
1391 :
1392 0 : CALL allocate_and_fill_local_array(B_iaQ_bse_local, fm_mat_S, gd_array, color_sub, homo, virtual, dimen_RI, para_env)
1393 :
1394 : CALL allocate_and_fill_local_array(B_bar_iaQ_bse_local, fm_mat_S_bar_ia_bse, gd_array, color_sub, homo, virtual, &
1395 0 : dimen_RI, para_env)
1396 :
1397 : CALL allocate_and_fill_local_array(B_bar_ijQ_bse_local, fm_mat_S_bar_ij_bse, gd_array, color_sub, homo, homo, &
1398 0 : dimen_RI, para_env)
1399 :
1400 : CALL allocate_and_fill_local_array(B_abQ_bse_local, fm_mat_S_ab_bse, gd_array, color_sub, virtual, virtual, &
1401 0 : dimen_RI, para_env)
1402 :
1403 0 : CALL timestop(handle)
1404 :
1405 0 : END SUBROUTINE
1406 :
1407 : ! **************************************************************************************************
1408 : !> \brief ...
1409 : !> \param B_local ...
1410 : !> \param fm_mat_S ...
1411 : !> \param gd_array ...
1412 : !> \param color_sub ...
1413 : !> \param small_size ...
1414 : !> \param big_size ...
1415 : !> \param dimen_RI ...
1416 : !> \param para_env ...
1417 : ! **************************************************************************************************
1418 0 : SUBROUTINE allocate_and_fill_local_array(B_local, fm_mat_S, gd_array, &
1419 : color_sub, small_size, big_size, dimen_RI, para_env)
1420 :
1421 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :), &
1422 : INTENT(OUT) :: B_local
1423 : TYPE(cp_fm_type), INTENT(IN) :: fm_mat_S
1424 : TYPE(group_dist_d1_type), INTENT(IN) :: gd_array
1425 : INTEGER, INTENT(IN) :: color_sub, small_size, big_size, dimen_RI
1426 : TYPE(mp_para_env_type), INTENT(IN) :: para_env
1427 :
1428 : CHARACTER(LEN=*), PARAMETER :: routineN = 'allocate_and_fill_local_array'
1429 :
1430 : INTEGER :: combi_index, end_RI, handle, handle1, i_comm, i_entry, iiB, imepos, jjB, &
1431 : level_big_size, level_small_size, ncol_local, nrow_local, num_comm_cycles, RI_index, &
1432 : size_RI, start_RI
1433 0 : INTEGER, ALLOCATABLE, DIMENSION(:) :: entry_counter, mepos_from_RI_index, &
1434 0 : num_entries_rec, num_entries_send
1435 0 : INTEGER, DIMENSION(:), POINTER :: col_indices, row_indices
1436 : REAL(KIND=dp) :: matrix_el
1437 : TYPE(integ_mat_buffer_type), ALLOCATABLE, &
1438 0 : DIMENSION(:) :: buffer_rec, buffer_send
1439 0 : TYPE(mp_request_type), DIMENSION(:, :), POINTER :: req_array
1440 :
1441 0 : CALL timeset(routineN, handle)
1442 :
1443 0 : ALLOCATE (mepos_from_RI_index(dimen_RI))
1444 0 : mepos_from_RI_index = 0
1445 :
1446 0 : DO imepos = 0, para_env%num_pe - 1
1447 :
1448 0 : CALL get_group_dist(gd_array, pos=imepos, starts=start_RI, ends=end_RI)
1449 :
1450 0 : mepos_from_RI_index(start_RI:end_RI) = imepos
1451 :
1452 : END DO
1453 :
1454 : ! color_sub is automatically the number of the process since every subgroup has only one MPI rank
1455 0 : CALL get_group_dist(gd_array, color_sub, start_RI, end_RI, size_RI)
1456 :
1457 0 : ALLOCATE (B_local(small_size, big_size, 1:size_RI))
1458 :
1459 0 : ALLOCATE (num_entries_send(0:para_env%num_pe - 1))
1460 0 : ALLOCATE (num_entries_rec(0:para_env%num_pe - 1))
1461 :
1462 0 : ALLOCATE (req_array(1:para_env%num_pe, 4))
1463 :
1464 0 : ALLOCATE (entry_counter(0:para_env%num_pe - 1))
1465 :
1466 : CALL cp_fm_get_info(matrix=fm_mat_S, &
1467 : nrow_local=nrow_local, &
1468 : ncol_local=ncol_local, &
1469 : row_indices=row_indices, &
1470 0 : col_indices=col_indices)
1471 :
1472 0 : num_comm_cycles = 10
1473 :
1474 : ! communicate not all due to huge memory overhead, since for every number in fm_mat_S, we store
1475 : ! three additional ones (RI index, first MO index, second MO index!!)
1476 0 : DO i_comm = 0, num_comm_cycles - 1
1477 :
1478 0 : num_entries_send = 0
1479 0 : num_entries_rec = 0
1480 :
1481 : ! loop over RI index to get the number of sent entries
1482 0 : DO jjB = 1, nrow_local
1483 :
1484 0 : RI_index = row_indices(jjB)
1485 :
1486 0 : IF (MODULO(RI_index, num_comm_cycles) /= i_comm) CYCLE
1487 :
1488 0 : imepos = mepos_from_RI_index(RI_index)
1489 :
1490 0 : num_entries_send(imepos) = num_entries_send(imepos) + ncol_local
1491 :
1492 : END DO
1493 :
1494 0 : CALL para_env%alltoall(num_entries_send, num_entries_rec, 1)
1495 :
1496 0 : ALLOCATE (buffer_rec(0:para_env%num_pe - 1))
1497 0 : ALLOCATE (buffer_send(0:para_env%num_pe - 1))
1498 :
1499 : ! allocate data message and corresponding indices
1500 0 : DO imepos = 0, para_env%num_pe - 1
1501 :
1502 0 : ALLOCATE (buffer_rec(imepos)%msg(num_entries_rec(imepos)))
1503 0 : buffer_rec(imepos)%msg = 0.0_dp
1504 :
1505 0 : ALLOCATE (buffer_send(imepos)%msg(num_entries_send(imepos)))
1506 0 : buffer_send(imepos)%msg = 0.0_dp
1507 :
1508 0 : ALLOCATE (buffer_rec(imepos)%indx(num_entries_rec(imepos), 3))
1509 0 : buffer_rec(imepos)%indx = 0
1510 :
1511 0 : ALLOCATE (buffer_send(imepos)%indx(num_entries_send(imepos), 3))
1512 0 : buffer_send(imepos)%indx = 0
1513 :
1514 : END DO
1515 :
1516 0 : entry_counter(:) = 0
1517 :
1518 : ! loop over RI index for filling the send-buffer
1519 0 : DO jjB = 1, nrow_local
1520 :
1521 0 : RI_index = row_indices(jjB)
1522 :
1523 0 : IF (MODULO(RI_index, num_comm_cycles) /= i_comm) CYCLE
1524 :
1525 0 : imepos = mepos_from_RI_index(RI_index)
1526 :
1527 0 : DO iiB = 1, ncol_local
1528 :
1529 0 : combi_index = col_indices(iiB)
1530 0 : level_small_size = MAX(1, combi_index - 1)/MAX(big_size, 2) + 1
1531 0 : level_big_size = combi_index - (level_small_size - 1)*big_size
1532 :
1533 0 : entry_counter(imepos) = entry_counter(imepos) + 1
1534 :
1535 0 : buffer_send(imepos)%msg(entry_counter(imepos)) = fm_mat_S%local_data(jjB, iiB)
1536 :
1537 0 : buffer_send(imepos)%indx(entry_counter(imepos), 1) = RI_index
1538 0 : buffer_send(imepos)%indx(entry_counter(imepos), 2) = level_small_size
1539 0 : buffer_send(imepos)%indx(entry_counter(imepos), 3) = level_big_size
1540 :
1541 : END DO
1542 :
1543 : END DO
1544 :
1545 0 : CALL timeset("BSE_comm_data", handle1)
1546 :
1547 0 : CALL communicate_buffer(para_env, num_entries_rec, num_entries_send, buffer_rec, buffer_send, req_array)
1548 :
1549 0 : CALL timestop(handle1)
1550 :
1551 : ! fill B_local
1552 0 : DO imepos = 0, para_env%num_pe - 1
1553 :
1554 0 : DO i_entry = 1, num_entries_rec(imepos)
1555 :
1556 0 : RI_index = buffer_rec(imepos)%indx(i_entry, 1) - start_RI + 1
1557 0 : level_small_size = buffer_rec(imepos)%indx(i_entry, 2)
1558 0 : level_big_size = buffer_rec(imepos)%indx(i_entry, 3)
1559 :
1560 0 : matrix_el = buffer_rec(imepos)%msg(i_entry)
1561 :
1562 0 : B_local(level_small_size, level_big_size, RI_index) = matrix_el
1563 :
1564 : END DO
1565 :
1566 : END DO
1567 :
1568 0 : DO imepos = 0, para_env%num_pe - 1
1569 0 : DEALLOCATE (buffer_send(imepos)%msg)
1570 0 : DEALLOCATE (buffer_send(imepos)%indx)
1571 0 : DEALLOCATE (buffer_rec(imepos)%msg)
1572 0 : DEALLOCATE (buffer_rec(imepos)%indx)
1573 : END DO
1574 :
1575 0 : DEALLOCATE (buffer_rec, buffer_send)
1576 :
1577 : END DO
1578 :
1579 0 : DEALLOCATE (num_entries_send, num_entries_rec)
1580 :
1581 0 : DEALLOCATE (mepos_from_RI_index)
1582 :
1583 0 : DEALLOCATE (entry_counter, req_array)
1584 :
1585 0 : CALL timestop(handle)
1586 :
1587 0 : END SUBROUTINE
1588 :
1589 : END MODULE bse_iterative
|