(git:8917686)
Loading...
Searching...
No Matches
rt_bse.F
Go to the documentation of this file.
1!--------------------------------------------------------------------------------------------------!
2! CP2K: A general program to perform molecular dynamics simulations !
3! Copyright 2000-2026 CP2K developers group <https://cp2k.org> !
4! !
5! SPDX-License-Identifier: GPL-2.0-or-later !
6!--------------------------------------------------------------------------------------------------!
7
8! **************************************************************************************************
9!> \brief Routines for the propagation via RT-BSE method.
10!> \note The control is handed directly from cp2k_runs
11!> \author Stepan Marek (12.23)
12! **************************************************************************************************
13
14MODULE rt_bse
15 USE bibliography, ONLY: marek2025, &
16 cite_reference
20 USE cp_fm_types, ONLY: cp_fm_type, &
25 USE cp_cfm_types, ONLY: cp_cfm_type, &
32 USE kinds, ONLY: dp
33 USE cp_dbcsr_api, ONLY: dbcsr_p_type, &
34 dbcsr_type, &
37 dbcsr_copy, &
38 dbcsr_add, &
39 dbcsr_set, &
49 USE dbt_api, ONLY: dbt_clear, &
50 dbt_contract, &
51 dbt_copy_matrix_to_tensor, &
52 dbt_copy_tensor_to_matrix, &
53 dbt_type
55 USE qs_tensors, ONLY: build_2c_integrals, &
73 USE cp_cfm_diag, ONLY: cp_cfm_geeig
78 USE efield_utils, ONLY: make_field
82 do_bch, &
83 do_exact, &
85 USE rt_bse_types, ONLY: rtbse_env_type, &
90 USE rt_bse_io, ONLY: output_moments, &
93 read_field, &
100 USE cp_log_handling, ONLY: cp_logger_type, &
107
108#include "../base/base_uses.f90"
109
110 IMPLICIT NONE
111
112 PRIVATE
113
114 CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = "rt_bse"
115
116
117
118
119 PUBLIC :: run_propagation_bse, &
120 get_hartree, &
121 get_sigma, &
128 init_hartree, &
129 rho_metric, &
131 cp_cfm_gexp, &
133
134 INTERFACE get_sigma
135 MODULE PROCEDURE get_sigma_complex, &
136 get_sigma_real, &
137 get_sigma_dbcsr, &
138 get_sigma_noenv
139 END INTERFACE
140 INTERFACE get_hartree
141 MODULE PROCEDURE get_hartree_env, &
142 get_hartree_noenv
143 END INTERFACE
144
145CONTAINS
146
147! **************************************************************************************************
148!> \brief Runs the electron-only real time BSE propagation
149!> \param force_env Force environment data, entry point of the calculation
150! **************************************************************************************************
151 SUBROUTINE run_propagation_bse(force_env)
152 TYPE(force_env_type), POINTER :: force_env
153 CHARACTER(len=*), PARAMETER :: routinen = 'run_propagation_bse'
154 TYPE(rtbse_env_type), POINTER :: rtbse_env
155 INTEGER :: i, j, k, handle
156 LOGICAL :: converged
157 REAL(kind=dp) :: metric, enum_re, enum_im, &
158 idempotence_dev, a_metric_1, a_metric_2
159 TYPE(cp_logger_type), POINTER :: logger
160
161 CALL timeset(routinen, handle)
162
163 ! Bibliography information
164 CALL cite_reference(marek2025)
165
166 logger => cp_get_default_logger()
167
168 ! Run the initial SCF calculation / read SCF restart information
169 CALL force_env_calc_energy_force(force_env, calc_force=.false., consistent_energies=.false.)
170
171 ! Allocate all persistant storage and read input that does not need further processing
172 CALL create_rtbse_env(rtbse_env, force_env)
173
174 CALL print_rtbse_header_info(rtbse_env)
175
176 ! Initiate iteration level "MD" in order to copy the structure of other RTP codes
177 CALL cp_add_iter_level(logger%iter_info, "MD")
178 ! Initialize non-trivial values
179 ! - calculates the moment operators
180 CALL initialize_moments(rtbse_env)
181 ! - populates overlap and inverse overlap matrices
182 CALL initialize_rtbse_env(rtbse_env)
183
184 ! - populates the initial density matrix
185 ! - reads the restart density if requested
186 CALL initialize_density_matrix(rtbse_env)
187 ! - reads the moment and field traces from previous runs (no-op if the files are absent)
188 CALL read_moments(rtbse_env%moments_section, rtbse_env%sim_start_orig, &
189 rtbse_env%sim_start, rtbse_env%moments_trace, rtbse_env%time_trace)
190 CALL read_field(rtbse_env)
191 ! - calculates/populates the G0W0/KS Hamiltonian, respectively
193 ! - calculates the Hartree reference potential
194 CALL initialize_hartree_potential(rtbse_env)
195 ! - calculates the COHSEX reference self-energy
196 CALL initialize_cohsex_selfenergy(rtbse_env)
197
198 ! Setup the time based on the starting step
199 ! Assumes identical dt between two runs
200 rtbse_env%sim_time = real(rtbse_env%sim_start, dp)*rtbse_env%sim_dt
201 ! Output 0 time moments and field
202 IF (.NOT. rtbse_env%restart_extracted) THEN
203 CALL output_field(rtbse_env, append_opt=.false.)
204 CALL output_moments(rtbse_env, rtbse_env%rho)
205 END IF
206
207 ! Do not apply the delta kick if we are doing a restart calculation
208 IF (rtbse_env%dft_control%rtp_control%apply_delta_pulse .AND. (.NOT. rtbse_env%restart_extracted)) THEN
209 CALL apply_delta_pulse(rtbse_env)
210 END IF
211
212 ! ********************** Start the time loop **********************
213 ! NOTE : Time-loop starts at index sim_start = 0, unless restarted or configured otherwise
214 DO i = rtbse_env%sim_start, rtbse_env%sim_nsteps - 1
215
216 ! Update the simulation time
217 rtbse_env%sim_time = real(i, dp)*rtbse_env%sim_dt
218 rtbse_env%sim_step = i
219 ! Carry out the ETRS self-consistent propagation - propagates rho to rho_new (through rho_M)
220 CALL etrs_scf_loop(rtbse_env, rtbse_env%rho, rtbse_env%rho_M, rtbse_env%rho_new, converged, k, metric)
221 CALL get_electron_number(rtbse_env, rtbse_env%rho_new, enum_re, enum_im)
222 IF (.false.) THEN
223 ! Not all of these are used, but they are all good metrics to check the convergence in problematic cases
224 ! TODO : Allow for conditional warning
225 CALL get_idempotence_deviation(rtbse_env, rtbse_env%rho_new, idempotence_dev)
226 DO j = 1, rtbse_env%n_spin
227 CALL cp_cfm_to_fm(rtbse_env%sigma_SEX(j), rtbse_env%real_workspace(1), rtbse_env%real_workspace(2))
228 CALL antiherm_metric(real_fm=rtbse_env%real_workspace(1), imag_fm=rtbse_env%real_workspace(2), &
229 workspace=rtbse_env%rho_workspace, metric=a_metric_1)
230 CALL antiherm_metric(real_fm=rtbse_env%hartree_curr(j), &
231 workspace=rtbse_env%rho_workspace, metric=a_metric_2)
232 END DO
233 END IF
234 CALL print_timestep_info(rtbse_env, i, [enum_re], metric, k)
235 IF (.NOT. converged) cpabort("ETRS did not converge")
236 CALL cp_iterate(logger%iter_info, iter_nr=i, last=(i == rtbse_env%sim_nsteps))
237 DO j = 1, rtbse_env%n_spin
238 CALL cp_cfm_to_cfm(rtbse_env%rho_new(j), rtbse_env%rho(j))
239 END DO
240 ! Print the updated field
241 CALL output_field(rtbse_env)
242 ! If needed, print out the density matrix in MO basis
243 CALL output_mos_contravariant(rtbse_env, rtbse_env%rho, rtbse_env%rho_section)
244 ! Also handles outputting to memory
245 CALL output_moments(rtbse_env, rtbse_env%rho)
246 ! Output restart files, so that the restart starts at the following time index
247 CALL output_restart(rtbse_env, rtbse_env%rho, i + 1)
248 END DO
249 ! ********************** End the time loop **********************
250
251 CALL cp_rm_iter_level(logger%iter_info, "MD")
252
253 ! Carry out the FT
254 CALL print_ft(rtbse_env%rtp_section, &
255 rtbse_env%moments_trace, &
256 rtbse_env%time_trace, &
257 rtbse_env%field_trace, &
258 rtbse_env%dft_control%rtp_control, &
259 info_opt=rtbse_env%unit_nr)
260
261 ! Deallocate everything
262 CALL release_rtbse_env(rtbse_env)
263
264 CALL timestop(handle)
265 END SUBROUTINE run_propagation_bse
266
267! **************************************************************************************************
268!> \brief Calculates the initial values, based on restart/scf density, and other non-trivial values
269!> \param rtbse_env RT-BSE environment
270!> \author Stepan Marek (09.24)
271! **************************************************************************************************
272 SUBROUTINE initialize_rtbse_env(rtbse_env)
273 TYPE(rtbse_env_type), POINTER :: rtbse_env
274 CHARACTER(len=*), PARAMETER :: routinen = "initialize_rtbse_env"
275 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
276 TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: matrix_s
277 INTEGER :: handle
278
279 CALL timeset(routinen, handle)
280
281 ! Get pointers to parameters from qs_env
282 CALL get_qs_env(rtbse_env%qs_env, bs_env=bs_env, matrix_s=matrix_s)
283
284 ! ****** START OVERLAP + INVERSE OVERLAP CALCULATION
285 CALL copy_dbcsr_to_fm(matrix_s(1)%matrix, rtbse_env%S_fm)
286 CALL cp_fm_to_cfm(msourcer=rtbse_env%S_fm, mtarget=rtbse_env%S_cfm)
287 CALL cp_fm_invert(rtbse_env%S_fm, rtbse_env%S_inv_fm)
288 ! ****** END OVERLAP + INVERSE OVERLAP CALCULATION
289
290 CALL timestop(handle)
291 END SUBROUTINE initialize_rtbse_env
292
293! **************************************************************************************************
294!> \brief Calculates the moment operators
295!> \param rtbse_env RT-BSE environment
296!> \author Stepan Marek (09.24)
297!> \author Maximilian Graml (03.26) - refactor in prep. of linearized propagation
298! **************************************************************************************************
299 SUBROUTINE initialize_moments(rtbse_env)
300 TYPE(rtbse_env_type), POINTER :: rtbse_env
301 CHARACTER(len=*), PARAMETER :: routinen = "initialize_moments"
302 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
303 TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: moments_dbcsr_p
304 INTEGER :: i, k, handle
305 TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: matrix_s
306 REAL(kind=dp), DIMENSION(3) :: rpoint
307
308 CALL timeset(routinen, handle)
309 ! Get pointers to parameters from qs_env
310 CALL get_qs_env(rtbse_env%qs_env, bs_env=bs_env, matrix_s=matrix_s)
311
312 ! ****** START MOMENTS OPERATOR CALCULATION
313 ! Construct moments from dbcsr
314 NULLIFY (moments_dbcsr_p)
315 ALLOCATE (moments_dbcsr_p(3))
316 DO k = 1, 3
317 ! Make sure the pointer is empty
318 NULLIFY (moments_dbcsr_p(k)%matrix)
319 ! Allocate a new matrix that the pointer points to
320 ALLOCATE (moments_dbcsr_p(k)%matrix)
321 ! Create the matrix storage - matrix copies the structure of overlap matrix
322 CALL dbcsr_copy(moments_dbcsr_p(k)%matrix, matrix_s(1)%matrix)
323 END DO
324 ! Run the moment calculation
325 ! check for presence to prevent memory errors
326 rpoint(:) = 0.0_dp
327 CALL get_reference_point(rpoint, qs_env=rtbse_env%qs_env, &
328 reference=rtbse_env%moment_ref_type, ref_point=rtbse_env%user_moment_ref_point)
329 CALL build_local_moment_matrix(rtbse_env%qs_env, moments_dbcsr_p, 1, rpoint)
330 ! Copy to full matrix
331 DO i = 1, rtbse_env%n_spin
332 DO k = 1, 3
333 ! AO dipole is spin-independent; replicate into each spin slot
334 CALL copy_dbcsr_to_fm(moments_dbcsr_p(k)%matrix, rtbse_env%moments(k, i))
335 END DO
336 END DO
337 ! Now, repeat without reference point to get the moments for field
338 CALL get_reference_point(rpoint, qs_env=rtbse_env%qs_env, &
339 reference=use_mom_ref_zero)
340 CALL build_local_moment_matrix(rtbse_env%qs_env, moments_dbcsr_p, 1, rpoint)
341 DO i = 1, rtbse_env%n_spin
342 DO k = 1, 3
343 CALL copy_dbcsr_to_fm(moments_dbcsr_p(k)%matrix, rtbse_env%moments_field(k, i))
344 END DO
345 END DO
346
347 ! Now can deallocate dbcsr matrices
348 DO k = 1, 3
349 CALL dbcsr_release(moments_dbcsr_p(k)%matrix)
350 DEALLOCATE (moments_dbcsr_p(k)%matrix)
351 END DO
352 DEALLOCATE (moments_dbcsr_p)
353 ! ****** END MOMENTS OPERATOR CALCULATION
354
355 CALL timestop(handle)
356 END SUBROUTINE initialize_moments
357
358! **************************************************************************************************
359!> \brief Calculates the initial density matrix, based on the SCF density or restart density if requested
360!> \param rtbse_env RT-BSE environment
361!> \author Stepan Marek (09.24)
362!> \author Maximilian Graml (03.26) - refactor in prep. of linearized propagation
363! **************************************************************************************************
364 SUBROUTINE initialize_density_matrix(rtbse_env)
365 TYPE(rtbse_env_type), POINTER :: rtbse_env
366 CHARACTER(len=*), PARAMETER :: routinen = "initialize_density_matrix"
367 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
368 REAL(kind=dp), DIMENSION(:), POINTER :: occupations
369 INTEGER :: i, handle
370
371 CALL timeset(routinen, handle)
372 ! Get pointers to parameters from qs_env
373 CALL get_qs_env(rtbse_env%qs_env, bs_env=bs_env)
374
375 ! ****** START INITIAL DENSITY MATRIX CALCULATION
376 ! Get the rho from fm_MOS
377 ! Uses real orbitals only - no kpoints
378 ALLOCATE (occupations(rtbse_env%n_ao))
379 ! Iterate over both spins
380 DO i = 1, rtbse_env%n_spin
381 occupations(:) = 0.0_dp
382 occupations(1:rtbse_env%n_occ(i)) = 1.0_dp
383 ! Create real part
384 CALL cp_fm_to_fm(bs_env%fm_mo_coeff_Gamma(i), rtbse_env%real_workspace(1))
385 CALL cp_fm_column_scale(rtbse_env%real_workspace(1), occupations)
386 CALL parallel_gemm("N", "T", rtbse_env%n_ao, rtbse_env%n_ao, rtbse_env%n_ao, &
387 1.0_dp, rtbse_env%real_workspace(1), bs_env%fm_mo_coeff_Gamma(i), &
388 0.0_dp, rtbse_env%real_workspace(2))
389 ! Sets imaginary part to zero
390 CALL cp_fm_to_cfm(msourcer=rtbse_env%real_workspace(2), mtarget=rtbse_env%rho(i))
391 ! Save the reference value for the case of delta kick
392 CALL cp_cfm_to_cfm(rtbse_env%rho(i), rtbse_env%rho_orig(i))
393 END DO
394 DEALLOCATE (occupations)
395 ! If the restart field is provided, overwrite rho from restart
396 IF (rtbse_env%dft_control%rtp_control%initial_wfn == use_rt_restart) THEN
397 CALL read_restart(rtbse_env)
398 END IF
399 ! ****** END INITIAL DENSITY MATRIX CALCULATION
400
401 CALL timestop(handle)
402 END SUBROUTINE initialize_density_matrix
403
404! **************************************************************************************************
405!> \brief Calculates the single particle Hamiltonian
406!> \param rtbse_env RT-BSE environment
407!> \author Stepan Marek (09.24)
408!> \author Maximilian Graml (03.26) - refactor in prep. of linearized propagation
409! **************************************************************************************************
411 TYPE(rtbse_env_type), POINTER :: rtbse_env
412 CHARACTER(len=*), PARAMETER :: routinen = "initialize_singleparticle_hamiltonian"
413 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
414 INTEGER :: i, handle
415
416 CALL timeset(routinen, handle)
417 ! Get pointers to parameters from qs_env
418 CALL get_qs_env(rtbse_env%qs_env, bs_env=bs_env)
419
420 ! ****** START SINGLE PARTICLE HAMILTONIAN CALCULATION
421 DO i = 1, rtbse_env%n_spin
422 IF (rtbse_env%ham_reference_type == rtp_bse_ham_g0w0) THEN
423 ! G0W0 Hamiltonian
424 CALL cp_fm_to_fm(bs_env%fm_mo_coeff_Gamma(i), rtbse_env%real_workspace(1))
425 ! NOTE : Gamma point is not always the zero k-point
426 ! C * Lambda
427 CALL cp_fm_column_scale(rtbse_env%real_workspace(1), bs_env%eigenval_G0W0(:, 1, i))
428 ! C * Lambda * C^T
429 CALL parallel_gemm("N", "T", rtbse_env%n_ao, rtbse_env%n_ao, rtbse_env%n_ao, &
430 1.0_dp, rtbse_env%real_workspace(1), bs_env%fm_mo_coeff_Gamma(i), &
431 0.0_dp, rtbse_env%real_workspace(2))
432 ! S * C * Lambda * C^T
433 CALL parallel_gemm("N", "N", rtbse_env%n_ao, rtbse_env%n_ao, rtbse_env%n_ao, &
434 1.0_dp, rtbse_env%S_fm, rtbse_env%real_workspace(2), &
435 0.0_dp, rtbse_env%real_workspace(1))
436 ! S * C * Lambda * C^T * S = H
437 CALL parallel_gemm("N", "N", rtbse_env%n_ao, rtbse_env%n_ao, rtbse_env%n_ao, &
438 1.0_dp, rtbse_env%real_workspace(1), rtbse_env%S_fm, &
439 0.0_dp, rtbse_env%real_workspace(2))
440 CALL cp_fm_to_cfm(msourcer=rtbse_env%real_workspace(2), mtarget=rtbse_env%ham_reference(i))
441 ELSE
442 ! KS Hamiltonian
443 CALL cp_fm_to_cfm(msourcer=bs_env%fm_ks_Gamma(i), mtarget=rtbse_env%ham_reference(i))
444 END IF
445 END DO
446 ! ****** END SINGLE PARTICLE HAMILTONIAN CALCULATION
447
448 CALL timestop(handle)
450
451! **************************************************************************************************
452!> \brief Calculates the Hartree potential
453!> \param rtbse_env RT-BSE environment
454!> \author Stepan Marek (09.24)
455!> \author Maximilian Graml (03.26) - refactor in prep. of linearized propagation
456! **************************************************************************************************
457 SUBROUTINE initialize_hartree_potential(rtbse_env)
458 TYPE(rtbse_env_type), POINTER :: rtbse_env
459 CHARACTER(len=*), PARAMETER :: routinen = "initialize_hartree_potential"
460 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
461 INTEGER :: i, handle
462
463 CALL timeset(routinen, handle)
464 ! Get pointers to parameters from qs_env
465 CALL get_qs_env(rtbse_env%qs_env, bs_env=bs_env)
466
467 ! ****** START HARTREE POTENTIAL REFERENCE CALCULATION
468 ! Calculate Coulomb RI elements, necessary for Hartree calculation
469 CALL init_hartree(rtbse_env, rtbse_env%v_dbcsr)
470 ! Calculate the original Hartree potential
471 ! Uses rho_orig - same as rho for initial run but different for continued run
472 DO i = 1, rtbse_env%n_spin
473 CALL get_hartree(rtbse_env, rtbse_env%rho_orig(i), rtbse_env%hartree_curr(i))
474 ! Scaling by spin degeneracy
475 CALL cp_fm_scale(rtbse_env%spin_degeneracy, rtbse_env%hartree_curr(i))
476 ! Subtract the reference from the reference Hamiltonian
477 CALL cp_fm_to_cfm(msourcer=rtbse_env%hartree_curr(i), mtarget=rtbse_env%ham_workspace(1))
478 CALL cp_cfm_scale_and_add(cmplx(1.0, 0.0, kind=dp), rtbse_env%ham_reference(i), &
479 cmplx(-1.0, 0.0, kind=dp), rtbse_env%ham_workspace(1))
480 END DO
481 ! ****** END HARTREE POTENTIAL REFERENCE CALCULATION
482
483 CALL timestop(handle)
484 END SUBROUTINE initialize_hartree_potential
485
486! **************************************************************************************************
487!> \brief Calculates the COHSEX reference self-energy
488!> \param rtbse_env RT-BSE environment
489!> \author Stepan Marek (09.24)
490!> \author Maximilian Graml (03.26) - refactor in prep. of linearized propagation
491! **************************************************************************************************
492 SUBROUTINE initialize_cohsex_selfenergy(rtbse_env)
493 TYPE(rtbse_env_type), POINTER :: rtbse_env
494 CHARACTER(len=*), PARAMETER :: routinen = "initialize_cohsex_selfenergy"
495 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
496 INTEGER :: i, handle
497
498 CALL timeset(routinen, handle)
499 ! Get pointers to parameters from qs_env
500 CALL get_qs_env(rtbse_env%qs_env, bs_env=bs_env)
501
502 ! ****** START COHSEX REFERENCE CALCULATION
503 IF (rtbse_env%ham_reference_type == rtp_bse_ham_g0w0) THEN
504 ! In a non-HF calculation, copy the actual correlation part of the interaction
505 CALL copy_fm_to_dbcsr(bs_env%fm_W_MIC_freq_zero, rtbse_env%w_dbcsr)
506 ELSE
507 ! In HF, correlation is set to zero
508 CALL dbcsr_set(rtbse_env%w_dbcsr, 0.0_dp)
509 END IF
510 ! Add the Hartree to the screened_dbt tensor - now W = V + W^c
511 CALL dbcsr_add(rtbse_env%w_dbcsr, rtbse_env%v_dbcsr, 1.0_dp, 1.0_dp)
512 CALL dbt_copy_matrix_to_tensor(rtbse_env%w_dbcsr, rtbse_env%screened_dbt)
513 ! Calculate the COHSEX starting energies
514 DO i = 1, rtbse_env%n_spin
515 IF (rtbse_env%ham_reference_type == rtp_bse_ham_g0w0) THEN
516 ! Subtract the v_xc from COH part of the self-energy, as V_xc is also not updated during the timestepping
517 ! TODO : Allow no COH calculation for static screening
518 CALL get_sigma(rtbse_env, rtbse_env%sigma_COH(i), -0.5_dp, rtbse_env%S_inv_fm)
519 ! Copy and subtract from the complex reference hamiltonian
520 CALL cp_fm_to_cfm(msourcer=rtbse_env%sigma_COH(i), mtarget=rtbse_env%ham_workspace(1))
521 CALL cp_cfm_scale_and_add(cmplx(1.0, 0.0, kind=dp), rtbse_env%ham_reference(i), &
522 cmplx(-1.0, 0.0, kind=dp), rtbse_env%ham_workspace(1))
523 END IF
524 ! Calculate exchange part - TODO : should this be applied for different spins? - TEST with O2 HF propagation?
525 ! So far only closed shell tested
526 ! Uses rho_orig - same as rho for initial run but different for continued run
527 ! For KS reference this is the time-dependent Fock exchange (w_dbcsr = v only).
528 CALL get_sigma(rtbse_env, rtbse_env%sigma_SEX(i), -1.0_dp, rtbse_env%rho_orig(i))
529 ! Subtract from the complex reference Hamiltonian
530 CALL cp_cfm_scale_and_add(cmplx(1.0, 0.0, kind=dp), rtbse_env%ham_reference(i), &
531 cmplx(-1.0, 0.0, kind=dp), rtbse_env%sigma_SEX(i))
532 END DO
533 ! ****** END COHSEX REFERENCE CALCULATION
534
535 CALL timestop(handle)
536 END SUBROUTINE initialize_cohsex_selfenergy
537
538! **************************************************************************************************
539!> \brief Custom reimplementation of the delta pulse routines
540!> \param rtbse_env RT-BSE environment
541!> \author Stepan Marek (09.24)
542! **************************************************************************************************
543 SUBROUTINE apply_delta_pulse(rtbse_env)
544 TYPE(rtbse_env_type), POINTER :: rtbse_env
545 CHARACTER(len=*), PARAMETER :: routinen = "apply_delta_pulse"
546 REAL(kind=dp) :: intensity, metric
547 REAL(kind=dp), DIMENSION(3) :: kvec
548 INTEGER :: i, k, handle
549
550 CALL timeset(routinen, handle)
551
552 ! Report application
553 IF (rtbse_env%unit_nr > 0) WRITE (rtbse_env%unit_nr, '(A28)') ' RTBSE| Applying delta pulse'
554 ! Extra minus for the propagation of density
555 intensity = -rtbse_env%dft_control%rtp_control%delta_pulse_scale
556 metric = 0.0_dp
557 kvec(:) = rtbse_env%dft_control%rtp_control%delta_pulse_direction(:)
558 IF (rtbse_env%unit_nr > 0) WRITE (rtbse_env%unit_nr, '(A38,E14.4E3,E14.4E3,E14.4E3)') &
559 " RTBSE| Delta pulse elements (a.u.) : ", intensity*kvec(:)
560 ! So far no spin dependence, but can be added by different structure of delta pulse
561 CALL cp_fm_set_all(rtbse_env%real_workspace(1), 0.0_dp)
562 DO k = 1, 3
563 CALL cp_fm_scale_and_add(1.0_dp, rtbse_env%real_workspace(1), &
564 kvec(k), rtbse_env%moments_field(k, 1))
565 END DO
566 ! enforce hermiticity of the effective Hamiltonian
567 CALL cp_fm_transpose(rtbse_env%real_workspace(1), rtbse_env%real_workspace(2))
568 CALL cp_fm_scale_and_add(0.5_dp, rtbse_env%real_workspace(1), &
569 0.5_dp, rtbse_env%real_workspace(2))
570 ! Prepare the exponential/exponent for propagation
571 IF (rtbse_env%mat_exp_method == do_bch) THEN
572 ! Multiply by the S_inv matrix - in the classic ordering
573 CALL parallel_gemm("N", "N", rtbse_env%n_ao, rtbse_env%n_ao, rtbse_env%n_ao, &
574 intensity, rtbse_env%S_inv_fm, rtbse_env%real_workspace(1), &
575 0.0_dp, rtbse_env%real_workspace(2))
576 DO i = 1, rtbse_env%n_spin
577 ! Sets real part to zero
578 CALL cp_fm_to_cfm(msourcei=rtbse_env%real_workspace(2), mtarget=rtbse_env%ham_workspace(i))
579 END DO
580 ELSE IF (rtbse_env%mat_exp_method == do_exact) THEN
581 DO i = 1, rtbse_env%n_spin
582 CALL cp_fm_to_cfm(msourcer=rtbse_env%real_workspace(1), mtarget=rtbse_env%ham_effective(i))
583 CALL cp_cfm_gexp(rtbse_env%ham_effective(i), rtbse_env%S_cfm, rtbse_env%ham_workspace(i), &
584 cmplx(0.0, intensity, kind=dp), rtbse_env%rho_workspace)
585 END DO
586 END IF
587 ! Propagate the density by the effect of the delta pulse
588 CALL propagate_density(rtbse_env, rtbse_env%ham_workspace, rtbse_env%rho, rtbse_env%rho_new)
589 metric = rho_metric(rtbse_env%rho_new, rtbse_env%rho, rtbse_env%n_spin)
590 IF (rtbse_env%unit_nr > 0) WRITE (rtbse_env%unit_nr, ('(A42,E38.8E3)')) " RTBSE| Metric difference after delta kick", metric
591 ! Copy the new density to the old density
592 DO i = 1, rtbse_env%n_spin
593 CALL cp_cfm_to_cfm(rtbse_env%rho_new(i), rtbse_env%rho(i))
594 END DO
595
596 CALL timestop(handle)
597 END SUBROUTINE apply_delta_pulse
598! **************************************************************************************************
599!> \brief Determines the metric for the density matrix, used for convergence criterion
600!> \param rho_new Array of new density matrices (one for each spin index)
601!> \param rho_old Array of old density matrices (one for each spin index)
602!> \param nspin Number of spin indices
603!> \param workspace_opt Optionally provide external workspace to save some allocation time
604! **************************************************************************************************
605 FUNCTION rho_metric(rho_new, rho_old, nspin, workspace_opt) RESULT(metric)
606 TYPE(cp_cfm_type), DIMENSION(:), POINTER, INTENT(IN):: rho_new, &
607 rho_old
608 INTEGER, INTENT(IN) :: nspin
609 TYPE(cp_cfm_type), POINTER, OPTIONAL :: workspace_opt
610 TYPE(cp_cfm_type) :: workspace
611 REAL(kind=dp) :: metric
612 REAL(kind=dp), DIMENSION(:), ALLOCATABLE :: partial_metric
613 INTEGER :: j
614 COMPLEX(kind=dp) :: scale_factor
615
616 ALLOCATE (partial_metric(nspin))
617
618 ! Only allocate/deallocate storage if required
619 IF (PRESENT(workspace_opt)) THEN
620 workspace = workspace_opt
621 ELSE
622 CALL cp_cfm_create(workspace, rho_new(1)%matrix_struct)
623 END IF
624 scale_factor = 1.0
625 DO j = 1, nspin
626 CALL cp_cfm_to_cfm(rho_new(j), workspace)
627 ! Get the difference in the resulting matrix
628 CALL cp_cfm_scale_and_add(scale_factor, workspace, -scale_factor, rho_old(j))
629 ! Now, get the relevant number
630 partial_metric(j) = cp_cfm_norm(workspace, 'M')
631 END DO
632 metric = 0.0_dp
633 ! For more than one spin, do Cartesian sum of the different spin norms
634 DO j = 1, nspin
635 metric = metric + partial_metric(j)*partial_metric(j)
636 END DO
637 metric = sqrt(metric)
638 ! Deallocate workspace
639 IF (.NOT. PRESENT(workspace_opt)) CALL cp_cfm_release(workspace)
640 DEALLOCATE (partial_metric)
641 END FUNCTION rho_metric
642
643! **************************************************************************************************
644!> \brief Determines the metric of the antihermitian part of the matrix
645!> \param real_fm Real part of the full matrix
646!> \param imag_fm Imaginary part of the full matrix
647! **************************************************************************************************
648 SUBROUTINE antiherm_metric(real_fm, imag_fm, workspace, metric)
649 TYPE(cp_fm_type), INTENT(IN) :: real_fm
650 TYPE(cp_fm_type), INTENT(IN), OPTIONAL :: imag_fm
651 REAL(kind=dp), INTENT(OUT) :: metric
652 TYPE(cp_cfm_type), DIMENSION(:), POINTER :: workspace
653 COMPLEX(kind=dp) :: complex_one
654
655 ! Get the complex and complex conjugate matrix
656 IF (PRESENT(imag_fm)) THEN
657 CALL cp_fm_to_cfm(real_fm, imag_fm, workspace(1))
658 ELSE
659 CALL cp_fm_to_cfm(msourcer=real_fm, mtarget=workspace(1))
660 END IF
661 CALL cp_cfm_transpose(workspace(1), "C", workspace(2))
662 ! Subtract these, and get the metric
663 complex_one = cmplx(1.0, 0.0, kind=dp)
664 CALL cp_cfm_scale_and_add(complex_one, workspace(1), -complex_one, workspace(2))
665 metric = cp_cfm_norm(workspace(1), "M")
666 END SUBROUTINE antiherm_metric
667
668! **************************************************************************************************
669!> \brief For Taylor and Exact exp_method, calculates the matrix exponential of the
670!> effective Hamiltonian. For BCH, calculates just the effective Hamiltonian. For other methods,
671!> aborts the execution, as they are not implemented yet.
672!> \param rtbse_env Entry point of the calculation. Uses rho_workspace for Taylor and BCH. For exact,
673!> uses complex_workspace, complex_ham, complex_s, real_eigvals and exp_eigvals.
674!> Results are stored in ham_workspace.
675! **************************************************************************************************
676 SUBROUTINE ham_to_exp(rtbse_env, ham, ham_exp)
677 TYPE(rtbse_env_type), POINTER :: rtbse_env
678 TYPE(cp_cfm_type), DIMENSION(:), POINTER :: ham, &
679 ham_exp
680 CHARACTER(len=*), PARAMETER :: routinen = "ham_to_exp"
681 INTEGER :: j, handle
682 CALL timeset(routinen, handle)
683 DO j = 1, rtbse_env%n_spin
684 IF (rtbse_env%mat_exp_method == do_bch) THEN
685 ! In Taylor and BCH, we first evaluate the entire exponent and then evaluate exponential in series
686 ! In order to produce correct result, need to remultiply by inverse overlap matrix
687 CALL multiply_fm_cfm("N", "N", rtbse_env%n_ao, rtbse_env%n_ao, rtbse_env%n_ao, &
688 1.0_dp, rtbse_env%S_inv_fm, ham(j), &
689 0.0_dp, rtbse_env%rho_workspace(1))
690
691 ! The evolution of density matrix is derived from the right multiplying term
692 ! Imaginary part of the exponent = -real part of the matrix
693 CALL cp_cfm_scale(cmplx(0.0, -rtbse_env%sim_dt/2, kind=dp), rtbse_env%rho_workspace(1))
694 ! In BCH, exponential is not calculated explicitly, but the propagation is solved in series
695 CALL cp_cfm_to_cfm(rtbse_env%rho_workspace(1), ham_exp(j))
696 ELSE IF (rtbse_env%mat_exp_method == do_exact) THEN
697 CALL cp_cfm_gexp(ham(j), rtbse_env%S_cfm, ham_exp(j), &
698 cmplx(0.0, -rtbse_env%sim_dt/2, kind=dp), rtbse_env%rho_workspace)
699 ELSE
700 cpabort("Only BCH and Taylor matrix exponentiation implemented")
701 END IF
702 END DO
703
704 CALL timestop(handle)
705 END SUBROUTINE ham_to_exp
706! **************************************************************************************************
707!> \brief Updates the effective Hamiltonian, given a density matrix rho
708!> \param rtbse_env Entry point of the calculation - contains current state of variables
709!> \param qs_env QS env
710!> \param rho Real and imaginary parts ( + spin) of the density at current time
711! **************************************************************************************************
712 SUBROUTINE update_effective_ham(rtbse_env, rho)
713 TYPE(rtbse_env_type), POINTER :: rtbse_env
714 TYPE(cp_cfm_type), DIMENSION(:), POINTER :: rho
715 CHARACTER(len=*), PARAMETER :: routinen = "update_effective_ham"
716 INTEGER :: k, j, nspin, handle
717
718 CALL timeset(routinen, handle)
719 ! Shorthand
720 nspin = rtbse_env%n_spin
721 ! Reset the effective Hamiltonian to KS Hamiltonian + G0W0 - reference COHSEX - reference Hartree
722 DO j = 1, nspin
723 ! Sets the imaginary part to zero
724 CALL cp_cfm_to_cfm(rtbse_env%ham_reference(j), rtbse_env%ham_effective(j))
725 END DO
726 ! Determine the field at current time
727 IF (rtbse_env%dft_control%apply_efield_field) THEN
728 CALL make_field(rtbse_env%dft_control, rtbse_env%field, rtbse_env%sim_step, rtbse_env%sim_time)
729 ELSE
730 ! No field
731 rtbse_env%field(:) = 0.0_dp
732 END IF
733 DO j = 1, nspin
734 DO k = 1, 3
735 ! Minus sign due to charge of electrons
736 CALL cp_fm_to_cfm(msourcer=rtbse_env%moments_field(k, 1), mtarget=rtbse_env%ham_workspace(1))
737 CALL cp_cfm_scale_and_add(cmplx(1.0, 0.0, kind=dp), rtbse_env%ham_effective(j), &
738 cmplx(rtbse_env%field(k), 0.0, kind=dp), rtbse_env%ham_workspace(1))
739 END DO
740 IF (rtbse_env%ham_reference_type == rtp_bse_ham_g0w0) THEN
741 ! Add the COH part - so far static but can be dynamic in principle through the W updates
742 CALL get_sigma(rtbse_env, rtbse_env%sigma_COH(j), -0.5_dp, rtbse_env%S_inv_fm)
743 CALL cp_fm_to_cfm(msourcer=rtbse_env%sigma_COH(j), mtarget=rtbse_env%ham_workspace(1))
744 CALL cp_cfm_scale_and_add(cmplx(1.0, 0.0, kind=dp), rtbse_env%ham_effective(j), &
745 cmplx(1.0, 0.0, kind=dp), rtbse_env%ham_workspace(1))
746 END IF
747 ! Calculate the (S)EX part - based on provided rho
748 ! iGW = - rho W
749 CALL get_sigma(rtbse_env, rtbse_env%sigma_SEX(j), -1.0_dp, rho(j))
750 CALL cp_cfm_scale_and_add(cmplx(1.0, 0.0, kind=dp), rtbse_env%ham_effective(j), &
751 cmplx(1.0, 0.0, kind=dp), rtbse_env%sigma_SEX(j))
752 ! Calculate Hartree potential
753 ! Hartree potential is scaled by number of electrons in each MO - spin degeneracy
754 CALL get_hartree(rtbse_env, rho(j), &
755 rtbse_env%hartree_curr(j))
756 CALL cp_fm_to_cfm(msourcer=rtbse_env%hartree_curr(j), mtarget=rtbse_env%ham_workspace(1))
757 CALL cp_cfm_scale_and_add(cmplx(1.0, 0.0, kind=dp), rtbse_env%ham_effective(j), &
758 cmplx(rtbse_env%spin_degeneracy, 0.0, kind=dp), rtbse_env%ham_workspace(1))
759 ! Enforce hermiticity of the effective Hamiltonian
760 ! Important components without forced Hermiticity - moments matrix, sigma matrices, Hartree matrix
761 ! single particle Ham
762 CALL cp_cfm_transpose(rtbse_env%ham_effective(j), 'C', rtbse_env%ham_workspace(1))
763 CALL cp_cfm_scale_and_add(cmplx(0.5, 0.0, kind=dp), rtbse_env%ham_effective(j), &
764 cmplx(0.5, 0.0, kind=dp), rtbse_env%ham_workspace(1))
765 END DO
766 CALL timestop(handle)
767 END SUBROUTINE update_effective_ham
768! **************************************************************************************************
769!> \brief Self-consistently (ETRS) propagates the density to the next timestep
770!> \note Uses rtbse_env%rho_new_last, assumes correct timestep information is given in rtbse_env
771!> \param rho_start Initial density matrix
772!> \param rho_mid Midpoint density (propagated to by the initial Hamiltonian)
773!> \param rho_end Endpoint density (propagated to by endpoint Hamiltonian)
774!> \param converged Whether the resulting rho_end is self-consistent
775!> \param k How many SC iterations were done
776!> \param metric The difference metric from the last self-consistent iteration (for printing/evaluation)
777! **************************************************************************************************
778 SUBROUTINE etrs_scf_loop(rtbse_env, rho_start, rho_mid, rho_end, converged, k, metric)
779 TYPE(rtbse_env_type), POINTER :: rtbse_env
780 TYPE(cp_cfm_type), DIMENSION(:), POINTER :: rho_start, &
781 rho_mid, &
782 rho_end
783 LOGICAL :: converged
784 INTEGER :: k
785 REAL(kind=dp) :: metric
786 CHARACTER(len=*), PARAMETER :: routinen = "etrs_scf_loop"
787 INTEGER :: j, handle
788
789 CALL timeset(routinen, handle)
790
791 ! This method determines the density matrix at time (t+dt) by guessing the effective Hamiltonian at (t + dt)
792 ! and using the Hamiltonian at time (t), it propagates density from time (t) while ensuring that the density
793 ! at (t + dt/2) is the same for both forward and backwards propagation. Then, density at (t + dt) is
794 ! used to calculate the new Hamiltonian at (t+dt), which is then used to get the new propagator, and so on
795 ! until the density matrix does not change within certain limit
796 ! Pseudocode of the algorithm
797 ! rho_M = exp(-i S^(-1) H[rho(t)] dt/2) rho(t) exp(i H[rho(t)] S^(-1) dt/2)
798 ! rho(t+dt, 0) = rho_M
799 ! for j in 1,max_self_iter
800 ! rho(t+dt,j) = exp(- i S^(-1) H[rho(t+dt,j-1)] dt/2) rho_M exp(i H [rho(t+dt,j-1)] S^(-1) dt/2)
801 ! if ||rho(t+dt,j) - rho(t+dt,j-1)|| < epsilon
802 ! break
803
804 ! Initial setup - calculate the Hamiltonian
805 CALL update_effective_ham(rtbse_env, rho_start)
806 ! Create the exponential
807 CALL ham_to_exp(rtbse_env, rtbse_env%ham_effective, rtbse_env%ham_workspace)
808 ! Propagate to rho_mid
809 CALL propagate_density(rtbse_env, rtbse_env%ham_workspace, rho_start, rho_mid)
810 ! Propagate to initial guess
811 CALL propagate_density(rtbse_env, rtbse_env%ham_workspace, rho_mid, rtbse_env%rho_new_last)
812 ! Update bookkeeping to the next timestep - Hamiltonians are now evaluated at the next timestep
813 rtbse_env%sim_step = rtbse_env%sim_step + 1
814 rtbse_env%sim_time = rtbse_env%sim_time + rtbse_env%sim_dt
815 converged = .false.
816 CALL print_etrs_info_header(rtbse_env)
817 DO k = 1, rtbse_env%etrs_max_iter
818 ! Get the Hamiltonian following from the last timestep
819 CALL update_effective_ham(rtbse_env, rtbse_env%rho_new_last)
820 CALL ham_to_exp(rtbse_env, rtbse_env%ham_effective, rtbse_env%ham_workspace)
821 ! Propagate to new guess
822 CALL propagate_density(rtbse_env, rtbse_env%ham_workspace, rho_mid, rho_end)
823 ! Check for self-consistency
824 metric = rho_metric(rho_end, rtbse_env%rho_new_last, rtbse_env%n_spin)
825 ! ETRS info - only for log level > medium
826 CALL print_etrs_info(rtbse_env, k, metric)
827 IF (metric < rtbse_env%etrs_threshold) THEN
828 converged = .true.
829 EXIT
830 ELSE
831 ! Copy rho_new to rho_new_last
832 DO j = 1, rtbse_env%n_spin
833 ! Leaving for free convergence
834 CALL cp_cfm_to_cfm(rho_end(j), rtbse_env%rho_new_last(j))
835 END DO
836 END IF
837 END DO
838 ! Error handling in the case where the propagation did not converge is left to the main routine
839 CALL timestop(handle)
840 END SUBROUTINE etrs_scf_loop
841
842! **************************************************************************************************
843!> \brief Does the BCH iterative determination of the exponential
844!> \param propagator_matrix Matrix X which is to be exponentiated
845!> \param target_matrix Matrix Y which the exponential acts upon
846!> \param result_matrix Propagated matrix
847!> \param workspace Matrices dedicated for work, 4 fm matrices with dimensions of X required
848!> \param threshold_opt Optionally, a threshold under which the iteration is considered converged (default 1e-10)
849!> \param max_iter_opt Optionally, maximum number of BCH iterations (default 20)
850! **************************************************************************************************
851 SUBROUTINE bch_propagate(propagator_matrix, target_matrix, result_matrix, workspace, threshold_opt, max_iter_opt)
852 ! Array of complex propagator matrix X, such that
853 ! the propagated matrix will follow Y' = e^X Y e^(-X), for each spin
854 ! effect of e^(-X) is calculated - provide the X on the left hand side
855 TYPE(cp_cfm_type), DIMENSION(:), POINTER :: propagator_matrix
856 ! Matrix Y to be propagated into matrix Y'
857 TYPE(cp_cfm_type), DIMENSION(:), POINTER :: target_matrix
858 ! Matrix Y' is stored here on exit
859 TYPE(cp_cfm_type), DIMENSION(:), POINTER :: result_matrix, workspace
860 ! Threshold for the metric which decides when to truncate the BCH expansion
861 REAL(kind=dp), OPTIONAL :: threshold_opt
862 INTEGER, OPTIONAL :: max_iter_opt
863 CHARACTER(len=*), PARAMETER :: routinen = "bch_propagate"
864 REAL(kind=dp) :: threshold, prefactor, metric
865 INTEGER :: max_iter, i, n_spin, n_ao, k, &
866 w_stride, handle
867 LOGICAL :: converged
868 CHARACTER(len=77) :: error
869
870 CALL timeset(routinen, handle)
871
872 converged = .false.
873
874 IF (PRESENT(threshold_opt)) THEN
875 threshold = threshold_opt
876 ELSE
877 threshold = 1.0e-10
878 END IF
879
880 IF (PRESENT(max_iter_opt)) THEN
881 max_iter = max_iter_opt
882 ELSE
883 max_iter = 20
884 END IF
885
886 n_spin = SIZE(target_matrix)
887 n_ao = 0
888 CALL cp_cfm_get_info(target_matrix(1), nrow_global=n_ao)
889 w_stride = n_spin
890
891 ! Initiate
892 DO i = 1, n_spin
893 CALL cp_cfm_to_cfm(target_matrix(i), result_matrix(i))
894 CALL cp_cfm_to_cfm(target_matrix(i), workspace(i))
895 END DO
896
897 ! Start the BCH iterations
898 ! So far, no spin mixing terms
899 DO k = 1, max_iter
900 prefactor = 1.0_dp/real(k, kind=dp)
901 DO i = 1, n_spin
902 CALL parallel_gemm("N", "N", n_ao, n_ao, n_ao, &
903 cmplx(prefactor, 0.0, kind=dp), propagator_matrix(i), workspace(i), &
904 cmplx(0.0, 0.0, kind=dp), workspace(i + w_stride))
905 CALL parallel_gemm("N", "C", n_ao, n_ao, n_ao, &
906 cmplx(prefactor, 0.0, kind=dp), workspace(i), propagator_matrix(i), &
907 cmplx(1.0, 0.0, kind=dp), workspace(i + w_stride))
908 ! Add to the result
909 CALL cp_cfm_scale_and_add(cmplx(1.0, 0.0, kind=dp), result_matrix(i), &
910 cmplx(1.0, 0.0, kind=dp), workspace(i + w_stride))
911 END DO
912 metric = rho_metric(workspace(w_stride + 1:), workspace(1:w_stride), n_spin)
913 IF (metric <= threshold) THEN
914 converged = .true.
915 EXIT
916 ELSE
917 DO i = 1, n_spin
918 CALL cp_cfm_to_cfm(workspace(i + w_stride), workspace(i))
919 END DO
920 END IF
921 END DO
922 IF (.NOT. converged) THEN
923 WRITE (error, '(A35,E13.4E3,A16,E13.4E3)') "BCH did not converge, BCH Metric : ", &
924 metric, "BCH Threshold : ", threshold
925 cpabort(error)
926 END IF
927
928 CALL timestop(handle)
929 END SUBROUTINE bch_propagate
930
931! **************************************************************************************************
932!> \brief Updates the density in rtbse_env, using the provided exponential
933!> The new density is saved to a different matrix, which enables for comparison of matrices
934!> \param rtbse_env Entry point of the calculation - contains current state of variables
935!> \param exponential Real and imaginary parts ( + spin) of the exponential propagator
936! **************************************************************************************************
937 SUBROUTINE propagate_density(rtbse_env, exponential, rho_old, rho_new)
938 TYPE(rtbse_env_type) :: rtbse_env
939 TYPE(cp_cfm_type), DIMENSION(:), POINTER :: exponential, &
940 rho_old, &
941 rho_new
942 CHARACTER(len=*), PARAMETER :: routinen = "propagate_density"
943 INTEGER :: j, handle
944
945 CALL timeset(routinen, handle)
946 IF (rtbse_env%mat_exp_method == do_exact) THEN
947 ! For these methods, exponential is explicitly constructed
948 DO j = 1, rtbse_env%n_spin
949 ! rho * (exp^dagger)
950 CALL parallel_gemm("N", "C", rtbse_env%n_ao, rtbse_env%n_ao, rtbse_env%n_ao, &
951 cmplx(1.0, 0.0, kind=dp), rho_old(j), exponential(j), &
952 cmplx(0.0, 0.0, kind=dp), rtbse_env%rho_workspace(1))
953 ! exp * rho * (exp^dagger)
954 CALL parallel_gemm("N", "N", rtbse_env%n_ao, rtbse_env%n_ao, rtbse_env%n_ao, &
955 cmplx(1.0, 0.0, kind=dp), exponential(j), rtbse_env%rho_workspace(1), &
956 cmplx(0.0, 0.0, kind=dp), rho_new(j))
957 END DO
958 ELSE IF (rtbse_env%mat_exp_method == do_bch .OR. rtbse_env%linearized) THEN
959 ! Same number of iterations as ETRS
960 CALL bch_propagate(exponential, rho_old, rho_new, rtbse_env%rho_workspace, threshold_opt=rtbse_env%exp_accuracy, &
961 max_iter_opt=rtbse_env%etrs_max_iter)
962 ELSE
963 cpabort("Only BCH and exact matrix exponentiation implemented.")
964 END IF
965
966 CALL timestop(handle)
967 END SUBROUTINE propagate_density
968
969! **************************************************************************************************
970!> \brief Outputs the number of electrons in the system from the density matrix
971!> \note Moments matrix is provided by the rtbse_env, uses rho_workspace(1:3)
972!> \param rtbse_env Entry point - rtbse environment
973!> \param rho Density matrix in AO basis
974!> \param electron_n_re Real number of electrons
975!> \param electron_n_im Imaginary number of electrons, which can arise from numerical non-hermiticity
976! **************************************************************************************************
977 SUBROUTINE get_electron_number(rtbse_env, rho, electron_n_re, electron_n_im)
978 TYPE(rtbse_env_type) :: rtbse_env
979 TYPE(cp_cfm_type), DIMENSION(:), POINTER :: rho
980 REAL(kind=dp), INTENT(OUT) :: electron_n_re, electron_n_im
981 COMPLEX(kind=dp) :: electron_n_buffer
982 INTEGER :: j
983
984 electron_n_re = 0.0_dp
985 electron_n_im = 0.0_dp
986 CALL cp_fm_to_cfm(msourcer=rtbse_env%S_fm, mtarget=rtbse_env%rho_workspace(1))
987 DO j = 1, rtbse_env%n_spin
988 CALL cp_cfm_trace(rtbse_env%rho_workspace(1), rho(j), electron_n_buffer)
989 electron_n_re = electron_n_re + real(electron_n_buffer, kind=dp)
990 electron_n_im = electron_n_im + real(aimag(electron_n_buffer), kind=dp)
991 END DO
992 ! Scale by spin degeneracy
993 electron_n_re = electron_n_re*rtbse_env%spin_degeneracy
994 electron_n_im = electron_n_im*rtbse_env%spin_degeneracy
995 END SUBROUTINE get_electron_number
996! **************************************************************************************************
997!> \brief Outputs the deviation from idempotence of density matrix
998!> \note Moments matrix is provided by the rtbse_env, uses rho_workspace(1:3)
999!> \param rtbse_env Entry point - rtbse environment
1000!> \param rho Density matrix in AO basis
1001!> \param electron_n_re Real number of electrons
1002!> \param electron_n_im Imaginary number of electrons, which can arise from numerical non-hermiticity
1003! **************************************************************************************************
1004 SUBROUTINE get_idempotence_deviation(rtbse_env, rho, deviation_metric)
1005 TYPE(rtbse_env_type) :: rtbse_env
1006 TYPE(cp_cfm_type), DIMENSION(:), POINTER :: rho
1007 REAL(kind=dp), INTENT(OUT) :: deviation_metric
1008 COMPLEX(kind=dp) :: buffer_1, buffer_2
1009 REAL(kind=dp) :: buffer_dev
1010 INTEGER :: j
1011
1012 deviation_metric = 0.0_dp
1013 buffer_dev = 0.0_dp
1014 ! First, determine Tr(S * rho_re) + i Tr (S * rho_im)
1015 CALL cp_fm_to_cfm(msourcer=rtbse_env%S_fm, mtarget=rtbse_env%rho_workspace(1))
1016 DO j = 1, rtbse_env%n_spin
1017 CALL cp_cfm_trace(rtbse_env%rho_workspace(1), rho(j), buffer_1)
1018 buffer_dev = buffer_dev + real(abs(buffer_1)*abs(buffer_1), kind=dp)
1019 END DO
1020 ! Now, determine Tr(S * rho_re * S * rho_re) - Tr(S * rho_im * S * rho_im) + 2i Tr(S * rho_re * S * rho_im)
1021 DO j = 1, rtbse_env%n_spin
1022 ! S * rho
1023 CALL multiply_fm_cfm("N", "N", rtbse_env%n_ao, rtbse_env%n_ao, rtbse_env%n_ao, &
1024 1.0_dp, rtbse_env%S_fm, rho(j), &
1025 0.0_dp, rtbse_env%rho_workspace(2))
1026 ! rho * S * rho
1027 CALL parallel_gemm("N", "N", rtbse_env%n_ao, rtbse_env%n_ao, rtbse_env%n_ao, &
1028 cmplx(1.0, 0.0, kind=dp), rho(j), rtbse_env%rho_workspace(2), &
1029 cmplx(0.0, 0.0, kind=dp), rtbse_env%rho_workspace(3))
1030 ! Tr (S * rho * S * rho)
1031 CALL cp_cfm_trace(rtbse_env%rho_workspace(1), rtbse_env%rho_workspace(3), buffer_2)
1032 deviation_metric = deviation_metric + real(abs(buffer_2)*abs(buffer_2), kind=dp)
1033 END DO
1034 deviation_metric = sqrt(deviation_metric) - sqrt(buffer_dev)
1035 END SUBROUTINE get_idempotence_deviation
1036
1037! **************************************************************************************************
1038!> \brief Calculates the self-energy by contraction of screened potential, for complex density
1039!> \note Can be used for both the Coulomb hole part and screened exchange part
1040!> \param rtbse_env Quickstep environment data, entry point of the calculation
1041!> \param sigma_cfm Pointer to the self-energy full matrix, which is overwritten by this routine
1042!> \param prefactor_opt Optional scaling factor applied to the contraction, defaults to 1.0
1043!> \param greens_cfm Pointer to the Green's function matrix, which is used as input data
1044!> \param grid_diag_re_accum Optional accumulator for the real part of the RI-RS grid diagonal
1045!> \param grid_diag_im_accum Optional accumulator for the imaginary part of the RI-RS grid diagonal
1046!> \author Stepan Marek
1047!> \date 09.2024
1048! **************************************************************************************************
1049 SUBROUTINE get_sigma_complex(rtbse_env, sigma_cfm, prefactor_opt, greens_cfm, &
1050 grid_diag_re_accum, grid_diag_im_accum)
1051 TYPE(rtbse_env_type), POINTER :: rtbse_env
1052 TYPE(cp_cfm_type) :: sigma_cfm ! resulting self energy
1053 REAL(kind=dp), INTENT(IN), OPTIONAL :: prefactor_opt
1054 TYPE(cp_cfm_type), INTENT(IN) :: greens_cfm ! matrix to contract with RI_W
1055 REAL(kind=dp), INTENT(INOUT), OPTIONAL :: grid_diag_re_accum(:), grid_diag_im_accum(:)
1056 REAL(kind=dp) :: prefactor
1057
1058 prefactor = 1.0_dp
1059 IF (PRESENT(prefactor_opt)) prefactor = prefactor_opt
1060
1061 ! RI-RS screened-exchange backend (linRTBSE only; rirs_kernel is forced .FALSE. for full RTBSE,
1062 ! so this is inert there). The RI-RS routine does its own Re/Im split, replacing the AO-RI body.
1063 ! The optional grid_diag_* accumulators harvest diag(φρφ^T) for the Hartree reuse (RI-RS only;
1064 ! absent on AO-RI calls, which build no grid).
1065 IF (rtbse_env%rirs_kernel) THEN
1066 CALL compute_sigma_ri_rs_complex(rtbse_env%bs_env, sigma_cfm, prefactor, greens_cfm, &
1067 grid_diag_re_accum=grid_diag_re_accum, &
1068 grid_diag_im_accum=grid_diag_im_accum)
1069 RETURN
1070 END IF
1071
1072 ! Carry out the sigma part twice
1073 ! Real part
1074 CALL cp_cfm_to_fm(msource=greens_cfm, mtargetr=rtbse_env%real_workspace(1))
1075 CALL get_sigma(rtbse_env, rtbse_env%real_workspace(2), prefactor, rtbse_env%real_workspace(1))
1076 CALL cp_fm_to_cfm(msourcer=rtbse_env%real_workspace(2), mtarget=rtbse_env%sigma_complex_workspace(1))
1077 ! Imaginary part
1078 CALL cp_cfm_to_fm(msource=greens_cfm, mtargeti=rtbse_env%real_workspace(1))
1079 CALL get_sigma(rtbse_env, rtbse_env%real_workspace(2), prefactor, rtbse_env%real_workspace(1))
1080 CALL cp_fm_to_cfm(msourcei=rtbse_env%real_workspace(2), mtarget=sigma_cfm)
1081 ! Add the real part
1082 CALL cp_cfm_scale_and_add(cmplx(1.0, 0.0, kind=dp), sigma_cfm, &
1083 cmplx(1.0, 0.0, kind=dp), rtbse_env%sigma_complex_workspace(1))
1084
1085 END SUBROUTINE get_sigma_complex
1086! **************************************************************************************************
1087!> \brief Calculates the self-energy by contraction of screened potential, for complex density
1088!> \note Can be used for both the Coulomb hole part and screened exchange part
1089!> \param rtbse_env Quickstep environment data, entry point of the calculation
1090!> \param sigma_fm Pointer to the self-energy full matrix, which is overwritten by this routine
1091!> \param greens_fm Pointer to the Green's function matrix, which is used as input data
1092!> \author Stepan Marek
1093!> \date 09.2024
1094! **************************************************************************************************
1095 SUBROUTINE get_sigma_real(rtbse_env, sigma_fm, prefactor_opt, greens_fm)
1096 TYPE(rtbse_env_type), POINTER :: rtbse_env
1097 TYPE(cp_fm_type) :: sigma_fm ! resulting self energy
1098 REAL(kind=dp), INTENT(IN), OPTIONAL :: prefactor_opt
1099 TYPE(cp_fm_type), INTENT(IN) :: greens_fm ! matrix to contract with RI_W
1100 REAL(kind=dp) :: prefactor
1101 TYPE(dbcsr_type) :: greens_dbcsr_scratch
1102 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
1103
1104 prefactor = 1.0_dp
1105 IF (PRESENT(prefactor_opt)) prefactor = prefactor_opt
1106
1107 ! Local AO-AO dbcsr scratch for the FM->DBCSR conversion. Previously this
1108 ! routine used rtbse_env%rho_dbcsr as the workspace, which coupled AO-RI SX
1109 ! to the AO-RI Hartree allocation path - the historical (RIRS-H + AO-RI-SX)
1110 ! cross-combo (no longer expressible under the single KERNEL_RI switch)
1111 ! then segfaulted because rho_dbcsr is skipped when rirs_kernel=T.
1112 CALL get_qs_env(rtbse_env%qs_env, bs_env=bs_env)
1113 CALL dbcsr_create(greens_dbcsr_scratch, name="get_sigma greens scratch", &
1114 template=bs_env%mat_ao_ao%matrix)
1115
1116 CALL copy_fm_to_dbcsr(greens_fm, greens_dbcsr_scratch)
1117 CALL get_sigma_dbcsr(rtbse_env, sigma_fm, prefactor, greens_dbcsr_scratch)
1118
1119 CALL dbcsr_release(greens_dbcsr_scratch)
1120 END SUBROUTINE get_sigma_real
1121! **************************************************************************************************
1122!> \brief Calculates the self-energy by contraction of screened potential
1123!> \note Can be used for both the Coulomb hole part and screened exchange part
1124!> \param greens_fm Pointer to the Green's function matrix, which is used as input data
1125!> \param sigma_fm Pointer to the self-energy full matrix, which is overwritten by this routine
1126!> \author Stepan Marek
1127!> \date 01.2024
1128! **************************************************************************************************
1129 SUBROUTINE get_sigma_dbcsr(rtbse_env, sigma_fm, prefactor_opt, greens_dbcsr)
1130 TYPE(rtbse_env_type), POINTER :: rtbse_env
1131 TYPE(cp_fm_type) :: sigma_fm ! resulting self energy
1132 REAL(kind=dp), INTENT(IN), OPTIONAL :: prefactor_opt
1133 TYPE(dbcsr_type) :: greens_dbcsr
1134 REAL(kind=dp) :: prefactor
1135
1136 prefactor = 1.0_dp
1137 IF (PRESENT(prefactor_opt)) prefactor = prefactor_opt
1138
1139 CALL get_sigma_noenv(sigma_fm, prefactor_opt, greens_dbcsr, &
1140 rtbse_env%screened_dbt, rtbse_env%t_3c_w, &
1141 rtbse_env%t_3c_work_RI_AO__AO, rtbse_env%t_3c_work2_RI_AO__AO, &
1142 rtbse_env%greens_dbt)
1143 END SUBROUTINE get_sigma_dbcsr
1144! **************************************************************************************************
1145!> \brief Calculates the self-energy by contraction of screened potential
1146!> \note Can be used for both the Coulomb hole part and screened exchange part
1147!> \note Separated from the rtbse_env - can be in principle called outside of the RTBSE code
1148!> \param sigma_fm Pointer to the self-energy full matrix, which is overwritten by this routine
1149!> \param prefactor_opt Optional argument for the prefactor (used for Coulomb hole calculation)
1150!> \param greens_dbcsr Matrix storing the lesser Green's function elements
1151!> \param screened_dbt Tensor storing the W_PQ screened Coulomb interaction RI matrix elements
1152!> \param int_3c_dbt Tensor storing the 3c integrals (RI| ORB ORB )
1153!> \param work_dbt_3c_1 Tensor workspace optimised for RI_AO__AO contractions
1154!> \param work_dbt_3c_2 Tensor workspace optimised for RI_AO__AO contractions
1155!> \param work_dbt_2c Tensor workspace for 2c integrals (Green's function and self-energy)
1156!> \author Stepan Marek
1157!> \date 01.2025
1158! **************************************************************************************************
1159 SUBROUTINE get_sigma_noenv(sigma_fm, prefactor_opt, greens_dbcsr, screened_dbt, &
1160 int_3c_dbt, work_dbt_3c_1, work_dbt_3c_2, work_dbt_2c)
1161 TYPE(cp_fm_type) :: sigma_fm ! resulting self energy
1162 REAL(kind=dp), INTENT(IN), OPTIONAL :: prefactor_opt
1163 TYPE(dbcsr_type) :: greens_dbcsr
1164 TYPE(dbt_type) :: screened_dbt, &
1165 int_3c_dbt, &
1166 work_dbt_3c_1, &
1167 work_dbt_3c_2, &
1168 work_dbt_2c
1169 CHARACTER(len=*), PARAMETER :: routineN = 'get_sigma'
1170 REAL(kind=dp) :: prefactor
1171 TYPE(dbcsr_type) :: sigma_dbcsr
1172 INTEGER :: handle
1173
1174 CALL timeset(routinen, handle)
1175
1176 IF (PRESENT(prefactor_opt)) THEN
1177 prefactor = prefactor_opt
1178 ELSE
1179 prefactor = 1.0_dp
1180 END IF
1181
1182 ! Three-centre integrals are obtained from build_3c_integrals, from qs_tensors
1183 ! These should use sparcity, while W and Sigma can be full matrices
1184 ! The summation is carried out by dbt library - dbt_contract in dbt_api
1185 ! The building of the tensors might be a bit hard, because it requires a lot of parallel information
1186 ! Probably just use the tensors already present in bs_env? They seem to be mostly work tensors
1187 ! Create by template
1188 CALL dbt_contract(alpha=1.0_dp, &
1189 tensor_1=screened_dbt, &
1190 tensor_2=int_3c_dbt, &
1191 beta=0.0_dp, &
1192 tensor_3=work_dbt_3c_1, &
1193 contract_1=[2], notcontract_1=[1], map_1=[1], &
1194 contract_2=[1], notcontract_2=[2, 3], map_2=[2, 3])!,&
1195 !filter_eps=bs_env%eps_filter)
1196 ! t_work1 now contains B^P_(nu beta) = sum _ Q W _ (PQ) (iomega = 0) (Q| nu beta)
1197 ! Next step is to convert the greens full matrix to dbcsr matrix
1198 CALL dbt_copy_matrix_to_tensor(greens_dbcsr, work_dbt_2c)
1199 ! Then contract it
1200 ! no scaling applied - this has to be applied externally
1201 CALL dbt_contract(alpha=1.0_dp, &
1202 tensor_1=work_dbt_3c_1, &
1203 tensor_2=work_dbt_2c, &
1204 beta=0.0_dp, &
1205 tensor_3=work_dbt_3c_2, &
1206 contract_1=[2], notcontract_1=[1, 3], map_1=[1, 3], &
1207 contract_2=[2], notcontract_2=[1], map_2=[2])
1208 ! workspace 2 now contains C ^ P _ (mu beta) sum _ nu B ^ P _ (nu beta) g _ (mu nu)
1209 CALL dbt_contract(alpha=prefactor, &
1210 tensor_1=int_3c_dbt, &
1211 tensor_2=work_dbt_3c_2, &
1212 beta=0.0_dp, &
1213 tensor_3=work_dbt_2c, &
1214 contract_1=[1, 3], notcontract_1=[2], map_1=[1], &
1215 contract_2=[1, 2], notcontract_2=[3], map_2=[2])!,&
1216 !filter_eps=bs_env%eps_filter)
1217 ! Finally, convert the COH tensor to matrix and then to fm matrix
1218 ! TODO : extra workspace?
1219 CALL dbcsr_create(sigma_dbcsr, name="sigma", template=greens_dbcsr)
1220 CALL dbt_copy_tensor_to_matrix(work_dbt_2c, sigma_dbcsr)
1221 CALL copy_dbcsr_to_fm(sigma_dbcsr, sigma_fm)
1222 CALL dbcsr_release(sigma_dbcsr)
1223 ! Clear workspaces - saves memory?
1224 CALL dbt_clear(work_dbt_3c_1)
1225 CALL dbt_clear(work_dbt_3c_2)
1226 CALL dbt_clear(work_dbt_2c)
1227 CALL timestop(handle)
1228
1229 END SUBROUTINE get_sigma_noenv
1230! **************************************************************************************************
1231!> \brief Creates the RI matrix and populates it with correct values
1232!> \note Tensor contains Hartree elements in the auxiliary basis
1233!> \param qs_env Quickstep environment - entry point of calculation
1234!> \author Stepan Marek
1235!> \date 01.2024
1236! **************************************************************************************************
1237 SUBROUTINE init_hartree(rtbse_env, v_dbcsr)
1238 TYPE(rtbse_env_type), POINTER, INTENT(IN) :: rtbse_env
1239 TYPE(dbcsr_type) :: v_dbcsr
1240 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
1241 TYPE(libint_potential_type) :: coulomb_op
1242 TYPE(cp_fm_type) :: v_fm
1243 TYPE(cp_fm_type) :: metric_fm
1244 TYPE(cp_fm_type) :: metric_inv_fm, &
1245 work_fm
1246 TYPE(dbcsr_type), DIMENSION(:), ALLOCATABLE :: v_dbcsr_a, &
1247 metric_dbcsr
1248 TYPE(neighbor_list_set_p_type), DIMENSION(:), &
1249 POINTER :: nl_2c
1250
1251 bs_env => rtbse_env%bs_env
1252
1253 ! Allocate for bare Hartree term
1254 ALLOCATE (v_dbcsr_a(1))
1255 ALLOCATE (metric_dbcsr(1))
1256 CALL dbcsr_create(v_dbcsr_a(1), name="Hartree_dbcsr", template=bs_env%mat_RI_RI%matrix)
1257 CALL dbcsr_create(metric_dbcsr(1), name="RI_metric_dbcsr", template=bs_env%mat_RI_RI%matrix)
1258
1259 ! Calculate full coulomb RI basis elements - V _ (PQ) matrix
1260 NULLIFY (nl_2c)
1261 CALL build_2c_neighbor_lists(nl_2c, bs_env%basis_set_RI, bs_env%basis_set_RI, &
1262 coulomb_op, "Coulomb_neighbor_2c_list", rtbse_env%qs_env, &
1263 sym_ij=.false., molecular=.true.)
1264 CALL build_2c_integrals(v_dbcsr_a, bs_env%eps_filter, rtbse_env%qs_env, nl_2c, &
1265 bs_env%basis_set_RI, bs_env%basis_set_RI, coulomb_op, &
1266 do_kpoints=.false., regularization_ri=bs_env%regularization_RI)
1267 ! Calculate the RI metric elements
1268 ! nl_2c is automatically rewritten (even reallocated) in this routine
1269 CALL build_2c_neighbor_lists(nl_2c, bs_env%basis_set_RI, bs_env%basis_set_RI, &
1270 bs_env%ri_metric, "Metric_neighbor_2c_list", rtbse_env%qs_env, &
1271 sym_ij=.false., molecular=.true.)
1272 CALL build_2c_integrals(metric_dbcsr, bs_env%eps_filter, rtbse_env%qs_env, nl_2c, &
1273 bs_env%basis_set_RI, bs_env%basis_set_RI, bs_env%ri_metric, &
1274 do_kpoints=.false., regularization_ri=bs_env%regularization_RI)
1275 ! nl_2c no longer needed
1276 CALL release_neighbor_list_sets(nl_2c)
1277 CALL cp_fm_create(metric_fm, bs_env%fm_RI_RI%matrix_struct)
1278 CALL cp_fm_set_all(metric_fm, 0.0_dp)
1279 CALL cp_fm_create(metric_inv_fm, bs_env%fm_RI_RI%matrix_struct)
1280 CALL cp_fm_set_all(metric_inv_fm, 0.0_dp)
1281 CALL cp_fm_create(work_fm, bs_env%fm_RI_RI%matrix_struct)
1282 CALL cp_fm_set_all(work_fm, 0.0_dp)
1283 CALL copy_dbcsr_to_fm(metric_dbcsr(1), metric_fm)
1284 CALL cp_fm_invert(metric_fm, metric_inv_fm)
1285 CALL cp_fm_create(v_fm, bs_env%fm_RI_RI%matrix_struct)
1286 CALL cp_fm_set_all(v_fm, 0.0_dp)
1287 ! Multiply by the inverse from each side (M^-1 is symmetric)
1288 CALL cp_dbcsr_sm_fm_multiply(v_dbcsr_a(1), metric_inv_fm, &
1289 work_fm, bs_env%n_RI)
1290 CALL parallel_gemm("N", "N", bs_env%n_RI, bs_env%n_RI, bs_env%n_RI, &
1291 1.0_dp, metric_inv_fm, work_fm, 0.0_dp, v_fm)
1292 ! Now, create the tensor from the matrix
1293 ! First, convert full matrix to dbcsr
1294 CALL dbcsr_clear(v_dbcsr_a(1))
1295 CALL copy_fm_to_dbcsr(v_fm, v_dbcsr_a(1))
1296 CALL dbcsr_create(v_dbcsr, "Hartree ri", v_dbcsr_a(1))
1297 CALL dbcsr_copy(v_dbcsr, v_dbcsr_a(1))
1298 ! Create and copy distinctly, so that unnecessary objects can be destroyed
1299 ! Destroy all unnecessary matrices
1300 CALL dbcsr_release(v_dbcsr_a(1))
1301 CALL dbcsr_release(metric_dbcsr(1))
1302 DEALLOCATE (v_dbcsr_a)
1303 DEALLOCATE (metric_dbcsr)
1304 CALL cp_fm_release(v_fm)
1305 ! CALL cp_fm_release(metric_fm(1,1))
1306 CALL cp_fm_release(metric_fm)
1307 ! DEALLOCATE(metric_fm)
1308 CALL cp_fm_release(work_fm)
1309 CALL cp_fm_release(metric_inv_fm)
1310 END SUBROUTINE init_hartree
1311! **************************************************************************************************
1312!> \brief Calculates the Hartree matrix in the atomic orbital basis, given a density matrix, in local arrays
1313!> Calculates the values for single spin species present in given rho
1314!> \param qs_env Entry point
1315!> \param rtbse_env Entry point of GWBSE - uses rho_dbcsr and some complex_workspace
1316!> \param rho_ao Density matrix in ao basis
1317!> \param v_ao Overwritten by the Hartree matrix in the atomic orbital basis
1318!> \author Stepan Marek
1319!> \date 01.2025
1320! **************************************************************************************************
1321 SUBROUTINE get_hartree_env(rtbse_env, rho_fm, v_fm)
1322 TYPE(rtbse_env_type), POINTER :: rtbse_env
1323 TYPE(cp_cfm_type) :: rho_fm
1324 TYPE(cp_fm_type) :: v_fm
1325 TYPE(mp_para_env_type), POINTER :: para_env
1326 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
1327
1328 CALL get_qs_env(rtbse_env%qs_env, para_env=para_env, bs_env=bs_env)
1329
1330 CALL get_hartree_noenv(v_fm, rho_fm, rtbse_env%int_3c_array, rtbse_env%v_dbcsr, &
1331 rtbse_env%n_RI, bs_env%sizes_RI, &
1332 para_env, rtbse_env%rho_dbcsr, rtbse_env%v_ao_dbcsr)
1333 END SUBROUTINE get_hartree_env
1334! **************************************************************************************************
1335!> \brief Calculates the Hartree matrix in the atomic orbital basis, given a density matrix, in local arrays
1336!> Calculates the values for single spin species present in given rho
1337!> \param v_fm Hartree potential in atomic orbital basis - is overwritten by the updated potential
1338!> \param rho_fm Density matrix corresponding to single spin species, in atomic orbital basis
1339!> \param int_3c Previously allocated array (best to use create_hartree_ri_3c) for 3c integrals
1340!> \param v_dbcsr Previously calculated 2c Coulomb repulsion between RI orbitals
1341!> \param n_RI Number of RI basis orbitals
1342!> \param sizes_RI Number of RI basis orbitals per atom
1343!> \param para_env MPI Parallel environment (used for summation across ranks)
1344!> \param rho_dbcsr Previously created dbcsr matrix, used as workspace
1345!> \param v_ao_dbcsr Previously created dbcsr matrix, used as workspace
1346!> \author Stepan Marek
1347!> \date 01.2025
1348! **************************************************************************************************
1349 SUBROUTINE get_hartree_noenv(v_fm, rho_fm, int_3c, v_dbcsr, n_RI, sizes_RI, para_env, rho_dbcsr, v_ao_dbcsr)
1350 TYPE(cp_fm_type) :: v_fm
1351 TYPE(cp_cfm_type), INTENT(IN) :: rho_fm
1352 REAL(kind=dp), DIMENSION(:, :, :), POINTER :: int_3c
1353 TYPE(dbcsr_type) :: v_dbcsr
1354 INTEGER :: n_ri
1355 INTEGER, DIMENSION(:) :: sizes_ri
1356 TYPE(mp_para_env_type), POINTER :: para_env
1357 TYPE(dbcsr_type) :: rho_dbcsr, v_ao_dbcsr
1358 CHARACTER(len=*), PARAMETER :: routineN = "get_hartree"
1359 TYPE(dbcsr_iterator_type) :: iterator_matrix
1360 INTEGER :: i, j, k, n, nblocks, ind_1, ind_2, row_offset, col_offset, &
1361 row_size, col_size, j_n_AO, k_n_AO, i_n_RI, &
1362 ri_offset, ind_i, handle
1363 REAL(kind=dp), DIMENSION(:), ALLOCATABLE :: pvector, qvector
1364 REAL(kind=dp), DIMENSION(:, :), POINTER :: block_matrix
1365 INTEGER :: nblkrows_local, nblkcols_local, j_blk, k_blk, j_offset, k_offset
1366 INTEGER, DIMENSION(:), POINTER :: local_blk_rows, local_blk_cols
1367 LOGICAL :: found
1368
1369 mark_used(i_n_ri)
1370 mark_used(ri_offset)
1371 mark_used(ind_i)
1372
1373 ! No memory optimisation so far - calculate all 3cs an all ranks
1374 ! Importantly - dbcsr blocks are ordered by atoms - i.e. ethene with 6 atoms will have 6x6 block structure
1375 ! Number of basis states on each basis set is known is post_scf_bandstructure env
1376
1377 CALL timeset(routinen, handle)
1378
1379 ! Allocate the Q and Pvector on each rank
1380 ALLOCATE (qvector(n_ri), source=0.0_dp)
1381 ALLOCATE (pvector(n_ri), source=0.0_dp)
1382
1383 ! First step - analyze the structure of copied dbcsr matrix on all ranks
1384 CALL dbcsr_clear(rho_dbcsr)
1385 ! Only the real part of the density matrix contributes
1386 ! Use v_fm as workspace
1387 CALL cp_cfm_to_fm(msource=rho_fm, mtargetr=v_fm)
1388 CALL copy_fm_to_dbcsr(v_fm, rho_dbcsr)
1389 j_offset = 0
1390 CALL dbcsr_get_info(rho_dbcsr, nblkrows_local=nblkrows_local, nblkcols_local=nblkcols_local, &
1391 local_rows=local_blk_rows, local_cols=local_blk_cols)
1392 DO j_blk = 1, nblkrows_local
1393 k_offset = 0
1394 DO k_blk = 1, nblkcols_local
1395 ! Check whether we can retrieve the rho block
1396 ! TODO : Handle transposed case?
1397 CALL dbcsr_get_block_p(rho_dbcsr, local_blk_rows(j_blk), local_blk_cols(k_blk), &
1398 block=block_matrix, found=found, row_size=row_size, col_size=col_size)
1399 ! If the block is not found, then the density matrix here has below threshold values
1400 IF (.NOT. found) cycle
1401 ! With the block retrieved, add its contributions to the Q-vector
1402 !$OMP PARALLEL DO DEFAULT(none) PRIVATE(i,j,k) &
1403 !$OMP SHARED(n_RI, row_size, col_size, Qvector, int_3c, j_offset, k_offset, block_matrix)
1404 DO i = 1, n_ri
1405 DO j = 1, row_size
1406 DO k = 1, col_size
1407 qvector(i) = qvector(i) + int_3c(j_offset + j, k_offset + k, i)*block_matrix(j, k)
1408 END DO
1409 END DO
1410 END DO
1411 !$OMP END PARALLEL DO
1412 ! Increment k-offset - setup for the next block
1413 k_offset = k_offset + col_size
1414 END DO
1415 ! Increments the j-offset - row_size is carried over from the last iteration
1416 j_offset = j_offset + row_size
1417 END DO
1418 ! Now, each rank has contributions from D_jk within its scope
1419 ! Need to sum over different ranks to get the total vector on all ranks
1420 CALL para_env%sum(qvector)
1421 ! Once this is done, Pvector is current on all ranks
1422 ! Continue with V_PQ summation
1423 nblocks = dbcsr_get_num_blocks(v_dbcsr)
1424 CALL dbcsr_iterator_start(iterator_matrix, v_dbcsr)
1425 DO n = 1, nblocks
1426 ! TODO : Try OMP parallelisation over different blocks - expect many more available speedup for large systems
1427 CALL dbcsr_iterator_next_block(iterator_matrix, ind_1, ind_2, block_matrix, &
1428 row_offset=row_offset, col_offset=col_offset, row_size=row_size, col_size=col_size)
1429 ! TODO : Better names for RI
1430 j_n_ao = sizes_ri(ind_1)
1431 k_n_ao = sizes_ri(ind_2)
1432 ! The allocations are as follows
1433 !$OMP PARALLEL DO DEFAULT(none) PRIVATE(j,k) &
1434 !$OMP SHARED(block_matrix, Pvector, Qvector,j_n_AO,k_n_AO,row_offset,col_offset)
1435 DO j = 1, j_n_ao
1436 DO k = 1, k_n_ao
1437 pvector(j + row_offset - 1) = pvector(j + row_offset - 1) + block_matrix(j, k)*qvector(k + col_offset - 1)
1438 END DO
1439 END DO
1440 !$OMP END PARALLEL DO
1441 END DO
1442 CALL dbcsr_iterator_stop(iterator_matrix)
1443 ! Again, make sure that the P vector is present on all ranks
1444 CALL para_env%sum(pvector)
1445 ! Now, for the final trick, iterate over local blocks of v_ao_dbcsr to get the Hartree as dbcsr, then convert to fm
1446 ! TODO : Clear or set blocks to zero
1447 ! CALL dbcsr_clear(v_ao_dbcsr)
1448 j_offset = 0
1449 DO j_blk = 1, nblkrows_local
1450 k_offset = 0
1451 DO k_blk = 1, nblkcols_local
1452 ! Check whether we can retrieve the rho block
1453 ! TODO : Handle transposed case?
1454 CALL dbcsr_get_block_p(v_ao_dbcsr, local_blk_rows(j_blk), local_blk_cols(k_blk), &
1455 block=block_matrix, found=found, row_size=row_size, col_size=col_size)
1456 ! If the block is not found, reserve it
1457 IF (.NOT. found) THEN
1458 ! Reservations
1459 CALL dbcsr_reserve_blocks(v_ao_dbcsr, local_blk_rows(j_blk:j_blk), local_blk_cols(k_blk:k_blk))
1460 ! Rerun the getter to get the new block
1461 CALL dbcsr_get_block_p(v_ao_dbcsr, local_blk_rows(j_blk), local_blk_cols(k_blk), &
1462 block=block_matrix, found=found, row_size=row_size, col_size=col_size)
1463 END IF
1464 ! With the block retrieved, contract with the P vector
1465 !$OMP PARALLEL DO DEFAULT(none) PRIVATE(i,j,k) &
1466 !$OMP SHARED(row_size, col_size, n_RI, block_matrix, Pvector, int_3c, j_offset, k_offset)
1467 DO j = 1, row_size
1468 DO k = 1, col_size
1469 block_matrix(j, k) = 0.0_dp
1470 DO i = 1, n_ri
1471 block_matrix(j, k) = block_matrix(j, k) + pvector(i)*int_3c(j_offset + j, k_offset + k, i)
1472 END DO
1473 END DO
1474 END DO
1475 !$OMP END PARALLEL DO
1476 ! Increment k-offset - setup for the next block
1477 k_offset = k_offset + col_size
1478 END DO
1479 ! Increments the j-offset - row_size is carried over from the last iteration
1480 j_offset = j_offset + row_size
1481 END DO
1482 ! Since P vector was present on all the ranks, v_dbcsr_ao has the complete Hartree result
1483 ! copy_dbcsr_to_fm should set all values in v_fm to zero
1484 CALL copy_dbcsr_to_fm(v_ao_dbcsr, v_fm)
1485 DEALLOCATE (qvector)
1486 DEALLOCATE (pvector)
1487
1488 CALL timestop(handle)
1489 END SUBROUTINE get_hartree_noenv
1490! **************************************************************************************************
1491!> \brief Calculates the exponential of a matrix in a generalized eigenvalue problem. Specifically,
1492!> it assumes we have a Hermitian matrix A in the eigenvalue problem AX = BXE, where B is some overlap
1493!> matrix and E is a diagonal matrix of real eigenvalues. Then, it calculates
1494!> exp(B^(-1) A) = X exp(E) X^C B
1495!> \param amatrix Matrix to exponentiate
1496!> \param bmatrix Overlap matrix
1497!> \param exponential Exponential exp(B^(-1) A) is stored here after the routine is finished
1498!> \param eig_scale_opt Optionally scale eigenvalues by a complex number before exponentiating them
1499!> \param work_opt Optionally provide workspace (of size at least 4) that is used in the calculation
1500!> \author Stepan Marek
1501!> \date 09.2024
1502! **************************************************************************************************
1503 SUBROUTINE cp_cfm_gexp(amatrix, bmatrix, exponential, eig_scale_opt, work_opt)
1504 ! TODO : Do interface for real matrices
1505 TYPE(cp_cfm_type), INTENT(IN) :: amatrix
1506 TYPE(cp_cfm_type), INTENT(IN) :: bmatrix
1507 TYPE(cp_cfm_type) :: exponential
1508 COMPLEX(kind=dp), INTENT(IN), OPTIONAL :: eig_scale_opt
1509 TYPE(cp_cfm_type), DIMENSION(:), POINTER, OPTIONAL :: work_opt
1510 CHARACTER(len=*), PARAMETER :: routinen = "cp_cfm_gexp"
1511 COMPLEX(kind=dp) :: eig_scale
1512 REAL(kind=dp), DIMENSION(:), ALLOCATABLE :: eigenvalues
1513 COMPLEX(kind=dp), DIMENSION(:), ALLOCATABLE :: expvalues
1514 TYPE(cp_cfm_type), DIMENSION(:), POINTER :: work
1515 LOGICAL :: deallocate_work
1516 INTEGER :: nrow, i, handle
1517
1518 CALL timeset(routinen, handle)
1519
1520 ! Argument parsing and sanity checks
1521 IF (PRESENT(eig_scale_opt)) THEN
1522 eig_scale = eig_scale_opt
1523 ELSE
1524 eig_scale = cmplx(1.0, 0.0, kind=dp)
1525 END IF
1526
1527 NULLIFY (work)
1528 deallocate_work = .true.
1529 IF (PRESENT(work_opt)) THEN
1530 deallocate_work = SIZE(work_opt) < 4
1531 END IF
1532 IF (.NOT. deallocate_work) THEN
1533 work => work_opt
1534 ELSE
1535 ALLOCATE (work(4))
1536 ! Allocate the work storage on the fly
1537 DO i = 1, 4
1538 CALL cp_cfm_create(work(i), amatrix%matrix_struct)
1539 END DO
1540 END IF
1541
1542 nrow = amatrix%matrix_struct%nrow_global
1543
1544 ALLOCATE (eigenvalues(nrow))
1545 ALLOCATE (expvalues(nrow))
1546
1547 ! Do not change the amatrix and bmatrix - need to copy them first
1548 CALL cp_cfm_to_cfm(amatrix, work(1))
1549 CALL cp_cfm_to_cfm(bmatrix, work(2))
1550
1551 ! Solve the generalized eigenvalue equation
1552 CALL cp_cfm_geeig(work(1), work(2), work(3), eigenvalues, work(4))
1553
1554 ! Scale and exponentiate the eigenvalues
1555 expvalues(:) = exp(eigenvalues(:)*eig_scale)
1556
1557 ! Copy eigenvectors to column scale them
1558 CALL cp_cfm_to_cfm(work(3), work(1))
1559 ! X * exp(E)
1560 CALL cp_cfm_column_scale(work(1), expvalues)
1561
1562 ! Carry out the remaining operations
1563 ! X * exp(E) * X^C
1564 CALL parallel_gemm("N", "C", nrow, nrow, nrow, &
1565 cmplx(1.0, 0.0, kind=dp), work(1), work(3), &
1566 cmplx(0.0, 0.0, kind=dp), work(2))
1567 ! X * exp(E) * X^C * B
1568 CALL parallel_gemm("N", "N", nrow, nrow, nrow, &
1569 cmplx(1.0, 0.0, kind=dp), work(2), bmatrix, &
1570 cmplx(0.0, 0.0, kind=dp), exponential)
1571
1572 ! Deallocate work storage if necessary
1573 IF (deallocate_work) THEN
1574 DO i = 1, 4
1575 CALL cp_cfm_release(work(i))
1576 END DO
1577 DEALLOCATE (work)
1578 END IF
1579
1580 DEALLOCATE (eigenvalues)
1581 DEALLOCATE (expvalues)
1582
1583 CALL timestop(handle)
1584 END SUBROUTINE cp_cfm_gexp
1585END MODULE rt_bse
collects all references to literature in CP2K as new algorithms / method are included from literature...
integer, save, public marek2025
Basic linear algebra operations for complex full matrices.
subroutine, public cp_cfm_scale_and_add(alpha, matrix_a, beta, matrix_b)
Scale and add two BLACS matrices (a = alpha*a + beta*b).
real(kind=dp) function, public cp_cfm_norm(matrix, mode)
Norm of matrix using (p)zlange.
subroutine, public cp_cfm_transpose(matrix, trans, matrixt)
Transposes a BLACS distributed complex matrix.
subroutine, public cp_cfm_column_scale(matrix_a, scaling)
Scales columns of the full matrix by corresponding factors.
subroutine, public cp_cfm_trace(matrix_a, matrix_b, trace)
Returns the trace of matrix_a^T matrix_b, i.e sum_{i,j}(matrix_a(i,j)*matrix_b(i,j)) .
used for collecting diagonalization schemes available for cp_cfm_type
Definition cp_cfm_diag.F:14
subroutine, public cp_cfm_geeig(amatrix, bmatrix, eigenvectors, eigenvalues, work)
General Eigenvalue Problem AX = BXE Single option version: Cholesky decomposition of B.
Represents a complex full matrix distributed on many processors.
subroutine, public cp_cfm_release(matrix)
Releases a full matrix.
subroutine, public cp_fm_to_cfm(msourcer, msourcei, mtarget)
Construct a complex full matrix by taking its real and imaginary parts from two separate real-value f...
subroutine, public cp_cfm_create(matrix, matrix_struct, name, nrow, ncol, set_zero)
Creates a new full matrix with the given structure.
subroutine, public cp_cfm_get_info(matrix, name, nrow_global, ncol_global, nrow_block, ncol_block, nrow_local, ncol_local, row_indices, col_indices, local_data, context, matrix_struct, para_env)
Returns information about a full matrix.
subroutine, public cp_cfm_to_fm(msource, mtargetr, mtargeti)
Copy real and imaginary parts of a complex full matrix into separate real-value full matrices.
subroutine, public dbcsr_iterator_stop(iterator)
...
subroutine, public dbcsr_copy(matrix_b, matrix_a, name, keep_sparsity, keep_imaginary)
...
subroutine, public dbcsr_get_block_p(matrix, row, col, block, found, row_size, col_size)
...
subroutine, public dbcsr_get_info(matrix, nblkrows_total, nblkcols_total, nfullrows_total, nfullcols_total, nblkrows_local, nblkcols_local, nfullrows_local, nfullcols_local, my_prow, my_pcol, local_rows, local_cols, proc_row_dist, proc_col_dist, row_blk_size, col_blk_size, row_blk_offset, col_blk_offset, distribution, name, matrix_type, group)
...
subroutine, public dbcsr_reserve_blocks(matrix, rows, cols)
...
subroutine, public dbcsr_iterator_next_block(iterator, row, column, block, block_number_argument_has_been_removed, row_size, col_size, row_offset, col_offset, transposed)
...
subroutine, public dbcsr_iterator_start(iterator, matrix, shared, dynamic, dynamic_byrows)
...
subroutine, public dbcsr_set(matrix, alpha)
...
subroutine, public dbcsr_release(matrix)
...
integer function, public dbcsr_get_num_blocks(matrix)
...
subroutine, public dbcsr_clear(matrix)
...
subroutine, public dbcsr_add(matrix_a, matrix_b, alpha_scalar, beta_scalar)
...
DBCSR operations in CP2K.
subroutine, public cp_dbcsr_sm_fm_multiply(matrix, fm_in, fm_out, ncol, alpha, beta)
multiply a dbcsr with a fm matrix
subroutine, public copy_dbcsr_to_fm(matrix, fm)
Copy a DBCSR matrix to a BLACS matrix.
subroutine, public copy_fm_to_dbcsr(fm, matrix, keep_sparsity)
Copy a BLACS matrix to a dbcsr matrix.
Basic linear algebra operations for full matrices.
subroutine, public cp_fm_column_scale(matrixa, scaling)
scales column i of matrix a with scaling(i)
subroutine, public cp_fm_transpose(matrix, matrixt)
transposes a matrix matrixt = matrix ^ T
subroutine, public cp_fm_scale_and_add(alpha, matrix_a, beta, matrix_b)
calc A <- alpha*A + beta*B optimized for alpha == 1.0 (just add beta*B) and beta == 0....
subroutine, public cp_fm_invert(matrix_a, matrix_inverse, det_a, eps_svd, eigval)
Inverts a cp_fm_type matrix, optionally returning the determinant of the input matrix.
subroutine, public cp_fm_scale(alpha, matrix_a)
scales a matrix matrix_a = alpha * matrix_b
represent a full matrix distributed on many processors
Definition cp_fm_types.F:15
subroutine, public cp_fm_set_all(matrix, alpha, beta)
set all elements of a matrix to the same value, and optionally the diagonal to a different one
subroutine, public cp_fm_create(matrix, matrix_struct, name, nrow, ncol, set_zero)
creates a new full matrix with the given structure
various routines to log and control the output. The idea is that decisions about where to log should ...
type(cp_logger_type) function, pointer, public cp_get_default_logger()
returns the default logger
routines to handle the output, The idea is to remove the decision of wheter to output and what to out...
subroutine, public cp_iterate(iteration_info, last, iter_nr, increment, iter_nr_out)
adds one to the actual iteration
subroutine, public cp_rm_iter_level(iteration_info, level_name, n_rlevel_att)
Removes an iteration level.
subroutine, public cp_add_iter_level(iteration_info, level_name, n_rlevel_new)
Adds an iteration level.
This is the start of a dbt_api, all publically needed functions are exported here....
Definition dbt_api.F:17
all routins needed for a nonperiodic electric field
subroutine, public make_field(dft_control, field, sim_step, sim_time)
computes the amplitude of the efield within a given envelop
Interface for the force calculations.
recursive subroutine, public force_env_calc_energy_force(force_env, calc_force, consistent_energies, skip_external_control, eval_energy_forces, require_consistent_energy_force, linres, calc_stress_tensor)
Interface routine for force and energy calculations.
Interface for the force calculations.
collects all constants needed in input so that they can be used without circular dependencies
integer, parameter, public do_bch
integer, parameter, public use_rt_restart
integer, parameter, public do_exact
integer, parameter, public use_mom_ref_zero
integer, parameter, public rtp_bse_ham_g0w0
Defines the basic variable types.
Definition kinds.F:23
integer, parameter, public dp
Definition kinds.F:34
2- and 3-center electron repulsion integral routines based on libint2 Currently available operators: ...
Interface to the message passing library MPI.
Calculates the moment integrals <a|r^m|b>
subroutine, public get_reference_point(rpoint, drpoint, qs_env, fist_env, reference, ref_point, ifirst, ilast)
...
basic linear algebra operations for full matrixes
subroutine, public get_qs_env(qs_env, atomic_kind_set, qs_kind_set, cell, super_cell, cell_ref, use_ref_cell, kpoints, dft_control, mos, sab_orb, sab_all, qmmm, qmmm_periodic, mimic, sac_ae, sac_ppl, sac_lri, sap_ppnl, sab_vdw, sab_scp, sap_oce, sab_lrc, sab_se, sab_xtbe, sab_tbe, sab_core, sab_xb, sab_xtb_pp, sab_xtb_nonbond, sab_almo, sab_kp, sab_kp_nosym, sab_cneo, particle_set, energy, force, matrix_h, matrix_h_im, matrix_ks, matrix_ks_im, matrix_vxc, run_rtp, rtp, matrix_h_kp, matrix_h_im_kp, matrix_ks_kp, matrix_ks_im_kp, matrix_vxc_kp, kinetic_kp, matrix_s_kp, matrix_w_kp, matrix_s_ri_aux_kp, matrix_s, matrix_s_ri_aux, matrix_w, matrix_p_mp2, matrix_p_mp2_admm, matrix_vhxc, rho, rho_xc, pw_env, ewald_env, ewald_pw, active_space, mpools, input, para_env, blacs_env, scf_control, rel_control, kinetic, qs_charges, vppl, xcint_weights, rho_core, rho_nlcc, rho_nlcc_g, ks_env, ks_qmmm_env, wf_history, scf_env, local_particles, local_molecules, distribution_2d, dbcsr_dist, molecule_kind_set, molecule_set, subsys, cp_subsys, oce, local_rho_set, rho_atom_set, task_list, task_list_soft, rho0_atom_set, rho0_mpole, rhoz_set, rhoz_cneo_set, ecoul_1c, rho0_s_rs, rho0_s_gs, rhoz_cneo_s_rs, rhoz_cneo_s_gs, do_kpoints, has_unit_metric, requires_mo_derivs, mo_derivs, mo_loc_history, nkind, natom, nelectron_total, nelectron_spin, efield, neighbor_list_id, linres_control, xas_env, virial, cp_ddapc_env, cp_ddapc_ewald, outer_scf_history, outer_scf_ihistory, x_data, et_coupling, dftb_potential, results, se_taper, se_store_int_env, se_nddo_mpole, se_nonbond_env, admm_env, lri_env, lri_density, exstate_env, ec_env, harris_env, dispersion_env, gcp_env, vee, rho_external, external_vxc, mask, mp2_env, bs_env, kg_env, wanniercentres, atprop, ls_scf_env, do_transport, transport_env, v_hartree_rspace, s_mstruct_changed, rho_changed, potential_changed, forces_up_to_date, mscfg_env, almo_scf_env, gradient_history, variable_history, embed_pot, spin_embed_pot, polar_env, mos_last_converged, eeq, rhs, do_rixs, tb_tblite)
Get the QUICKSTEP environment.
Calculates the moment integrals <a|r^m|b> and <a|r x d/dr|b>
Definition qs_moments.F:14
subroutine, public build_local_moment_matrix(qs_env, moments, nmoments, ref_point, ref_points, basis_type)
...
Definition qs_moments.F:593
Define the neighbor list data types and the corresponding functionality.
subroutine, public release_neighbor_list_sets(nlists)
releases an array of neighbor_list_sets
Utility methods to build 3-center integral tensors of various types.
Definition qs_tensors.F:11
subroutine, public build_2c_integrals(t2c, filter_eps, qs_env, nl_2c, basis_i, basis_j, potential_parameter, do_kpoints, do_hfx_kpoints, ext_kpoints, regularization_ri)
...
subroutine, public build_2c_neighbor_lists(ij_list, basis_i, basis_j, potential_parameter, name, qs_env, sym_ij, molecular, dist_2d, pot_to_rad)
Build 2-center neighborlists adapted to different operators This mainly wraps build_neighbor_lists fo...
Definition qs_tensors.F:144
Input/output from the propagation via RT-BSE method.
Definition rt_bse_io.F:13
subroutine, public print_rtbse_header_info(rtbse_env)
Writes the header and basic info to the standard output.
Definition rt_bse_io.F:91
subroutine, public output_restart(rtbse_env, rho, time_index)
Outputs the restart info (last finished iteration step) + restard density matrix.
Definition rt_bse_io.F:495
subroutine, public print_etrs_info(rtbse_env, step, metric)
Writes the update after single etrs iteration - only for log level > medium.
Definition rt_bse_io.F:140
subroutine, public read_field(rtbse_env)
Reads the field from the files provided by input - useful for the continuation run.
Definition rt_bse_io.F:410
subroutine, public print_etrs_info_header(rtbse_env)
Writes the header for the etrs iteration updates - only for log level > medium.
Definition rt_bse_io.F:157
subroutine, public output_mos_contravariant(rtbse_env, rho, print_key_section)
Outputs the matrix in MO basis for matrix coefficients corresponding to contravariant operator,...
Definition rt_bse_io.F:261
subroutine, public output_field(rtbse_env, append_opt)
Prints the current field components into a file provided by input.
Definition rt_bse_io.F:365
subroutine, public print_timestep_info(rtbse_env, step, electron_num_re, convergence, etrs_num, step_walltime)
Writes the summary line of a completed propagation timestep.
Definition rt_bse_io.F:178
subroutine, public read_restart(rtbse_env)
Reads the density matrix from restart files and updates the starting time.
Definition rt_bse_io.F:539
subroutine, public output_moments(rtbse_env, rho)
Outputs the expectation value of moments from a given density matrix.
Definition rt_bse_io.F:448
RT-BSE RI-RS kernels: SEX and Hartree evaluated by collocation on grid points r_l....
subroutine, public compute_sigma_ri_rs_complex(bs_env, sigma_ao_cfm, prefactor, rho_ao_cfm, grid_diag_re_accum, grid_diag_im_accum)
Complex-input AO SEX via Re/Im split: the kernel is real, so complex linearity holds as Σ[Δρ] = Σ[Re ...
Data storage and other types for propagation via RT-BSE method.
subroutine, public create_rtbse_env(rtbse_env, force_env, linearized)
Allocates structures and prepares rtbse_env for run.
subroutine, public release_rtbse_env(rtbse_env)
Releases the environment allocated structures.
subroutine, public multiply_fm_cfm(trans_r, trans_c, na, nb, nc, alpha, matrix_r, matrix_c, beta, res)
Multiplies real matrix by a complex matrix from the right.
Routines for the propagation via RT-BSE method.
Definition rt_bse.F:14
subroutine, public antiherm_metric(real_fm, imag_fm, workspace, metric)
Determines the metric of the antihermitian part of the matrix.
Definition rt_bse.F:649
subroutine, public initialize_cohsex_selfenergy(rtbse_env)
Calculates the COHSEX reference self-energy.
Definition rt_bse.F:493
subroutine, public propagate_density(rtbse_env, exponential, rho_old, rho_new)
Updates the density in rtbse_env, using the provided exponential The new density is saved to a differ...
Definition rt_bse.F:938
subroutine, public get_electron_number(rtbse_env, rho, electron_n_re, electron_n_im)
Outputs the number of electrons in the system from the density matrix.
Definition rt_bse.F:978
subroutine, public initialize_rtbse_env(rtbse_env)
Calculates the initial values, based on restart/scf density, and other non-trivial values.
Definition rt_bse.F:273
subroutine, public get_idempotence_deviation(rtbse_env, rho, deviation_metric)
Outputs the deviation from idempotence of density matrix.
Definition rt_bse.F:1005
real(kind=dp) function, public rho_metric(rho_new, rho_old, nspin, workspace_opt)
Determines the metric for the density matrix, used for convergence criterion.
Definition rt_bse.F:606
subroutine, public initialize_hartree_potential(rtbse_env)
Calculates the Hartree potential.
Definition rt_bse.F:458
subroutine, public cp_cfm_gexp(amatrix, bmatrix, exponential, eig_scale_opt, work_opt)
Calculates the exponential of a matrix in a generalized eigenvalue problem. Specifically,...
Definition rt_bse.F:1504
subroutine, public initialize_singleparticle_hamiltonian(rtbse_env)
Calculates the single particle Hamiltonian.
Definition rt_bse.F:411
subroutine, public init_hartree(rtbse_env, v_dbcsr)
Creates the RI matrix and populates it with correct values.
Definition rt_bse.F:1238
subroutine, public run_propagation_bse(force_env)
Runs the electron-only real time BSE propagation.
Definition rt_bse.F:152
Routine for the real time propagation output.
subroutine, public print_ft(rtp_section, moments, times, fields, rtc, info_opt, cell)
Calculate and print the Fourier transforms + polarizabilites from moment trace.
Routines needed for EMD.
subroutine, public read_moments(moments_section, orig_start, current_start, moments, times, mom_read)
Attempt to read the moments from a previously written file.
Represent a complex full matrix.
represent a full matrix
type of a logger, at the moment it contains just a print level starting at which level it should be l...
wrapper to abstract the force evaluation of the various methods
stores all the informations relevant to an mpi environment