57 USE dbt_api,
ONLY: dbt_copy_matrix_to_tensor
93#include "../base/base_uses.f90"
99 CHARACTER(len=*),
PARAMETER,
PRIVATE :: moduleN =
'rt_bse_linearized'
103 INTEGER,
PARAMETER,
PRIVATE :: kernel_input_ov = 1, kernel_input_ovvo = 2, kernel_input_full = 3
116 CHARACTER(len=*),
PARAMETER :: routinen =
'run_propagation_linearized_bse'
118 INTEGER :: handle, i, j
119 REAL(kind=
dp) :: t_phys, t_start, timestep_walltime, &
120 timestep_walltime_start
121 REAL(kind=
dp),
DIMENSION(2) :: enum_im, enum_re
122 TYPE(
cp_cfm_type),
DIMENSION(:),
POINTER :: rho_lab
128 CALL timeset(routinen, handle)
130 CALL cp_warn(__location__, &
131 "Linearized RT-BSE is under active development. Make sure you understand "// &
132 "the method and validate results before using it for production calculations.")
146 IF (rtbse_env%dft_control%rtp_control%initial_wfn ==
use_rt_restart)
THEN
150 CALL initialize_maximum_timestep(rtbse_env)
153 IF (rtbse_env%dft_control%rtp_control%initial_wfn ==
use_rt_restart)
THEN
154 IF (rtbse_env%sim_start >= rtbse_env%sim_nsteps)
THEN
155 cpabort(
"RT_RESTART: restart step >= STEPS - increase MOTION%MD%STEPS")
160 CALL print_linrtbse_header_info(rtbse_env)
164 CALL populate_c_active(rtbse_env)
170 CALL initialize_moments(rtbse_env)
175 CALL initialize_density_matrix(rtbse_env)
179 IF (rtbse_env%dft_control%rtp_control%initial_wfn ==
use_rt_restart)
THEN
181 IF (rtbse_env%restart_extracted)
THEN
182 CALL apply_restart_basis_bridge(rtbse_env)
183 t_start = real(rtbse_env%sim_start,
dp)*rtbse_env%sim_dt
184 DO i = 1, rtbse_env%n_spin
185 CALL rotate_rho_phase(rtbse_env, rtbse_env%rho(i), i, -rtbse_env%omega_shift*t_start)
194 DO i = 1, rtbse_env%n_spin
195 CALL transform_mo_to_ao_contravariant_cfm(rtbse_env, rtbse_env%rho_orig(i), rtbse_env%rho_ao_scratch(i), i)
198 DO i = 1, rtbse_env%n_spin
199 CALL cp_cfm_set_all(rtbse_env%ham_reference(i), cmplx(0.0_dp, 0.0_dp, kind=
dp))
203 CALL initialize_sex_selfenergy(rtbse_env)
207 IF (rtbse_env%diagnose_liouvillian_eig)
THEN
208 CALL diagnose_liouvillian_eigenvalues(rtbse_env)
213 rtbse_env%sim_time = real(rtbse_env%sim_start,
dp)*rtbse_env%sim_dt
216 IF (.NOT. rtbse_env%restart_extracted)
THEN
218 CALL build_rho_lab(rtbse_env, rtbse_env%rho, rtbse_env%sim_time, rho_lab)
223 IF (rtbse_env%dft_control%rtp_control%apply_delta_pulse .AND. (.NOT. rtbse_env%restart_extracted))
THEN
224 CALL apply_delta_pulse_mo(rtbse_env)
229 DO i = rtbse_env%sim_start, rtbse_env%sim_nsteps - 1
233 rtbse_env%sim_time = real(i,
dp)*rtbse_env%sim_dt
234 rtbse_env%sim_step = i
236 CALL solve_rk4_timestep(rtbse_env, rtbse_env%rho, rtbse_env%rho_new)
237 CALL get_electron_number_mo(rtbse_env, rtbse_env%rho_new, &
238 enum_re(1:rtbse_env%n_spin), enum_im(1:rtbse_env%n_spin))
239 timestep_walltime =
m_walltime() - timestep_walltime_start
240 CALL print_timestep_info(rtbse_env, i, enum_re(1:rtbse_env%n_spin), step_walltime=timestep_walltime)
241 CALL cp_iterate(logger%iter_info, iter_nr=i, last=(i == rtbse_env%sim_nsteps - 1))
244 DO j = 1, rtbse_env%n_spin
251 t_phys = real(i + 1,
dp)*rtbse_env%sim_dt
252 CALL build_rho_lab(rtbse_env, rtbse_env%rho, t_phys, rho_lab)
265 CALL print_ft(rtbse_env%rtp_section, &
266 rtbse_env%moments_trace, &
267 rtbse_env%time_trace, &
268 rtbse_env%field_trace, &
269 rtbse_env%dft_control%rtp_control, &
270 info_opt=rtbse_env%unit_nr)
275 CALL timestop(handle)
285 SUBROUTINE initialize_maximum_timestep(rtbse_env)
288 CHARACTER(len=*),
PARAMETER :: routinen =
'initialize_maximum_timestep'
290 CHARACTER(len=256) :: hint_msg
291 INTEGER :: handle, i_first, i_last, ispin, &
292 n_steps_new, n_steps_old
293 REAL(kind=
dp) :: eps_max_ai, eps_min_ai, eps_occ_max, eps_occ_min, eps_virt_max, &
294 eps_virt_min, ev_tmp, grace_factor, omega_max, sim_dt_as, total_time
296 CALL timeset(routinen, handle)
298 i_first = rtbse_env%first_active_mo
299 i_last = rtbse_env%last_active_mo
302 omega_max = maxval(rtbse_env%bs_env%eigenval_G0W0(i_first:i_last, :, :)) - &
303 minval(rtbse_env%bs_env%eigenval_G0W0(i_first:i_last, :, :))
305 omega_max = maxval(rtbse_env%bs_env%eigenval_scf_Gamma(i_first:i_last, :)) - &
306 minval(rtbse_env%bs_env%eigenval_scf_Gamma(i_first:i_last, :))
315 rtbse_env%omega_shift = 0.0_dp
316 IF (rtbse_env%tda_active .AND. rtbse_env%tda_shift_to_first_peak)
THEN
317 eps_occ_min = huge(0.0_dp)
318 eps_occ_max = -huge(0.0_dp)
319 eps_virt_min = huge(0.0_dp)
320 eps_virt_max = -huge(0.0_dp)
321 DO ispin = 1, rtbse_env%n_spin
323 IF (rtbse_env%n_occ(ispin) >= i_first)
THEN
325 ev_tmp = minval(rtbse_env%bs_env%eigenval_G0W0(i_first:rtbse_env%n_occ(ispin), :, ispin))
326 eps_occ_min = min(eps_occ_min, ev_tmp)
327 ev_tmp = maxval(rtbse_env%bs_env%eigenval_G0W0(i_first:rtbse_env%n_occ(ispin), :, ispin))
328 eps_occ_max = max(eps_occ_max, ev_tmp)
330 ev_tmp = minval(rtbse_env%bs_env%eigenval_scf_Gamma(i_first:rtbse_env%n_occ(ispin), ispin))
331 eps_occ_min = min(eps_occ_min, ev_tmp)
332 ev_tmp = maxval(rtbse_env%bs_env%eigenval_scf_Gamma(i_first:rtbse_env%n_occ(ispin), ispin))
333 eps_occ_max = max(eps_occ_max, ev_tmp)
337 IF (rtbse_env%n_occ(ispin) < i_last)
THEN
339 ev_tmp = minval(rtbse_env%bs_env%eigenval_G0W0(rtbse_env%n_occ(ispin) + 1:i_last, :, ispin))
340 eps_virt_min = min(eps_virt_min, ev_tmp)
341 ev_tmp = maxval(rtbse_env%bs_env%eigenval_G0W0(rtbse_env%n_occ(ispin) + 1:i_last, :, ispin))
342 eps_virt_max = max(eps_virt_max, ev_tmp)
344 ev_tmp = minval(rtbse_env%bs_env%eigenval_scf_Gamma(rtbse_env%n_occ(ispin) + 1:i_last, ispin))
345 eps_virt_min = min(eps_virt_min, ev_tmp)
346 ev_tmp = maxval(rtbse_env%bs_env%eigenval_scf_Gamma(rtbse_env%n_occ(ispin) + 1:i_last, ispin))
347 eps_virt_max = max(eps_virt_max, ev_tmp)
352 IF (eps_occ_max > -huge(0.0_dp) .AND. eps_virt_min < huge(0.0_dp))
THEN
353 eps_min_ai = eps_virt_min - eps_occ_max
354 eps_max_ai = eps_virt_max - eps_occ_min
355 rtbse_env%omega_shift = eps_min_ai
356 omega_max = eps_max_ai - eps_min_ai
357 IF (rtbse_env%unit_nr > 0)
THEN
358 WRITE (rtbse_env%unit_nr,
'(A)') &
359 " RTBSE| ---------- First-peak shift diagnostics (TDA, active OV pairs) ----------"
360 WRITE (rtbse_env%unit_nr,
'(A,F14.6,A,F14.6)') &
361 " RTBSE| eps_occ [eV] min / max =", eps_occ_min*
evolt, &
362 " /", eps_occ_max*
evolt
363 WRITE (rtbse_env%unit_nr,
'(A,F14.6,A,F14.6)') &
364 " RTBSE| eps_virt [eV] min / max =", eps_virt_min*
evolt, &
365 " /", eps_virt_max*
evolt
366 WRITE (rtbse_env%unit_nr,
'(A,F14.6,A,F14.6)') &
367 " RTBSE| eps_ai [eV] min / max =", eps_min_ai*
evolt, &
368 " /", eps_max_ai*
evolt
369 WRITE (rtbse_env%unit_nr,
'(A,F14.6)') &
370 " RTBSE| omega_shift [eV] =", rtbse_env%omega_shift*
evolt
371 WRITE (rtbse_env%unit_nr,
'(A,F14.6)') &
372 " RTBSE| omega_max [eV] (full) =", omega_max*
evolt
373 WRITE (rtbse_env%unit_nr,
'(A)') &
374 " RTBSE| ------------------------------------------------------------------------"
378 rtbse_env%omega_shift = 0.0_dp
379 rtbse_env%tda_shift_to_first_peak = .false.
383 rtbse_env%omega_max = omega_max
385 IF (omega_max > 0.0_dp)
THEN
387 rtbse_env%maximum_timestep = 2.0_dp*sqrt(2.0_dp)/omega_max
389 CALL cp_abort(__location__, &
390 "Error in estimating maximum timestep: largest KS/GW gap is "// &
391 "non-positive. Check the active MO window (cutoffs) and the "// &
395 IF (rtbse_env%sim_dt <= 0.0_dp)
THEN
396 CALL cp_abort(__location__, &
397 "TIMESTEP must be positive for linearized RT-BSE. Use RTBSE%ENFORCE_MAX_DT "// &
398 "with a positive TIMESTEP to automatically rewrite TIMESTEP and STEPS.")
401 n_steps_old = max(0, rtbse_env%sim_nsteps)
403 IF (rtbse_env%enforce_max_dt)
THEN
404 total_time = real(n_steps_old,
dp)*rtbse_env%sim_dt
406 IF (rtbse_env%tda_active)
THEN
407 grace_factor = 1.0_dp
409 grace_factor = 4.0_dp
411 IF (rtbse_env%dft_control%rtp_control%initial_wfn ==
use_rt_restart .AND. &
412 rtbse_env%sim_dt_restart > 0.0_dp)
THEN
416 rtbse_env%sim_dt = rtbse_env%sim_dt_restart
417 n_steps_new = max(1, nint(total_time/rtbse_env%sim_dt))
418 rtbse_env%sim_nsteps = n_steps_new
419 sim_dt_as = rtbse_env%sim_dt*
seconds*1e18_dp
420 WRITE (hint_msg,
'(A,F16.4,A,I0,A)') &
421 'ENFORCE_MAX_DT on restart: inheriting original TIMESTEP ', sim_dt_as, &
422 ' as and setting STEPS to ', n_steps_new,
'.'
423 CALL cp_hint(__location__, trim(hint_msg))
426 IF (rtbse_env%sim_dt > rtbse_env%maximum_timestep/grace_factor)
THEN
427 CALL cp_warn(__location__, &
428 "ENFORCE_MAX_DT restart: inherited dt exceeds this run's stability "// &
429 "limit - the recomputed Hamiltonian may make the propagation unstable.")
432 n_steps_new = max(1, ceiling(total_time/(rtbse_env%maximum_timestep/grace_factor)))
433 rtbse_env%sim_dt = total_time/real(n_steps_new,
dp)
434 rtbse_env%sim_nsteps = n_steps_new
435 sim_dt_as = rtbse_env%sim_dt*
seconds*1e18_dp
436 WRITE (hint_msg,
'(A,F16.4,A,I0,A)') &
437 'ENFORCE_MAX_DT enabled. Resetting TIMESTEP to ', sim_dt_as, &
438 ' as and STEPS to ', n_steps_new,
'.'
439 CALL cp_hint(__location__, trim(hint_msg))
443 IF (rtbse_env%sim_nsteps /= n_steps_old)
THEN
444 CALL reallocate_ft_traces(rtbse_env)
447 CALL timestop(handle)
448 END SUBROUTINE initialize_maximum_timestep
454 SUBROUTINE reallocate_ft_traces(rtbse_env)
457 CHARACTER(len=*),
PARAMETER :: routinen =
'reallocate_ft_traces'
461 CALL timeset(routinen, handle)
463 IF (
ASSOCIATED(rtbse_env%moments_trace))
DEALLOCATE (rtbse_env%moments_trace)
464 IF (
ASSOCIATED(rtbse_env%field_trace))
DEALLOCATE (rtbse_env%field_trace)
465 IF (
ASSOCIATED(rtbse_env%time_trace))
DEALLOCATE (rtbse_env%time_trace)
467 ALLOCATE (rtbse_env%moments_trace(rtbse_env%n_spin, 3, rtbse_env%sim_nsteps + 1), &
468 source=cmplx(0.0_dp, 0.0_dp, kind=
dp))
469 ALLOCATE (rtbse_env%field_trace(3, rtbse_env%sim_nsteps + 1), &
470 source=cmplx(0.0_dp, 0.0_dp, kind=
dp))
471 ALLOCATE (rtbse_env%time_trace(rtbse_env%sim_nsteps + 1), source=0.0_dp)
473 CALL timestop(handle)
474 END SUBROUTINE reallocate_ft_traces
481 SUBROUTINE print_linrtbse_header_info(rtbse_env)
484 INTEGER :: ispin, n_steps
485 REAL(kind=
dp) :: e_first, e_last, fft_resolution, &
486 nyquist_frequency, total_time
490 n_steps = max(0, rtbse_env%sim_nsteps)
491 total_time = real(n_steps,
dp)*rtbse_env%sim_dt
492 fft_resolution = 0.0_dp
493 nyquist_frequency = 0.0_dp
494 IF (total_time > 0.0_dp) fft_resolution =
twopi/total_time
495 IF (rtbse_env%sim_dt > 0.0_dp) nyquist_frequency =
twopi/(2.0_dp*rtbse_env%sim_dt)
497 IF (rtbse_env%unit_nr > 0)
THEN
498 WRITE (rtbse_env%unit_nr, *)
''
499 WRITE (rtbse_env%unit_nr,
'(A)')
' /-----------------------------------------------'// &
500 '------------------------------\'
501 WRITE (rtbse_env%unit_nr,
'(A)')
' | '// &
503 WRITE (rtbse_env%unit_nr,
'(A)')
' | Linearized Real Time Bethe-Salpeter Propagation'// &
505 WRITE (rtbse_env%unit_nr,
'(A)')
' | '// &
507 WRITE (rtbse_env%unit_nr,
'(A)')
' \-----------------------------------------------'// &
508 '------------------------------/'
509 WRITE (rtbse_env%unit_nr, *)
''
511 WRITE (rtbse_env%unit_nr,
'(A18,L62)')
' Apply delta pulse', &
512 rtbse_env%dft_control%rtp_control%apply_delta_pulse
513 WRITE (rtbse_env%unit_nr,
'(A)')
''
514 WRITE (rtbse_env%unit_nr,
'(A18,L62)')
' Use Tamm-Dancoff approximation', &
516 IF (rtbse_env%tda_active)
THEN
517 WRITE (rtbse_env%unit_nr,
'(A,T71,L10)')
' TDA first-peak shift active', &
518 rtbse_env%tda_shift_to_first_peak
519 IF (rtbse_env%tda_shift_to_first_peak)
THEN
520 WRITE (rtbse_env%unit_nr,
'(A,T65,F16.6)')
' TDA first-peak shift Omega_0 [eV]:', &
521 rtbse_env%omega_shift*
evolt
525 WRITE (rtbse_env%unit_nr,
'(A)')
''
527 WRITE (rtbse_env%unit_nr,
'(A,T65,F16.4)')
' Estimated maximum timestep within stability region [as]:', &
528 rtbse_env%maximum_timestep*
seconds*1e18_dp
529 WRITE (rtbse_env%unit_nr,
'(A,T65,F16.4)')
' Applied timestep [as]:', &
530 rtbse_env%sim_dt*
seconds*1e18_dp
531 WRITE (rtbse_env%unit_nr,
'(A,T71,I10)')
' Number of propagation steps:', n_steps
532 WRITE (rtbse_env%unit_nr,
'(A,T65,F16.4)')
' Total propagation time [as]:', &
534 WRITE (rtbse_env%unit_nr,
'(A,T65,F16.6)')
' Estimated FFT frequency resolution without interpolation [eV]:', &
536 WRITE (rtbse_env%unit_nr,
'(A,T65,F16.6)')
' Nyquist frequency [eV]:', &
537 nyquist_frequency*
evolt
538 WRITE (rtbse_env%unit_nr,
'(A,T65,F16.6)')
' Estimated maximum oscillation frequency (gap-based) [eV]:', &
539 rtbse_env%omega_max*
evolt
543 WRITE (rtbse_env%unit_nr,
'(A,T75,A6)')
' Active-window single-particle spectrum source:',
' G0W0'
545 WRITE (rtbse_env%unit_nr,
'(A,T75,A6)')
' Active-window single-particle spectrum source:',
' KS'
547 IF (rtbse_env%rtbse_energy_cutoff_occ > 0.0_dp)
THEN
548 WRITE (rtbse_env%unit_nr,
'(A,T71,F10.3)')
' Active-window occupied energy cutoff [eV]:', &
549 rtbse_env%rtbse_energy_cutoff_occ*
evolt
551 WRITE (rtbse_env%unit_nr,
'(A,T71,A10)')
' Active-window occupied energy cutoff [eV]:',
' disabled'
553 IF (rtbse_env%rtbse_energy_cutoff_empty > 0.0_dp)
THEN
554 WRITE (rtbse_env%unit_nr,
'(A,T71,F10.3)')
' Active-window virtual energy cutoff [eV]:', &
555 rtbse_env%rtbse_energy_cutoff_empty*
evolt
557 WRITE (rtbse_env%unit_nr,
'(A,T71,A10)')
' Active-window virtual energy cutoff [eV]:',
' disabled'
559 WRITE (rtbse_env%unit_nr,
'(A,T71,I10)')
' First active occupied MO index:', rtbse_env%first_active_mo
560 WRITE (rtbse_env%unit_nr,
'(A,T71,I10)')
' Last active virtual MO index:', rtbse_env%last_active_mo
561 WRITE (rtbse_env%unit_nr,
'(A,T71,I10)')
' Number of active MOs:', rtbse_env%mo_active
562 IF (rtbse_env%active_mo_truncation)
THEN
565 DO ispin = 1, rtbse_env%n_spin
566 e_first = (rtbse_env%bs_env%eigenval_scf_Gamma(rtbse_env%first_active_mo, ispin) - &
567 rtbse_env%bs_env%eigenval_scf_Gamma(rtbse_env%n_occ(ispin), ispin))*
evolt
568 e_last = (rtbse_env%bs_env%eigenval_scf_Gamma(rtbse_env%last_active_mo, ispin) - &
569 rtbse_env%bs_env%eigenval_scf_Gamma(rtbse_env%n_occ(ispin) + 1, ispin))*
evolt
570 WRITE (rtbse_env%unit_nr,
'(A,I1,A,T71,F10.3)')
' Spin ', ispin, &
571 ' first active MO, E - E_HOMO (KS) [eV]:', e_first
572 WRITE (rtbse_env%unit_nr,
'(A,I1,A,T71,F10.3)')
' Spin ', ispin, &
573 ' last active MO, E - E_LUMO (KS) [eV]:', e_last
575 e_first = (rtbse_env%bs_env%eigenval_G0W0(rtbse_env%first_active_mo, 1, ispin) - &
576 rtbse_env%bs_env%eigenval_G0W0(rtbse_env%n_occ(ispin), 1, ispin))*
evolt
577 e_last = (rtbse_env%bs_env%eigenval_G0W0(rtbse_env%last_active_mo, 1, ispin) - &
578 rtbse_env%bs_env%eigenval_G0W0(rtbse_env%n_occ(ispin) + 1, 1, ispin))*
evolt
579 WRITE (rtbse_env%unit_nr,
'(A,I1,A,T71,F10.3)')
' Spin ', ispin, &
580 ' first active MO, E - E_HOMO (QP) [eV]:', e_first
581 WRITE (rtbse_env%unit_nr,
'(A,I1,A,T71,F10.3)')
' Spin ', ispin, &
582 ' last active MO, E - E_LUMO (QP) [eV]:', e_last
588 END SUBROUTINE print_linrtbse_header_info
596 SUBROUTINE populate_c_active(rtbse_env)
599 CHARACTER(len=*),
PARAMETER :: routinen =
'populate_C_active'
603 CALL timeset(routinen, handle)
605 DO i = 1, rtbse_env%n_spin
608 rtbse_env%bs_env%fm_mo_coeff_Gamma(i), rtbse_env%C_active(i), &
609 rtbse_env%n_ao, rtbse_env%mo_active, &
610 1, rtbse_env%first_active_mo, &
612 rtbse_env%bs_env%fm_mo_coeff_Gamma(i)%matrix_struct%context)
615 CALL timestop(handle)
616 END SUBROUTINE populate_c_active
625 SUBROUTINE initialize_moments(rtbse_env)
628 CHARACTER(len=*),
PARAMETER :: routinen =
'initialize_moments'
630 INTEGER :: handle, i_spin, k
631 REAL(kind=
dp),
DIMENSION(3) :: rpoint
633 TYPE(
dbcsr_p_type),
DIMENSION(:),
POINTER :: matrix_s, moments_dbcsr_p
636 CALL timeset(routinen, handle)
638 CALL get_qs_env(rtbse_env%qs_env, bs_env=bs_env, matrix_s=matrix_s)
641 CALL cp_fm_create(tmp_ao, bs_env%fm_s_Gamma%matrix_struct)
645 NULLIFY (moments_dbcsr_p)
646 ALLOCATE (moments_dbcsr_p(3))
649 NULLIFY (moments_dbcsr_p(k)%matrix)
651 ALLOCATE (moments_dbcsr_p(k)%matrix)
653 CALL dbcsr_copy(moments_dbcsr_p(k)%matrix, matrix_s(1)%matrix)
659 reference=rtbse_env%moment_ref_type, ref_point=rtbse_env%user_moment_ref_point)
664 DO i_spin = 1, rtbse_env%n_spin
665 CALL transform_ao_to_mo_covariant_fm(rtbse_env, tmp_ao, rtbse_env%moments(k, i_spin), i_spin)
675 DO i_spin = 1, rtbse_env%n_spin
676 CALL transform_ao_to_mo_covariant_fm(rtbse_env, tmp_ao, rtbse_env%moments_field(k, i_spin), i_spin)
683 DEALLOCATE (moments_dbcsr_p(k)%matrix)
685 DEALLOCATE (moments_dbcsr_p)
689 CALL timestop(handle)
690 END SUBROUTINE initialize_moments
699 SUBROUTINE initialize_density_matrix(rtbse_env)
702 CHARACTER(len=*),
PARAMETER :: routinen =
'initialize_density_matrix'
704 INTEGER :: handle, i, i_row_global, ii, &
705 j_col_global, jj, ncol_global, &
706 ncol_local, nrow_global, nrow_local
707 INTEGER,
DIMENSION(:),
POINTER :: col_indices, row_indices
709 CALL timeset(routinen, handle)
713 nrow_global=nrow_global, ncol_global=ncol_global, &
714 nrow_local=nrow_local, ncol_local=ncol_local, &
715 row_indices=row_indices, col_indices=col_indices)
718 DO i = 1, rtbse_env%n_spin
721 DO ii = 1, nrow_local
722 i_row_global = row_indices(ii)
723 DO jj = 1, ncol_local
724 j_col_global = col_indices(jj)
725 IF (i_row_global == j_col_global .AND. &
726 (i_row_global + rtbse_env%first_active_mo - 1) <= rtbse_env%n_occ(i))
THEN
727 rtbse_env%real_workspace_mo(1)%local_data(ii, jj) = 1.0_dp
732 CALL cp_fm_to_cfm(msourcer=rtbse_env%real_workspace_mo(1), mtarget=rtbse_env%rho(i))
739 CALL timestop(handle)
740 END SUBROUTINE initialize_density_matrix
752 CHARACTER(len=*),
PARAMETER :: routinen =
'initialize_singleparticle_hamiltonian'
754 INTEGER :: abs_mo_idx, handle, i, i_row_global, ii, &
755 j_col_global, jj, ncol_global, &
756 ncol_local, nrow_global, nrow_local
757 INTEGER,
DIMENSION(:),
POINTER :: col_indices, row_indices
760 CALL timeset(routinen, handle)
762 CALL get_qs_env(rtbse_env%qs_env, bs_env=bs_env)
766 nrow_global=nrow_global, ncol_global=ncol_global, &
767 nrow_local=nrow_local, ncol_local=ncol_local, &
768 row_indices=row_indices, col_indices=col_indices)
772 rtbse_env%eps_active(:, :) = 0.0_dp
774 DO i = 1, rtbse_env%n_spin
775 DO ii = 1, nrow_local
776 i_row_global = row_indices(ii)
777 DO jj = 1, ncol_local
778 j_col_global = col_indices(jj)
779 IF (i_row_global == j_col_global)
THEN
780 abs_mo_idx = i_row_global + rtbse_env%first_active_mo - 1
783 rtbse_env%real_workspace_mo(1)%local_data(ii, jj) = bs_env%eigenval_G0W0(abs_mo_idx, 1, i)
786 rtbse_env%real_workspace_mo(1)%local_data(ii, jj) = bs_env%eigenval_scf_Gamma(abs_mo_idx, i)
793 IF (rtbse_env%tda_active .AND. rtbse_env%tda_shift_to_first_peak)
THEN
794 IF (abs_mo_idx <= rtbse_env%n_occ(i))
THEN
795 rtbse_env%real_workspace_mo(1)%local_data(ii, jj) = &
796 rtbse_env%real_workspace_mo(1)%local_data(ii, jj) + 0.5_dp*rtbse_env%omega_shift
798 rtbse_env%real_workspace_mo(1)%local_data(ii, jj) = &
799 rtbse_env%real_workspace_mo(1)%local_data(ii, jj) - 0.5_dp*rtbse_env%omega_shift
803 rtbse_env%eps_active(i_row_global, i) = rtbse_env%real_workspace_mo(1)%local_data(ii, jj)
807 CALL cp_fm_to_cfm(msourcer=rtbse_env%real_workspace_mo(1), mtarget=rtbse_env%ham_reference_singleparticle(i))
810 CALL rtbse_env%real_workspace_mo(1)%matrix_struct%para_env%sum(rtbse_env%eps_active)
813 CALL timestop(handle)
827 CHARACTER(len=*),
PARAMETER :: routinen =
'initialize_hartree_potential'
829 INTEGER :: handle, i, n_grid
830 LOGICAL :: use_hartree_reference, use_rirs_kernel
833 CALL timeset(routinen, handle)
835 CALL get_qs_env(rtbse_env%qs_env, bs_env=bs_env)
836 use_hartree_reference = (.NOT. rtbse_env%tda_active) .AND. (rtbse_env%n_spin == 1) .AND. &
837 (.NOT. rtbse_env%debug_disable_hartree)
838 use_rirs_kernel = rtbse_env%rirs_kernel
847 IF (use_rirs_kernel .AND. (.NOT. rtbse_env%debug_disable_hartree))
THEN
848 CALL dbcsr_get_info(bs_env%ri_rs%mat_phi_mu_l, nfullrows_total=n_grid)
849 ALLOCATE (rtbse_env%hartree_diag_re(n_grid), rtbse_env%hartree_diag_im(n_grid))
856 IF (use_rirs_kernel .AND. (.NOT. rtbse_env%debug_disable_hartree) .AND. rtbse_env%debug_disable_sex)
THEN
857 CALL cp_warn(__location__, &
858 "RI-RS Hartree rebuilds the full density grid every RK4 stage because SEX is "// &
859 "disabled (DEBUG_DISABLE_SEX) and no SEX-harvested diagonal is available to reuse. "// &
860 "This slows down the Hartree computation considerably.")
865 IF (.NOT. use_rirs_kernel)
THEN
870 DO i = 1, rtbse_env%n_spin
871 CALL cp_cfm_set_all(rtbse_env%ham_reference(i), cmplx(0.0_dp, 0.0_dp, kind=
dp))
878 IF (use_hartree_reference)
THEN
879 DO i = 1, rtbse_env%n_spin
880 IF (use_rirs_kernel)
THEN
883 CALL cp_cfm_to_fm(msource=rtbse_env%rho_ao_scratch(i), &
884 mtargetr=rtbse_env%real_workspace(1))
886 rtbse_env%hartree_curr_ao(i))
889 CALL get_hartree(rtbse_env, rtbse_env%rho_ao_scratch(i), rtbse_env%hartree_curr_ao(i))
892 CALL cp_fm_scale(rtbse_env%spin_degeneracy, rtbse_env%hartree_curr_ao(i))
894 CALL transform_ao_to_mo_covariant_fm(rtbse_env, rtbse_env%hartree_curr_ao(i), rtbse_env%hartree_curr(i), i)
896 CALL transform_mo_occupation_factor_diff_fm(rtbse_env, rtbse_env%hartree_curr(i), i)
899 CALL cp_fm_to_cfm(msourcer=rtbse_env%hartree_curr(i), mtarget=rtbse_env%ham_workspace(1))
901 cmplx(-1.0, 0.0, kind=
dp), rtbse_env%ham_workspace(1))
906 CALL timestop(handle)
916 SUBROUTINE initialize_sex_selfenergy(rtbse_env)
919 CHARACTER(len=*),
PARAMETER :: routinen =
'initialize_sex_selfenergy'
922 LOGICAL :: use_rirs_kernel, use_sex_reference
924 CALL timeset(routinen, handle)
925 use_sex_reference = (.NOT. rtbse_env%tda_active) .AND. (rtbse_env%n_spin == 1) .AND. &
926 (.NOT. rtbse_env%debug_disable_sex)
927 use_rirs_kernel = rtbse_env%rirs_kernel
935 IF (.NOT. use_rirs_kernel)
THEN
939 IF (.NOT.
ASSOCIATED(rtbse_env%bs_env%fm_W_MIC_freq_zero%matrix_struct))
THEN
940 CALL cp_abort(__location__, &
941 "RT-BSE AO-RI kernel needs the screened interaction W(w=0), which the "// &
942 "GW step did not build. Select the RT-BSE propagator with '&RTBSE' or "// &
943 "'&RTBSE RTBSE', not '&RTBSE TDDFT'.")
946 CALL copy_fm_to_dbcsr(rtbse_env%bs_env%fm_W_MIC_freq_zero, rtbse_env%w_dbcsr)
949 CALL dbcsr_set(rtbse_env%w_dbcsr, 0.0_dp)
952 CALL dbcsr_add(rtbse_env%w_dbcsr, rtbse_env%v_dbcsr, 1.0_dp, 1.0_dp)
953 CALL dbt_copy_matrix_to_tensor(rtbse_env%w_dbcsr, rtbse_env%screened_dbt)
956 DO i = 1, rtbse_env%n_spin
963 IF (use_sex_reference)
THEN
965 CALL get_sigma(rtbse_env, rtbse_env%sigma_SEX_ao(i), -1.0_dp, rtbse_env%rho_ao_scratch(i))
967 CALL transform_ao_to_mo_covariant_cfm(rtbse_env, rtbse_env%sigma_SEX_ao(i), rtbse_env%sigma_SEX(i), i)
969 CALL transform_mo_occupation_factor_diff_cfm(rtbse_env, rtbse_env%sigma_SEX(i), i)
972 cmplx(-1.0, 0.0, kind=
dp), rtbse_env%sigma_SEX(i))
977 CALL timestop(handle)
978 END SUBROUTINE initialize_sex_selfenergy
988 SUBROUTINE solve_rk4_timestep(rtbse_env, rho_start, rho_end)
990 TYPE(
cp_cfm_type),
DIMENSION(:),
POINTER :: rho_start, rho_end
992 CHARACTER(len=*),
PARAMETER :: routinen =
'solve_rk4_timestep'
996 CALL timeset(routinen, handle)
1013 DO i = 1, rtbse_env%n_spin
1021 CALL do_rk4_stage(rtbse_env, rho_start, rho_start, rho_end, &
1022 result_weight=1.0_dp/6.0_dp, advance_weight=0.5_dp)
1024 CALL do_rk4_stage(rtbse_env, rtbse_env%rho_workspace, rho_start, rho_end, &
1025 result_weight=1.0_dp/3.0_dp, advance_weight=0.5_dp)
1027 CALL do_rk4_stage(rtbse_env, rtbse_env%rho_workspace, rho_start, rho_end, &
1028 result_weight=1.0_dp/3.0_dp, advance_weight=1.0_dp)
1030 CALL do_rk4_stage(rtbse_env, rtbse_env%rho_workspace, rho_start, rho_end, &
1031 result_weight=1.0_dp/6.0_dp)
1034 rtbse_env%sim_step = rtbse_env%sim_step + 1
1035 rtbse_env%sim_time = rtbse_env%sim_time + rtbse_env%sim_dt
1037 CALL timestop(handle)
1038 END SUBROUTINE solve_rk4_timestep
1057 SUBROUTINE do_rk4_stage(rtbse_env, rho_eval, rho_base, rho_end, result_weight, advance_weight)
1059 TYPE(
cp_cfm_type),
DIMENSION(:),
POINTER :: rho_eval, rho_base, rho_end
1060 REAL(kind=
dp),
INTENT(IN) :: result_weight
1061 REAL(kind=
dp),
INTENT(IN),
OPTIONAL :: advance_weight
1063 INTEGER :: i, mask_mode
1066 IF (rtbse_env%tda_active)
THEN
1067 mask_mode = kernel_input_ov
1068 ELSE IF (rtbse_env%n_spin > 1)
THEN
1069 mask_mode = kernel_input_ovvo
1071 mask_mode = kernel_input_full
1074 CALL build_shared_sex_and_hartree(rtbse_env, rho_eval, mask_mode)
1075 DO i = 1, rtbse_env%n_spin
1076 CALL update_effective_ham_mo(rtbse_env, rho_eval(i), rtbse_env%rk4_coefficients(i), i)
1077 IF (rtbse_env%tda_active .OR. rtbse_env%n_spin > 1)
THEN
1078 CALL project_drho_to_ov(rtbse_env, rtbse_env%rk4_coefficients(i), i)
1083 DO i = 1, rtbse_env%n_spin
1085 cmplx(result_weight*rtbse_env%sim_dt, 0.0_dp, kind=
dp), rtbse_env%rk4_coefficients(i))
1086 IF (
PRESENT(advance_weight))
THEN
1089 cmplx(advance_weight*rtbse_env%sim_dt, 0.0_dp, kind=
dp), rtbse_env%rk4_coefficients(i))
1092 END SUBROUTINE do_rk4_stage
1106 SUBROUTINE build_shared_hartree_ao(rtbse_env, rho_stage, keep_ovvo)
1108 TYPE(
cp_cfm_type),
DIMENSION(:),
POINTER :: rho_stage
1109 LOGICAL,
INTENT(IN) :: keep_ovvo
1111 CHARACTER(len=*),
PARAMETER :: routinen =
'build_shared_hartree_ao'
1113 INTEGER :: handle, isp
1115 CALL timeset(routinen, handle)
1117 DO isp = 1, rtbse_env%n_spin
1118 CALL cp_cfm_to_cfm(rho_stage(isp), rtbse_env%rho_delta_mo(isp))
1119 CALL mask_mo_block_cfm(rtbse_env, rtbse_env%rho_delta_mo(isp), isp, &
1120 keep_ov=.true., keep_ovvo=keep_ovvo)
1121 CALL transform_mo_to_ao_contravariant_cfm(rtbse_env, rtbse_env%rho_delta_mo(isp), &
1122 rtbse_env%rho_ao_scratch(isp), isp)
1125 CALL cp_cfm_set_all(rtbse_env%rho_total_ao_scratch, cmplx(0.0_dp, 0.0_dp, kind=
dp))
1126 DO isp = 1, rtbse_env%n_spin
1128 cmplx(rtbse_env%spin_degeneracy, 0.0_dp, kind=
dp), &
1129 rtbse_env%rho_ao_scratch(isp))
1134 IF (rtbse_env%rirs_kernel)
THEN
1137 rtbse_env%hartree_total_ao)
1140 CALL get_hartree_complex(rtbse_env, rtbse_env%rho_total_ao_scratch, &
1141 rtbse_env%hartree_total_ao, 1)
1143 CALL timestop(handle)
1144 END SUBROUTINE build_shared_hartree_ao
1159 SUBROUTINE build_shared_sex_and_hartree(rtbse_env, rho_stage, mask_mode)
1161 TYPE(
cp_cfm_type),
DIMENSION(:),
POINTER :: rho_stage
1162 INTEGER,
INTENT(IN) :: mask_mode
1164 CHARACTER(len=*),
PARAMETER :: routinen =
'build_shared_sex_and_hartree'
1166 INTEGER :: handle, isp
1167 LOGICAL :: harvest_im, use_hartree, &
1168 use_rirs_kernel, use_sex
1170 CALL timeset(routinen, handle)
1171 use_hartree = .NOT. rtbse_env%debug_disable_hartree
1172 use_sex = .NOT. rtbse_env%debug_disable_sex
1173 use_rirs_kernel = rtbse_env%rirs_kernel
1176 harvest_im = (mask_mode == kernel_input_ov)
1179 IF (use_rirs_kernel .AND. use_sex .AND. use_hartree)
THEN
1180 rtbse_env%hartree_diag_re(:) = 0.0_dp
1181 IF (harvest_im) rtbse_env%hartree_diag_im(:) = 0.0_dp
1185 DO isp = 1, rtbse_env%n_spin
1186 CALL cp_cfm_to_cfm(rho_stage(isp), rtbse_env%rho_delta_mo(isp))
1187 SELECT CASE (mask_mode)
1188 CASE (kernel_input_ov)
1189 CALL mask_mo_block_cfm(rtbse_env, rtbse_env%rho_delta_mo(isp), isp, &
1190 keep_ov=.true., keep_ovvo=.false.)
1191 CASE (kernel_input_ovvo)
1192 CALL mask_mo_block_cfm(rtbse_env, rtbse_env%rho_delta_mo(isp), isp, &
1193 keep_ov=.true., keep_ovvo=.true.)
1194 CASE (kernel_input_full)
1197 cpabort(
"Unknown mask_mode in build_shared_sex_and_hartree")
1199 CALL transform_mo_to_ao_contravariant_cfm(rtbse_env, rtbse_env%rho_delta_mo(isp), &
1200 rtbse_env%rho_ao_scratch(isp), isp)
1204 IF (harvest_im)
THEN
1205 CALL get_sigma(rtbse_env, rtbse_env%sigma_SEX_ao(isp), -1.0_dp, rtbse_env%rho_ao_scratch(isp), &
1206 grid_diag_re_accum=rtbse_env%hartree_diag_re, &
1207 grid_diag_im_accum=rtbse_env%hartree_diag_im)
1209 CALL get_sigma(rtbse_env, rtbse_env%sigma_SEX_ao(isp), -1.0_dp, rtbse_env%rho_ao_scratch(isp), &
1210 grid_diag_re_accum=rtbse_env%hartree_diag_re)
1217 IF (use_hartree)
THEN
1218 IF (use_rirs_kernel .AND. use_sex)
THEN
1219 IF (harvest_im)
THEN
1221 rtbse_env%hartree_total_ao, n_im=rtbse_env%hartree_diag_im)
1224 rtbse_env%hartree_total_ao)
1227 CALL cp_cfm_set_all(rtbse_env%rho_total_ao_scratch, cmplx(0.0_dp, 0.0_dp, kind=
dp))
1228 DO isp = 1, rtbse_env%n_spin
1230 cmplx(1.0_dp, 0.0_dp, kind=
dp), rtbse_env%rho_ao_scratch(isp))
1232 IF (use_rirs_kernel)
THEN
1233 IF (harvest_im)
THEN
1235 rtbse_env%hartree_total_ao)
1238 CALL cp_cfm_to_fm(msource=rtbse_env%rho_total_ao_scratch, &
1239 mtargetr=rtbse_env%real_workspace(1))
1241 rtbse_env%hartree_curr_ao(1))
1242 CALL cp_cfm_set_all(rtbse_env%hartree_total_ao, cmplx(0.0_dp, 0.0_dp, kind=
dp))
1243 CALL cp_fm_to_cfm(msourcer=rtbse_env%hartree_curr_ao(1), &
1244 mtarget=rtbse_env%hartree_total_ao)
1247 IF (harvest_im)
THEN
1248 CALL get_hartree_complex(rtbse_env, rtbse_env%rho_total_ao_scratch, &
1249 rtbse_env%hartree_total_ao, 1)
1252 CALL get_hartree(rtbse_env, rtbse_env%rho_total_ao_scratch, &
1253 rtbse_env%hartree_curr_ao(1))
1254 CALL cp_cfm_set_all(rtbse_env%hartree_total_ao, cmplx(0.0_dp, 0.0_dp, kind=
dp))
1255 CALL cp_fm_to_cfm(msourcer=rtbse_env%hartree_curr_ao(1), &
1256 mtarget=rtbse_env%hartree_total_ao)
1261 CALL timestop(handle)
1262 END SUBROUTINE build_shared_sex_and_hartree
1277 SUBROUTINE update_effective_ham_mo(rtbse_env, rho, ham_effective, ispin)
1282 CHARACTER(len=*),
PARAMETER :: routinen =
'update_effective_ham_MO'
1284 INTEGER :: handle, i_global, i_loc, j_global, &
1286 INTEGER,
DIMENSION(:),
POINTER :: c_idx, r_idx
1287 LOGICAL :: use_hartree, use_sex
1289 CALL timeset(routinen, handle)
1290 use_hartree = .NOT. rtbse_env%debug_disable_hartree
1291 use_sex = .NOT. rtbse_env%debug_disable_sex
1295 CALL cp_cfm_to_cfm(rtbse_env%ham_reference(ispin), ham_effective)
1299 CALL cp_cfm_get_info(matrix=ham_effective, nrow_local=nrl, ncol_local=ncl, &
1300 row_indices=r_idx, col_indices=c_idx)
1302 j_global = c_idx(j_loc)
1304 i_global = r_idx(i_loc)
1305 ham_effective%local_data(i_loc, j_loc) = ham_effective%local_data(i_loc, j_loc) &
1306 + cmplx(rtbse_env%eps_active(i_global, ispin) - rtbse_env%eps_active(j_global, ispin), &
1307 0.0_dp, kind=
dp)*rho%local_data(i_loc, j_loc)
1311 IF (rtbse_env%dft_control%apply_efield_field)
THEN
1312 CALL cp_abort(__location__, &
1313 "Continuous/pulsed E(t) field coupling is not implemented for linearized "// &
1314 "RT-BSE. Only the delta-kick (impulsive) absorption spectrum is supported; "// &
1315 "use APPLY_DELTA_PULSE.")
1318 rtbse_env%field(:) = 0.0_dp
1320 IF (.NOT. rtbse_env%tda_active)
THEN
1326 CALL transform_ao_to_mo_covariant_cfm(rtbse_env, rtbse_env%sigma_SEX_ao(ispin), &
1327 rtbse_env%sigma_SEX(ispin), ispin)
1328 CALL transform_mo_occupation_factor_diff_cfm(rtbse_env, rtbse_env%sigma_SEX(ispin), ispin)
1330 cmplx(1.0_dp, 0.0_dp, kind=
dp), rtbse_env%sigma_SEX(ispin))
1332 IF (use_hartree)
THEN
1334 CALL transform_ao_to_mo_covariant_cfm(rtbse_env, rtbse_env%hartree_total_ao, &
1335 rtbse_env%ham_workspace(1), ispin)
1336 CALL transform_mo_occupation_factor_diff_cfm(rtbse_env, rtbse_env%ham_workspace(1), ispin)
1337 CALL cp_cfm_scale(cmplx(rtbse_env%spin_degeneracy, 0.0_dp, kind=
dp), rtbse_env%ham_workspace(1))
1339 cmplx(1.0_dp, 0.0_dp, kind=
dp), rtbse_env%ham_workspace(1))
1349 CALL transform_ao_to_mo_covariant_cfm(rtbse_env, rtbse_env%sigma_SEX_ao(ispin), &
1350 rtbse_env%sigma_SEX(ispin), ispin)
1351 CALL mask_mo_block_cfm(rtbse_env, rtbse_env%sigma_SEX(ispin), ispin, keep_ov=.true.)
1356 IF (use_hartree)
THEN
1357 CALL transform_ao_to_mo_covariant_cfm(rtbse_env, rtbse_env%hartree_total_ao, &
1358 rtbse_env%ham_workspace(1), ispin)
1359 CALL mask_mo_block_cfm(rtbse_env, rtbse_env%ham_workspace(1), ispin, keep_ov=.true.)
1360 CALL cp_cfm_scale(cmplx(rtbse_env%spin_degeneracy, 0.0_dp, kind=
dp), rtbse_env%ham_workspace(1))
1362 cmplx(-1.0_dp, 0.0_dp, kind=
dp), rtbse_env%ham_workspace(1))
1363 CALL cp_cfm_transpose(rtbse_env%ham_workspace(1),
'C', rtbse_env%rho_delta_mo(ispin))
1365 cmplx(1.0_dp, 0.0_dp, kind=
dp), rtbse_env%rho_delta_mo(ispin))
1371 cmplx(-1.0_dp, 0.0_dp, kind=
dp), rtbse_env%sigma_SEX(ispin))
1372 CALL cp_cfm_transpose(rtbse_env%sigma_SEX(ispin),
'C', rtbse_env%rho_delta_mo(ispin))
1374 cmplx(1.0_dp, 0.0_dp, kind=
dp), rtbse_env%rho_delta_mo(ispin))
1379 CALL transform_mo_to_ao_contravariant_cfm(rtbse_env, rho, rtbse_env%rho_ao_scratch(ispin), ispin)
1382 CALL cp_cfm_scale(cmplx(0.0_dp, -1.0_dp, kind=
dp), ham_effective)
1384 CALL timestop(handle)
1385 END SUBROUTINE update_effective_ham_mo
1409 SUBROUTINE apply_liouvillian_to_drho_spin(rtbse_env, drho_in, L_drho_out, ispin)
1413 INTEGER,
INTENT(IN) :: ispin
1415 CHARACTER(len=*),
PARAMETER :: routinen =
'apply_liouvillian_to_drho_spin'
1417 INTEGER :: abs_mo_idx, handle, i_row_global, ii, &
1418 j_col_global, jj, ncol_local, &
1420 INTEGER,
DIMENSION(:),
POINTER :: col_indices, row_indices
1421 LOGICAL :: use_hartree, use_sex
1423 CALL timeset(routinen, handle)
1427 use_hartree = .NOT. rtbse_env%debug_disable_hartree
1428 use_sex = .NOT. rtbse_env%debug_disable_sex
1437 IF (rtbse_env%tda_active)
THEN
1438 CALL mask_mo_block_cfm(rtbse_env, rtbse_env%drho_probe(ispin), ispin, keep_ov=.true.)
1442 CALL transform_mo_to_ao_contravariant_cfm(rtbse_env, rtbse_env%drho_probe(ispin), &
1443 rtbse_env%rho_ao_scratch(ispin), ispin)
1457 nrow_local=nrow_local, ncol_local=ncol_local, &
1458 row_indices=row_indices, col_indices=col_indices)
1460 DO ii = 1, nrow_local
1461 i_row_global = row_indices(ii)
1462 DO jj = 1, ncol_local
1463 j_col_global = col_indices(jj)
1464 IF (i_row_global == j_col_global)
THEN
1465 abs_mo_idx = i_row_global + rtbse_env%first_active_mo - 1
1466 rtbse_env%real_workspace_mo(1)%local_data(ii, jj) = &
1467 rtbse_env%bs_env%eigenval_G0W0(abs_mo_idx, 1, ispin)
1471 CALL cp_fm_to_cfm(msourcer=rtbse_env%real_workspace_mo(1), &
1472 mtarget=rtbse_env%ham_workspace(1))
1474 CALL cp_cfm_gemm(
'N',
'N', rtbse_env%mo_active, rtbse_env%mo_active, rtbse_env%mo_active, &
1475 cmplx(1.0_dp, 0.0_dp, kind=
dp), drho_in, rtbse_env%ham_workspace(1), &
1476 cmplx(1.0_dp, 0.0_dp, kind=
dp), l_drho_out)
1478 CALL cp_cfm_gemm(
'N',
'N', rtbse_env%mo_active, rtbse_env%mo_active, rtbse_env%mo_active, &
1479 cmplx(-1.0_dp, 0.0_dp, kind=
dp), rtbse_env%ham_workspace(1), drho_in, &
1480 cmplx(1.0_dp, 0.0_dp, kind=
dp), l_drho_out)
1488 IF (use_hartree)
THEN
1489 IF (rtbse_env%rirs_kernel)
THEN
1492 rtbse_env%hartree_total_ao)
1495 CALL get_hartree_complex(rtbse_env, rtbse_env%rho_ao_scratch(ispin), &
1496 rtbse_env%hartree_total_ao, ispin)
1498 CALL transform_ao_to_mo_covariant_cfm(rtbse_env, rtbse_env%hartree_total_ao, &
1499 rtbse_env%ham_workspace(1), ispin)
1500 CALL add_k_mo_to_l_drho(rtbse_env, rtbse_env%ham_workspace(1), l_drho_out, &
1501 cmplx(rtbse_env%spin_degeneracy, 0.0_dp, kind=
dp), ispin)
1510 CALL get_sigma(rtbse_env, rtbse_env%sigma_SEX_ao(ispin), -1.0_dp, rtbse_env%rho_ao_scratch(ispin))
1511 CALL transform_ao_to_mo_covariant_cfm(rtbse_env, rtbse_env%sigma_SEX_ao(ispin), &
1512 rtbse_env%sigma_SEX(ispin), ispin)
1513 CALL add_k_mo_to_l_drho(rtbse_env, rtbse_env%sigma_SEX(ispin), l_drho_out, &
1514 cmplx(1.0_dp, 0.0_dp, kind=
dp), ispin)
1517 CALL timestop(handle)
1518 END SUBROUTINE apply_liouvillian_to_drho_spin
1536 SUBROUTINE add_k_mo_to_l_drho(rtbse_env, K_MO, L_drho_out, scale, ispin)
1538 TYPE(
cp_cfm_type),
INTENT(INOUT) :: k_mo, l_drho_out
1539 COMPLEX(kind=dp),
INTENT(IN) :: scale
1540 INTEGER,
INTENT(IN) :: ispin
1542 CHARACTER(len=*),
PARAMETER :: routinen =
'add_K_MO_to_L_drho'
1546 CALL timeset(routinen, handle)
1548 IF (rtbse_env%tda_active)
THEN
1549 CALL mask_mo_block_cfm(rtbse_env, k_mo, ispin, keep_ov=.true.)
1552 CALL cp_cfm_scale_and_add(cmplx(1.0_dp, 0.0_dp, kind=
dp), l_drho_out, scale, rtbse_env%rho_delta_mo(ispin))
1557 CALL timestop(handle)
1558 END SUBROUTINE add_k_mo_to_l_drho
1573 SUBROUTINE apply_liouvillian_to_drho(rtbse_env, drho_in, L_drho_out)
1575 TYPE(
cp_cfm_type),
DIMENSION(:),
POINTER :: drho_in, l_drho_out
1577 CHARACTER(len=*),
PARAMETER :: routinen =
'apply_liouvillian_to_drho'
1579 INTEGER :: abs_mo_idx, handle, i_row_global, ii, &
1580 isp, isp_out, j_col_global, jj, &
1581 ncol_local, nrow_local
1582 INTEGER,
DIMENSION(:),
POINTER :: col_indices, row_indices
1583 LOGICAL :: use_hartree, use_sex
1585 CALL timeset(routinen, handle)
1587 use_hartree = .NOT. rtbse_env%debug_disable_hartree
1588 use_sex = .NOT. rtbse_env%debug_disable_sex
1591 DO isp = 1, rtbse_env%n_spin
1599 nrow_local=nrow_local, ncol_local=ncol_local, &
1600 row_indices=row_indices, col_indices=col_indices)
1601 DO isp = 1, rtbse_env%n_spin
1603 DO ii = 1, nrow_local
1604 i_row_global = row_indices(ii)
1605 DO jj = 1, ncol_local
1606 j_col_global = col_indices(jj)
1607 IF (i_row_global == j_col_global)
THEN
1608 abs_mo_idx = i_row_global + rtbse_env%first_active_mo - 1
1609 rtbse_env%real_workspace_mo(1)%local_data(ii, jj) = &
1610 rtbse_env%bs_env%eigenval_G0W0(abs_mo_idx, 1, isp)
1614 CALL cp_fm_to_cfm(msourcer=rtbse_env%real_workspace_mo(1), &
1615 mtarget=rtbse_env%ham_workspace(1))
1617 CALL cp_cfm_gemm(
'N',
'N', rtbse_env%mo_active, rtbse_env%mo_active, rtbse_env%mo_active, &
1618 cmplx(1.0_dp, 0.0_dp, kind=
dp), drho_in(isp), rtbse_env%ham_workspace(1), &
1619 cmplx(1.0_dp, 0.0_dp, kind=
dp), l_drho_out(isp))
1620 CALL cp_cfm_gemm(
'N',
'N', rtbse_env%mo_active, rtbse_env%mo_active, rtbse_env%mo_active, &
1621 cmplx(-1.0_dp, 0.0_dp, kind=
dp), rtbse_env%ham_workspace(1), drho_in(isp), &
1622 cmplx(1.0_dp, 0.0_dp, kind=
dp), l_drho_out(isp))
1628 IF (use_hartree .OR. use_sex)
THEN
1629 CALL build_shared_hartree_ao(rtbse_env, drho_in, keep_ovvo=.false.)
1635 IF (use_hartree)
THEN
1636 DO isp_out = 1, rtbse_env%n_spin
1637 CALL transform_ao_to_mo_covariant_cfm(rtbse_env, rtbse_env%hartree_total_ao, &
1638 rtbse_env%ham_workspace(1), isp_out)
1639 CALL add_k_mo_to_l_drho(rtbse_env, rtbse_env%ham_workspace(1), l_drho_out(isp_out), &
1640 cmplx(1.0_dp, 0.0_dp, kind=
dp), isp_out)
1647 DO isp = 1, rtbse_env%n_spin
1649 CALL get_sigma(rtbse_env, rtbse_env%sigma_SEX_ao(isp), -1.0_dp, rtbse_env%rho_ao_scratch(isp))
1650 CALL transform_ao_to_mo_covariant_cfm(rtbse_env, rtbse_env%sigma_SEX_ao(isp), &
1651 rtbse_env%sigma_SEX(isp), isp)
1652 CALL add_k_mo_to_l_drho(rtbse_env, rtbse_env%sigma_SEX(isp), l_drho_out(isp), &
1653 cmplx(1.0_dp, 0.0_dp, kind=
dp), isp)
1657 CALL timestop(handle)
1658 END SUBROUTINE apply_liouvillian_to_drho
1669 SUBROUTINE diagnose_liouvillian_eigenvalues(rtbse_env)
1672 CHARACTER(len=*),
PARAMETER :: routinen =
'diagnose_liouvillian_eigenvalues'
1676 CALL timeset(routinen, handle)
1678 IF (rtbse_env%tda_active)
THEN
1679 CALL diagnose_tda_liouvillian(rtbse_env)
1681 CALL diagnose_abba_liouvillian(rtbse_env)
1684 CALL timestop(handle)
1685 END SUBROUTINE diagnose_liouvillian_eigenvalues
1701 SUBROUTINE diagnose_tda_liouvillian(rtbse_env)
1704 CHARACTER(len=*),
PARAMETER :: routinen =
'diagnose_TDA_liouvillian'
1706 COMPLEX(kind=dp),
ALLOCATABLE,
DIMENSION(:, :) :: ov_block
1707 INTEGER :: b, eig_unit, handle, j, k_col, k_local, &
1708 n, n_ov_joint, sigma_out, sigma_probe
1709 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: n_act_occ, n_act_virt, n_ov, off
1710 REAL(kind=
dp) :: residual_max
1713 CALL timeset(routinen, handle)
1718 ALLOCATE (n_act_occ(rtbse_env%n_spin), n_act_virt(rtbse_env%n_spin), &
1719 n_ov(rtbse_env%n_spin), off(rtbse_env%n_spin))
1721 DO sigma_probe = 1, rtbse_env%n_spin
1722 n_act_occ(sigma_probe) = rtbse_env%n_occ(sigma_probe) - rtbse_env%first_active_mo + 1
1723 n_act_virt(sigma_probe) = rtbse_env%last_active_mo - rtbse_env%n_occ(sigma_probe)
1724 n_ov(sigma_probe) = n_act_occ(sigma_probe)*n_act_virt(sigma_probe)
1725 off(sigma_probe) = n_ov_joint
1726 n_ov_joint = n_ov_joint + n_ov(sigma_probe)
1729 IF (rtbse_env%unit_nr > 0)
THEN
1730 WRITE (rtbse_env%unit_nr,
'(A)')
' RTBSE| ----- TDA Liouvillian diagnostic -----'
1731 WRITE (rtbse_env%unit_nr,
'(A,I0,A,I0)') &
1732 ' RTBSE| n_spin = ', rtbse_env%n_spin,
', joint N_OV = ', n_ov_joint
1733 WRITE (rtbse_env%unit_nr,
'(A)')
' RTBSE|'
1740 file_form=
"FORMATTED", &
1741 file_position=
"REWIND", &
1742 ignore_should_output=.true.)
1743 IF (eig_unit > 0)
THEN
1744 WRITE (eig_unit,
'(A)')
'# Joint spin-block TDA Liouvillian eigenvalues'
1745 IF (rtbse_env%n_spin == 1)
THEN
1746 WRITE (eig_unit,
'(A,I0,A,I0)')
'# n_spin = ', rtbse_env%n_spin,
', N_OV = ', n_ov(1)
1748 WRITE (eig_unit,
'(A,I0,A,I0,A,I0)')
'# n_spin = ', rtbse_env%n_spin, &
1749 ', N_OV(1) = ', n_ov(1),
', N_OV(2) = ', n_ov(2)
1759 DO sigma_probe = 1, rtbse_env%n_spin
1760 DO b = rtbse_env%n_occ(sigma_probe) + 1, rtbse_env%last_active_mo
1761 DO j = rtbse_env%first_active_mo, rtbse_env%n_occ(sigma_probe)
1762 k_local = (b - rtbse_env%n_occ(sigma_probe) - 1)*n_act_occ(sigma_probe) + &
1763 (j - rtbse_env%first_active_mo + 1)
1764 k_col = off(sigma_probe) + k_local
1766 DO sigma_out = 1, rtbse_env%n_spin
1767 CALL cp_cfm_set_all(rtbse_env%drho_probe(sigma_out), cmplx(0.0_dp, 0.0_dp, kind=
dp))
1770 j - rtbse_env%first_active_mo + 1, &
1771 b - rtbse_env%first_active_mo + 1, &
1772 cmplx(1.0_dp, 0.0_dp, kind=
dp))
1776 IF (rtbse_env%n_spin == 1)
THEN
1777 CALL apply_liouvillian_to_drho_spin(rtbse_env, rtbse_env%drho_probe(1), &
1778 rtbse_env%L_drho(1), 1)
1780 CALL apply_liouvillian_to_drho(rtbse_env, rtbse_env%drho_probe, rtbse_env%L_drho)
1784 DO sigma_out = 1, rtbse_env%n_spin
1785 ALLOCATE (ov_block(n_act_occ(sigma_out), n_act_virt(sigma_out)))
1787 start_row=1, start_col=n_act_occ(sigma_out) + 1, &
1788 n_rows=n_act_occ(sigma_out), n_cols=n_act_virt(sigma_out))
1790 reshape(ov_block, [n_ov(sigma_out), 1]), &
1791 start_row=off(sigma_out) + 1, start_col=k_col, &
1792 n_rows=n_ov(sigma_out), n_cols=1)
1793 DEALLOCATE (ov_block)
1804 cmplx(-1.0_dp, 0.0_dp, kind=
dp), rtbse_env%L_pairs)
1805 residual_max =
cp_cfm_norm(rtbse_env%eigvecs_pairs,
'M')
1806 IF (rtbse_env%unit_nr > 0)
THEN
1807 WRITE (rtbse_env%unit_nr,
'(A,ES16.6)') &
1808 ' RTBSE| Hermitian residual ||L - L^H||_max = ', residual_max
1809 WRITE (rtbse_env%unit_nr,
'(A)')
' RTBSE|'
1811 IF (residual_max > 1.0e-6_dp)
THEN
1812 cpabort(
"Liouvillian Hermitian residual > 1e-6 - check kernel signs / symmetry.")
1816 CALL cp_cfm_heevd(rtbse_env%L_pairs, rtbse_env%eigvecs_pairs, &
1817 rtbse_env%eigenvalues_liouvillian)
1820 IF (rtbse_env%unit_nr > 0)
THEN
1821 WRITE (rtbse_env%unit_nr,
'(A,T26,A,T59,A)') &
1822 ' RTBSE|',
"Excitation index n",
"Excitation energy (eV)"
1823 DO n = 1, n_ov_joint
1824 WRITE (rtbse_env%unit_nr,
'(A,T40,I4,T69,F12.4)') &
1825 ' RTBSE|', n, rtbse_env%eigenvalues_liouvillian(n)*
evolt
1827 WRITE (rtbse_env%unit_nr,
'(A)')
' RTBSE|'
1829 IF (eig_unit > 0)
THEN
1830 WRITE (eig_unit,
'(A)')
'# n Omega [a.u.] Omega [eV]'
1831 DO n = 1, n_ov_joint
1832 WRITE (eig_unit,
'(I5,4X,ES24.14E3,4X,ES24.14E3)') n, &
1833 rtbse_env%eigenvalues_liouvillian(n), &
1834 rtbse_env%eigenvalues_liouvillian(n)*
evolt
1840 DEALLOCATE (n_act_occ, n_act_virt, n_ov, off)
1842 CALL timestop(handle)
1843 END SUBROUTINE diagnose_tda_liouvillian
1860 SUBROUTINE diagnose_abba_liouvillian(rtbse_env)
1863 CHARACTER(len=*),
PARAMETER :: routinen =
'diagnose_ABBA_liouvillian'
1865 COMPLEX(kind=dp),
ALLOCATABLE,
DIMENSION(:, :) :: ov_block, vo_block
1866 COMPLEX(kind=dp),
DIMENSION(:, :),
POINTER :: b_local
1867 INTEGER :: b, eig_unit, handle, j, k_col, k_local, &
1868 n, n_ov_joint, sigma_out, sigma_probe
1869 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: n_act_occ, n_act_virt, n_ov, off
1870 REAL(kind=
dp) :: lambda_min_amb, residual_a, residual_b
1873 CALL timeset(routinen, handle)
1879 ALLOCATE (n_act_occ(rtbse_env%n_spin), n_act_virt(rtbse_env%n_spin), &
1880 n_ov(rtbse_env%n_spin), off(rtbse_env%n_spin))
1882 DO sigma_probe = 1, rtbse_env%n_spin
1883 n_act_occ(sigma_probe) = rtbse_env%n_occ(sigma_probe) - rtbse_env%first_active_mo + 1
1884 n_act_virt(sigma_probe) = rtbse_env%last_active_mo - rtbse_env%n_occ(sigma_probe)
1885 n_ov(sigma_probe) = n_act_occ(sigma_probe)*n_act_virt(sigma_probe)
1886 off(sigma_probe) = n_ov_joint
1887 n_ov_joint = n_ov_joint + n_ov(sigma_probe)
1890 IF (rtbse_env%unit_nr > 0)
THEN
1891 WRITE (rtbse_env%unit_nr,
'(A)')
' RTBSE| ----- ABBA Liouvillian diagnostic -----'
1892 WRITE (rtbse_env%unit_nr,
'(A,I0,A,I0)') &
1893 ' RTBSE| n_spin = ', rtbse_env%n_spin,
', joint N_OV = ', n_ov_joint
1894 WRITE (rtbse_env%unit_nr,
'(A)')
' RTBSE|'
1899 file_form=
"FORMATTED", &
1900 file_position=
"REWIND", &
1901 ignore_should_output=.true.)
1902 IF (eig_unit > 0)
THEN
1903 WRITE (eig_unit,
'(A)')
'# Joint spin-block ABBA Liouvillian eigenvalues'
1904 IF (rtbse_env%n_spin == 1)
THEN
1905 WRITE (eig_unit,
'(A,I0,A,I0)')
'# n_spin = ', rtbse_env%n_spin,
', N_OV = ', n_ov(1)
1907 WRITE (eig_unit,
'(A,I0,A,I0,A,I0)')
'# n_spin = ', rtbse_env%n_spin, &
1908 ', N_OV(1) = ', n_ov(1),
', N_OV(2) = ', n_ov(2)
1918 DO sigma_probe = 1, rtbse_env%n_spin
1919 DO b = rtbse_env%n_occ(sigma_probe) + 1, rtbse_env%last_active_mo
1920 DO j = rtbse_env%first_active_mo, rtbse_env%n_occ(sigma_probe)
1921 k_local = (b - rtbse_env%n_occ(sigma_probe) - 1)*n_act_occ(sigma_probe) + &
1922 (j - rtbse_env%first_active_mo + 1)
1923 k_col = off(sigma_probe) + k_local
1925 DO sigma_out = 1, rtbse_env%n_spin
1926 CALL cp_cfm_set_all(rtbse_env%drho_probe(sigma_out), cmplx(0.0_dp, 0.0_dp, kind=
dp))
1929 j - rtbse_env%first_active_mo + 1, &
1930 b - rtbse_env%first_active_mo + 1, &
1931 cmplx(1.0_dp, 0.0_dp, kind=
dp))
1933 IF (rtbse_env%n_spin == 1)
THEN
1934 CALL apply_liouvillian_to_drho_spin(rtbse_env, rtbse_env%drho_probe(1), &
1935 rtbse_env%L_drho(1), 1)
1937 CALL apply_liouvillian_to_drho(rtbse_env, rtbse_env%drho_probe, rtbse_env%L_drho)
1940 DO sigma_out = 1, rtbse_env%n_spin
1941 ALLOCATE (ov_block(n_act_occ(sigma_out), n_act_virt(sigma_out)))
1942 ALLOCATE (vo_block(n_act_virt(sigma_out), n_act_occ(sigma_out)))
1944 start_row=1, start_col=n_act_occ(sigma_out) + 1, &
1945 n_rows=n_act_occ(sigma_out), n_cols=n_act_virt(sigma_out))
1947 reshape(ov_block, [n_ov(sigma_out), 1]), &
1948 start_row=off(sigma_out) + 1, start_col=k_col, &
1949 n_rows=n_ov(sigma_out), n_cols=1)
1952 start_row=n_act_occ(sigma_out) + 1, start_col=1, &
1953 n_rows=n_act_virt(sigma_out), n_cols=n_act_occ(sigma_out))
1955 reshape(transpose(vo_block), [n_ov(sigma_out), 1]), &
1956 start_row=off(sigma_out) + 1, start_col=k_col, &
1957 n_rows=n_ov(sigma_out), n_cols=1)
1958 DEALLOCATE (ov_block, vo_block)
1966 b_local => rtbse_env%B_mat%local_data
1967 b_local = -conjg(b_local)
1972 cmplx(-1.0_dp, 0.0_dp, kind=
dp), rtbse_env%A_mat)
1973 residual_a =
cp_cfm_norm(rtbse_env%eigvecs_pairs,
'M')
1977 cmplx(-1.0_dp, 0.0_dp, kind=
dp), rtbse_env%B_mat)
1978 residual_b =
cp_cfm_norm(rtbse_env%eigvecs_pairs,
'M')
1980 IF (rtbse_env%unit_nr > 0)
THEN
1981 WRITE (rtbse_env%unit_nr,
'(A,ES16.6)') &
1982 ' RTBSE| Hermitian residual ||A - A^H||_max = ', residual_a
1983 WRITE (rtbse_env%unit_nr,
'(A,ES16.6)') &
1984 ' RTBSE| Symmetry residual ||B - B^T||_max = ', residual_b
1986 IF (residual_a > 1.0e-6_dp)
THEN
1987 cpabort(
"A is not Hermitian within 1e-6 - check kernel signs / symmetry.")
1989 IF (residual_b > 1.0e-6_dp)
THEN
1990 cpabort(
"B is not symmetric within 1e-6 - check kernel signs / symmetry.")
1996 cmplx(-1.0_dp, 0.0_dp, kind=
dp), rtbse_env%B_mat)
1999 cmplx(1.0_dp, 0.0_dp, kind=
dp), rtbse_env%B_mat)
2002 CALL cp_cfm_to_cfm(rtbse_env%AmB_scratch, rtbse_env%L_pairs)
2003 CALL cp_cfm_heevd(rtbse_env%L_pairs, rtbse_env%eigvecs_pairs, rtbse_env%eigenvalues_liouvillian)
2004 lambda_min_amb = rtbse_env%eigenvalues_liouvillian(1)
2005 IF (rtbse_env%unit_nr > 0)
THEN
2006 WRITE (rtbse_env%unit_nr,
'(A,ES16.6,A,F12.6,A)') &
2007 ' RTBSE| lambda_min(A - B) = ', &
2008 lambda_min_amb,
' a.u. (', lambda_min_amb*
evolt,
' eV)'
2011 IF (lambda_min_amb < 0.0_dp)
THEN
2012 CALL cp_abort(__location__, &
2013 "(A - B) not positive definite - this may hint at a triplet or "// &
2014 "charge-transfer instability of the reference state.")
2019 CALL cp_cfm_power(rtbse_env%AmB_scratch, threshold=0.0_dp, exponent=0.5_dp)
2022 CALL cp_cfm_gemm(
'N',
'N', n_ov_joint, n_ov_joint, n_ov_joint, &
2023 cmplx(1.0_dp, 0.0_dp, kind=
dp), &
2024 rtbse_env%AmB_scratch, rtbse_env%ApB_scratch, &
2025 cmplx(0.0_dp, 0.0_dp, kind=
dp), &
2027 CALL cp_cfm_gemm(
'N',
'N', n_ov_joint, n_ov_joint, n_ov_joint, &
2028 cmplx(1.0_dp, 0.0_dp, kind=
dp), &
2029 rtbse_env%B_mat, rtbse_env%AmB_scratch, &
2030 cmplx(0.0_dp, 0.0_dp, kind=
dp), &
2034 CALL cp_cfm_heevd(rtbse_env%L_pairs, rtbse_env%eigvecs_pairs, rtbse_env%eigenvalues_liouvillian)
2035 DO n = 1, n_ov_joint
2036 IF (rtbse_env%eigenvalues_liouvillian(n) < 0.0_dp)
THEN
2037 rtbse_env%eigenvalues_liouvillian(n) = 0.0_dp
2039 rtbse_env%eigenvalues_liouvillian(n) = sqrt(rtbse_env%eigenvalues_liouvillian(n))
2043 IF (rtbse_env%unit_nr > 0)
THEN
2044 WRITE (rtbse_env%unit_nr,
'(A)')
' RTBSE|'
2045 WRITE (rtbse_env%unit_nr,
'(A,T26,A,T59,A)') &
2046 ' RTBSE|',
"Excitation index n",
"Excitation energy (eV)"
2047 DO n = 1, n_ov_joint
2048 WRITE (rtbse_env%unit_nr,
'(A,T40,I4,T69,F12.4)') &
2049 ' RTBSE|', n, rtbse_env%eigenvalues_liouvillian(n)*
evolt
2051 WRITE (rtbse_env%unit_nr,
'(A)')
' RTBSE|'
2053 IF (eig_unit > 0)
THEN
2054 WRITE (eig_unit,
'(A)')
'# n Omega [a.u.] Omega [eV]'
2055 DO n = 1, n_ov_joint
2056 WRITE (eig_unit,
'(I5,4X,ES24.14E3,4X,ES24.14E3)') n, &
2057 rtbse_env%eigenvalues_liouvillian(n), &
2058 rtbse_env%eigenvalues_liouvillian(n)*
evolt
2064 DEALLOCATE (n_act_occ, n_act_virt, n_ov, off)
2066 CALL timestop(handle)
2067 END SUBROUTINE diagnose_abba_liouvillian
2077 SUBROUTINE transform_ao_to_mo_covariant_fm(rtbse_env, fm_ao, fm_mo, i_spin)
2080 INTEGER,
INTENT(IN) :: i_spin
2082 CHARACTER(len=*),
PARAMETER :: routinen =
'transform_ao_to_mo_covariant_fm'
2086 CALL timeset(routinen, handle)
2089 CALL parallel_gemm(
"N",
"N", rtbse_env%n_ao, rtbse_env%mo_active, rtbse_env%n_ao, &
2090 1.0_dp, fm_ao, rtbse_env%C_active(i_spin), &
2091 0.0_dp, rtbse_env%ao_mo_workspace(1))
2093 CALL parallel_gemm(
"T",
"N", rtbse_env%mo_active, rtbse_env%mo_active, rtbse_env%n_ao, &
2094 1.0_dp, rtbse_env%C_active(i_spin), rtbse_env%ao_mo_workspace(1), &
2097 CALL timestop(handle)
2098 END SUBROUTINE transform_ao_to_mo_covariant_fm
2108 SUBROUTINE transform_ao_to_mo_covariant_cfm(rtbse_env, fm_ao, fm_mo, i_spin)
2111 INTEGER,
INTENT(IN) :: i_spin
2113 CHARACTER(len=*),
PARAMETER :: routinen =
'transform_ao_to_mo_covariant_cfm'
2117 CALL timeset(routinen, handle)
2120 CALL cp_cfm_to_fm(msource=fm_ao, mtargetr=rtbse_env%real_workspace(1), &
2121 mtargeti=rtbse_env%real_workspace(2))
2123 CALL parallel_gemm(
"N",
"N", rtbse_env%n_ao, rtbse_env%mo_active, rtbse_env%n_ao, &
2124 1.0_dp, rtbse_env%real_workspace(1), rtbse_env%C_active(i_spin), &
2125 0.0_dp, rtbse_env%ao_mo_workspace(1))
2126 CALL parallel_gemm(
"T",
"N", rtbse_env%mo_active, rtbse_env%mo_active, rtbse_env%n_ao, &
2127 1.0_dp, rtbse_env%C_active(i_spin), rtbse_env%ao_mo_workspace(1), &
2128 0.0_dp, rtbse_env%real_workspace_mo(1))
2130 CALL parallel_gemm(
"N",
"N", rtbse_env%n_ao, rtbse_env%mo_active, rtbse_env%n_ao, &
2131 1.0_dp, rtbse_env%real_workspace(2), rtbse_env%C_active(i_spin), &
2132 0.0_dp, rtbse_env%ao_mo_workspace(1))
2133 CALL parallel_gemm(
"T",
"N", rtbse_env%mo_active, rtbse_env%mo_active, rtbse_env%n_ao, &
2134 1.0_dp, rtbse_env%C_active(i_spin), rtbse_env%ao_mo_workspace(1), &
2135 0.0_dp, rtbse_env%real_workspace_mo(2))
2137 CALL cp_fm_to_cfm(msourcer=rtbse_env%real_workspace_mo(1), &
2138 msourcei=rtbse_env%real_workspace_mo(2), &
2141 CALL timestop(handle)
2142 END SUBROUTINE transform_ao_to_mo_covariant_cfm
2152 SUBROUTINE transform_mo_to_ao_contravariant_cfm(rtbse_env, fm_mo, fm_ao, i_spin)
2155 INTEGER,
INTENT(IN) :: i_spin
2157 CHARACTER(len=*),
PARAMETER :: routinen =
'transform_mo_to_ao_contravariant_cfm'
2161 CALL timeset(routinen, handle)
2164 CALL cp_cfm_to_fm(msource=fm_mo, mtargetr=rtbse_env%real_workspace_mo(1), &
2165 mtargeti=rtbse_env%real_workspace_mo(2))
2167 CALL parallel_gemm(
"N",
"N", rtbse_env%n_ao, rtbse_env%mo_active, rtbse_env%mo_active, &
2168 1.0_dp, rtbse_env%C_active(i_spin), rtbse_env%real_workspace_mo(1), &
2169 0.0_dp, rtbse_env%ao_mo_workspace(1))
2170 CALL parallel_gemm(
"N",
"T", rtbse_env%n_ao, rtbse_env%n_ao, rtbse_env%mo_active, &
2171 1.0_dp, rtbse_env%ao_mo_workspace(1), rtbse_env%C_active(i_spin), &
2172 0.0_dp, rtbse_env%real_workspace(1))
2174 CALL parallel_gemm(
"N",
"N", rtbse_env%n_ao, rtbse_env%mo_active, rtbse_env%mo_active, &
2175 1.0_dp, rtbse_env%C_active(i_spin), rtbse_env%real_workspace_mo(2), &
2176 0.0_dp, rtbse_env%ao_mo_workspace(1))
2177 CALL parallel_gemm(
"N",
"T", rtbse_env%n_ao, rtbse_env%n_ao, rtbse_env%mo_active, &
2178 1.0_dp, rtbse_env%ao_mo_workspace(1), rtbse_env%C_active(i_spin), &
2179 0.0_dp, rtbse_env%real_workspace(2))
2181 CALL cp_fm_to_cfm(msourcer=rtbse_env%real_workspace(1), &
2182 msourcei=rtbse_env%real_workspace(2), mtarget=fm_ao)
2184 CALL timestop(handle)
2185 END SUBROUTINE transform_mo_to_ao_contravariant_cfm
2195 SUBROUTINE transform_mo_occupation_factor_diff_cfm(rtbse_env, cfm, i_spin)
2200 CHARACTER(len=*),
PARAMETER :: routinen =
'transform_mo_occupation_factor_diff_cfm'
2204 CALL timeset(routinen, handle)
2206 CALL cp_cfm_to_fm(msource=cfm, mtargetr=rtbse_env%real_workspace_mo(1), &
2207 mtargeti=rtbse_env%real_workspace_mo(2))
2209 CALL transform_mo_occupation_factor_diff_fm(rtbse_env, rtbse_env%real_workspace_mo(1), i_spin)
2211 CALL transform_mo_occupation_factor_diff_fm(rtbse_env, rtbse_env%real_workspace_mo(2), i_spin)
2213 CALL cp_fm_to_cfm(msourcer=rtbse_env%real_workspace_mo(1), &
2214 msourcei=rtbse_env%real_workspace_mo(2), &
2217 CALL timestop(handle)
2218 END SUBROUTINE transform_mo_occupation_factor_diff_cfm
2228 SUBROUTINE transform_mo_occupation_factor_diff_fm(rtbse_env, fm, i_spin)
2233 CHARACTER(len=*),
PARAMETER :: routinen =
'transform_mo_occupation_factor_diff_fm'
2235 INTEGER :: handle, i_global, i_global_mo, i_local, &
2236 j_global, j_global_mo, j_local, n_occ, &
2237 ncol_local, nrow_local, shift
2238 INTEGER,
DIMENSION(:),
POINTER :: col_indices, row_indices
2239 REAL(kind=
dp) :: occ_factor
2240 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: local_data
2242 CALL timeset(routinen, handle)
2244 n_occ = rtbse_env%n_occ(i_spin)
2246 shift = rtbse_env%first_active_mo - 1
2249 nrow_local=nrow_local, ncol_local=ncol_local, &
2250 row_indices=row_indices, col_indices=col_indices)
2252 local_data => fm%local_data
2254 DO i_local = 1, nrow_local
2255 i_global = row_indices(i_local)
2256 i_global_mo = i_global + shift
2257 DO j_local = 1, ncol_local
2258 j_global = col_indices(j_local)
2259 j_global_mo = j_global + shift
2261 IF (i_global_mo <= n_occ .AND. j_global_mo > n_occ)
THEN
2262 occ_factor = -1.0_dp
2263 ELSE IF (i_global_mo > n_occ .AND. j_global_mo <= n_occ)
THEN
2269 local_data(i_local, j_local) = occ_factor*local_data(i_local, j_local)
2273 CALL timestop(handle)
2274 END SUBROUTINE transform_mo_occupation_factor_diff_fm
2285 SUBROUTINE mask_mo_block_cfm(rtbse_env, cfm, i_spin, keep_OV, keep_ovvo)
2288 INTEGER,
INTENT(IN) :: i_spin
2289 LOGICAL,
INTENT(IN) :: keep_ov
2290 LOGICAL,
INTENT(IN),
OPTIONAL :: keep_ovvo
2292 CHARACTER(len=*),
PARAMETER :: routinen =
'mask_mo_block_cfm'
2294 COMPLEX(kind=dp),
DIMENSION(:, :),
POINTER :: local_data
2295 INTEGER :: handle, i_global, i_global_mo, i_local, &
2296 j_global, j_global_mo, j_local, n_occ, &
2297 ncol_local, nrow_local, shift
2298 INTEGER,
DIMENSION(:),
POINTER :: col_indices, row_indices
2299 LOGICAL :: keep, l_keep_ovvo
2301 CALL timeset(routinen, handle)
2303 l_keep_ovvo = .false.
2304 IF (
PRESENT(keep_ovvo)) l_keep_ovvo = keep_ovvo
2306 n_occ = rtbse_env%n_occ(i_spin)
2307 shift = rtbse_env%first_active_mo - 1
2310 nrow_local=nrow_local, ncol_local=ncol_local, &
2311 row_indices=row_indices, col_indices=col_indices)
2313 local_data => cfm%local_data
2315 DO i_local = 1, nrow_local
2316 i_global = row_indices(i_local)
2317 i_global_mo = i_global + shift
2318 DO j_local = 1, ncol_local
2319 j_global = col_indices(j_local)
2320 j_global_mo = j_global + shift
2321 IF (l_keep_ovvo)
THEN
2323 keep = ((i_global_mo <= n_occ) .NEQV. (j_global_mo <= n_occ))
2324 ELSE IF (keep_ov)
THEN
2325 keep = (i_global_mo <= n_occ .AND. j_global_mo > n_occ)
2327 keep = (i_global_mo > n_occ .AND. j_global_mo <= n_occ)
2329 IF (.NOT. keep) local_data(i_local, j_local) = cmplx(0.0_dp, 0.0_dp, kind=
dp)
2333 CALL timestop(handle)
2334 END SUBROUTINE mask_mo_block_cfm
2343 SUBROUTINE mask_mo_block_fm(rtbse_env, fm, i_spin, keep_OV)
2346 INTEGER,
INTENT(IN) :: i_spin
2347 LOGICAL,
INTENT(IN) :: keep_ov
2349 CHARACTER(len=*),
PARAMETER :: routinen =
'mask_mo_block_fm'
2351 INTEGER :: handle, i_global, i_global_mo, i_local, &
2352 j_global, j_global_mo, j_local, n_occ, &
2353 ncol_local, nrow_local, shift
2354 INTEGER,
DIMENSION(:),
POINTER :: col_indices, row_indices
2356 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: local_data
2358 CALL timeset(routinen, handle)
2360 n_occ = rtbse_env%n_occ(i_spin)
2361 shift = rtbse_env%first_active_mo - 1
2364 nrow_local=nrow_local, ncol_local=ncol_local, &
2365 row_indices=row_indices, col_indices=col_indices)
2367 local_data => fm%local_data
2369 DO i_local = 1, nrow_local
2370 i_global = row_indices(i_local)
2371 i_global_mo = i_global + shift
2372 DO j_local = 1, ncol_local
2373 j_global = col_indices(j_local)
2374 j_global_mo = j_global + shift
2376 keep = (i_global_mo <= n_occ .AND. j_global_mo > n_occ)
2378 keep = (i_global_mo > n_occ .AND. j_global_mo <= n_occ)
2380 IF (.NOT. keep) local_data(i_local, j_local) = 0.0_dp
2384 CALL timestop(handle)
2385 END SUBROUTINE mask_mo_block_fm
2398 SUBROUTINE rotate_rho_phase(rtbse_env, rho, i_spin, phase)
2401 INTEGER,
INTENT(IN) :: i_spin
2402 REAL(kind=
dp),
INTENT(IN) :: phase
2404 CHARACTER(len=*),
PARAMETER :: routinen =
'rotate_rho_phase'
2406 COMPLEX(kind=dp) :: phase_ov, phase_vo
2407 COMPLEX(kind=dp),
DIMENSION(:, :),
POINTER :: local_data
2408 INTEGER :: handle, i_global, i_global_mo, i_local, &
2409 j_global, j_global_mo, j_local, n_occ, &
2410 ncol_local, nrow_local, shift
2411 INTEGER,
DIMENSION(:),
POINTER :: col_indices, row_indices
2413 IF (rtbse_env%omega_shift == 0.0_dp)
RETURN
2415 CALL timeset(routinen, handle)
2417 n_occ = rtbse_env%n_occ(i_spin)
2418 shift = rtbse_env%first_active_mo - 1
2419 phase_ov = cmplx(cos(phase), sin(phase), kind=
dp)
2420 phase_vo = conjg(phase_ov)
2423 nrow_local=nrow_local, ncol_local=ncol_local, &
2424 row_indices=row_indices, col_indices=col_indices)
2425 local_data => rho%local_data
2427 DO i_local = 1, nrow_local
2428 i_global = row_indices(i_local)
2429 i_global_mo = i_global + shift
2430 DO j_local = 1, ncol_local
2431 j_global = col_indices(j_local)
2432 j_global_mo = j_global + shift
2433 IF (i_global_mo <= n_occ .AND. j_global_mo > n_occ)
THEN
2435 local_data(i_local, j_local) = phase_ov*local_data(i_local, j_local)
2436 ELSE IF (i_global_mo > n_occ .AND. j_global_mo <= n_occ)
THEN
2438 local_data(i_local, j_local) = phase_vo*local_data(i_local, j_local)
2443 CALL timestop(handle)
2444 END SUBROUTINE rotate_rho_phase
2457 SUBROUTINE build_rho_lab(rtbse_env, rho_in, t_phys, rho_lab)
2459 TYPE(
cp_cfm_type),
DIMENSION(:),
POINTER :: rho_in
2460 REAL(kind=
dp),
INTENT(IN) :: t_phys
2461 TYPE(
cp_cfm_type),
DIMENSION(:),
POINTER :: rho_lab
2463 CHARACTER(len=*),
PARAMETER :: routinen =
'build_rho_lab'
2465 INTEGER :: handle, i
2467 IF (rtbse_env%omega_shift == 0.0_dp .OR. .NOT.
ASSOCIATED(rtbse_env%rho_new_last))
THEN
2472 CALL timeset(routinen, handle)
2474 DO i = 1, rtbse_env%n_spin
2478 CALL rotate_rho_phase(rtbse_env, rtbse_env%rho_new_last(i), i, rtbse_env%omega_shift*t_phys)
2480 rho_lab => rtbse_env%rho_new_last
2482 CALL timestop(handle)
2483 END SUBROUTINE build_rho_lab
2495 SUBROUTINE apply_restart_basis_bridge(rtbse_env)
2498 CHARACTER(len=*),
PARAMETER :: routinen =
'apply_restart_basis_bridge'
2499 COMPLEX(kind=dp),
PARAMETER :: c_one = cmplx(1.0_dp, 0.0_dp, kind=
dp), &
2500 c_zero = cmplx(0.0_dp, 0.0_dp, kind=
dp)
2502 INTEGER :: handle, i, i_glob, i_mo, ii, j_glob, &
2503 j_mo, jj, n_flip, ncol_local, &
2505 INTEGER,
DIMENSION(:),
POINTER :: col_indices, row_indices
2507 REAL(kind=
dp) :: dev_ident, dev_offdiag, dev_ov, &
2509 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: u_diag
2510 REAL(kind=
dp),
CONTIGUOUS,
DIMENSION(:, :), &
2513 TYPE(
cp_fm_type),
DIMENSION(:),
POINTER :: c_old
2515 CALL timeset(routinen, handle)
2518 ALLOCATE (c_old(rtbse_env%n_spin))
2519 DO i = 1, rtbse_env%n_spin
2520 CALL cp_fm_create(c_old(i), rtbse_env%fm_struct_ao_mo_active)
2523 IF (.NOT. found)
THEN
2524 DO i = 1, rtbse_env%n_spin
2528 CALL timestop(handle)
2532 CALL cp_fm_create(sc_old, rtbse_env%fm_struct_ao_mo_active)
2533 ALLOCATE (u_diag(rtbse_env%mo_active))
2535 DO i = 1, rtbse_env%n_spin
2537 CALL parallel_gemm(
"N",
"N", rtbse_env%n_ao, rtbse_env%mo_active, rtbse_env%n_ao, &
2538 1.0_dp, rtbse_env%S_fm, c_old(i), 0.0_dp, sc_old)
2540 CALL parallel_gemm(
"T",
"N", rtbse_env%mo_active, rtbse_env%mo_active, rtbse_env%n_ao, &
2541 1.0_dp, rtbse_env%C_active(i), sc_old, 0.0_dp, rtbse_env%real_workspace_mo(1))
2545 n_flip = count(u_diag < 0.0_dp)
2546 CALL cp_fm_get_info(rtbse_env%real_workspace_mo(1), nrow_local=nrow_local, ncol_local=ncol_local, &
2547 row_indices=row_indices, col_indices=col_indices, local_data=u_data)
2548 dev_ident = 0.0_dp; dev_offdiag = 0.0_dp; dev_ov = 0.0_dp
2549 DO ii = 1, nrow_local
2550 i_glob = row_indices(ii)
2551 i_mo = i_glob + rtbse_env%first_active_mo - 1
2552 DO jj = 1, ncol_local
2553 j_glob = col_indices(jj)
2554 j_mo = j_glob + rtbse_env%first_active_mo - 1
2555 IF (i_glob == j_glob)
THEN
2556 dev_ident = max(dev_ident, abs(u_data(ii, jj) - 1.0_dp))
2558 dev_ident = max(dev_ident, abs(u_data(ii, jj)))
2559 dev_offdiag = max(dev_offdiag, abs(u_data(ii, jj)))
2561 IF ((i_mo <= rtbse_env%n_occ(i)) .NEQV. (j_mo <= rtbse_env%n_occ(i)))
THEN
2562 dev_ov = max(dev_ov, abs(u_data(ii, jj)))
2567 CALL parallel_gemm(
"T",
"N", rtbse_env%mo_active, rtbse_env%mo_active, rtbse_env%mo_active, &
2568 1.0_dp, rtbse_env%real_workspace_mo(1), rtbse_env%real_workspace_mo(1), &
2569 0.0_dp, rtbse_env%real_workspace_mo(2))
2570 CALL cp_fm_get_info(rtbse_env%real_workspace_mo(2), nrow_local=nrow_local, ncol_local=ncol_local, &
2571 row_indices=row_indices, col_indices=col_indices, local_data=u_data)
2572 dev_unitary = 0.0_dp
2573 DO ii = 1, nrow_local
2574 i_glob = row_indices(ii)
2575 DO jj = 1, ncol_local
2576 j_glob = col_indices(jj)
2577 dev_unitary = max(dev_unitary, abs(u_data(ii, jj) - merge(1.0_dp, 0.0_dp, i_glob == j_glob)))
2580 CALL rtbse_env%real_workspace_mo(1)%matrix_struct%para_env%max(dev_ident)
2581 CALL rtbse_env%real_workspace_mo(1)%matrix_struct%para_env%max(dev_offdiag)
2582 CALL rtbse_env%real_workspace_mo(1)%matrix_struct%para_env%max(dev_ov)
2583 CALL rtbse_env%real_workspace_mo(1)%matrix_struct%para_env%max(dev_unitary)
2585 IF (rtbse_env%unit_nr > 0)
THEN
2586 WRITE (rtbse_env%unit_nr,
'(A,I3,A)')
" RTBSE| Restart basis bridge U = C2^T S C1 (spin ", i,
"):"
2587 WRITE (rtbse_env%unit_nr,
'(A,ES12.3,A)')
" RTBSE| max |U - 1| ", dev_ident, &
2588 " (total gauge correction)"
2589 WRITE (rtbse_env%unit_nr,
'(A,I12)')
" RTBSE| sign flips (U_ii<0)", n_flip
2590 WRITE (rtbse_env%unit_nr,
'(A,ES12.3,A)')
" RTBSE| max offdiag |U_ij| ", dev_offdiag, &
2591 " (degenerate-subspace rotation)"
2592 WRITE (rtbse_env%unit_nr,
'(A,ES12.3,A)')
" RTBSE| max |U^T U - 1| ", dev_unitary, &
2593 " (representability loss)"
2594 WRITE (rtbse_env%unit_nr,
'(A,ES12.3,A)')
" RTBSE| max |U_OV| ", dev_ov, &
2595 " (occ/virt structure change)"
2597 IF (dev_unitary >= 1.0e-3_dp)
THEN
2598 CALL cp_abort(__location__, &
2599 "Restart basis bridge: active spaces of the two runs differ severely (|U^T U - 1| >= 1e-3)")
2601 IF (dev_unitary >= 1.0e-10_dp .AND. dev_unitary < 1.0e-3_dp)
THEN
2602 CALL cp_warn(__location__, &
2603 "Restart basis bridge: representability loss above 1e-10 - active windows differ slightly.")
2607 IF (dev_ov >= 1.0e-6_dp)
THEN
2608 CALL cp_warn(__location__, &
2609 "Restart basis bridge: occupied/virtual mixing above 1e-6 - occupation structure changed.")
2613 CALL cp_fm_to_cfm(msourcer=rtbse_env%real_workspace_mo(1), mtarget=rtbse_env%rho_workspace(1))
2614 CALL cp_cfm_gemm(
'N',
'N', rtbse_env%mo_active, rtbse_env%mo_active, rtbse_env%mo_active, &
2615 c_one, rtbse_env%rho_workspace(1), rtbse_env%rho(i), c_zero, rtbse_env%rho_workspace(2))
2616 CALL cp_cfm_gemm(
'N',
'C', rtbse_env%mo_active, rtbse_env%mo_active, rtbse_env%mo_active, &
2617 c_one, rtbse_env%rho_workspace(2), rtbse_env%rho_workspace(1), c_zero, rtbse_env%rho(i))
2622 DO i = 1, rtbse_env%n_spin
2626 CALL timestop(handle)
2627 END SUBROUTINE apply_restart_basis_bridge
2641 SUBROUTINE get_hartree_complex(rtbse_env, rho_cfm, v_cfm, ispin)
2645 INTEGER,
INTENT(IN) :: ispin
2647 CHARACTER(len=*),
PARAMETER :: routinen =
'get_hartree_complex'
2653 CALL timeset(routinen, handle)
2664 CALL cp_cfm_to_fm(msource=rho_cfm, mtargetr=rtbse_env%real_workspace(1))
2665 CALL cp_cfm_set_all(rtbse_env%sigma_complex_workspace(1), cmplx(0.0_dp, 0.0_dp, kind=
dp))
2666 CALL cp_fm_to_cfm(msourcer=rtbse_env%real_workspace(1), &
2667 mtarget=rtbse_env%sigma_complex_workspace(1))
2668 CALL get_hartree(rtbse_env, rtbse_env%sigma_complex_workspace(1), &
2669 rtbse_env%real_workspace(1))
2672 CALL cp_cfm_to_fm(msource=rho_cfm, mtargeti=rtbse_env%real_workspace(2))
2673 CALL cp_cfm_set_all(rtbse_env%sigma_complex_workspace(1), cmplx(0.0_dp, 0.0_dp, kind=
dp))
2674 CALL cp_fm_to_cfm(msourcer=rtbse_env%real_workspace(2), &
2675 mtarget=rtbse_env%sigma_complex_workspace(1))
2676 CALL get_hartree(rtbse_env, rtbse_env%sigma_complex_workspace(1), &
2677 rtbse_env%real_workspace(2))
2680 CALL cp_fm_to_cfm(msourcer=rtbse_env%real_workspace(1), &
2681 msourcei=rtbse_env%real_workspace(2), &
2684 CALL timestop(handle)
2685 END SUBROUTINE get_hartree_complex
2695 SUBROUTINE apply_delta_pulse_mo(rtbse_env)
2698 CHARACTER(len=*),
PARAMETER :: routinen =
'apply_delta_pulse_MO'
2700 INTEGER :: handle, i, k
2701 REAL(kind=
dp) :: intensity, metric
2702 REAL(kind=
dp),
DIMENSION(3) :: kvec
2704 CALL timeset(routinen, handle)
2707 IF (rtbse_env%unit_nr > 0)
WRITE (rtbse_env%unit_nr,
'(A28)')
' RTBSE| Applying delta pulse'
2709 intensity = -rtbse_env%dft_control%rtp_control%delta_pulse_scale
2711 kvec(:) = rtbse_env%dft_control%rtp_control%delta_pulse_direction(:)
2712 IF (rtbse_env%unit_nr > 0)
WRITE (rtbse_env%unit_nr,
'(A38,E14.4E3,E14.4E3,E14.4E3)') &
2713 " RTBSE| Delta pulse elements (a.u.) : ", intensity*kvec(:)
2715 DO i = 1, rtbse_env%n_spin
2719 kvec(k), rtbse_env%moments_field(k, i))
2722 CALL cp_fm_transpose(rtbse_env%real_workspace_mo(1), rtbse_env%real_workspace_mo(2))
2724 0.5_dp, rtbse_env%real_workspace_mo(2))
2726 CALL cp_fm_scale(intensity, rtbse_env%real_workspace_mo(1))
2727 CALL cp_fm_to_cfm(msourcei=rtbse_env%real_workspace_mo(1), mtarget=rtbse_env%ham_workspace(i))
2730 CALL propagate_density(rtbse_env, rtbse_env%ham_workspace, rtbse_env%rho, rtbse_env%rho_new)
2731 metric =
rho_metric(rtbse_env%rho_new, rtbse_env%rho, rtbse_env%n_spin)
2732 IF (rtbse_env%unit_nr > 0)
WRITE (rtbse_env%unit_nr, (
'(A42,E38.8E3)'))
" RTBSE| Metric difference after delta kick", metric
2734 DO i = 1, rtbse_env%n_spin
2738 CALL timestop(handle)
2739 END SUBROUTINE apply_delta_pulse_mo
2750 SUBROUTINE project_drho_to_ov(rtbse_env, cfm, i_spin)
2753 INTEGER,
INTENT(IN) :: i_spin
2755 COMPLEX(kind=dp),
DIMENSION(:, :),
POINTER :: local_data
2756 INTEGER :: i_global, i_global_mo, i_local, &
2757 j_global, j_global_mo, j_local, n_occ, &
2758 ncol_local, nrow_local, shift
2759 INTEGER,
DIMENSION(:),
POINTER :: col_indices, row_indices
2761 n_occ = rtbse_env%n_occ(i_spin)
2762 shift = rtbse_env%first_active_mo - 1
2765 nrow_local=nrow_local, ncol_local=ncol_local, &
2766 row_indices=row_indices, col_indices=col_indices)
2767 local_data => cfm%local_data
2770 DO j_local = 1, ncol_local
2771 j_global = col_indices(j_local)
2772 j_global_mo = j_global + shift
2773 DO i_local = 1, nrow_local
2774 i_global = row_indices(i_local)
2775 i_global_mo = i_global + shift
2776 IF ((i_global_mo <= n_occ .AND. j_global_mo <= n_occ) .OR. &
2777 (i_global_mo > n_occ .AND. j_global_mo > n_occ))
THEN
2778 local_data(i_local, j_local) = cmplx(0.0_dp, 0.0_dp, kind=
dp)
2782 END SUBROUTINE project_drho_to_ov
2794 SUBROUTINE get_electron_number_mo(rtbse_env, rho, electron_n_re, electron_n_im)
2797 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: electron_n_re, electron_n_im
2799 CHARACTER(len=*),
PARAMETER :: routinen =
'get_electron_number_MO'
2801 COMPLEX(kind=dp),
DIMENSION(:, :),
POINTER :: local_data
2802 INTEGER :: handle, i_global, i_local, j, j_global, &
2803 j_local, ncol_local, nrow_local
2804 INTEGER,
DIMENSION(:),
POINTER :: col_indices, row_indices
2806 CALL timeset(routinen, handle)
2807 electron_n_re(:) = 0.0_dp
2808 electron_n_im(:) = 0.0_dp
2809 DO j = 1, rtbse_env%n_spin
2811 nrow_local=nrow_local, &
2812 ncol_local=ncol_local, &
2813 row_indices=row_indices, &
2814 col_indices=col_indices)
2815 local_data => rho(j)%local_data
2817 DO i_local = 1, nrow_local
2818 i_global = row_indices(i_local)
2820 DO j_local = 1, ncol_local
2821 j_global = col_indices(j_local)
2822 IF (j_global == i_global)
THEN
2824 electron_n_re(j) = electron_n_re(j) + real(local_data(i_local, j_local), kind=
dp)
2825 electron_n_im(j) = electron_n_im(j) + aimag(local_data(i_local, j_local))
2831 CALL rho(j)%matrix_struct%para_env%sum(electron_n_re(j))
2832 CALL rho(j)%matrix_struct%para_env%sum(electron_n_im(j))
2834 electron_n_re(j) = electron_n_re(j)*rtbse_env%spin_degeneracy
2835 electron_n_im(j) = electron_n_im(j)*rtbse_env%spin_degeneracy
2838 CALL timestop(handle)
2839 END SUBROUTINE get_electron_number_mo
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_gemm(transa, transb, m, n, k, alpha, matrix_a, matrix_b, beta, matrix_c, a_first_col, a_first_row, b_first_col, b_first_row, c_first_col, c_first_row)
Performs one of the matrix-matrix operations: matrix_c = alpha * op1( matrix_a ) * op2( matrix_b ) + ...
subroutine, public cp_cfm_transpose(matrix, trans, matrixt)
Transposes a BLACS distributed complex matrix.
used for collecting diagonalization schemes available for cp_cfm_type
subroutine, public cp_cfm_heevd(matrix, eigenvectors, eigenvalues)
Perform a diagonalisation of a complex matrix.
Represents a complex full matrix distributed on many processors.
subroutine, public cp_cfm_get_submatrix(fm, target_m, start_row, start_col, n_rows, n_cols, transpose)
Extract a sub-matrix from the full matrix: op(target_m)(1:n_rows,1:n_cols) = fm(start_row:start_row+n...
subroutine, public cp_cfm_set_element(matrix, irow_global, icol_global, alpha)
Set the matrix element (irow_global,icol_global) of the full matrix to alpha.
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_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_set_submatrix(matrix, new_values, start_row, start_col, n_rows, n_cols, alpha, beta, transpose)
Set a sub-matrix of the full matrix: matrix(start_row:start_row+n_rows,start_col:start_col+n_cols) = ...
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.
subroutine, public dbcsr_copy(matrix_b, matrix_a, name, keep_sparsity, keep_imaginary)
...
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_set(matrix, alpha)
...
subroutine, public dbcsr_release(matrix)
...
subroutine, public dbcsr_add(matrix_a, matrix_b, alpha_scalar, beta_scalar)
...
DBCSR operations in CP2K.
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_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_scale(alpha, matrix_a)
scales a matrix matrix_a = alpha * matrix_b
represent a full matrix distributed on many processors
subroutine, public cp_fm_get_diag(matrix, diag)
returns the diagonal elements of a fm
subroutine, public cp_fm_get_info(matrix, name, nrow_global, ncol_global, nrow_block, ncol_block, nrow_local, ncol_local, row_indices, col_indices, local_data, context, nrow_locals, ncol_locals, matrix_struct, para_env)
returns all kind of information about the full matrix
subroutine, public cp_fm_to_fm_submat_general(source, destination, nrows, ncols, s_firstrow, s_firstcol, d_firstrow, d_firstcol, global_context)
General copy of a submatrix of fm matrix to a submatrix of another fm matrix. The two matrices can ha...
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...
integer function, public cp_print_key_unit_nr(logger, basis_section, print_key_path, extension, middle_name, local, log_filename, ignore_should_output, file_form, file_position, file_action, file_status, do_backup, on_file, is_new_file, mpi_io, fout)
...
subroutine, public cp_print_key_finished_output(unit_nr, logger, basis_section, print_key_path, local, ignore_should_output, on_file, mpi_io)
should be called after you finish working with a unit obtained with cp_print_key_unit_nr,...
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....
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.
Defines the basic variable types.
integer, parameter, public dp
Machine interface based on Fortran 2003 and POSIX.
real(kind=dp) function, public m_walltime()
returns time from a real-time clock, protected against rolling early/easily
Definition of mathematical constants and functions.
real(kind=dp), parameter, public twopi
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
Definition of physical constants:
real(kind=dp), parameter, public seconds
real(kind=dp), parameter, public evolt
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>
subroutine, public build_local_moment_matrix(qs_env, moments, nmoments, ref_point, ref_points, basis_type)
...
Routines treating GW and RPA calculations with kpoints.
subroutine, public cp_cfm_power(matrix, threshold, exponent, min_eigval)
...
Input/output from the propagation via RT-BSE method.
subroutine, public read_restart_c(rtbse_env, c_old, found)
Reads the previous run's C_active slabs (gauge reference for the restart basis bridge).
subroutine, public output_restart_linearized(rtbse_env, rho)
Linearized RT-BSE restart writer. Writes the restart set: lab-frame MO-active density matrices,...
subroutine, public check_restart_eps_consistency(rtbse_env)
Compares the original run's active eigenvalues (stashed by read_restart_trace) against the recomputed...
subroutine, public output_mos_contravariant(rtbse_env, rho, print_key_section)
Outputs the matrix in MO basis for matrix coefficients corresponding to contravariant operator,...
subroutine, public output_field(rtbse_env, append_opt)
Prints the current field components into a file provided by input.
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.
subroutine, public read_restart_info(rtbse_env)
Early phase of the restart read: the starting step index from the .info file, the original run's dt p...
subroutine, public read_restart_density(rtbse_env)
Late phase of the restart read: overwrites rho from the lab-frame restart matrices and sets restart_e...
subroutine, public read_restart_trace(rtbse_env)
Reads the RESTART.trace prefix (records 1..sim_start) into the in-memory moment/field/ time traces so...
subroutine, public output_moments(rtbse_env, rho)
Outputs the expectation value of moments from a given density matrix.
Routines for the propagation of the linearized RT-BSE equations of motion. Propagates the first-order...
subroutine, public run_propagation_linearized_bse(force_env)
Runs the electron-only real time propagation of the linearized BSE.
RT-BSE RI-RS kernels: SEX and Hartree evaluated by collocation on grid points r_l....
subroutine, public compute_hartree_ri_rs_complex(bs_env, rho_ao_cfm, v_h_ao_cfm)
Complex-input Hartree potential via RI-RS. Re/Im split: feed each part to the real compute_hartree_ri...
subroutine, public rt_bse_ri_rs_ensure_w0_grid(bs_env, qs_env)
Build W^0_ll' = sum_PQ Z_lP (V + W^c(ω=0))_PQ Z_l'Q (statically screened W on the grid)....
subroutine, public compute_hartree_ri_rs(bs_env, rho_ao_fm, v_h_ao_fm)
AO-domain Hartree via RI-RS: n_l = sum_µν φ_lµ Δρ_µν φ_lν = (φ ρ φ^T)_ll (diagonal of materialized gr...
subroutine, public compute_hartree_ri_rs_from_diag(bs_env, n_re, v_h_ao_cfm, n_im)
Complex Hartree from precomputed grid diagonals: V^H = V^H[n_re] + i V^H[n_im], each via hartree_pote...
subroutine, public rt_bse_ri_rs_ensure_v_grid(bs_env, qs_env)
Build V^aux_PQ = [M^-1 V^tr M^-1]_PQ (truncated Coulomb in the RI basis, M^-1-sandwiched to match the...
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.
Routines for the propagation via RT-BSE method.
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...
subroutine, public initialize_rtbse_env(rtbse_env)
Calculates the initial values, based on restart/scf density, and other non-trivial values.
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.
subroutine, public initialize_hartree_potential(rtbse_env)
Calculates the Hartree potential.
subroutine, public initialize_singleparticle_hamiltonian(rtbse_env)
Calculates the single particle Hamiltonian.
subroutine, public init_hartree(rtbse_env, v_dbcsr)
Creates the RI matrix and populates it with correct values.
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.
Represent a complex 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