(git:f2099e5)
Loading...
Searching...
No Matches
rt_bse_types.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 Data storage and other types for propagation via RT-BSE method.
10!> \author Stepan Marek (01.24)
11! **************************************************************************************************
12
14
15 USE kinds, ONLY: dp
16 USE cp_fm_types, ONLY: cp_fm_type, &
23 USE cp_cfm_types, ONLY: cp_cfm_type, &
29 USE cp_dbcsr_api, ONLY: dbcsr_type, &
35 USE dbt_api, ONLY: dbt_type, &
36 dbt_create, &
37 dbt_destroy
38 USE qs_mo_types, ONLY: mo_set_type
45 eps_qp_gap, &
53 USE libint_2c_3c, ONLY: libint_potential_type
55 do_bch, &
56 do_exact, &
60 USE physcon, ONLY: evolt
61 USE mathconstants, ONLY: z_zero
66
67#include "../base/base_uses.f90"
68
69 IMPLICIT NONE
70
71 PRIVATE
72
73 CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = "rt_bse"
74
75
76
77
78 PUBLIC :: rtbse_env_type, &
85
86 ! ! Created so that we can have an array of pointers to arrays
87 ! TYPE series_real_type
88 ! REAL(kind=dp), DIMENSION(:), POINTER :: series => NULL()
89 ! END TYPE series_real_type
90 ! TYPE series_complex_type
91 ! COMPLEX(kind=dp), DIMENSION(:), POINTER :: series => NULL()
92 ! END TYPE series_complex_type
93
94! **************************************************************************************************
95!> \param n_spin Number of spin channels that are present
96!> \param n_ao Number of atomic orbitals
97!> \param n_RI Number of RI orbitals
98!> \param n_occ Number of occupied orbitals, spin dependent
99!> \param spin_degeneracy Number of electrons per orbital
100!> \param field Electric field calculated at the given timestep
101!> \param moments Moment operators (2nd index = spin) along cartesian directions - centered at zero charge - used for plotting
102!> \param moments_field Moment operators (2nd index = spin) along cartesian directions - used to coupling to the field -
103!> origin bound to unit cell
104!> \param sim_step Current step of the simulation
105!> \param sim_start Starting step of the simulation
106!> \param sim_nsteps Number of steps of the simulation
107!> \param sim_time Current time of the simulation
108!> \param sim_dt Timestep of the simulation
109!> \param sim_dt_restart Original-run timestep read from the trace on restart (< 0 when not a restart)
110!> \param etrs_threshold Self-consistency threshold for enforced time reversal symmetry propagation
111!> \param exp_accuracy Threshold for matrix exponential calculation
112!> \param dft_control DFT control parameters
113!> \param ham_effective Real and imaginary part of the effective Hamiltonian used to propagate
114!> the density matrix
115!> \param ham_reference Reference Hamiltonian, which does not change in the
116!> propagation = DFT+G0W0 - initial Hartree - initial COHSEX
117!> \param ham_workspace Workspace matrices for use with the Hamiltonian propagation - storage of
118!> exponential propagators etc.
119!> \param rho Density matrix at the current time step
120!> \param rho_new Density matrix - workspace in ETRS
121!> \param rho_last Density matrix - workspace in ETRS
122!> \param rho_new_last Density matrix - workspace in ETRS
123!> \param rho_M Density matrix - workspace in ETRS
124!> \param S_inv_fm Inverse overlap matrix, full matrix
125!> \param S_fm Overlap matrix, full matrix
126!> \param S_inv Inverse overlap matrix, sparse matrix
127!> \param rho_dbcsr Density matrix, sparse matrix
128!> \param rho_workspace Matrices for storage of density matrix at different timesteps for
129!> interpolation and self-consistency checks etc.
130!> \param complex_workspace Workspace for complex density (exact diagonalisation)
131!> \param complex_s Complex overlap matrix (exact diagonalisation)
132!> \param real_eigvals Eigenvalues of hermitian matrix (exact diagonalisation)
133!> \param exp_eigvals Exponentiated eigenvalues (exact diagonalisation)
134!> \param v_dbcsr Sparse matrix with bare Coulomb in RI basis
135!> \param w_dbcsr Sparse matrix with correlation part of dressed Coulomb in RI basis (without bare Coulomb)
136!> \param screened_dbt Tensor for screened Coulomb interaction
137!> \param greens_dbt Tensor for greens function/density matrix
138!> \param t_3c_w Tensor containing 3c integrals
139!> \param t_3c_work_RI_AO__AO Tensor sigma contraction
140!> \param t_3c_work2_RI_AO__AO Tensor sigma contraction
141!> \param sigma_SEX Screened exchange self-energy
142!> \param sigma_COH Coulomb hole self-energy
143!> \param hartree_curr Current Hartree matrix
144!> \param etrs_max_iter Maximum number of ETRS iterations
145!> \param ham_reference_type Which Hamiltonian to use as single particle basis
146!> \param mat_exp_method Which method to use for matrix exponentiation
147!> \param unit_nr Number of output unit
148!> \param int_3c_array Array containing the local 3c integrals
149!> \author Stepan Marek (01.24)
150! **************************************************************************************************
152 INTEGER :: n_spin = 1, &
153 n_ao = -1, &
154 n_ri = -1
155 INTEGER, DIMENSION(2) :: n_occ = -1
156 ! Active MO window for linearized RT-BSE truncation. When no truncation is requested,
157 ! first_active_mo=1, last_active_mo=n_ao, and mo_active=n_ao. The window is the
158 ! combined inclusive bound that covers both spin channels.
159 INTEGER :: first_active_mo = 1, &
160 last_active_mo = -1, &
161 mo_active = -1
162 REAL(kind=dp) :: rtbse_energy_cutoff_occ = -1.0_dp, &
163 rtbse_energy_cutoff_empty = -1.0_dp
164 LOGICAL :: active_mo_truncation = .false.
165 LOGICAL :: linearized = .false.
166 ! Tamm-Dancoff approximation switch (linearized RT-BSE only).
167 LOGICAL :: tda_active = .false.
168 ! First-peak shift for the TDA path (linearized RT-BSE only).
169 ! Shifts active-MO single-particle diagonals by +Omega_0/2 (occ) / -Omega_0/2 (virt)
170 ! with Omega_0 = eps_min_ai so the lowest active OV mode oscillates at zero in the
171 ! rotating frame (RK4-exact for peak 1). omega_max becomes the full active OV width
172 ! Delta = eps_max_ai - eps_min_ai. The resulting rotating-frame density is undone
173 ! at I/O so observables stay lab-frame.
174 LOGICAL :: tda_shift_to_first_peak = .false.
175 REAL(kind=dp) :: omega_shift = 0.0_dp
176 ! Debug-only kernel switches shared by initialization and propagation.
177 LOGICAL :: debug_disable_hartree = .false., &
178 debug_disable_sex = .false.
179 ! RI framework for the linRTBSE Hartree + screened-exchange kernels, set by the KERNEL_RI
180 ! input keyword (DEFAULT inherits bs_env%do_gw_ri_rs; RS/AO force; full RT-BSE forced AO).
181 ! .TRUE. = RI-RS grid kernels, .FALSE. = AO-RI. The required grid and V_grid/W0_grid
182 ! kernels are built on demand and reused across steps.
183 LOGICAL :: rirs_kernel = .false.
184 ! Liouvillian eigenvalue diagnostic (TDA + n_spin=1 only). When .TRUE., at job
185 ! init the linearized RT-BSE assembles the OV-subspace Liouvillian by probing
186 ! apply_liouvillian_to_drho with canonical OV basis vectors and diagonalizes
187 ! via cp_cfm_heevd. In TDA this equals the Casida-A eigenvalue problem.
188 ! Run once, no propagation impact.
189 LOGICAL :: diagnose_liouvillian_eig = .false.
190 ! Whether to enforce max_dt within stability region of rk4
191 LOGICAL :: enforce_max_dt = .false.
192 ! Owned fm structures sized to the active MO window. Equal to the full n_ao x n_ao
193 ! when no truncation is active.
194 TYPE(cp_fm_struct_type), POINTER :: fm_struct_mo_active => null()
195 ! n_ao x mo_active fm struct used for C_active and AO<->MO rectangular intermediates.
196 TYPE(cp_fm_struct_type), POINTER :: fm_struct_ao_mo_active => null()
197 ! Liouvillian-diagnostic struct: (N_OV_joint x N_OV_joint), spin blocks stacked, on the
198 ! same BLACS context as fm_struct_mo_active. Allocated only when diagnose_liouvillian_eig=.TRUE..
199 TYPE(cp_fm_struct_type), POINTER :: fm_struct_ov_pairs => null()
200 ! Truncated MO coefficient slabs C_active(:,:) of size n_ao x mo_active for each spin
201 ! (only allocated for the linearized path).
202 TYPE(cp_fm_type), DIMENSION(:), POINTER :: c_active => null()
203 ! Rectangular n_ao x mo_active scratch used by linearized AO<->MO transforms.
204 TYPE(cp_fm_type), DIMENSION(:), POINTER :: ao_mo_workspace => null()
205 REAL(kind=dp) :: spin_degeneracy = 2
206 REAL(kind=dp), DIMENSION(3) :: field = 0.0_dp
207 TYPE(cp_fm_type), DIMENSION(:, :), POINTER :: moments => null(), &
208 moments_field => null()
209 INTEGER :: sim_step = 0, &
210 sim_start = 0, &
211 ! Needed to continue runs by loading previous moments trace
212 sim_start_orig = 0, &
213 sim_nsteps = -1, &
214 ! Default reference point type for output moments
215 ! Field moments always use zero reference
216 moment_ref_type = use_mom_ref_coac
217 ! Restart output bookkeeping: RESTART.trace header+prefix and (linearized) C_active are
218 ! (re)written on the first output_restart call of a run, then .trace is appended per step.
219 LOGICAL :: restart_trace_written = .false., &
220 restart_c_written = .false.
221 REAL(kind=dp), DIMENSION(:), POINTER :: user_moment_ref_point => null()
222 REAL(kind=dp) :: sim_time = 0.0_dp, &
223 sim_dt = 0.1_dp, &
224 ! Original-run dt from the trace header on restart (< 0 when not
225 ! a restart); ENFORCE_MAX_DT reuses it instead of recomputing dt
226 sim_dt_restart = -1.0_dp, &
227 maximum_timestep = -1.0_dp, &
228 omega_max = -1.0_dp, &
229 etrs_threshold = 1.0e-7_dp, &
230 exp_accuracy = 1.0e-10_dp, &
231 ft_damping = 0.0_dp, &
232 ft_start = 0.0_dp
233 ! Which element of polarizability to print out
234 INTEGER, DIMENSION(:, :), POINTER :: pol_elements => null()
235 TYPE(dft_control_type), POINTER :: dft_control => null()
236 ! DEBUG : Trying keeping the reference to previous environments inside this one
237 TYPE(qs_environment_type), POINTER :: qs_env => null()
238 TYPE(post_scf_bandstructure_type), POINTER :: bs_env => null()
239 ! Stores data needed for reading/writing to the restart files
240 TYPE(section_vals_type), POINTER :: restart_section => null(), &
241 field_section => null(), &
242 rho_section => null(), &
243 ft_section => null(), &
244 pol_section => null(), &
245 eig_section => null(), &
246 moments_section => null(), &
247 rtp_section => null()
248 LOGICAL :: restart_extracted = .false.
249
250 ! Different indices signify different spins
251 TYPE(cp_cfm_type), DIMENSION(:), POINTER :: ham_effective => null()
252 TYPE(cp_cfm_type), DIMENSION(:), POINTER :: ham_reference => null()
253 !Only for linearised RTBSE
254 TYPE(cp_cfm_type), DIMENSION(:), POINTER :: ham_reference_singleparticle => null()
255 ! Active single-particle energies = diag(ham_reference_singleparticle), replicated over all
256 ! ranks. Drives the [H^0,rho]_mn = (eps_m - eps_n) rho_mn element-wise commutator (mo_active x n_spin).
257 REAL(kind=dp), DIMENSION(:, :), POINTER :: eps_active => null()
258 ! Original run's active eigenvalues stashed from RESTART.trace at read time; compared against
259 ! the recomputed eps_active once the Hamiltonian is built (consistency heads-up), then freed.
260 REAL(kind=dp), DIMENSION(:, :), POINTER :: eps_active_restart => null()
261 TYPE(cp_cfm_type), DIMENSION(:), POINTER :: ham_workspace => null()
262 TYPE(cp_cfm_type), DIMENSION(:), POINTER :: sigma_sex => null()
263 TYPE(cp_fm_type), DIMENSION(:), POINTER :: sigma_coh => null(), &
264 hartree_curr => null()
265 ! AO-sized scratch buffers used in the linearized RT-BSE path so that the MO-sized
266 ! sigma_COH/sigma_SEX/hartree_curr matrices above can be allocated on
267 ! fm_struct_mo_active. Only allocated when linearized=.TRUE..
268 TYPE(cp_cfm_type), DIMENSION(:), POINTER :: sigma_sex_ao => null()
269 TYPE(cp_fm_type), DIMENSION(:), POINTER :: hartree_curr_ao => null()
270 ! Open-shell cross-spin Hartree (TDA AO-RI), single shared AO buffers built once per
271 ! RK4 stage: rho_total_ao_scratch (fm_s struct, matches rho_ao_scratch for the spin sum);
272 ! hartree_total_ao = V_H[sum] (fm_ks struct, matches sigma_SEX_ao as the Hartree output).
273 TYPE(cp_cfm_type) :: rho_total_ao_scratch = cp_cfm_type(), &
274 hartree_total_ao = cp_cfm_type()
275 ! RI-RS Hartree diagonal reuse: spin-summed grid density n_l = diag(phi.rho.phi^T), harvested
276 ! from the SEX rho_grid (before its Hadamard, scaled by spin_degeneracy) and consumed by
277 ! compute_hartree_ri_rs_from_diag so Hartree never rebuilds the grid product. Re/Im; sized
278 ! n_grid; allocated in initialize_hartree_potential when rirs_kernel. rtbse_env-owned (not
279 ! bs_env%ri_rs) to avoid aliasing bs_env when passed through get_sigma_complex.
280 REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: hartree_diag_re, hartree_diag_im
281 ! mo_active x mo_active real workspace pair used in MO-side transforms (linearized only).
282 TYPE(cp_fm_type), DIMENSION(:), POINTER :: real_workspace_mo => null()
283 ! Liouvillian-diagnostic scratch (allocated only when diagnose_liouvillian_eig=.TRUE.).
284 ! drho_probe(:) / L_drho(:) are per-spin arrays on fm_struct_mo_active: the joint TDA
285 ! diagnostic probes one spin and reads the Liouvillian response on every spin block.
286 ! L_pairs / eigvecs_pairs live on fm_struct_ov_pairs (N_OV_joint x N_OV_joint, the spin
287 ! blocks stacked). A_mat / B_mat / AmB_scratch / ApB_scratch are ABBA-only blocks holding
288 ! A, B, (A-B) -> (A-B)^{1/2}, and (A+B) for the Furche reduction; allocated only
289 ! when .NOT. tda_active (n_spin=1; TDA path uses L_pairs alone).
290 ! eigenvalues_liouvillian holds the N_OV_joint real eigenvalues from cp_cfm_heevd.
291 TYPE(cp_cfm_type) :: l_pairs = cp_cfm_type(), &
292 eigvecs_pairs = cp_cfm_type(), &
293 a_mat = cp_cfm_type(), &
294 b_mat = cp_cfm_type(), &
295 amb_scratch = cp_cfm_type(), &
296 apb_scratch = cp_cfm_type()
297 REAL(kind=dp), DIMENSION(:), POINTER :: eigenvalues_liouvillian => null()
298
299 TYPE(cp_cfm_type), DIMENSION(:), POINTER :: rho => null(), &
300 rho_new => null(), &
301 rho_new_last => null(), &
302 rho_m => null(), &
303 rho_orig => null(), &
304 rho_ao_scratch => null(), &
305 rho_delta_mo => null(), &
306 drho_probe => null(), &
307 l_drho => null()
308 ! Workspace for rk4 in linearized RTBSE
309 TYPE(cp_cfm_type), DIMENSION(:), POINTER :: rk4_coefficients => null()
310
311 TYPE(cp_fm_type) :: s_inv_fm = cp_fm_type(), &
312 s_fm = cp_fm_type()
313 ! Many routines require overlap in the complex format
314 TYPE(cp_cfm_type) :: s_cfm = cp_cfm_type()
315 TYPE(dbcsr_type) :: rho_dbcsr = dbcsr_type(), &
316 v_ao_dbcsr = dbcsr_type()
317 ! Indices only correspond to different workspaces
318 TYPE(cp_cfm_type), DIMENSION(:), POINTER :: rho_workspace => null()
319 ! Many methods use real and imaginary parts separately - prevent unnecessary reallocation
320 TYPE(cp_fm_type), DIMENSION(:), POINTER :: real_workspace => null()
321 ! AO-sized complex scratch used to stage the real part in get_sigma_complex.
322 TYPE(cp_cfm_type), DIMENSION(:), POINTER :: sigma_complex_workspace => null()
323 ! Workspace required for exact matrix exponentiation
324 REAL(kind=dp), DIMENSION(:), POINTER :: real_eigvals => null()
325 COMPLEX(kind=dp), DIMENSION(:), POINTER :: exp_eigvals => null()
326 ! Workspace for saving the values for FT
327 ! TODO : Change back to multi-dimensional arrays
328 ! Index 1 : spin, Index 2 : direction, Index 3 : time point
329 COMPLEX(kind=dp), DIMENSION(:, :, :), POINTER :: moments_trace => null()
330 REAL(kind=dp), DIMENSION(:), POINTER :: time_trace => null()
331 ! Index 1 : direction, Index 2 : time point
332 COMPLEX(kind=dp), DIMENSION(:, :), POINTER :: field_trace => null()
333 ! Workspace required for hartree_pw
334 TYPE(dbcsr_type) :: v_dbcsr = dbcsr_type(), &
335 w_dbcsr = dbcsr_type()
336#if defined(FTN_NO_DEFAULT_INIT)
337 TYPE(dbt_type) :: screened_dbt, &
338 greens_dbt, &
339 t_3c_w, &
340 t_3c_work_ri_ao__ao, &
341 t_3c_work2_ri_ao__ao
342#else
343 TYPE(dbt_type) :: screened_dbt = dbt_type(), &
344 greens_dbt = dbt_type(), &
345 t_3c_w = dbt_type(), &
346 t_3c_work_ri_ao__ao = dbt_type(), &
347 t_3c_work2_ri_ao__ao = dbt_type()
348#endif
349 ! These matrices are always real
350 INTEGER :: etrs_max_iter = 10
351 INTEGER :: ham_reference_type = 2
352 INTEGER :: mat_exp_method = 4
353 INTEGER :: unit_nr = -1
354 REAL(kind=dp), DIMENSION(:, :, :), POINTER :: int_3c_array => null()
355 ! Parameters for Padé refinement
356 REAL(kind=dp) :: pade_e_min = 0.0_dp, &
357 pade_e_max = 100.0_dp, &
358 pade_e_step = 0.05_dp, &
359 pade_fit_e_min = 0.0_dp, &
360 pade_fit_e_max = -1.0_dp
361 INTEGER :: pade_npoints = 0
362 LOGICAL :: pade_requested = .false.
363 COMPLEX(kind=dp), DIMENSION(:), POINTER :: pade_x_eval => null()
364
365 END TYPE rtbse_env_type
366
367CONTAINS
368
369! **************************************************************************************************
370!> \brief Allocates structures and prepares rtbse_env for run
371!> \param rtbse_env rtbse_env_type that is initialised
372!> \param force_env Force environment - entry point of the calculation
373!> \param linearized Optional; when present and .TRUE., configure the environment for the linearized RT-BSE path
374!> \author Stepan Marek
375!> \date 02.2024
376! **************************************************************************************************
377 SUBROUTINE create_rtbse_env(rtbse_env, force_env, linearized)
378 TYPE(rtbse_env_type), POINTER :: rtbse_env
379 TYPE(force_env_type), POINTER :: force_env
380 LOGICAL, OPTIONAL :: linearized
381 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
382 TYPE(rt_prop_type), POINTER :: rtp
383 TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: matrix_s
384 TYPE(mo_set_type), DIMENSION(:), POINTER :: mos
385 INTEGER :: i, k, n_ov, i_spin
386 TYPE(section_vals_type), POINTER :: input, bs_sec, md_sec
387 TYPE(cp_fm_struct_type), POINTER :: mo_struct
388
389 ! Allocate the storage for the gwbse environment
390 NULLIFY (rtbse_env, mo_struct)
391 ALLOCATE (rtbse_env)
392 IF (PRESENT(linearized)) rtbse_env%linearized = linearized
393 ! Extract the other types first
394 CALL get_qs_env(force_env%qs_env, &
395 bs_env=bs_env, &
396 rtp=rtp, &
397 matrix_s=matrix_s, &
398 mos=mos, &
399 dft_control=rtbse_env%dft_control, &
400 input=input)
401 bs_sec => section_vals_get_subs_vals(input, "PROPERTIES%BANDSTRUCTURE")
402 IF (.NOT. ASSOCIATED(bs_env)) THEN
403 cpabort("Cannot run RT-BSE without running GW calculation (PROPERTIES) before")
404 END IF
405 ! Number of spins
406 rtbse_env%n_spin = bs_env%n_spin
407 ! Open shell (n_spin>1) is only implemented and tested for the linearized
408 ! propagation; the full RT-BSE open-shell path is untested.
409 IF (rtbse_env%n_spin > 1 .AND. .NOT. rtbse_env%linearized) THEN
410 CALL cp_abort(__location__, &
411 "Open-shell (n_spin>1) RT-BSE is only implemented and tested for the "// &
412 "linearized propagation. Set DFT%REAL_TIME_PROPAGATION%RTBSE%LRRTBSE "// &
413 ".TRUE.; the full (non-linearized) open-shell RT-BSE path is untested.")
414 END IF
415 ! Number of atomic orbitals
416 rtbse_env%n_ao = bs_env%n_ao
417 ! Number of auxiliary basis orbitals
418 rtbse_env%n_RI = bs_env%n_RI
419 ! Number of occupied orbitals - for closed shell equals to half the number of electrons
420 rtbse_env%n_occ(:) = bs_env%n_occ(:)
421 ! Spin degeneracy - number of spins per orbital
422 rtbse_env%spin_degeneracy = bs_env%spin_degeneracy
423 ! Default field is zero
424 rtbse_env%field(:) = 0.0_dp
425 ! Default time is zero
426 rtbse_env%sim_step = 0
427 rtbse_env%sim_time = 0
428 ! Time step is taken from rtp
429 md_sec => section_vals_get_subs_vals(force_env%root_section, "MOTION%MD")
430 CALL section_vals_val_get(md_sec, "TIMESTEP", r_val=rtbse_env%sim_dt)
431 ! rtbse_env%sim_dt = rtp%dt
432 ! Threshold for etrs is taken from the eps_energy from RT propagation
433 rtbse_env%etrs_threshold = rtbse_env%dft_control%rtp_control%eps_ener
434 rtbse_env%exp_accuracy = rtbse_env%dft_control%rtp_control%eps_exp
435 ! Recover custom options
436 CALL section_vals_val_get(input, "DFT%REAL_TIME_PROPAGATION%RTBSE%RTBSE_HAMILTONIAN", &
437 i_val=rtbse_env%ham_reference_type)
438 CALL section_vals_val_get(input, "DFT%REAL_TIME_PROPAGATION%MAX_ITER", &
439 i_val=rtbse_env%etrs_max_iter)
440 CALL section_vals_val_get(input, "DFT%REAL_TIME_PROPAGATION%MAT_EXP", &
441 i_val=rtbse_env%mat_exp_method)
442 CALL section_vals_val_get(input, "DFT%REAL_TIME_PROPAGATION%RTBSE%ENERGY_CUTOFF_OCC", &
443 r_val=rtbse_env%rtbse_energy_cutoff_occ)
444 CALL section_vals_val_get(input, "DFT%REAL_TIME_PROPAGATION%RTBSE%ENERGY_CUTOFF_EMPTY", &
445 r_val=rtbse_env%rtbse_energy_cutoff_empty)
446 CALL section_vals_val_get(input, "DFT%REAL_TIME_PROPAGATION%RTBSE%TDA", &
447 l_val=rtbse_env%tda_active)
448 CALL section_vals_val_get(input, "DFT%REAL_TIME_PROPAGATION%RTBSE%TDA_SHIFT_TO_FIRST_PEAK", &
449 l_val=rtbse_env%tda_shift_to_first_peak)
450 CALL section_vals_val_get(input, "DFT%REAL_TIME_PROPAGATION%RTBSE%ENFORCE_MAX_DT", &
451 l_val=rtbse_env%enforce_max_dt)
452 CALL section_vals_val_get(input, "DFT%REAL_TIME_PROPAGATION%RTBSE%DEBUG_DISABLE_HARTREE", &
453 l_val=rtbse_env%debug_disable_hartree)
454 CALL section_vals_val_get(input, "DFT%REAL_TIME_PROPAGATION%RTBSE%DEBUG_DISABLE_SEX", &
455 l_val=rtbse_env%debug_disable_sex)
456 ! RI-RS kernel switch (KERNEL_RI: DEFAULT=do_gw_ri_rs, RS/AO force, full-RTBSE force-off)
457 ! is resolved by the shared helper so de_init_bs_env reaches the same verdict when
458 ! deciding whether to retain nl_3c.
459 CALL rtbse_resolve_rirs_flag(force_env%qs_env, bs_env, rirs_kernel=rtbse_env%rirs_kernel)
460 CALL section_vals_val_get(input, "DFT%REAL_TIME_PROPAGATION%RTBSE%DIAGNOSE_LIOUVILLIAN_EIG", &
461 l_val=rtbse_env%diagnose_liouvillian_eig)
462 CALL section_vals_val_get(input, "DFT%REAL_TIME_PROPAGATION%RTBSE%EPS_FILTER_RHO", &
463 r_val=bs_env%ri_rs%eps_filter_rho)
464 CALL section_vals_val_get(input, "DFT%REAL_TIME_PROPAGATION%RTBSE%CUTOFF_RADIUS_W0", &
465 r_val=bs_env%ri_rs%cutoff_radius_w0)
466
467 IF (.NOT. rtbse_env%dft_control%rtp_control%rtp_method == rtp_method_bse_linearized) THEN
468 rtbse_env%rtbse_energy_cutoff_occ = -1.0_dp
469 rtbse_env%rtbse_energy_cutoff_empty = -1.0_dp
470 rtbse_env%enforce_max_dt = .false.
471 rtbse_env%debug_disable_hartree = .false.
472 rtbse_env%debug_disable_sex = .false.
473 rtbse_env%tda_shift_to_first_peak = .false.
474 ! rirs_kernel is already forced .FALSE. here by rtbse_resolve_rirs_flag.
475 rtbse_env%diagnose_liouvillian_eig = .false.
476 bs_env%ri_rs%eps_filter_rho = -1.0_dp
477 bs_env%ri_rs%cutoff_radius_w0 = -1.0_dp
478 END IF
479 ! First-peak shift only makes sense within TDA; force-disable otherwise.
480 IF (.NOT. rtbse_env%tda_active) rtbse_env%tda_shift_to_first_peak = .false.
481 rtbse_env%omega_shift = 0.0_dp
482
483 IF (rtbse_env%tda_active .AND. .NOT. rtbse_env%linearized) THEN
484 cpabort("RTBSE TDA keyword requires LINEARIZED_BSE_PROPAGATION=.TRUE.")
485 END IF
486 ! Open shell: omega_shift would be referenced to a non-physical cross-spin
487 ! pseudo-gap (global MIN/MAX over both spins); abort until made per-spin.
488 IF (rtbse_env%tda_shift_to_first_peak .AND. rtbse_env%n_spin > 1) THEN
489 CALL cp_abort(__location__, &
490 "TDA_SHIFT_TO_FIRST_PEAK is not implemented for open-shell (n_spin>1) "// &
491 "systems - the first-peak gap estimate would mix spin channels. "// &
492 "Set TDA_SHIFT_TO_FIRST_PEAK=.FALSE. for open-shell runs.")
493 END IF
494 CALL check_qp_gap_sanity(rtbse_env, bs_env)
495 CALL determine_active_mo_window(rtbse_env, bs_env)
496 ! Owned active-MO matrix structure (currently identical to the full n_ao x n_ao struct
497 ! when no truncation is active; will be used by the linearized RT-BSE allocation path).
498 NULLIFY (rtbse_env%fm_struct_mo_active)
499 CALL cp_fm_struct_create(rtbse_env%fm_struct_mo_active, &
500 bs_env%fm_ks_Gamma(1)%matrix_struct%para_env, &
501 bs_env%fm_ks_Gamma(1)%matrix_struct%context, &
502 rtbse_env%mo_active, rtbse_env%mo_active)
503 ! Rectangular n_ao x mo_active struct used for C_active and AO<->MO intermediates
504 NULLIFY (rtbse_env%fm_struct_ao_mo_active)
505 CALL cp_fm_struct_create(rtbse_env%fm_struct_ao_mo_active, &
506 bs_env%fm_ks_Gamma(1)%matrix_struct%para_env, &
507 bs_env%fm_ks_Gamma(1)%matrix_struct%context, &
508 rtbse_env%n_ao, rtbse_env%mo_active)
509 ! Choose the matrix struct used for MO-side persistent matrices.
510 ! Linearized RT-BSE: mo_active x mo_active. Full RT-BSE: full AO struct (unchanged).
511 IF (rtbse_env%linearized) THEN
512 mo_struct => rtbse_env%fm_struct_mo_active
513 ELSE
514 mo_struct => bs_env%fm_ks_Gamma(1)%matrix_struct
515 END IF
516 ! Output unit number, recovered from the post_scf_bandstructure_type
517 rtbse_env%unit_nr = bs_env%unit_nr
518 ! Sim start index and total number of steps as well
519 CALL section_vals_val_get(md_sec, "STEP_START_VAL", i_val=rtbse_env%sim_start)
520 ! Copy this value to sim_start_orig for continuation runs
521 rtbse_env%sim_start_orig = rtbse_env%sim_start
522 CALL section_vals_val_get(md_sec, "STEPS", i_val=rtbse_env%sim_nsteps)
523 ! Get the values for the FT
524 rtbse_env%ft_damping = rtbse_env%dft_control%rtp_control%ft_damping
525 rtbse_env%ft_damping = rtbse_env%dft_control%rtp_control%ft_t0
526 rtbse_env%pol_elements => rtbse_env%dft_control%rtp_control%print_pol_elements
527
528 rtbse_env%rtp_section => section_vals_get_subs_vals(input, "DFT%REAL_TIME_PROPAGATION")
529 ! Get the restart section
530 rtbse_env%restart_section => section_vals_get_subs_vals(rtbse_env%rtp_section, "PRINT%RESTART")
531 rtbse_env%restart_extracted = .false.
532 rtbse_env%field_section => section_vals_get_subs_vals(rtbse_env%rtp_section, "PRINT%FIELD")
533 rtbse_env%moments_section => section_vals_get_subs_vals(rtbse_env%rtp_section, "PRINT%MOMENTS")
534 ! Moment specification
535 CALL section_vals_val_get(rtbse_env%rtp_section, "PRINT%MOMENTS%REFERENCE", &
536 i_val=rtbse_env%moment_ref_type)
537 CALL section_vals_val_get(rtbse_env%rtp_section, "PRINT%MOMENTS%REFERENCE_POINT", &
538 r_vals=rtbse_env%user_moment_ref_point)
539 rtbse_env%rho_section => section_vals_get_subs_vals(rtbse_env%rtp_section, "PRINT%DENSITY_MATRIX")
540 rtbse_env%ft_section => section_vals_get_subs_vals(rtbse_env%rtp_section, "PRINT%MOMENTS_FT")
541 rtbse_env%pol_section => section_vals_get_subs_vals(rtbse_env%rtp_section, "PRINT%POLARIZABILITY")
542 rtbse_env%eig_section => section_vals_get_subs_vals(rtbse_env%rtp_section, "PRINT%LIOUVILLIAN_EIG")
543 ! Warn the user about print sections which are not yet implemented in the RTBSE run
544 CALL warn_section_unused(rtbse_env%rtp_section, "PRINT%CURRENT", &
545 "CURRENT print section not yet implemented for RTBSE.")
546 CALL warn_section_unused(rtbse_env%rtp_section, "PRINT%E_CONSTITUENTS", &
547 "E_CONSTITUENTS print section not yet implemented for RTBSE.")
548 CALL warn_section_unused(rtbse_env%rtp_section, "PRINT%PROGRAM_RUN_INFO", &
549 "PROGRAM_RUN_INFO print section not yet implemented for RTBSE.")
550 CALL warn_section_unused(rtbse_env%rtp_section, "PRINT%PROJECTION_MO", &
551 "PROJECTION_MO print section not yet implemented for RTBSE.")
552 CALL warn_section_unused(rtbse_env%rtp_section, "PRINT%RESTART_HISTORY", &
553 "RESTART_HISTORY print section not yet implemented for RTBSE.")
554 ! References to the parent qs_env / bs_env
555 rtbse_env%qs_env => force_env%qs_env
556 rtbse_env%bs_env => bs_env
557 ! Padé refinement
558 rtbse_env%pade_requested = rtbse_env%dft_control%rtp_control%pade_requested
559 rtbse_env%pade_e_min = rtbse_env%dft_control%rtp_control%pade_e_min
560 rtbse_env%pade_e_step = rtbse_env%dft_control%rtp_control%pade_e_step
561 rtbse_env%pade_e_max = rtbse_env%dft_control%rtp_control%pade_e_max
562 rtbse_env%pade_fit_e_min = rtbse_env%dft_control%rtp_control%pade_fit_e_min
563 rtbse_env%pade_fit_e_max = rtbse_env%dft_control%rtp_control%pade_fit_e_max
564 rtbse_env%pade_npoints = int((rtbse_env%pade_e_max - rtbse_env%pade_e_min)/rtbse_env%pade_e_step)
565 ! Evaluate the evaluation grid
566 IF (rtbse_env%pade_requested) THEN
567 NULLIFY (rtbse_env%pade_x_eval)
568 ALLOCATE (rtbse_env%pade_x_eval(rtbse_env%pade_npoints))
569 DO i = 1, rtbse_env%pade_npoints
570 rtbse_env%pade_x_eval(i) = cmplx(rtbse_env%pade_e_step*real(i - 1, kind=dp), 0.0, kind=dp)
571 END DO
572 END IF
573
574 ! Allocate moments matrices.
575 ! In linearized RT-BSE these store the MO-active transformed dipole moments;
576 ! in full RT-BSE they remain AO-sized (initialized from overlap template).
577 NULLIFY (rtbse_env%moments)
578 ALLOCATE (rtbse_env%moments(3, rtbse_env%n_spin))
579 NULLIFY (rtbse_env%moments_field)
580 ALLOCATE (rtbse_env%moments_field(3, rtbse_env%n_spin))
581 DO i_spin = 1, rtbse_env%n_spin
582 DO k = 1, 3
583 CALL cp_fm_create(rtbse_env%moments(k, i_spin), mo_struct)
584 CALL cp_fm_create(rtbse_env%moments_field(k, i_spin), mo_struct)
585 END DO
586 END DO
587
588 ! Allocate space for density propagation and other operations.
589 ! In linearized RT-BSE these workspaces are MO-active sized; in full RT-BSE
590 ! they remain at the full AO size.
591 NULLIFY (rtbse_env%rho_workspace)
592 ALLOCATE (rtbse_env%rho_workspace(4))
593 DO i = 1, SIZE(rtbse_env%rho_workspace)
594 CALL cp_cfm_create(rtbse_env%rho_workspace(i), mo_struct)
595 CALL cp_cfm_set_all(rtbse_env%rho_workspace(i), cmplx(0.0, 0.0, kind=dp))
596 END DO
597
598 ! TODO: gate workspace allocation so methods skip workspaces they don't need
599
600 ! Allocate real workspace
601 NULLIFY (rtbse_env%real_workspace)
602 IF (rtbse_env%linearized) THEN
603 ALLOCATE (rtbse_env%real_workspace(2))
604 ELSE
605 SELECT CASE (rtbse_env%mat_exp_method)
606 CASE (do_exact)
607 ALLOCATE (rtbse_env%real_workspace(4))
608 CASE (do_bch)
609 ALLOCATE (rtbse_env%real_workspace(2))
610 CASE DEFAULT
611 cpabort("Only exact and BCH matrix propagation implemented in RT-BSE")
612 END SELECT
613 END IF
614 DO i = 1, SIZE(rtbse_env%real_workspace)
615 CALL cp_fm_create(rtbse_env%real_workspace(i), bs_env%fm_ks_Gamma(1)%matrix_struct)
616 CALL cp_fm_set_all(rtbse_env%real_workspace(i), 0.0_dp)
617 END DO
618 NULLIFY (rtbse_env%sigma_complex_workspace)
619 ALLOCATE (rtbse_env%sigma_complex_workspace(1))
620 CALL cp_cfm_create(rtbse_env%sigma_complex_workspace(1), bs_env%fm_ks_Gamma(1)%matrix_struct)
621 CALL cp_cfm_set_all(rtbse_env%sigma_complex_workspace(1), cmplx(0.0_dp, 0.0_dp, kind=dp))
622 ! Allocate density matrix (MO-active sized when linearized; AO-sized otherwise)
623 NULLIFY (rtbse_env%rho)
624 ALLOCATE (rtbse_env%rho(rtbse_env%n_spin))
625 DO i = 1, rtbse_env%n_spin
626 CALL cp_cfm_create(rtbse_env%rho(i), matrix_struct=mo_struct)
627 END DO
628 ! Allocate additional space for AO density matrix
629 ! in linearised RTBSE, where default is MO
630 IF (rtbse_env%linearized) THEN
631 NULLIFY (rtbse_env%rho_ao_scratch)
632 ALLOCATE (rtbse_env%rho_ao_scratch(rtbse_env%n_spin))
633 DO i = 1, rtbse_env%n_spin
634 CALL cp_cfm_create(rtbse_env%rho_ao_scratch(i), matrix_struct=bs_env%fm_s_Gamma%matrix_struct)
635 END DO
636 END IF
637 ! Create the inverse overlap matrix, for use in density propagation
638 ! Start by creating the actual overlap matrix
639 CALL cp_fm_create(rtbse_env%S_fm, bs_env%fm_s_Gamma%matrix_struct)
640 CALL cp_fm_create(rtbse_env%S_inv_fm, bs_env%fm_s_Gamma%matrix_struct)
641 CALL cp_cfm_create(rtbse_env%S_cfm, bs_env%fm_s_Gamma%matrix_struct)
642
643 ! Create the single particle hamiltonian
644 ! Allocate workspace (MO-active sized in linearized RT-BSE; AO sized otherwise)
645 NULLIFY (rtbse_env%ham_workspace)
646 ALLOCATE (rtbse_env%ham_workspace(rtbse_env%n_spin))
647 DO i = 1, rtbse_env%n_spin
648 CALL cp_cfm_create(rtbse_env%ham_workspace(i), mo_struct)
649 CALL cp_cfm_set_all(rtbse_env%ham_workspace(i), cmplx(0.0, 0.0, kind=dp))
650 END DO
651 ! Now onto the Hamiltonian itself
652 ! full RTBSE: Contains energy differences and Hartree/COHSEX ρ_0 parts
653 ! linearised RTBSE: Contains only the Hartree/SEX ρ_0 parts as Δε * Δρ(t) need to be updated
654 NULLIFY (rtbse_env%ham_reference)
655 ALLOCATE (rtbse_env%ham_reference(rtbse_env%n_spin))
656 DO i = 1, rtbse_env%n_spin
657 CALL cp_cfm_create(rtbse_env%ham_reference(i), mo_struct)
658 END DO
659 ! Single particle Hamiltonian (Δε * Δρ(t)) for updates during timesteps in LR-RTBSE
660 IF (rtbse_env%linearized) THEN
661 NULLIFY (rtbse_env%ham_reference_singleparticle)
662 ALLOCATE (rtbse_env%ham_reference_singleparticle(rtbse_env%n_spin))
663 DO i = 1, rtbse_env%n_spin
664 CALL cp_cfm_create(rtbse_env%ham_reference_singleparticle(i), mo_struct)
665 END DO
666 NULLIFY (rtbse_env%eps_active)
667 ALLOCATE (rtbse_env%eps_active(rtbse_env%mo_active, rtbse_env%n_spin))
668 rtbse_env%eps_active(:, :) = 0.0_dp
669 END IF
670
671 ! Create the matrices and workspaces for ETRS propagation
672 NULLIFY (rtbse_env%ham_effective)
673 NULLIFY (rtbse_env%rho_new)
674 NULLIFY (rtbse_env%rho_new_last)
675 NULLIFY (rtbse_env%rho_M)
676 NULLIFY (rtbse_env%rho_orig)
677 ALLOCATE (rtbse_env%ham_effective(rtbse_env%n_spin))
678 ALLOCATE (rtbse_env%rho_new(rtbse_env%n_spin))
679 ALLOCATE (rtbse_env%rho_new_last(rtbse_env%n_spin))
680 ALLOCATE (rtbse_env%rho_M(rtbse_env%n_spin))
681 ALLOCATE (rtbse_env%rho_orig(rtbse_env%n_spin))
682 DO i = 1, rtbse_env%n_spin
683 CALL cp_cfm_create(rtbse_env%ham_effective(i), mo_struct)
684 CALL cp_cfm_set_all(rtbse_env%ham_effective(i), cmplx(0.0, 0.0, kind=dp))
685 CALL cp_cfm_create(rtbse_env%rho_new(i), mo_struct)
686 CALL cp_cfm_set_all(rtbse_env%rho_new(i), cmplx(0.0, 0.0, kind=dp))
687 CALL cp_cfm_create(rtbse_env%rho_new_last(i), mo_struct)
688 CALL cp_cfm_set_all(rtbse_env%rho_new_last(i), cmplx(0.0, 0.0, kind=dp))
689 CALL cp_cfm_create(rtbse_env%rho_M(i), mo_struct)
690 CALL cp_cfm_set_all(rtbse_env%rho_M(i), cmplx(0.0, 0.0, kind=dp))
691 CALL cp_cfm_create(rtbse_env%rho_orig(i), mo_struct)
692 END DO
693
694 !For LR-RTBSE we need RK4 coefficients - create new workspace
695 IF (rtbse_env%linearized) THEN
696 ! Indexed by SPIN, not by RK4 stage: the spin loop is inner to each stage (do_rk4_stage), so every
697 ! spin's current-stage k must be live at once, but only one stage's k per spin - each is folded
698 ! into rho_end and the next stage density before the next stage overwrites it. Hence size n_spin.
699 NULLIFY (rtbse_env%rk4_coefficients)
700 ALLOCATE (rtbse_env%rk4_coefficients(rtbse_env%n_spin))
701 DO i = 1, rtbse_env%n_spin
702 CALL cp_cfm_create(rtbse_env%rk4_coefficients(i), mo_struct)
703 CALL cp_cfm_set_all(rtbse_env%rk4_coefficients(i), cmplx(0.0, 0.0, kind=dp))
704 END DO
705 END IF
706
707 ! Fields for exact diagonalisation
708 NULLIFY (rtbse_env%real_eigvals)
709 ALLOCATE (rtbse_env%real_eigvals(rtbse_env%n_ao))
710 rtbse_env%real_eigvals(:) = 0.0_dp
711 NULLIFY (rtbse_env%exp_eigvals)
712 ALLOCATE (rtbse_env%exp_eigvals(rtbse_env%n_ao))
713 rtbse_env%exp_eigvals(:) = cmplx(0.0, 0.0, kind=dp)
714
715 ! Workspace for FT - includes (in principle) the zeroth step and the extra last step
716 NULLIFY (rtbse_env%moments_trace)
717 ! TODO : Unite the number of steps with TD-DFT
718 ALLOCATE (rtbse_env%moments_trace(rtbse_env%n_spin, 3, rtbse_env%sim_nsteps + 1), source=z_zero)
719 NULLIFY (rtbse_env%field_trace)
720 ALLOCATE (rtbse_env%field_trace(3, rtbse_env%sim_nsteps + 1), source=z_zero)
721 NULLIFY (rtbse_env%time_trace)
722 ALLOCATE (rtbse_env%time_trace(rtbse_env%sim_nsteps + 1), source=0.0_dp)
723
724 ! Allocate self-energy parts and dynamic Hartree potential.
725 ! In linearized RT-BSE these matrices hold the MO-active-sized result of the
726 ! AO->MO transform; the AO-sized buffer is allocated as sigma_*_ao below.
727 NULLIFY (rtbse_env%hartree_curr)
728 NULLIFY (rtbse_env%sigma_SEX)
729 NULLIFY (rtbse_env%sigma_COH)
730 ALLOCATE (rtbse_env%hartree_curr(rtbse_env%n_spin))
731 ALLOCATE (rtbse_env%sigma_SEX(rtbse_env%n_spin))
732 ALLOCATE (rtbse_env%sigma_COH(rtbse_env%n_spin))
733 DO i = 1, rtbse_env%n_spin
734 CALL cp_fm_create(rtbse_env%sigma_COH(i), mo_struct)
735 CALL cp_cfm_create(rtbse_env%sigma_SEX(i), mo_struct)
736 CALL cp_fm_create(rtbse_env%hartree_curr(i), mo_struct)
737 CALL cp_fm_set_all(rtbse_env%sigma_COH(i), 0.0_dp)
738 CALL cp_cfm_set_all(rtbse_env%sigma_SEX(i), cmplx(0.0, 0.0, kind=dp))
739 CALL cp_fm_set_all(rtbse_env%hartree_curr(i), 0.0_dp)
740 END DO
741 ! AO-sized scratch buffers used by the linearized RT-BSE path
742 IF (rtbse_env%linearized) THEN
743 NULLIFY (rtbse_env%hartree_curr_ao)
744 NULLIFY (rtbse_env%sigma_SEX_ao)
745 ALLOCATE (rtbse_env%hartree_curr_ao(rtbse_env%n_spin))
746 ALLOCATE (rtbse_env%sigma_SEX_ao(rtbse_env%n_spin))
747 DO i = 1, rtbse_env%n_spin
748 CALL cp_cfm_create(rtbse_env%sigma_SEX_ao(i), bs_env%fm_ks_Gamma(1)%matrix_struct)
749 CALL cp_fm_create(rtbse_env%hartree_curr_ao(i), bs_env%fm_ks_Gamma(1)%matrix_struct)
750 CALL cp_cfm_set_all(rtbse_env%sigma_SEX_ao(i), cmplx(0.0, 0.0, kind=dp))
751 CALL cp_fm_set_all(rtbse_env%hartree_curr_ao(i), 0.0_dp)
752 END DO
753 ! mo_active x mo_active real workspace pair for MO-side intermediates
754 NULLIFY (rtbse_env%real_workspace_mo)
755 ALLOCATE (rtbse_env%real_workspace_mo(2))
756 DO i = 1, SIZE(rtbse_env%real_workspace_mo)
757 CALL cp_fm_create(rtbse_env%real_workspace_mo(i), rtbse_env%fm_struct_mo_active)
758 CALL cp_fm_set_all(rtbse_env%real_workspace_mo(i), 0.0_dp)
759 END DO
760 NULLIFY (rtbse_env%ao_mo_workspace)
761 ALLOCATE (rtbse_env%ao_mo_workspace(1))
762 CALL cp_fm_create(rtbse_env%ao_mo_workspace(1), rtbse_env%fm_struct_ao_mo_active)
763 CALL cp_fm_set_all(rtbse_env%ao_mo_workspace(1), 0.0_dp)
764 ! Truncated MO coefficient slabs C_active (n_ao x mo_active) for each spin.
765 ! Filled in initialize_rtbse_env from bs_env%fm_mo_coeff_Gamma via submatrix copy.
766 NULLIFY (rtbse_env%C_active)
767 ALLOCATE (rtbse_env%C_active(rtbse_env%n_spin))
768 DO i = 1, rtbse_env%n_spin
769 CALL cp_fm_create(rtbse_env%C_active(i), rtbse_env%fm_struct_ao_mo_active)
770 CALL cp_fm_set_all(rtbse_env%C_active(i), 0.0_dp)
771 END DO
772 ! Masked-copy staging scratch for the builder (all propagation paths including closed-shell ABBA).
773 ! Also used as conjugate-transpose scratch in the TDA consumer.
774 NULLIFY (rtbse_env%rho_delta_mo)
775 ALLOCATE (rtbse_env%rho_delta_mo(rtbse_env%n_spin))
776 DO i = 1, rtbse_env%n_spin
777 CALL cp_cfm_create(rtbse_env%rho_delta_mo(i), rtbse_env%fm_struct_mo_active)
778 CALL cp_cfm_set_all(rtbse_env%rho_delta_mo(i), cmplx(0.0_dp, 0.0_dp, kind=dp))
779 END DO
780 ! Shared AO Hartree buffers: widened from (tda_active .OR. n_spin>1) so n_spin=1 ABBA
781 ! (diagnostic + propagator) gets a dedicated buffer instead of aliasing sigma_SEX_ao.
782 IF (.NOT. rtbse_env%debug_disable_hartree) THEN
783 CALL cp_cfm_create(rtbse_env%rho_total_ao_scratch, bs_env%fm_s_Gamma%matrix_struct)
784 CALL cp_cfm_create(rtbse_env%hartree_total_ao, bs_env%fm_ks_Gamma(1)%matrix_struct)
785 CALL cp_cfm_set_all(rtbse_env%rho_total_ao_scratch, cmplx(0.0_dp, 0.0_dp, kind=dp))
786 CALL cp_cfm_set_all(rtbse_env%hartree_total_ao, cmplx(0.0_dp, 0.0_dp, kind=dp))
787 END IF
788 ! Liouvillian-eigenvalue diagnostic state. n_spin=1 enforced upstream.
789 ! Shared scratch (TDA + ABBA) allocated on diagnose_liouvillian_eig=T;
790 ! ABBA-only A/B/A±B blocks added below under .NOT. tda_active. Mirror of the
791 ! existing shared-scratch pattern, with the extra tda_active gate as the deviation.
792 IF (rtbse_env%diagnose_liouvillian_eig) THEN
793 ! Joint OV dimension: the spin blocks are stacked (n_spin=1 -> the old single-spin
794 ! size). drho_probe/L_drho stay mo_active-sized per spin; L_pairs is N_OV_joint.
795 n_ov = 0
796 DO i = 1, rtbse_env%n_spin
797 n_ov = n_ov + (rtbse_env%n_occ(i) - rtbse_env%first_active_mo + 1)* &
798 (rtbse_env%last_active_mo - rtbse_env%n_occ(i))
799 END DO
800 NULLIFY (rtbse_env%fm_struct_ov_pairs)
801 CALL cp_fm_struct_create(rtbse_env%fm_struct_ov_pairs, &
802 bs_env%fm_ks_Gamma(1)%matrix_struct%para_env, &
803 bs_env%fm_ks_Gamma(1)%matrix_struct%context, &
804 n_ov, n_ov)
805 ALLOCATE (rtbse_env%drho_probe(rtbse_env%n_spin))
806 ALLOCATE (rtbse_env%L_drho(rtbse_env%n_spin))
807 DO i = 1, rtbse_env%n_spin
808 CALL cp_cfm_create(rtbse_env%drho_probe(i), rtbse_env%fm_struct_mo_active)
809 CALL cp_cfm_create(rtbse_env%L_drho(i), rtbse_env%fm_struct_mo_active)
810 CALL cp_cfm_set_all(rtbse_env%drho_probe(i), cmplx(0.0_dp, 0.0_dp, kind=dp))
811 CALL cp_cfm_set_all(rtbse_env%L_drho(i), cmplx(0.0_dp, 0.0_dp, kind=dp))
812 END DO
813 CALL cp_cfm_create(rtbse_env%L_pairs, rtbse_env%fm_struct_ov_pairs)
814 CALL cp_cfm_create(rtbse_env%eigvecs_pairs, rtbse_env%fm_struct_ov_pairs)
815 CALL cp_cfm_set_all(rtbse_env%L_pairs, cmplx(0.0_dp, 0.0_dp, kind=dp))
816 CALL cp_cfm_set_all(rtbse_env%eigvecs_pairs, cmplx(0.0_dp, 0.0_dp, kind=dp))
817 NULLIFY (rtbse_env%eigenvalues_liouvillian)
818 ALLOCATE (rtbse_env%eigenvalues_liouvillian(n_ov))
819 rtbse_env%eigenvalues_liouvillian = 0.0_dp
820 ! ABBA-only Furche-reduction scratch (A, B, A-B->sqrt, A+B).
821 IF (.NOT. rtbse_env%tda_active) THEN
822 CALL cp_cfm_create(rtbse_env%A_mat, rtbse_env%fm_struct_ov_pairs)
823 CALL cp_cfm_create(rtbse_env%B_mat, rtbse_env%fm_struct_ov_pairs)
824 CALL cp_cfm_create(rtbse_env%AmB_scratch, rtbse_env%fm_struct_ov_pairs)
825 CALL cp_cfm_create(rtbse_env%ApB_scratch, rtbse_env%fm_struct_ov_pairs)
826 CALL cp_cfm_set_all(rtbse_env%A_mat, cmplx(0.0_dp, 0.0_dp, kind=dp))
827 CALL cp_cfm_set_all(rtbse_env%B_mat, cmplx(0.0_dp, 0.0_dp, kind=dp))
828 CALL cp_cfm_set_all(rtbse_env%AmB_scratch, cmplx(0.0_dp, 0.0_dp, kind=dp))
829 CALL cp_cfm_set_all(rtbse_env%ApB_scratch, cmplx(0.0_dp, 0.0_dp, kind=dp))
830 END IF
831 END IF
832 END IF
833
834 ! Allocate workspaces for get_sigma
835 CALL create_sigma_workspace(rtbse_env)
836
837 ! Depending on the chosen methods, allocate extra workspace
838 CALL create_hartree_ri_workspace(rtbse_env)
839
840 END SUBROUTINE create_rtbse_env
841
842! **************************************************************************************************
843!> \brief Simple reimplementation of cp_fm_release_pp1 for complex matrices
844!> \param matrices cp_cfm_type(:)
845!> \author Stepan Marek
846!> \date 02.2024
847! **************************************************************************************************
848 SUBROUTINE cp_cfm_release_pa1(matrices)
849 TYPE(cp_cfm_type), DIMENSION(:), POINTER :: matrices
850 INTEGER :: i
851
852 DO i = 1, SIZE(matrices)
853 CALL cp_cfm_release(matrices(i))
854 END DO
855 DEALLOCATE (matrices)
856 NULLIFY (matrices)
857 END SUBROUTINE cp_cfm_release_pa1
858
859! **************************************************************************************************
860!> \brief Releases the environment allocated structures
861!> \param rtbse_env
862!> \author Stepan Marek
863!> \date 02.2024
864! **************************************************************************************************
865 SUBROUTINE release_rtbse_env(rtbse_env)
866 TYPE(rtbse_env_type), POINTER :: rtbse_env
867
868 CALL cp_cfm_release_pa1(rtbse_env%ham_effective)
869 CALL cp_cfm_release_pa1(rtbse_env%ham_workspace)
870 CALL cp_fm_release(rtbse_env%sigma_COH)
871 CALL cp_cfm_release_pa1(rtbse_env%sigma_SEX)
872 CALL cp_fm_release(rtbse_env%hartree_curr)
873 CALL cp_cfm_release_pa1(rtbse_env%ham_reference)
874 IF (ASSOCIATED(rtbse_env%ham_reference_singleparticle)) THEN
875 CALL cp_cfm_release_pa1(rtbse_env%ham_reference_singleparticle)
876 END IF
877 IF (ASSOCIATED(rtbse_env%eps_active)) DEALLOCATE (rtbse_env%eps_active)
878 IF (ASSOCIATED(rtbse_env%eps_active_restart)) DEALLOCATE (rtbse_env%eps_active_restart)
879 CALL cp_cfm_release_pa1(rtbse_env%rho)
880 CALL cp_cfm_release_pa1(rtbse_env%rho_workspace)
881 CALL cp_cfm_release_pa1(rtbse_env%rho_new)
882 CALL cp_cfm_release_pa1(rtbse_env%rho_new_last)
883 CALL cp_cfm_release_pa1(rtbse_env%rho_M)
884 CALL cp_cfm_release_pa1(rtbse_env%rho_orig)
885 IF (ASSOCIATED(rtbse_env%rk4_coefficients)) THEN
886 CALL cp_cfm_release_pa1(rtbse_env%rk4_coefficients)
887 END IF
888 CALL cp_fm_release(rtbse_env%real_workspace)
889 IF (ASSOCIATED(rtbse_env%sigma_complex_workspace)) CALL cp_cfm_release_pa1(rtbse_env%sigma_complex_workspace)
890 CALL cp_fm_release(rtbse_env%S_inv_fm)
891 CALL cp_fm_release(rtbse_env%S_fm)
892 CALL cp_cfm_release(rtbse_env%S_cfm)
893
894 CALL cp_fm_release(rtbse_env%moments)
895 CALL cp_fm_release(rtbse_env%moments_field)
896
897 CALL release_sigma_workspace(rtbse_env)
898
899 CALL release_hartree_ri_workspace(rtbse_env)
900
901 DEALLOCATE (rtbse_env%real_eigvals)
902 DEALLOCATE (rtbse_env%exp_eigvals)
903 DEALLOCATE (rtbse_env%moments_trace)
904 DEALLOCATE (rtbse_env%field_trace)
905 DEALLOCATE (rtbse_env%time_trace)
906
907 IF (ASSOCIATED(rtbse_env%pol_elements)) DEALLOCATE (rtbse_env%pol_elements)
908 IF (ASSOCIATED(rtbse_env%pade_x_eval)) DEALLOCATE (rtbse_env%pade_x_eval)
909
910 ! Deallocate the neighbour list that is not deallocated in gw anymore
911 IF (ASSOCIATED(rtbse_env%bs_env%nl_3c%ij_list)) CALL neighbor_list_3c_destroy(rtbse_env%bs_env%nl_3c)
912 ! Release linearized-only AO scratches and MO-side workspaces
913 IF (ASSOCIATED(rtbse_env%rho_ao_scratch)) CALL cp_cfm_release_pa1(rtbse_env%rho_ao_scratch)
914 IF (ASSOCIATED(rtbse_env%sigma_SEX_ao)) CALL cp_cfm_release_pa1(rtbse_env%sigma_SEX_ao)
915 IF (ASSOCIATED(rtbse_env%hartree_curr_ao)) CALL cp_fm_release(rtbse_env%hartree_curr_ao)
916 IF (ASSOCIATED(rtbse_env%real_workspace_mo)) CALL cp_fm_release(rtbse_env%real_workspace_mo)
917 IF (ASSOCIATED(rtbse_env%ao_mo_workspace)) CALL cp_fm_release(rtbse_env%ao_mo_workspace)
918 IF (ASSOCIATED(rtbse_env%C_active)) CALL cp_fm_release(rtbse_env%C_active)
919 IF (ASSOCIATED(rtbse_env%rho_delta_mo)) CALL cp_cfm_release_pa1(rtbse_env%rho_delta_mo)
920 ! Release shared bare-Hartree scratch. Mirror the alloc gate exactly (linearized .AND.
921 ! .NOT. debug_disable_hartree, every shell incl closed-shell ABBA) — the old
922 ! (tda_active .OR. n_spin>1) gate leaked both buffers on the closed-shell ABBA path.
923 IF (rtbse_env%linearized .AND. .NOT. rtbse_env%debug_disable_hartree) THEN
924 CALL cp_cfm_release(rtbse_env%rho_total_ao_scratch)
925 CALL cp_cfm_release(rtbse_env%hartree_total_ao)
926 END IF
927 ! Release the RI-RS Hartree diagonal-reuse accumulators (allocated in initialize_hartree_potential).
928 IF (ALLOCATED(rtbse_env%hartree_diag_re)) DEALLOCATE (rtbse_env%hartree_diag_re)
929 IF (ALLOCATED(rtbse_env%hartree_diag_im)) DEALLOCATE (rtbse_env%hartree_diag_im)
930 ! Release Liouvillian-diagnostic scratch (only when the diagnostic was requested).
931 IF (rtbse_env%diagnose_liouvillian_eig) THEN
932 IF (ASSOCIATED(rtbse_env%drho_probe)) CALL cp_cfm_release_pa1(rtbse_env%drho_probe)
933 IF (ASSOCIATED(rtbse_env%L_drho)) CALL cp_cfm_release_pa1(rtbse_env%L_drho)
934 CALL cp_cfm_release(rtbse_env%L_pairs)
935 CALL cp_cfm_release(rtbse_env%eigvecs_pairs)
936 IF (ASSOCIATED(rtbse_env%eigenvalues_liouvillian)) DEALLOCATE (rtbse_env%eigenvalues_liouvillian)
937 IF (.NOT. rtbse_env%tda_active) THEN
938 CALL cp_cfm_release(rtbse_env%A_mat)
939 CALL cp_cfm_release(rtbse_env%B_mat)
940 CALL cp_cfm_release(rtbse_env%AmB_scratch)
941 CALL cp_cfm_release(rtbse_env%ApB_scratch)
942 END IF
943 IF (ASSOCIATED(rtbse_env%fm_struct_ov_pairs)) THEN
944 CALL cp_fm_struct_release(rtbse_env%fm_struct_ov_pairs)
945 END IF
946 END IF
947 ! Release owned active-MO matrix structures
948 IF (ASSOCIATED(rtbse_env%fm_struct_mo_active)) THEN
949 CALL cp_fm_struct_release(rtbse_env%fm_struct_mo_active)
950 END IF
951 IF (ASSOCIATED(rtbse_env%fm_struct_ao_mo_active)) THEN
952 CALL cp_fm_struct_release(rtbse_env%fm_struct_ao_mo_active)
953 END IF
954 ! Deallocate the storage for the environment itself
955 DEALLOCATE (rtbse_env)
956 ! Nullify to make sure it is not used again
957 NULLIFY (rtbse_env)
958
959 END SUBROUTINE release_rtbse_env
960
961! **************************************************************************************************
962!> \brief Abort if the quasiparticle spectrum handed to the propagator is inverted or has diverged.
963!>
964!> Tests the fundamental gap per spin channel - not E(HOMO+1) - E(HOMO), since G0W0 reorders levels -
965!> on the very array the propagator consumes. Under RTBSE_HAMILTONIAN KS the quasiparticle energies
966!> never enter the propagator, so a broken G0W0 spectrum is irrelevant there and does not abort.
967!> \param rtbse_env RT-BSE environment with n_ao, n_occ, n_spin, ham_reference_type populated.
968!> \param bs_env Bandstructure environment providing the eigenvalues.
969! **************************************************************************************************
970 SUBROUTINE check_qp_gap_sanity(rtbse_env, bs_env)
971 TYPE(rtbse_env_type), POINTER :: rtbse_env
972 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
973
974 INTEGER :: homo, ispin
975 REAL(kind=dp) :: gap, gap_scf
976
977 IF (rtbse_env%ham_reference_type /= rtp_bse_ham_gw) RETURN
978
979 DO ispin = 1, rtbse_env%n_spin
980 homo = rtbse_env%n_occ(ispin)
981 IF (homo < 1 .OR. homo >= rtbse_env%n_ao) cycle
982
983 gap = minval(bs_env%eigenval_GW(homo + 1:rtbse_env%n_ao, 1, ispin)) - &
984 maxval(bs_env%eigenval_GW(1:homo, 1, ispin))
985 gap_scf = minval(bs_env%eigenval_scf_Gamma(homo + 1:rtbse_env%n_ao, ispin)) - &
986 maxval(bs_env%eigenval_scf_Gamma(1:homo, ispin))
987
988 ! requiring a healthy SCF gap keeps the inversion test from firing on a genuine metal
989 IF (gap < -eps_qp_gap .AND. gap_scf > eps_qp_gap) THEN
990 CALL cp_abort(__location__, &
991 "RTBSE: G0W0 gap of spin "//trim(adjustl(cp_to_string(ispin)))// &
992 " is negative ("//trim(adjustl(cp_to_string(gap*evolt, '(F12.3)')))// &
993 " eV): propagating an inverted spectrum is meaningless. Check the GW "// &
994 "numerical parameters, or use RTBSE_HAMILTONIAN KS.")
995 ELSE IF (abs(gap) > max_qp_gap) THEN
996 CALL cp_abort(__location__, &
997 "RTBSE: G0W0 gap of spin "//trim(adjustl(cp_to_string(ispin)))// &
998 " is implausibly large ("// &
999 trim(adjustl(cp_to_string(gap*evolt, '(F12.3)')))//" eV): the GW step "// &
1000 "has likely diverged. Check the GW numerical parameters, or use "// &
1001 "RTBSE_HAMILTONIAN KS.")
1002 END IF
1003 END DO
1004
1005 END SUBROUTINE check_qp_gap_sanity
1006
1007! **************************************************************************************************
1008!> \brief Determine the combined active MO window for linearized RT-BSE truncation.
1009!>
1010!> Evaluates BSE-like cutoff indices per spin from the requested single-particle spectrum
1011!> (G0W0 or KS Gamma-point eigenvalues) and collapses them into a single combined window
1012!> covering both spin channels by choosing the most inclusive bounds. Issues a CPWARN if the
1013!> spin-resolved cutoff candidates differ. When cutoffs are disabled (or the run is not
1014!> linearized RT-BSE), the window is set to the full MO range.
1015!> \param rtbse_env RT-BSE environment with cutoff values, n_ao, n_occ, n_spin, ham_reference_type
1016!> already populated.
1017!> \param bs_env Bandstructure environment providing the eigenvalues.
1018! **************************************************************************************************
1019 SUBROUTINE determine_active_mo_window(rtbse_env, bs_env)
1020 TYPE(rtbse_env_type), POINTER :: rtbse_env
1021 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
1022 CHARACTER(LEN=*), PARAMETER :: routinen = "determine_active_mo_window"
1023
1024 INTEGER :: handle, ispin, n_ao_full
1025 LOGICAL :: spins_differ, do_truncation
1026 REAL(kind=dp) :: cutoff_occ, cutoff_empty
1027 TYPE(mo_window_type), ALLOCATABLE, DIMENSION(:) :: spin_windows
1028 TYPE(mo_window_type) :: combined_window
1029
1030 CALL timeset(routinen, handle)
1031
1032 n_ao_full = rtbse_env%n_ao
1033 cutoff_occ = rtbse_env%rtbse_energy_cutoff_occ
1034 cutoff_empty = rtbse_env%rtbse_energy_cutoff_empty
1035 do_truncation = rtbse_env%linearized .AND. (cutoff_occ > 0.0_dp .OR. cutoff_empty > 0.0_dp)
1036
1037 ! Default: full MO window
1038 rtbse_env%first_active_mo = 1
1039 rtbse_env%last_active_mo = n_ao_full
1040 rtbse_env%mo_active = n_ao_full
1041 rtbse_env%active_mo_truncation = .false.
1042
1043 IF (.NOT. do_truncation) THEN
1044 CALL timestop(handle)
1045 RETURN
1046 END IF
1047
1048 ALLOCATE (spin_windows(rtbse_env%n_spin))
1049 DO ispin = 1, rtbse_env%n_spin
1050 ! Cut on the DFT axis, as LRBSE does: it is ascending by construction, so the window is a
1051 ! well-defined contiguous MO range, which is all C_active can extract. The G0W0 axis is
1052 ! not ordered.
1053 CALL determine_mo_window(bs_env%eigenval_scf_Gamma(:, ispin), n_ao_full, &
1054 rtbse_env%n_occ(ispin), cutoff_occ, cutoff_empty, &
1055 spin_windows(ispin))
1056 END DO
1057
1058 CALL combine_mo_windows(spin_windows, combined_window, spins_differ)
1059 IF (spins_differ) THEN
1060 cpwarn("RTBSE: spin-resolved active MO cutoff candidates differ; using combined window.")
1061 END IF
1062
1063 rtbse_env%first_active_mo = combined_window%first_mo
1064 rtbse_env%last_active_mo = combined_window%last_mo
1065 rtbse_env%mo_active = combined_window%last_mo - combined_window%first_mo + 1
1066 rtbse_env%active_mo_truncation = (rtbse_env%mo_active < n_ao_full)
1067
1068 DEALLOCATE (spin_windows)
1069 CALL timestop(handle)
1070 END SUBROUTINE determine_active_mo_window
1071
1072! **************************************************************************************************
1073!> \brief Allocates the workspaces for Hartree RI method
1074!> \note RI method calculates the Hartree contraction without the use of DBT, as it cannot emulate vectors
1075!> \param rtbse_env
1076!> \author Stepan Marek
1077!> \date 05.2024
1078! **************************************************************************************************
1079 SUBROUTINE create_hartree_ri_workspace(rtbse_env)
1080 TYPE(rtbse_env_type) :: rtbse_env
1081 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
1082
1083 ! Skip the AO-RI Hartree scratch when the RT-BSE Hartree path is fully RI-RS.
1084 ! In that case rho_dbcsr / v_ao_dbcsr / int_3c_array are never read.
1085 ! get_sigma_real (AO-RI SX) used to borrow rho_dbcsr as a workspace; that
1086 ! cross-dependency was removed by giving get_sigma_real its own local
1087 ! dbcsr scratch (see rt_bse.F::get_sigma_real). rho_dbcsr is now AO-RI
1088 ! Hartree only, as its name suggests.
1089 IF (rtbse_env%rirs_kernel) RETURN
1090
1091 CALL get_qs_env(rtbse_env%qs_env, bs_env=bs_env)
1092
1093 CALL dbcsr_create(rtbse_env%rho_dbcsr, name="Sparse density", template=bs_env%mat_ao_ao%matrix)
1094 CALL dbcsr_create(rtbse_env%v_ao_dbcsr, name="Sparse Hartree", template=bs_env%mat_ao_ao%matrix)
1095
1096 CALL create_hartree_ri_3c(rtbse_env%rho_dbcsr, rtbse_env%int_3c_array, rtbse_env%n_ao, rtbse_env%n_RI, &
1097 bs_env%basis_set_AO, bs_env%basis_set_RI, bs_env%i_RI_start_from_atom, &
1098 bs_env%ri_metric, rtbse_env%qs_env, rtbse_env%unit_nr)
1099 END SUBROUTINE create_hartree_ri_workspace
1100! **************************************************************************************************
1101!> \brief Separated method for allocating the 3c integrals for RI Hartree
1102!> \note RI method calculates the Hartree contraction without the use of DBT, as it cannot emulate vectors
1103!> \param rho_dbcsr matrix used for the description of shape of 3c array
1104!> \param int_3c 3-center integral array to be allocated and filled
1105!> \param n_ao Number of atomic orbitals
1106!> \param n_RI Number of auxiliary RI orbitals
1107!> \param basis_set_AO AO basis set
1108!> \param basis_set_RI RI auxiliary basis set
1109!> \param i_RI_start_from_atom Array of indices where functions of a given atom in RI basis start
1110!> \param unit_nr Unit number used for printing information about the size of int_3c
1111!> \author Stepan Marek
1112!> \date 01.2025
1113! **************************************************************************************************
1114 SUBROUTINE create_hartree_ri_3c(rho_dbcsr, int_3c, n_ao, n_RI, basis_set_AO, basis_set_RI, &
1115 i_RI_start_from_atom, ri_metric, qs_env, unit_nr)
1116 TYPE(dbcsr_type) :: rho_dbcsr
1117 REAL(kind=dp), DIMENSION(:, :, :), POINTER :: int_3c
1118 INTEGER :: n_ao, n_ri
1119 TYPE(gto_basis_set_p_type), DIMENSION(:) :: basis_set_ao, &
1120 basis_set_ri
1121 INTEGER, DIMENSION(:) :: i_ri_start_from_atom
1122 TYPE(libint_potential_type) :: ri_metric
1123 TYPE(qs_environment_type), POINTER :: qs_env
1124 INTEGER :: unit_nr
1125 REAL(kind=dp) :: size_mb
1126 INTEGER :: nblkrows_local, &
1127 nblkcols_local, &
1128 i_blk_local, &
1129 j_blk_local, &
1130 nrows_local, &
1131 ncols_local, &
1132 col_local_offset, &
1133 row_local_offset, &
1134 start_col_index, &
1135 end_col_index, &
1136 start_row_index, &
1137 end_row_index
1138 INTEGER, DIMENSION(:), POINTER :: local_blk_rows, &
1139 local_blk_cols, &
1140 row_blk_size, &
1141 col_blk_size
1142 ! TODO : Implement option/decision to not precompute all the 3c integrals
1143 size_mb = real(n_ao, kind=dp)*real(n_ao, kind=dp)*real(n_ri, kind=dp)* &
1144 REAL(storage_size(size_mb), kind=dp)/8.0_dp/1024.0_dp/1024.0_dp
1145 IF (unit_nr > 0) WRITE (unit_nr, '(A44,E32.2E3,A4)') &
1146 " RTBSE| Approximate size of the 3c integrals", size_mb, " MiB"
1147
1148 ! Get the number of block rows and columns
1149 CALL dbcsr_get_info(rho_dbcsr, nblkrows_local=nblkrows_local, nblkcols_local=nblkcols_local)
1150 ! Get the global indices of local rows and columns
1151 CALL dbcsr_get_info(rho_dbcsr, local_rows=local_blk_rows, local_cols=local_blk_cols)
1152 ! Get the sizes of all blocks
1153 CALL dbcsr_get_info(rho_dbcsr, row_blk_size=row_blk_size, col_blk_size=col_blk_size)
1154
1155 ! Get the total required local rows and cols
1156 nrows_local = 0
1157 DO i_blk_local = 1, nblkrows_local
1158 nrows_local = nrows_local + row_blk_size(local_blk_rows(i_blk_local))
1159 END DO
1160 ncols_local = 0
1161 DO j_blk_local = 1, nblkcols_local
1162 ncols_local = ncols_local + col_blk_size(local_blk_cols(j_blk_local))
1163 END DO
1164
1165 ! Allocate the appropriate storage
1166 ALLOCATE (int_3c(nrows_local, ncols_local, n_ri))
1167
1168 ! Fill the storage with appropriate values, block by block
1169 row_local_offset = 1
1170 DO i_blk_local = 1, nblkrows_local
1171 col_local_offset = 1
1172 DO j_blk_local = 1, nblkcols_local
1173 start_row_index = row_local_offset
1174 end_row_index = start_row_index + row_blk_size(local_blk_rows(i_blk_local)) - 1
1175 start_col_index = col_local_offset
1176 end_col_index = start_col_index + col_blk_size(local_blk_cols(j_blk_local)) - 1
1177 CALL build_3c_integral_block(int_3c(start_row_index:end_row_index, &
1178 start_col_index:end_col_index, &
1179 1:n_ri), &
1180 qs_env, potential_parameter=ri_metric, &
1181 basis_j=basis_set_ao, basis_k=basis_set_ao, &
1182 basis_i=basis_set_ri, &
1183 atom_j=local_blk_rows(i_blk_local), &
1184 atom_k=local_blk_cols(j_blk_local), &
1185 i_bf_start_from_atom=i_ri_start_from_atom)
1186 col_local_offset = col_local_offset + col_blk_size(local_blk_cols(j_blk_local))
1187 END DO
1188 row_local_offset = row_local_offset + row_blk_size(local_blk_rows(i_blk_local))
1189 END DO
1190 END SUBROUTINE create_hartree_ri_3c
1191! **************************************************************************************************
1192!> \brief Releases the workspace for the Hartree RI method
1193!> \param rtbse_env RT-BSE Environment, containing specific RI Hartree storage
1194!> \author Stepan Marek
1195!> \date 09.2024
1196! **************************************************************************************************
1197 SUBROUTINE release_hartree_ri_workspace(rtbse_env)
1198 TYPE(rtbse_env_type) :: rtbse_env
1199
1200 ! Mirror the gate in create_hartree_ri_workspace and the v_dbcsr gate in
1201 ! initialize_hartree_potential. With one KERNEL_RI switch the AO-RI Hartree
1202 ! scratch (3c integrals + dbcsr work + v_dbcsr) is created iff `.NOT. rirs_kernel`.
1203 IF (.NOT. rtbse_env%rirs_kernel) THEN
1204 DEALLOCATE (rtbse_env%int_3c_array)
1205 CALL dbcsr_release(rtbse_env%rho_dbcsr)
1206 CALL dbcsr_release(rtbse_env%v_ao_dbcsr)
1207 CALL dbcsr_release(rtbse_env%v_dbcsr)
1208 END IF
1209 END SUBROUTINE release_hartree_ri_workspace
1210! **************************************************************************************************
1211!> \brief Allocates the workspaces for self-energy determination routine
1212!> \param rtbse_env Structure for holding information and workspace structures
1213!> \author Stepan Marek
1214!> \date 02.2024
1215! **************************************************************************************************
1216 SUBROUTINE create_sigma_workspace(rtbse_env)
1217 TYPE(rtbse_env_type) :: rtbse_env
1218
1219 ! Skip the AO-RI sigma scratch (W matrix + 3c integrals + work tensors)
1220 ! when the RT-BSE SEX path is fully RI-RS — these workspaces are read
1221 ! only by get_sigma in the `.NOT. rirs_kernel` branches.
1222 IF (rtbse_env%rirs_kernel) RETURN
1223
1224 CALL create_sigma_workspace_qs_only(rtbse_env%qs_env, rtbse_env%screened_dbt, rtbse_env%w_dbcsr, &
1225 rtbse_env%t_3c_w, rtbse_env%t_3c_work_RI_AO__AO, &
1226 rtbse_env%t_3c_work2_RI_AO__AO, rtbse_env%greens_dbt)
1227 END SUBROUTINE create_sigma_workspace
1228! **************************************************************************************************
1229!> \brief Allocates the workspaces for self-energy determination routine
1230!> \note Does so without referencing the rtbse_env
1231!> \note References bs_env
1232!> \param rtbse_env Structure for holding information and workspace structures
1233!> \param qs_env Quickstep environment - entry point of calculation
1234!> \author Stepan Marek
1235!> \date 02.2024
1236! **************************************************************************************************
1237 SUBROUTINE create_sigma_workspace_qs_only(qs_env, screened_dbt, screened_dbcsr, int_3c_dbt, &
1238 work_dbt_3c_1, work_dbt_3c_2, work_dbt_2c)
1239 TYPE(qs_environment_type), POINTER :: qs_env
1240 TYPE(dbcsr_type) :: screened_dbcsr
1241 TYPE(dbt_type) :: screened_dbt, &
1242 int_3c_dbt, &
1243 work_dbt_3c_1, &
1244 work_dbt_3c_2, &
1245 work_dbt_2c
1246 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
1247
1248 CALL get_qs_env(qs_env, bs_env=bs_env)
1249
1250 ! t_3c_w
1251 CALL dbt_create(bs_env%t_RI__AO_AO, int_3c_dbt)
1252 ! TODO : Provide option/decision whether to store the 3c integrals precomputed
1253 CALL compute_3c_integrals(qs_env, bs_env, int_3c_dbt)
1254 ! t_3c_work_RI_AO__AO
1255 CALL dbt_create(bs_env%t_RI_AO__AO, work_dbt_3c_1)
1256 ! t_3c_work2_RI_AO__AO
1257 CALL dbt_create(bs_env%t_RI_AO__AO, work_dbt_3c_2)
1258 ! t_W
1259 ! Populate screened_dbt from gw run
1260 CALL dbcsr_create(screened_dbcsr, name="W", template=bs_env%mat_RI_RI%matrix)
1261 CALL dbt_create(screened_dbcsr, screened_dbt)
1262 ! greens_dbt
1263 CALL dbt_create(bs_env%mat_ao_ao%matrix, work_dbt_2c)
1264 END SUBROUTINE create_sigma_workspace_qs_only
1265! **************************************************************************************************
1266!> \brief Releases the workspaces for self-energy determination
1267!> \param rtbse_env
1268!> \author Stepan Marek
1269!> \date 02.2024
1270! **************************************************************************************************
1271 SUBROUTINE release_sigma_workspace(rtbse_env)
1272 TYPE(rtbse_env_type) :: rtbse_env
1273
1274 ! Mirror the gate in create_sigma_workspace.
1275 IF (rtbse_env%rirs_kernel) RETURN
1276
1277 CALL dbt_destroy(rtbse_env%t_3c_w)
1278 CALL dbt_destroy(rtbse_env%t_3c_work_RI_AO__AO)
1279 CALL dbt_destroy(rtbse_env%t_3c_work2_RI_AO__AO)
1280 CALL dbt_destroy(rtbse_env%screened_dbt)
1281 CALL dbt_destroy(rtbse_env%greens_dbt)
1282 CALL dbcsr_release(rtbse_env%w_dbcsr)
1283 END SUBROUTINE release_sigma_workspace
1284! **************************************************************************************************
1285!> \brief Multiplies real matrix by a complex matrix from the right
1286!> \note So far only converts the real matrix to complex one, potentially doubling the work
1287!> \param rtbse_env
1288!> \author Stepan Marek
1289!> \date 09.2024
1290! **************************************************************************************************
1291 SUBROUTINE multiply_fm_cfm(trans_r, trans_c, na, nb, nc, &
1292 alpha, matrix_r, matrix_c, beta, res)
1293 ! Transposition
1294 CHARACTER(len=1) :: trans_r, trans_c
1295 INTEGER :: na, nb, nc
1296 ! accept real numbers
1297 ! TODO : Just use complex numbers and import z_one, z_zero etc.
1298 REAL(kind=dp) :: alpha, beta
1299 TYPE(cp_fm_type) :: matrix_r
1300 TYPE(cp_cfm_type) :: matrix_c, res
1301 TYPE(cp_fm_type) :: work_re, work_im, res_re, res_im
1302 REAL(kind=dp) :: i_unit
1303 CHARACTER(len=1) :: trans_cr
1304
1305 CALL cp_fm_create(work_re, matrix_c%matrix_struct)
1306 CALL cp_fm_create(work_im, matrix_c%matrix_struct)
1307 CALL cp_fm_create(res_re, res%matrix_struct)
1308 CALL cp_fm_create(res_im, res%matrix_struct)
1309 CALL cp_cfm_to_fm(matrix_c, work_re, work_im)
1310 SELECT CASE (trans_c)
1311 CASE ("C")
1312 i_unit = -1.0_dp
1313 trans_cr = "T"
1314 CASE ("T")
1315 i_unit = 1.0_dp
1316 trans_cr = "T"
1317 CASE default
1318 i_unit = 1.0_dp
1319 trans_cr = "N"
1320 END SELECT
1321 ! Actual multiplication
1322 CALL parallel_gemm(trans_r, trans_cr, na, nb, nc, &
1323 alpha, matrix_r, work_re, beta, res_re)
1324 CALL parallel_gemm(trans_r, trans_cr, na, nb, nc, &
1325 i_unit*alpha, matrix_r, work_im, beta, res_im)
1326 CALL cp_fm_to_cfm(res_re, res_im, res)
1327 CALL cp_fm_release(work_re)
1328 CALL cp_fm_release(work_im)
1329 CALL cp_fm_release(res_re)
1330 CALL cp_fm_release(res_im)
1331
1332 END SUBROUTINE multiply_fm_cfm
1333! **************************************************************************************************
1334!> \brief Multiplies complex matrix by a real matrix from the right
1335!> \note So far only converts the real matrix to complex one, potentially doubling the work
1336!> \param rtbse_env
1337!> \author Stepan Marek
1338!> \date 09.2024
1339! **************************************************************************************************
1340 SUBROUTINE multiply_cfm_fm(trans_c, trans_r, na, nb, nc, &
1341 alpha, matrix_c, matrix_r, beta, res)
1342 ! Transposition
1343 CHARACTER(len=1) :: trans_c, trans_r
1344 INTEGER :: na, nb, nc
1345 ! accept real numbers
1346 ! TODO : complex number support via interface?
1347 REAL(kind=dp) :: alpha, beta
1348 TYPE(cp_cfm_type) :: matrix_c, res
1349 TYPE(cp_fm_type) :: matrix_r
1350 TYPE(cp_fm_type) :: work_re, work_im, res_re, res_im
1351 REAL(kind=dp) :: i_unit
1352 CHARACTER(len=1) :: trans_cr
1353
1354 CALL cp_fm_create(work_re, matrix_c%matrix_struct)
1355 CALL cp_fm_create(work_im, matrix_c%matrix_struct)
1356 CALL cp_fm_create(res_re, res%matrix_struct)
1357 CALL cp_fm_create(res_im, res%matrix_struct)
1358 CALL cp_cfm_to_fm(matrix_c, work_re, work_im)
1359 SELECT CASE (trans_c)
1360 CASE ("C")
1361 i_unit = -1.0_dp
1362 trans_cr = "T"
1363 CASE ("T")
1364 i_unit = 1.0_dp
1365 trans_cr = "T"
1366 CASE default
1367 i_unit = 1.0_dp
1368 trans_cr = "N"
1369 END SELECT
1370 ! Actual multiplication
1371 CALL parallel_gemm(trans_cr, trans_r, na, nb, nc, &
1372 alpha, work_re, matrix_r, beta, res_re)
1373 CALL parallel_gemm(trans_cr, trans_r, na, nb, nc, &
1374 i_unit*alpha, work_im, matrix_r, beta, res_im)
1375 CALL cp_fm_to_cfm(res_re, res_im, res)
1376 CALL cp_fm_release(work_re)
1377 CALL cp_fm_release(work_im)
1378 CALL cp_fm_release(res_re)
1379 CALL cp_fm_release(res_im)
1380
1381 END SUBROUTINE multiply_cfm_fm
1382END MODULE rt_bse_types
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_set_all(matrix, alpha, beta)
Set all elements of the full matrix to alpha. Besides, set all diagonal matrix elements to beta (if g...
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.
Defines control structures, which contain the parameters and the settings for the DFT-based calculati...
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_release(matrix)
...
represent the structure of a full matrix
subroutine, public cp_fm_struct_create(fmstruct, para_env, context, nrow_global, ncol_global, nrow_block, ncol_block, descriptor, first_p_pos, local_leading_dimension, template_fmstruct, square_blocks, force_block)
allocates and initializes a full matrix structure
subroutine, public cp_fm_struct_release(fmstruct)
releases a full matrix structure
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 ...
This is the start of a dbt_api, all publically needed functions are exported here....
Definition dbt_api.F:17
Interface for the force calculations.
Routines from paper [Graml2024].
subroutine, public compute_3c_integrals(qs_env, bs_env, t_3c, atoms_ao_1, atoms_ao_2, atoms_ri)
...
Utility method to build 3-center integrals for small cell GW.
subroutine, public build_3c_integral_block(int_3c, qs_env, potential_parameter, basis_j, basis_k, basis_i, cell_j, cell_k, cell_i, atom_j, atom_k, atom_i, j_bf_start_from_atom, k_bf_start_from_atom, i_bf_start_from_atom)
...
subroutine, public rtbse_resolve_rirs_flag(qs_env, bs_env, rirs_kernel)
Resolve the linRTBSE RI-RS kernel switch from the KERNEL_RI input and the GW default.
Definition gw_utils.F:3456
collects all constants needed in input so that they can be used without circular dependencies
integer, parameter, public use_mom_ref_coac
integer, parameter, public rtp_method_bse_linearized
integer, parameter, public do_bch
integer, parameter, public rtp_bse_ham_gw
integer, parameter, public do_exact
objects that represent the structure of input sections and the data contained in an input section
recursive type(section_vals_type) function, pointer, public section_vals_get_subs_vals(section_vals, subsection_name, i_rep_section, can_return_null)
returns the values of the requested subsection
subroutine, public section_vals_val_get(section_vals, keyword_name, i_rep_section, i_rep_val, n_rep_val, val, l_val, i_val, r_val, c_val, l_vals, i_vals, r_vals, c_vals, explicit)
returns the requested value
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: ...
Definition of mathematical constants and functions.
complex(kind=dp), parameter, public z_zero
Common selection and union operations for contiguous molecular-orbital windows.
Definition mo_window.F:11
subroutine, public combine_mo_windows(spin_windows, combined_window, windows_differ)
Forms the smallest contiguous window covering all supplied spin windows.
Definition mo_window.F:98
subroutine, public determine_mo_window(eigenvalues, n_mo, n_occ, cutoff_occ, cutoff_empty, window)
Selects one contiguous MO window from an ordered reference spectrum.
Definition mo_window.F:44
basic linear algebra operations for full matrixes
Definition of physical constants:
Definition physcon.F:68
real(kind=dp), parameter, public evolt
Definition physcon.F:183
real(kind=dp), parameter, public max_qp_gap
real(kind=dp), parameter, public eps_qp_gap
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.
Definition and initialisation of the mo data type.
Definition qs_mo_types.F:22
Utility methods to build 3-center integral tensors of various types.
Definition qs_tensors.F:11
subroutine, public neighbor_list_3c_destroy(ijk_list)
Destroy 3c neighborlist.
Definition qs_tensors.F:381
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 create_hartree_ri_3c(rho_dbcsr, int_3c, n_ao, n_ri, basis_set_ao, basis_set_ri, i_ri_start_from_atom, ri_metric, qs_env, unit_nr)
Separated method for allocating the 3c integrals for RI Hartree.
subroutine, public multiply_cfm_fm(trans_c, trans_r, na, nb, nc, alpha, matrix_c, matrix_r, beta, res)
Multiplies complex matrix by a real matrix from the right.
subroutine, public create_sigma_workspace_qs_only(qs_env, screened_dbt, screened_dbcsr, int_3c_dbt, work_dbt_3c_1, work_dbt_3c_2, work_dbt_2c)
Allocates the workspaces for self-energy determination routine.
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.
Types and set_get for real time propagation depending on runtype and diagonalization method different...
Routines needed for EMD.
subroutine, public warn_section_unused(section, subsection_name, error_message)
Warn about unused sections of the print section - only implemented for some of the methods.
Represent a complex full matrix.
keeps the information about the structure of a full matrix
represent a full matrix
wrapper to abstract the force evaluation of the various methods