57 USE dbt_api,
ONLY: dbt_copy_matrix_to_tensor
94#include "../base/base_uses.f90"
100 CHARACTER(len=*),
PARAMETER,
PRIVATE :: moduleN =
'rt_bse_linearized'
104 INTEGER,
PARAMETER,
PRIVATE :: kernel_input_ov = 1, kernel_input_ovvo = 2, kernel_input_full = 3
117 CHARACTER(len=*),
PARAMETER :: routinen =
'run_propagation_linearized_bse'
119 INTEGER :: handle, i, j
120 REAL(kind=
dp) :: t_phys, t_start, timestep_walltime, &
121 timestep_walltime_start
122 REAL(kind=
dp),
DIMENSION(2) :: enum_im, enum_re
123 TYPE(
cp_cfm_type),
DIMENSION(:),
POINTER :: rho_lab
129 CALL timeset(routinen, handle)
131 CALL cp_warn(__location__, &
132 "Linearized RT-BSE is under active development. Make sure you understand "// &
133 "the method and validate results before using it for production calculations.")
147 IF (rtbse_env%dft_control%rtp_control%initial_wfn ==
use_rt_restart)
THEN
151 CALL initialize_maximum_timestep(rtbse_env)
154 IF (rtbse_env%dft_control%rtp_control%initial_wfn ==
use_rt_restart)
THEN
155 IF (rtbse_env%sim_start >= rtbse_env%sim_nsteps)
THEN
156 cpabort(
"RT_RESTART: restart step >= STEPS - increase MOTION%MD%STEPS")
161 CALL print_linrtbse_header_info(rtbse_env)
165 CALL populate_c_active(rtbse_env)
171 CALL initialize_moments(rtbse_env)
176 CALL initialize_density_matrix(rtbse_env)
180 IF (rtbse_env%dft_control%rtp_control%initial_wfn ==
use_rt_restart)
THEN
182 IF (rtbse_env%restart_extracted)
THEN
183 CALL apply_restart_basis_bridge(rtbse_env)
184 t_start = real(rtbse_env%sim_start,
dp)*rtbse_env%sim_dt
185 DO i = 1, rtbse_env%n_spin
186 CALL rotate_rho_phase(rtbse_env, rtbse_env%rho(i), i, -rtbse_env%omega_shift*t_start)
195 DO i = 1, rtbse_env%n_spin
196 CALL transform_mo_to_ao_contravariant_cfm(rtbse_env, rtbse_env%rho_orig(i), rtbse_env%rho_ao_scratch(i), i)
199 DO i = 1, rtbse_env%n_spin
200 CALL cp_cfm_set_all(rtbse_env%ham_reference(i), cmplx(0.0_dp, 0.0_dp, kind=
dp))
204 CALL initialize_sex_selfenergy(rtbse_env)
208 IF (rtbse_env%diagnose_liouvillian_eig)
THEN
209 CALL diagnose_liouvillian_eigenvalues(rtbse_env)
214 rtbse_env%sim_time = real(rtbse_env%sim_start,
dp)*rtbse_env%sim_dt
217 IF (.NOT. rtbse_env%restart_extracted)
THEN
219 CALL build_rho_lab(rtbse_env, rtbse_env%rho, rtbse_env%sim_time, rho_lab)
224 IF (rtbse_env%dft_control%rtp_control%apply_delta_pulse .AND. (.NOT. rtbse_env%restart_extracted))
THEN
225 CALL apply_delta_pulse_mo(rtbse_env)
230 DO i = rtbse_env%sim_start, rtbse_env%sim_nsteps - 1
234 rtbse_env%sim_time = real(i,
dp)*rtbse_env%sim_dt
235 rtbse_env%sim_step = i
237 CALL solve_rk4_timestep(rtbse_env, rtbse_env%rho, rtbse_env%rho_new)
238 CALL get_electron_number_mo(rtbse_env, rtbse_env%rho_new, &
239 enum_re(1:rtbse_env%n_spin), enum_im(1:rtbse_env%n_spin))
240 timestep_walltime =
m_walltime() - timestep_walltime_start
241 CALL print_timestep_info(rtbse_env, i, enum_re(1:rtbse_env%n_spin), step_walltime=timestep_walltime)
242 CALL cp_iterate(logger%iter_info, iter_nr=i, last=(i == rtbse_env%sim_nsteps - 1))
245 DO j = 1, rtbse_env%n_spin
252 t_phys = real(i + 1,
dp)*rtbse_env%sim_dt
253 CALL build_rho_lab(rtbse_env, rtbse_env%rho, t_phys, rho_lab)
266 CALL print_ft(rtbse_env%rtp_section, &
267 rtbse_env%moments_trace, &
268 rtbse_env%time_trace, &
269 rtbse_env%field_trace, &
270 rtbse_env%dft_control%rtp_control, &
271 info_opt=rtbse_env%unit_nr)
276 CALL timestop(handle)
286 SUBROUTINE initialize_maximum_timestep(rtbse_env)
289 CHARACTER(len=*),
PARAMETER :: routinen =
'initialize_maximum_timestep'
291 CHARACTER(len=256) :: hint_msg
292 INTEGER :: handle, i_first, i_last, ispin, &
293 n_steps_new, n_steps_old
294 REAL(kind=
dp) :: eps_max_ai, eps_min_ai, eps_occ_max, eps_occ_min, eps_virt_max, &
295 eps_virt_min, ev_tmp, grace_factor, omega_max, sim_dt_as, total_time
297 CALL timeset(routinen, handle)
299 i_first = rtbse_env%first_active_mo
300 i_last = rtbse_env%last_active_mo
303 omega_max = maxval(rtbse_env%bs_env%eigenval_GW(i_first:i_last, :, :)) - &
304 minval(rtbse_env%bs_env%eigenval_GW(i_first:i_last, :, :))
306 omega_max = maxval(rtbse_env%bs_env%eigenval_scf_Gamma(i_first:i_last, :)) - &
307 minval(rtbse_env%bs_env%eigenval_scf_Gamma(i_first:i_last, :))
316 rtbse_env%omega_shift = 0.0_dp
317 IF (rtbse_env%tda_active .AND. rtbse_env%tda_shift_to_first_peak)
THEN
318 eps_occ_min = huge(0.0_dp)
319 eps_occ_max = -huge(0.0_dp)
320 eps_virt_min = huge(0.0_dp)
321 eps_virt_max = -huge(0.0_dp)
322 DO ispin = 1, rtbse_env%n_spin
324 IF (rtbse_env%n_occ(ispin) >= i_first)
THEN
326 ev_tmp = minval(rtbse_env%bs_env%eigenval_GW(i_first:rtbse_env%n_occ(ispin), :, ispin))
327 eps_occ_min = min(eps_occ_min, ev_tmp)
328 ev_tmp = maxval(rtbse_env%bs_env%eigenval_GW(i_first:rtbse_env%n_occ(ispin), :, ispin))
329 eps_occ_max = max(eps_occ_max, ev_tmp)
331 ev_tmp = minval(rtbse_env%bs_env%eigenval_scf_Gamma(i_first:rtbse_env%n_occ(ispin), ispin))
332 eps_occ_min = min(eps_occ_min, ev_tmp)
333 ev_tmp = maxval(rtbse_env%bs_env%eigenval_scf_Gamma(i_first:rtbse_env%n_occ(ispin), ispin))
334 eps_occ_max = max(eps_occ_max, ev_tmp)
338 IF (rtbse_env%n_occ(ispin) < i_last)
THEN
340 ev_tmp = minval(rtbse_env%bs_env%eigenval_GW(rtbse_env%n_occ(ispin) + 1:i_last, :, ispin))
341 eps_virt_min = min(eps_virt_min, ev_tmp)
342 ev_tmp = maxval(rtbse_env%bs_env%eigenval_GW(rtbse_env%n_occ(ispin) + 1:i_last, :, ispin))
343 eps_virt_max = max(eps_virt_max, ev_tmp)
345 ev_tmp = minval(rtbse_env%bs_env%eigenval_scf_Gamma(rtbse_env%n_occ(ispin) + 1:i_last, ispin))
346 eps_virt_min = min(eps_virt_min, ev_tmp)
347 ev_tmp = maxval(rtbse_env%bs_env%eigenval_scf_Gamma(rtbse_env%n_occ(ispin) + 1:i_last, ispin))
348 eps_virt_max = max(eps_virt_max, ev_tmp)
353 IF (eps_occ_max > -huge(0.0_dp) .AND. eps_virt_min < huge(0.0_dp))
THEN
354 eps_min_ai = eps_virt_min - eps_occ_max
355 eps_max_ai = eps_virt_max - eps_occ_min
356 rtbse_env%omega_shift = eps_min_ai
357 omega_max = eps_max_ai - eps_min_ai
358 IF (rtbse_env%unit_nr > 0)
THEN
359 WRITE (rtbse_env%unit_nr,
'(A)') &
360 " RTBSE| ---------- First-peak shift diagnostics (TDA, active OV pairs) ----------"
361 WRITE (rtbse_env%unit_nr,
'(A,F14.6,A,F14.6)') &
362 " RTBSE| eps_occ [eV] min / max =", eps_occ_min*
evolt, &
363 " /", eps_occ_max*
evolt
364 WRITE (rtbse_env%unit_nr,
'(A,F14.6,A,F14.6)') &
365 " RTBSE| eps_virt [eV] min / max =", eps_virt_min*
evolt, &
366 " /", eps_virt_max*
evolt
367 WRITE (rtbse_env%unit_nr,
'(A,F14.6,A,F14.6)') &
368 " RTBSE| eps_ai [eV] min / max =", eps_min_ai*
evolt, &
369 " /", eps_max_ai*
evolt
370 WRITE (rtbse_env%unit_nr,
'(A,F14.6)') &
371 " RTBSE| omega_shift [eV] =", rtbse_env%omega_shift*
evolt
372 WRITE (rtbse_env%unit_nr,
'(A,F14.6)') &
373 " RTBSE| omega_max [eV] (full) =", omega_max*
evolt
374 WRITE (rtbse_env%unit_nr,
'(A)') &
375 " RTBSE| ------------------------------------------------------------------------"
379 rtbse_env%omega_shift = 0.0_dp
380 rtbse_env%tda_shift_to_first_peak = .false.
384 rtbse_env%omega_max = omega_max
386 IF (omega_max > 0.0_dp)
THEN
388 rtbse_env%maximum_timestep = 2.0_dp*sqrt(2.0_dp)/omega_max
390 CALL cp_abort(__location__, &
391 "Error in estimating maximum timestep: largest KS/GW gap is "// &
392 "non-positive. Check the active MO window (cutoffs) and the "// &
396 IF (rtbse_env%sim_dt <= 0.0_dp)
THEN
397 CALL cp_abort(__location__, &
398 "TIMESTEP must be positive for linearized RT-BSE. Use RTBSE%ENFORCE_MAX_DT "// &
399 "with a positive TIMESTEP to automatically rewrite TIMESTEP and STEPS.")
402 n_steps_old = max(0, rtbse_env%sim_nsteps)
404 IF (rtbse_env%enforce_max_dt)
THEN
405 total_time = real(n_steps_old,
dp)*rtbse_env%sim_dt
407 IF (rtbse_env%tda_active)
THEN
408 grace_factor = 1.0_dp
410 grace_factor = 4.0_dp
412 IF (rtbse_env%dft_control%rtp_control%initial_wfn ==
use_rt_restart .AND. &
413 rtbse_env%sim_dt_restart > 0.0_dp)
THEN
417 rtbse_env%sim_dt = rtbse_env%sim_dt_restart
418 n_steps_new = max(1, nint(total_time/rtbse_env%sim_dt))
419 rtbse_env%sim_nsteps = n_steps_new
420 sim_dt_as = rtbse_env%sim_dt*
seconds*1e18_dp
421 WRITE (hint_msg,
'(A,F16.4,A,I0,A)') &
422 'ENFORCE_MAX_DT on restart: inheriting original TIMESTEP ', sim_dt_as, &
423 ' as and setting STEPS to ', n_steps_new,
'.'
424 CALL cp_hint(__location__, trim(hint_msg))
427 IF (rtbse_env%sim_dt > rtbse_env%maximum_timestep/grace_factor)
THEN
428 CALL cp_warn(__location__, &
429 "ENFORCE_MAX_DT restart: inherited dt exceeds this run's stability "// &
430 "limit - the recomputed Hamiltonian may make the propagation unstable.")
433 n_steps_new = max(1, ceiling(total_time/(rtbse_env%maximum_timestep/grace_factor)))
434 rtbse_env%sim_dt = total_time/real(n_steps_new,
dp)
435 rtbse_env%sim_nsteps = n_steps_new
436 sim_dt_as = rtbse_env%sim_dt*
seconds*1e18_dp
437 WRITE (hint_msg,
'(A,F16.4,A,I0,A)') &
438 'ENFORCE_MAX_DT enabled. Resetting TIMESTEP to ', sim_dt_as, &
439 ' as and STEPS to ', n_steps_new,
'.'
440 CALL cp_hint(__location__, trim(hint_msg))
444 IF (rtbse_env%sim_nsteps /= n_steps_old)
THEN
445 CALL reallocate_ft_traces(rtbse_env)
448 CALL timestop(handle)
449 END SUBROUTINE initialize_maximum_timestep
455 SUBROUTINE reallocate_ft_traces(rtbse_env)
458 CHARACTER(len=*),
PARAMETER :: routinen =
'reallocate_ft_traces'
462 CALL timeset(routinen, handle)
464 IF (
ASSOCIATED(rtbse_env%moments_trace))
DEALLOCATE (rtbse_env%moments_trace)
465 IF (
ASSOCIATED(rtbse_env%field_trace))
DEALLOCATE (rtbse_env%field_trace)
466 IF (
ASSOCIATED(rtbse_env%time_trace))
DEALLOCATE (rtbse_env%time_trace)
468 ALLOCATE (rtbse_env%moments_trace(rtbse_env%n_spin, 3, rtbse_env%sim_nsteps + 1), &
469 source=cmplx(0.0_dp, 0.0_dp, kind=
dp))
470 ALLOCATE (rtbse_env%field_trace(3, rtbse_env%sim_nsteps + 1), &
471 source=cmplx(0.0_dp, 0.0_dp, kind=
dp))
472 ALLOCATE (rtbse_env%time_trace(rtbse_env%sim_nsteps + 1), source=0.0_dp)
474 CALL timestop(handle)
475 END SUBROUTINE reallocate_ft_traces
482 SUBROUTINE print_linrtbse_header_info(rtbse_env)
485 INTEGER :: ispin, n_steps
486 REAL(kind=
dp) :: e_first, e_last, fft_resolution, &
487 nyquist_frequency, total_time
491 n_steps = max(0, rtbse_env%sim_nsteps)
492 total_time = real(n_steps,
dp)*rtbse_env%sim_dt
493 fft_resolution = 0.0_dp
494 nyquist_frequency = 0.0_dp
495 IF (total_time > 0.0_dp) fft_resolution =
twopi/total_time
496 IF (rtbse_env%sim_dt > 0.0_dp) nyquist_frequency =
twopi/(2.0_dp*rtbse_env%sim_dt)
498 IF (rtbse_env%unit_nr > 0)
THEN
499 WRITE (rtbse_env%unit_nr, *)
''
500 WRITE (rtbse_env%unit_nr,
'(A)')
' /-----------------------------------------------'// &
501 '------------------------------\'
502 WRITE (rtbse_env%unit_nr,
'(A)')
' | '// &
504 WRITE (rtbse_env%unit_nr,
'(A)')
' | Linearized Real Time Bethe-Salpeter Propagation'// &
506 WRITE (rtbse_env%unit_nr,
'(A)')
' | '// &
508 WRITE (rtbse_env%unit_nr,
'(A)')
' \-----------------------------------------------'// &
509 '------------------------------/'
510 WRITE (rtbse_env%unit_nr, *)
''
512 WRITE (rtbse_env%unit_nr,
'(A18,L62)')
' Apply delta pulse', &
513 rtbse_env%dft_control%rtp_control%apply_delta_pulse
514 WRITE (rtbse_env%unit_nr,
'(A)')
''
515 WRITE (rtbse_env%unit_nr,
'(A18,L62)')
' Use Tamm-Dancoff approximation', &
517 IF (rtbse_env%tda_active)
THEN
518 WRITE (rtbse_env%unit_nr,
'(A,T71,L10)')
' TDA first-peak shift active', &
519 rtbse_env%tda_shift_to_first_peak
520 IF (rtbse_env%tda_shift_to_first_peak)
THEN
521 WRITE (rtbse_env%unit_nr,
'(A,T65,F16.6)')
' TDA first-peak shift Omega_0 [eV]:', &
522 rtbse_env%omega_shift*
evolt
526 WRITE (rtbse_env%unit_nr,
'(A)')
''
528 WRITE (rtbse_env%unit_nr,
'(A,T65,F16.4)')
' Estimated maximum timestep within stability region [as]:', &
529 rtbse_env%maximum_timestep*
seconds*1e18_dp
530 WRITE (rtbse_env%unit_nr,
'(A,T65,F16.4)')
' Applied timestep [as]:', &
531 rtbse_env%sim_dt*
seconds*1e18_dp
532 WRITE (rtbse_env%unit_nr,
'(A,T71,I10)')
' Number of propagation steps:', n_steps
533 WRITE (rtbse_env%unit_nr,
'(A,T65,F16.4)')
' Total propagation time [as]:', &
535 WRITE (rtbse_env%unit_nr,
'(A,T65,F16.6)')
' Estimated FFT frequency resolution without interpolation [eV]:', &
537 WRITE (rtbse_env%unit_nr,
'(A,T65,F16.6)')
' Nyquist frequency [eV]:', &
538 nyquist_frequency*
evolt
539 WRITE (rtbse_env%unit_nr,
'(A,T65,F16.6)')
' Estimated maximum oscillation frequency (gap-based) [eV]:', &
540 rtbse_env%omega_max*
evolt
545 IF (rtbse_env%bs_env%gw_flavour ==
evgw0)
THEN
546 WRITE (rtbse_env%unit_nr,
'(A,T75,A6)') &
547 ' GW flavor for computing GW eigenvalues used in RT-BSE:',
' evGW0'
549 WRITE (rtbse_env%unit_nr,
'(A,T75,A6)') &
550 ' GW flavor for computing GW eigenvalues used in RT-BSE:',
' G0W0'
553 WRITE (rtbse_env%unit_nr,
'(A,T75,A6)') &
554 ' Single-particle eigenvalues used in RT-BSE:',
' KS'
558 IF (rtbse_env%rtbse_energy_cutoff_occ > 0.0_dp)
THEN
559 WRITE (rtbse_env%unit_nr,
'(A,T71,F10.3)')
' Active-window occupied energy cutoff [eV]:', &
560 rtbse_env%rtbse_energy_cutoff_occ*
evolt
562 WRITE (rtbse_env%unit_nr,
'(A,T71,A10)')
' Active-window occupied energy cutoff [eV]:',
' disabled'
564 IF (rtbse_env%rtbse_energy_cutoff_empty > 0.0_dp)
THEN
565 WRITE (rtbse_env%unit_nr,
'(A,T71,F10.3)')
' Active-window virtual energy cutoff [eV]:', &
566 rtbse_env%rtbse_energy_cutoff_empty*
evolt
568 WRITE (rtbse_env%unit_nr,
'(A,T71,A10)')
' Active-window virtual energy cutoff [eV]:',
' disabled'
570 WRITE (rtbse_env%unit_nr,
'(A,T71,I10)')
' First active occupied MO index:', rtbse_env%first_active_mo
571 WRITE (rtbse_env%unit_nr,
'(A,T71,I10)')
' Last active virtual MO index:', rtbse_env%last_active_mo
572 WRITE (rtbse_env%unit_nr,
'(A,T71,I10)')
' Number of active MOs:', rtbse_env%mo_active
573 IF (rtbse_env%active_mo_truncation)
THEN
576 DO ispin = 1, rtbse_env%n_spin
577 e_first = (rtbse_env%bs_env%eigenval_scf_Gamma(rtbse_env%first_active_mo, ispin) - &
578 rtbse_env%bs_env%eigenval_scf_Gamma(rtbse_env%n_occ(ispin), ispin))*
evolt
579 e_last = (rtbse_env%bs_env%eigenval_scf_Gamma(rtbse_env%last_active_mo, ispin) - &
580 rtbse_env%bs_env%eigenval_scf_Gamma(rtbse_env%n_occ(ispin) + 1, ispin))*
evolt
581 WRITE (rtbse_env%unit_nr,
'(A,I1,A,T71,F10.3)')
' Spin ', ispin, &
582 ' first active MO, E - E_HOMO (KS) [eV]:', e_first
583 WRITE (rtbse_env%unit_nr,
'(A,I1,A,T71,F10.3)')
' Spin ', ispin, &
584 ' last active MO, E - E_LUMO (KS) [eV]:', e_last
586 e_first = (rtbse_env%bs_env%eigenval_GW(rtbse_env%first_active_mo, 1, ispin) - &
587 rtbse_env%bs_env%eigenval_GW(rtbse_env%n_occ(ispin), 1, ispin))*
evolt
588 e_last = (rtbse_env%bs_env%eigenval_GW(rtbse_env%last_active_mo, 1, ispin) - &
589 rtbse_env%bs_env%eigenval_GW(rtbse_env%n_occ(ispin) + 1, 1, ispin))*
evolt
590 WRITE (rtbse_env%unit_nr,
'(A,I1,A,T71,F10.3)')
' Spin ', ispin, &
591 ' first active MO, E - E_HOMO (QP) [eV]:', e_first
592 WRITE (rtbse_env%unit_nr,
'(A,I1,A,T71,F10.3)')
' Spin ', ispin, &
593 ' last active MO, E - E_LUMO (QP) [eV]:', e_last
599 END SUBROUTINE print_linrtbse_header_info
607 SUBROUTINE populate_c_active(rtbse_env)
610 CHARACTER(len=*),
PARAMETER :: routinen =
'populate_C_active'
614 CALL timeset(routinen, handle)
616 DO i = 1, rtbse_env%n_spin
619 rtbse_env%bs_env%fm_mo_coeff_Gamma(i), rtbse_env%C_active(i), &
620 rtbse_env%n_ao, rtbse_env%mo_active, &
621 1, rtbse_env%first_active_mo, &
623 rtbse_env%bs_env%fm_mo_coeff_Gamma(i)%matrix_struct%context)
626 CALL timestop(handle)
627 END SUBROUTINE populate_c_active
636 SUBROUTINE initialize_moments(rtbse_env)
639 CHARACTER(len=*),
PARAMETER :: routinen =
'initialize_moments'
641 INTEGER :: handle, i_spin, k
642 REAL(kind=
dp),
DIMENSION(3) :: rpoint
644 TYPE(
dbcsr_p_type),
DIMENSION(:),
POINTER :: matrix_s, moments_dbcsr_p
647 CALL timeset(routinen, handle)
649 CALL get_qs_env(rtbse_env%qs_env, bs_env=bs_env, matrix_s=matrix_s)
652 CALL cp_fm_create(tmp_ao, bs_env%fm_s_Gamma%matrix_struct)
656 NULLIFY (moments_dbcsr_p)
657 ALLOCATE (moments_dbcsr_p(3))
660 NULLIFY (moments_dbcsr_p(k)%matrix)
662 ALLOCATE (moments_dbcsr_p(k)%matrix)
664 CALL dbcsr_copy(moments_dbcsr_p(k)%matrix, matrix_s(1)%matrix)
670 reference=rtbse_env%moment_ref_type, ref_point=rtbse_env%user_moment_ref_point)
675 DO i_spin = 1, rtbse_env%n_spin
676 CALL transform_ao_to_mo_covariant_fm(rtbse_env, tmp_ao, rtbse_env%moments(k, i_spin), i_spin)
686 DO i_spin = 1, rtbse_env%n_spin
687 CALL transform_ao_to_mo_covariant_fm(rtbse_env, tmp_ao, rtbse_env%moments_field(k, i_spin), i_spin)
694 DEALLOCATE (moments_dbcsr_p(k)%matrix)
696 DEALLOCATE (moments_dbcsr_p)
700 CALL timestop(handle)
701 END SUBROUTINE initialize_moments
710 SUBROUTINE initialize_density_matrix(rtbse_env)
713 CHARACTER(len=*),
PARAMETER :: routinen =
'initialize_density_matrix'
715 INTEGER :: handle, i, i_row_global, ii, &
716 j_col_global, jj, ncol_global, &
717 ncol_local, nrow_global, nrow_local
718 INTEGER,
DIMENSION(:),
POINTER :: col_indices, row_indices
720 CALL timeset(routinen, handle)
724 nrow_global=nrow_global, ncol_global=ncol_global, &
725 nrow_local=nrow_local, ncol_local=ncol_local, &
726 row_indices=row_indices, col_indices=col_indices)
729 DO i = 1, rtbse_env%n_spin
732 DO ii = 1, nrow_local
733 i_row_global = row_indices(ii)
734 DO jj = 1, ncol_local
735 j_col_global = col_indices(jj)
736 IF (i_row_global == j_col_global .AND. &
737 (i_row_global + rtbse_env%first_active_mo - 1) <= rtbse_env%n_occ(i))
THEN
738 rtbse_env%real_workspace_mo(1)%local_data(ii, jj) = 1.0_dp
743 CALL cp_fm_to_cfm(msourcer=rtbse_env%real_workspace_mo(1), mtarget=rtbse_env%rho(i))
750 CALL timestop(handle)
751 END SUBROUTINE initialize_density_matrix
763 CHARACTER(len=*),
PARAMETER :: routinen =
'initialize_singleparticle_hamiltonian'
765 INTEGER :: abs_mo_idx, handle, i, i_row_global, ii, &
766 j_col_global, jj, ncol_global, &
767 ncol_local, nrow_global, nrow_local
768 INTEGER,
DIMENSION(:),
POINTER :: col_indices, row_indices
771 CALL timeset(routinen, handle)
773 CALL get_qs_env(rtbse_env%qs_env, bs_env=bs_env)
777 nrow_global=nrow_global, ncol_global=ncol_global, &
778 nrow_local=nrow_local, ncol_local=ncol_local, &
779 row_indices=row_indices, col_indices=col_indices)
783 rtbse_env%eps_active(:, :) = 0.0_dp
785 DO i = 1, rtbse_env%n_spin
786 DO ii = 1, nrow_local
787 i_row_global = row_indices(ii)
788 DO jj = 1, ncol_local
789 j_col_global = col_indices(jj)
790 IF (i_row_global == j_col_global)
THEN
791 abs_mo_idx = i_row_global + rtbse_env%first_active_mo - 1
794 rtbse_env%real_workspace_mo(1)%local_data(ii, jj) = bs_env%eigenval_GW(abs_mo_idx, 1, i)
797 rtbse_env%real_workspace_mo(1)%local_data(ii, jj) = bs_env%eigenval_scf_Gamma(abs_mo_idx, i)
804 IF (rtbse_env%tda_active .AND. rtbse_env%tda_shift_to_first_peak)
THEN
805 IF (abs_mo_idx <= rtbse_env%n_occ(i))
THEN
806 rtbse_env%real_workspace_mo(1)%local_data(ii, jj) = &
807 rtbse_env%real_workspace_mo(1)%local_data(ii, jj) + 0.5_dp*rtbse_env%omega_shift
809 rtbse_env%real_workspace_mo(1)%local_data(ii, jj) = &
810 rtbse_env%real_workspace_mo(1)%local_data(ii, jj) - 0.5_dp*rtbse_env%omega_shift
814 rtbse_env%eps_active(i_row_global, i) = rtbse_env%real_workspace_mo(1)%local_data(ii, jj)
818 CALL cp_fm_to_cfm(msourcer=rtbse_env%real_workspace_mo(1), mtarget=rtbse_env%ham_reference_singleparticle(i))
821 CALL rtbse_env%real_workspace_mo(1)%matrix_struct%para_env%sum(rtbse_env%eps_active)
824 CALL timestop(handle)
838 CHARACTER(len=*),
PARAMETER :: routinen =
'initialize_hartree_potential'
840 INTEGER :: handle, i, n_grid
841 LOGICAL :: use_hartree_reference, use_rirs_kernel
844 CALL timeset(routinen, handle)
846 CALL get_qs_env(rtbse_env%qs_env, bs_env=bs_env)
847 use_hartree_reference = (.NOT. rtbse_env%tda_active) .AND. (rtbse_env%n_spin == 1) .AND. &
848 (.NOT. rtbse_env%debug_disable_hartree)
849 use_rirs_kernel = rtbse_env%rirs_kernel
858 IF (use_rirs_kernel .AND. (.NOT. rtbse_env%debug_disable_hartree))
THEN
859 CALL dbcsr_get_info(bs_env%ri_rs%mat_phi_mu_l, nfullrows_total=n_grid)
860 ALLOCATE (rtbse_env%hartree_diag_re(n_grid), rtbse_env%hartree_diag_im(n_grid))
867 IF (use_rirs_kernel .AND. (.NOT. rtbse_env%debug_disable_hartree) .AND. rtbse_env%debug_disable_sex)
THEN
868 CALL cp_warn(__location__, &
869 "RI-RS Hartree rebuilds the full density grid every RK4 stage because SEX is "// &
870 "disabled (DEBUG_DISABLE_SEX) and no SEX-harvested diagonal is available to reuse. "// &
871 "This slows down the Hartree computation considerably.")
876 IF (.NOT. use_rirs_kernel)
THEN
881 DO i = 1, rtbse_env%n_spin
882 CALL cp_cfm_set_all(rtbse_env%ham_reference(i), cmplx(0.0_dp, 0.0_dp, kind=
dp))
889 IF (use_hartree_reference)
THEN
890 DO i = 1, rtbse_env%n_spin
891 IF (use_rirs_kernel)
THEN
894 CALL cp_cfm_to_fm(msource=rtbse_env%rho_ao_scratch(i), &
895 mtargetr=rtbse_env%real_workspace(1))
897 rtbse_env%hartree_curr_ao(i))
900 CALL get_hartree(rtbse_env, rtbse_env%rho_ao_scratch(i), rtbse_env%hartree_curr_ao(i))
903 CALL cp_fm_scale(rtbse_env%spin_degeneracy, rtbse_env%hartree_curr_ao(i))
905 CALL transform_ao_to_mo_covariant_fm(rtbse_env, rtbse_env%hartree_curr_ao(i), rtbse_env%hartree_curr(i), i)
907 CALL transform_mo_occupation_factor_diff_fm(rtbse_env, rtbse_env%hartree_curr(i), i)
910 CALL cp_fm_to_cfm(msourcer=rtbse_env%hartree_curr(i), mtarget=rtbse_env%ham_workspace(1))
912 cmplx(-1.0, 0.0, kind=
dp), rtbse_env%ham_workspace(1))
917 CALL timestop(handle)
927 SUBROUTINE initialize_sex_selfenergy(rtbse_env)
930 CHARACTER(len=*),
PARAMETER :: routinen =
'initialize_sex_selfenergy'
933 LOGICAL :: use_rirs_kernel, use_sex_reference
935 CALL timeset(routinen, handle)
936 use_sex_reference = (.NOT. rtbse_env%tda_active) .AND. (rtbse_env%n_spin == 1) .AND. &
937 (.NOT. rtbse_env%debug_disable_sex)
938 use_rirs_kernel = rtbse_env%rirs_kernel
946 IF (.NOT. use_rirs_kernel)
THEN
950 IF (.NOT.
ASSOCIATED(rtbse_env%bs_env%fm_W_MIC_freq_zero%matrix_struct))
THEN
951 CALL cp_abort(__location__, &
952 "RT-BSE AO-RI kernel needs the screened interaction W(w=0), which the "// &
953 "GW step did not build. Select the RT-BSE propagator with '&RTBSE' or "// &
954 "'&RTBSE RTBSE', not '&RTBSE TDDFT'.")
957 CALL copy_fm_to_dbcsr(rtbse_env%bs_env%fm_W_MIC_freq_zero, rtbse_env%w_dbcsr)
960 CALL dbcsr_set(rtbse_env%w_dbcsr, 0.0_dp)
963 CALL dbcsr_add(rtbse_env%w_dbcsr, rtbse_env%v_dbcsr, 1.0_dp, 1.0_dp)
964 CALL dbt_copy_matrix_to_tensor(rtbse_env%w_dbcsr, rtbse_env%screened_dbt)
967 DO i = 1, rtbse_env%n_spin
974 IF (use_sex_reference)
THEN
976 CALL get_sigma(rtbse_env, rtbse_env%sigma_SEX_ao(i), -1.0_dp, rtbse_env%rho_ao_scratch(i))
978 CALL transform_ao_to_mo_covariant_cfm(rtbse_env, rtbse_env%sigma_SEX_ao(i), rtbse_env%sigma_SEX(i), i)
980 CALL transform_mo_occupation_factor_diff_cfm(rtbse_env, rtbse_env%sigma_SEX(i), i)
983 cmplx(-1.0, 0.0, kind=
dp), rtbse_env%sigma_SEX(i))
988 CALL timestop(handle)
989 END SUBROUTINE initialize_sex_selfenergy
999 SUBROUTINE solve_rk4_timestep(rtbse_env, rho_start, rho_end)
1001 TYPE(
cp_cfm_type),
DIMENSION(:),
POINTER :: rho_start, rho_end
1003 CHARACTER(len=*),
PARAMETER :: routinen =
'solve_rk4_timestep'
1005 INTEGER :: handle, i
1007 CALL timeset(routinen, handle)
1024 DO i = 1, rtbse_env%n_spin
1032 CALL do_rk4_stage(rtbse_env, rho_start, rho_start, rho_end, &
1033 result_weight=1.0_dp/6.0_dp, advance_weight=0.5_dp)
1035 CALL do_rk4_stage(rtbse_env, rtbse_env%rho_workspace, rho_start, rho_end, &
1036 result_weight=1.0_dp/3.0_dp, advance_weight=0.5_dp)
1038 CALL do_rk4_stage(rtbse_env, rtbse_env%rho_workspace, rho_start, rho_end, &
1039 result_weight=1.0_dp/3.0_dp, advance_weight=1.0_dp)
1041 CALL do_rk4_stage(rtbse_env, rtbse_env%rho_workspace, rho_start, rho_end, &
1042 result_weight=1.0_dp/6.0_dp)
1045 rtbse_env%sim_step = rtbse_env%sim_step + 1
1046 rtbse_env%sim_time = rtbse_env%sim_time + rtbse_env%sim_dt
1048 CALL timestop(handle)
1049 END SUBROUTINE solve_rk4_timestep
1068 SUBROUTINE do_rk4_stage(rtbse_env, rho_eval, rho_base, rho_end, result_weight, advance_weight)
1070 TYPE(
cp_cfm_type),
DIMENSION(:),
POINTER :: rho_eval, rho_base, rho_end
1071 REAL(kind=
dp),
INTENT(IN) :: result_weight
1072 REAL(kind=
dp),
INTENT(IN),
OPTIONAL :: advance_weight
1074 INTEGER :: i, mask_mode
1077 IF (rtbse_env%tda_active)
THEN
1078 mask_mode = kernel_input_ov
1079 ELSE IF (rtbse_env%n_spin > 1)
THEN
1080 mask_mode = kernel_input_ovvo
1082 mask_mode = kernel_input_full
1085 CALL build_shared_sex_and_hartree(rtbse_env, rho_eval, mask_mode)
1086 DO i = 1, rtbse_env%n_spin
1087 CALL update_effective_ham_mo(rtbse_env, rho_eval(i), rtbse_env%rk4_coefficients(i), i)
1088 IF (rtbse_env%tda_active .OR. rtbse_env%n_spin > 1)
THEN
1089 CALL project_drho_to_ov(rtbse_env, rtbse_env%rk4_coefficients(i), i)
1094 DO i = 1, rtbse_env%n_spin
1096 cmplx(result_weight*rtbse_env%sim_dt, 0.0_dp, kind=
dp), rtbse_env%rk4_coefficients(i))
1097 IF (
PRESENT(advance_weight))
THEN
1100 cmplx(advance_weight*rtbse_env%sim_dt, 0.0_dp, kind=
dp), rtbse_env%rk4_coefficients(i))
1103 END SUBROUTINE do_rk4_stage
1117 SUBROUTINE build_shared_hartree_ao(rtbse_env, rho_stage, keep_ovvo)
1119 TYPE(
cp_cfm_type),
DIMENSION(:),
POINTER :: rho_stage
1120 LOGICAL,
INTENT(IN) :: keep_ovvo
1122 CHARACTER(len=*),
PARAMETER :: routinen =
'build_shared_hartree_ao'
1124 INTEGER :: handle, isp
1126 CALL timeset(routinen, handle)
1128 DO isp = 1, rtbse_env%n_spin
1129 CALL cp_cfm_to_cfm(rho_stage(isp), rtbse_env%rho_delta_mo(isp))
1130 CALL mask_mo_block_cfm(rtbse_env, rtbse_env%rho_delta_mo(isp), isp, &
1131 keep_ov=.true., keep_ovvo=keep_ovvo)
1132 CALL transform_mo_to_ao_contravariant_cfm(rtbse_env, rtbse_env%rho_delta_mo(isp), &
1133 rtbse_env%rho_ao_scratch(isp), isp)
1136 CALL cp_cfm_set_all(rtbse_env%rho_total_ao_scratch, cmplx(0.0_dp, 0.0_dp, kind=
dp))
1137 DO isp = 1, rtbse_env%n_spin
1139 cmplx(rtbse_env%spin_degeneracy, 0.0_dp, kind=
dp), &
1140 rtbse_env%rho_ao_scratch(isp))
1145 IF (rtbse_env%rirs_kernel)
THEN
1148 rtbse_env%hartree_total_ao)
1151 CALL get_hartree_complex(rtbse_env, rtbse_env%rho_total_ao_scratch, &
1152 rtbse_env%hartree_total_ao, 1)
1154 CALL timestop(handle)
1155 END SUBROUTINE build_shared_hartree_ao
1170 SUBROUTINE build_shared_sex_and_hartree(rtbse_env, rho_stage, mask_mode)
1172 TYPE(
cp_cfm_type),
DIMENSION(:),
POINTER :: rho_stage
1173 INTEGER,
INTENT(IN) :: mask_mode
1175 CHARACTER(len=*),
PARAMETER :: routinen =
'build_shared_sex_and_hartree'
1177 INTEGER :: handle, isp
1178 LOGICAL :: harvest_im, use_hartree, &
1179 use_rirs_kernel, use_sex
1181 CALL timeset(routinen, handle)
1182 use_hartree = .NOT. rtbse_env%debug_disable_hartree
1183 use_sex = .NOT. rtbse_env%debug_disable_sex
1184 use_rirs_kernel = rtbse_env%rirs_kernel
1187 harvest_im = (mask_mode == kernel_input_ov)
1190 IF (use_rirs_kernel .AND. use_sex .AND. use_hartree)
THEN
1191 rtbse_env%hartree_diag_re(:) = 0.0_dp
1192 IF (harvest_im) rtbse_env%hartree_diag_im(:) = 0.0_dp
1196 DO isp = 1, rtbse_env%n_spin
1197 CALL cp_cfm_to_cfm(rho_stage(isp), rtbse_env%rho_delta_mo(isp))
1198 SELECT CASE (mask_mode)
1199 CASE (kernel_input_ov)
1200 CALL mask_mo_block_cfm(rtbse_env, rtbse_env%rho_delta_mo(isp), isp, &
1201 keep_ov=.true., keep_ovvo=.false.)
1202 CASE (kernel_input_ovvo)
1203 CALL mask_mo_block_cfm(rtbse_env, rtbse_env%rho_delta_mo(isp), isp, &
1204 keep_ov=.true., keep_ovvo=.true.)
1205 CASE (kernel_input_full)
1208 cpabort(
"Unknown mask_mode in build_shared_sex_and_hartree")
1210 CALL transform_mo_to_ao_contravariant_cfm(rtbse_env, rtbse_env%rho_delta_mo(isp), &
1211 rtbse_env%rho_ao_scratch(isp), isp)
1215 IF (harvest_im)
THEN
1216 CALL get_sigma(rtbse_env, rtbse_env%sigma_SEX_ao(isp), -1.0_dp, rtbse_env%rho_ao_scratch(isp), &
1217 grid_diag_re_accum=rtbse_env%hartree_diag_re, &
1218 grid_diag_im_accum=rtbse_env%hartree_diag_im)
1220 CALL get_sigma(rtbse_env, rtbse_env%sigma_SEX_ao(isp), -1.0_dp, rtbse_env%rho_ao_scratch(isp), &
1221 grid_diag_re_accum=rtbse_env%hartree_diag_re)
1228 IF (use_hartree)
THEN
1229 IF (use_rirs_kernel .AND. use_sex)
THEN
1230 IF (harvest_im)
THEN
1232 rtbse_env%hartree_total_ao, n_im=rtbse_env%hartree_diag_im)
1235 rtbse_env%hartree_total_ao)
1238 CALL cp_cfm_set_all(rtbse_env%rho_total_ao_scratch, cmplx(0.0_dp, 0.0_dp, kind=
dp))
1239 DO isp = 1, rtbse_env%n_spin
1241 cmplx(1.0_dp, 0.0_dp, kind=
dp), rtbse_env%rho_ao_scratch(isp))
1243 IF (use_rirs_kernel)
THEN
1244 IF (harvest_im)
THEN
1246 rtbse_env%hartree_total_ao)
1249 CALL cp_cfm_to_fm(msource=rtbse_env%rho_total_ao_scratch, &
1250 mtargetr=rtbse_env%real_workspace(1))
1252 rtbse_env%hartree_curr_ao(1))
1253 CALL cp_cfm_set_all(rtbse_env%hartree_total_ao, cmplx(0.0_dp, 0.0_dp, kind=
dp))
1254 CALL cp_fm_to_cfm(msourcer=rtbse_env%hartree_curr_ao(1), &
1255 mtarget=rtbse_env%hartree_total_ao)
1258 IF (harvest_im)
THEN
1259 CALL get_hartree_complex(rtbse_env, rtbse_env%rho_total_ao_scratch, &
1260 rtbse_env%hartree_total_ao, 1)
1263 CALL get_hartree(rtbse_env, rtbse_env%rho_total_ao_scratch, &
1264 rtbse_env%hartree_curr_ao(1))
1265 CALL cp_cfm_set_all(rtbse_env%hartree_total_ao, cmplx(0.0_dp, 0.0_dp, kind=
dp))
1266 CALL cp_fm_to_cfm(msourcer=rtbse_env%hartree_curr_ao(1), &
1267 mtarget=rtbse_env%hartree_total_ao)
1272 CALL timestop(handle)
1273 END SUBROUTINE build_shared_sex_and_hartree
1288 SUBROUTINE update_effective_ham_mo(rtbse_env, rho, ham_effective, ispin)
1293 CHARACTER(len=*),
PARAMETER :: routinen =
'update_effective_ham_MO'
1295 INTEGER :: handle, i_global, i_loc, j_global, &
1297 INTEGER,
DIMENSION(:),
POINTER :: c_idx, r_idx
1298 LOGICAL :: use_hartree, use_sex
1300 CALL timeset(routinen, handle)
1301 use_hartree = .NOT. rtbse_env%debug_disable_hartree
1302 use_sex = .NOT. rtbse_env%debug_disable_sex
1306 CALL cp_cfm_to_cfm(rtbse_env%ham_reference(ispin), ham_effective)
1310 CALL cp_cfm_get_info(matrix=ham_effective, nrow_local=nrl, ncol_local=ncl, &
1311 row_indices=r_idx, col_indices=c_idx)
1313 j_global = c_idx(j_loc)
1315 i_global = r_idx(i_loc)
1316 ham_effective%local_data(i_loc, j_loc) = ham_effective%local_data(i_loc, j_loc) &
1317 + cmplx(rtbse_env%eps_active(i_global, ispin) - rtbse_env%eps_active(j_global, ispin), &
1318 0.0_dp, kind=
dp)*rho%local_data(i_loc, j_loc)
1322 IF (rtbse_env%dft_control%apply_efield_field)
THEN
1323 CALL cp_abort(__location__, &
1324 "Continuous/pulsed E(t) field coupling is not implemented for linearized "// &
1325 "RT-BSE. Only the delta-kick (impulsive) absorption spectrum is supported; "// &
1326 "use APPLY_DELTA_PULSE.")
1329 rtbse_env%field(:) = 0.0_dp
1331 IF (.NOT. rtbse_env%tda_active)
THEN
1337 CALL transform_ao_to_mo_covariant_cfm(rtbse_env, rtbse_env%sigma_SEX_ao(ispin), &
1338 rtbse_env%sigma_SEX(ispin), ispin)
1339 CALL transform_mo_occupation_factor_diff_cfm(rtbse_env, rtbse_env%sigma_SEX(ispin), ispin)
1341 cmplx(1.0_dp, 0.0_dp, kind=
dp), rtbse_env%sigma_SEX(ispin))
1343 IF (use_hartree)
THEN
1345 CALL transform_ao_to_mo_covariant_cfm(rtbse_env, rtbse_env%hartree_total_ao, &
1346 rtbse_env%ham_workspace(1), ispin)
1347 CALL transform_mo_occupation_factor_diff_cfm(rtbse_env, rtbse_env%ham_workspace(1), ispin)
1348 CALL cp_cfm_scale(cmplx(rtbse_env%spin_degeneracy, 0.0_dp, kind=
dp), rtbse_env%ham_workspace(1))
1350 cmplx(1.0_dp, 0.0_dp, kind=
dp), rtbse_env%ham_workspace(1))
1360 CALL transform_ao_to_mo_covariant_cfm(rtbse_env, rtbse_env%sigma_SEX_ao(ispin), &
1361 rtbse_env%sigma_SEX(ispin), ispin)
1362 CALL mask_mo_block_cfm(rtbse_env, rtbse_env%sigma_SEX(ispin), ispin, keep_ov=.true.)
1367 IF (use_hartree)
THEN
1368 CALL transform_ao_to_mo_covariant_cfm(rtbse_env, rtbse_env%hartree_total_ao, &
1369 rtbse_env%ham_workspace(1), ispin)
1370 CALL mask_mo_block_cfm(rtbse_env, rtbse_env%ham_workspace(1), ispin, keep_ov=.true.)
1371 CALL cp_cfm_scale(cmplx(rtbse_env%spin_degeneracy, 0.0_dp, kind=
dp), rtbse_env%ham_workspace(1))
1373 cmplx(-1.0_dp, 0.0_dp, kind=
dp), rtbse_env%ham_workspace(1))
1374 CALL cp_cfm_transpose(rtbse_env%ham_workspace(1),
'C', rtbse_env%rho_delta_mo(ispin))
1376 cmplx(1.0_dp, 0.0_dp, kind=
dp), rtbse_env%rho_delta_mo(ispin))
1382 cmplx(-1.0_dp, 0.0_dp, kind=
dp), rtbse_env%sigma_SEX(ispin))
1383 CALL cp_cfm_transpose(rtbse_env%sigma_SEX(ispin),
'C', rtbse_env%rho_delta_mo(ispin))
1385 cmplx(1.0_dp, 0.0_dp, kind=
dp), rtbse_env%rho_delta_mo(ispin))
1390 CALL transform_mo_to_ao_contravariant_cfm(rtbse_env, rho, rtbse_env%rho_ao_scratch(ispin), ispin)
1393 CALL cp_cfm_scale(cmplx(0.0_dp, -1.0_dp, kind=
dp), ham_effective)
1395 CALL timestop(handle)
1396 END SUBROUTINE update_effective_ham_mo
1420 SUBROUTINE apply_liouvillian_to_drho_spin(rtbse_env, drho_in, L_drho_out, ispin)
1424 INTEGER,
INTENT(IN) :: ispin
1426 CHARACTER(len=*),
PARAMETER :: routinen =
'apply_liouvillian_to_drho_spin'
1428 INTEGER :: abs_mo_idx, handle, i_row_global, ii, &
1429 j_col_global, jj, ncol_local, &
1431 INTEGER,
DIMENSION(:),
POINTER :: col_indices, row_indices
1432 LOGICAL :: use_hartree, use_sex
1434 CALL timeset(routinen, handle)
1438 use_hartree = .NOT. rtbse_env%debug_disable_hartree
1439 use_sex = .NOT. rtbse_env%debug_disable_sex
1448 IF (rtbse_env%tda_active)
THEN
1449 CALL mask_mo_block_cfm(rtbse_env, rtbse_env%drho_probe(ispin), ispin, keep_ov=.true.)
1453 CALL transform_mo_to_ao_contravariant_cfm(rtbse_env, rtbse_env%drho_probe(ispin), &
1454 rtbse_env%rho_ao_scratch(ispin), ispin)
1468 nrow_local=nrow_local, ncol_local=ncol_local, &
1469 row_indices=row_indices, col_indices=col_indices)
1471 DO ii = 1, nrow_local
1472 i_row_global = row_indices(ii)
1473 DO jj = 1, ncol_local
1474 j_col_global = col_indices(jj)
1475 IF (i_row_global == j_col_global)
THEN
1476 abs_mo_idx = i_row_global + rtbse_env%first_active_mo - 1
1477 rtbse_env%real_workspace_mo(1)%local_data(ii, jj) = &
1478 rtbse_env%bs_env%eigenval_GW(abs_mo_idx, 1, ispin)
1482 CALL cp_fm_to_cfm(msourcer=rtbse_env%real_workspace_mo(1), &
1483 mtarget=rtbse_env%ham_workspace(1))
1485 CALL cp_cfm_gemm(
'N',
'N', rtbse_env%mo_active, rtbse_env%mo_active, rtbse_env%mo_active, &
1486 cmplx(1.0_dp, 0.0_dp, kind=
dp), drho_in, rtbse_env%ham_workspace(1), &
1487 cmplx(1.0_dp, 0.0_dp, kind=
dp), l_drho_out)
1489 CALL cp_cfm_gemm(
'N',
'N', rtbse_env%mo_active, rtbse_env%mo_active, rtbse_env%mo_active, &
1490 cmplx(-1.0_dp, 0.0_dp, kind=
dp), rtbse_env%ham_workspace(1), drho_in, &
1491 cmplx(1.0_dp, 0.0_dp, kind=
dp), l_drho_out)
1499 IF (use_hartree)
THEN
1500 IF (rtbse_env%rirs_kernel)
THEN
1503 rtbse_env%hartree_total_ao)
1506 CALL get_hartree_complex(rtbse_env, rtbse_env%rho_ao_scratch(ispin), &
1507 rtbse_env%hartree_total_ao, ispin)
1509 CALL transform_ao_to_mo_covariant_cfm(rtbse_env, rtbse_env%hartree_total_ao, &
1510 rtbse_env%ham_workspace(1), ispin)
1511 CALL add_k_mo_to_l_drho(rtbse_env, rtbse_env%ham_workspace(1), l_drho_out, &
1512 cmplx(rtbse_env%spin_degeneracy, 0.0_dp, kind=
dp), ispin)
1521 CALL get_sigma(rtbse_env, rtbse_env%sigma_SEX_ao(ispin), -1.0_dp, rtbse_env%rho_ao_scratch(ispin))
1522 CALL transform_ao_to_mo_covariant_cfm(rtbse_env, rtbse_env%sigma_SEX_ao(ispin), &
1523 rtbse_env%sigma_SEX(ispin), ispin)
1524 CALL add_k_mo_to_l_drho(rtbse_env, rtbse_env%sigma_SEX(ispin), l_drho_out, &
1525 cmplx(1.0_dp, 0.0_dp, kind=
dp), ispin)
1528 CALL timestop(handle)
1529 END SUBROUTINE apply_liouvillian_to_drho_spin
1547 SUBROUTINE add_k_mo_to_l_drho(rtbse_env, K_MO, L_drho_out, scale, ispin)
1549 TYPE(
cp_cfm_type),
INTENT(INOUT) :: k_mo, l_drho_out
1550 COMPLEX(kind=dp),
INTENT(IN) :: scale
1551 INTEGER,
INTENT(IN) :: ispin
1553 CHARACTER(len=*),
PARAMETER :: routinen =
'add_K_MO_to_L_drho'
1557 CALL timeset(routinen, handle)
1559 IF (rtbse_env%tda_active)
THEN
1560 CALL mask_mo_block_cfm(rtbse_env, k_mo, ispin, keep_ov=.true.)
1563 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))
1568 CALL timestop(handle)
1569 END SUBROUTINE add_k_mo_to_l_drho
1584 SUBROUTINE apply_liouvillian_to_drho(rtbse_env, drho_in, L_drho_out)
1586 TYPE(
cp_cfm_type),
DIMENSION(:),
POINTER :: drho_in, l_drho_out
1588 CHARACTER(len=*),
PARAMETER :: routinen =
'apply_liouvillian_to_drho'
1590 INTEGER :: abs_mo_idx, handle, i_row_global, ii, &
1591 isp, isp_out, j_col_global, jj, &
1592 ncol_local, nrow_local
1593 INTEGER,
DIMENSION(:),
POINTER :: col_indices, row_indices
1594 LOGICAL :: use_hartree, use_sex
1596 CALL timeset(routinen, handle)
1598 use_hartree = .NOT. rtbse_env%debug_disable_hartree
1599 use_sex = .NOT. rtbse_env%debug_disable_sex
1602 DO isp = 1, rtbse_env%n_spin
1610 nrow_local=nrow_local, ncol_local=ncol_local, &
1611 row_indices=row_indices, col_indices=col_indices)
1612 DO isp = 1, rtbse_env%n_spin
1614 DO ii = 1, nrow_local
1615 i_row_global = row_indices(ii)
1616 DO jj = 1, ncol_local
1617 j_col_global = col_indices(jj)
1618 IF (i_row_global == j_col_global)
THEN
1619 abs_mo_idx = i_row_global + rtbse_env%first_active_mo - 1
1620 rtbse_env%real_workspace_mo(1)%local_data(ii, jj) = &
1621 rtbse_env%bs_env%eigenval_GW(abs_mo_idx, 1, isp)
1625 CALL cp_fm_to_cfm(msourcer=rtbse_env%real_workspace_mo(1), &
1626 mtarget=rtbse_env%ham_workspace(1))
1628 CALL cp_cfm_gemm(
'N',
'N', rtbse_env%mo_active, rtbse_env%mo_active, rtbse_env%mo_active, &
1629 cmplx(1.0_dp, 0.0_dp, kind=
dp), drho_in(isp), rtbse_env%ham_workspace(1), &
1630 cmplx(1.0_dp, 0.0_dp, kind=
dp), l_drho_out(isp))
1631 CALL cp_cfm_gemm(
'N',
'N', rtbse_env%mo_active, rtbse_env%mo_active, rtbse_env%mo_active, &
1632 cmplx(-1.0_dp, 0.0_dp, kind=
dp), rtbse_env%ham_workspace(1), drho_in(isp), &
1633 cmplx(1.0_dp, 0.0_dp, kind=
dp), l_drho_out(isp))
1639 IF (use_hartree .OR. use_sex)
THEN
1640 CALL build_shared_hartree_ao(rtbse_env, drho_in, keep_ovvo=.false.)
1646 IF (use_hartree)
THEN
1647 DO isp_out = 1, rtbse_env%n_spin
1648 CALL transform_ao_to_mo_covariant_cfm(rtbse_env, rtbse_env%hartree_total_ao, &
1649 rtbse_env%ham_workspace(1), isp_out)
1650 CALL add_k_mo_to_l_drho(rtbse_env, rtbse_env%ham_workspace(1), l_drho_out(isp_out), &
1651 cmplx(1.0_dp, 0.0_dp, kind=
dp), isp_out)
1658 DO isp = 1, rtbse_env%n_spin
1660 CALL get_sigma(rtbse_env, rtbse_env%sigma_SEX_ao(isp), -1.0_dp, rtbse_env%rho_ao_scratch(isp))
1661 CALL transform_ao_to_mo_covariant_cfm(rtbse_env, rtbse_env%sigma_SEX_ao(isp), &
1662 rtbse_env%sigma_SEX(isp), isp)
1663 CALL add_k_mo_to_l_drho(rtbse_env, rtbse_env%sigma_SEX(isp), l_drho_out(isp), &
1664 cmplx(1.0_dp, 0.0_dp, kind=
dp), isp)
1668 CALL timestop(handle)
1669 END SUBROUTINE apply_liouvillian_to_drho
1680 SUBROUTINE diagnose_liouvillian_eigenvalues(rtbse_env)
1683 CHARACTER(len=*),
PARAMETER :: routinen =
'diagnose_liouvillian_eigenvalues'
1687 CALL timeset(routinen, handle)
1689 IF (rtbse_env%tda_active)
THEN
1690 CALL diagnose_tda_liouvillian(rtbse_env)
1692 CALL diagnose_abba_liouvillian(rtbse_env)
1695 CALL timestop(handle)
1696 END SUBROUTINE diagnose_liouvillian_eigenvalues
1712 SUBROUTINE diagnose_tda_liouvillian(rtbse_env)
1715 CHARACTER(len=*),
PARAMETER :: routinen =
'diagnose_TDA_liouvillian'
1717 COMPLEX(kind=dp),
ALLOCATABLE,
DIMENSION(:, :) :: ov_block
1718 INTEGER :: b, eig_unit, handle, j, k_col, k_local, &
1719 n, n_ov_joint, sigma_out, sigma_probe
1720 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: n_act_occ, n_act_virt, n_ov, off
1721 REAL(kind=
dp) :: residual_max
1724 CALL timeset(routinen, handle)
1729 ALLOCATE (n_act_occ(rtbse_env%n_spin), n_act_virt(rtbse_env%n_spin), &
1730 n_ov(rtbse_env%n_spin), off(rtbse_env%n_spin))
1732 DO sigma_probe = 1, rtbse_env%n_spin
1733 n_act_occ(sigma_probe) = rtbse_env%n_occ(sigma_probe) - rtbse_env%first_active_mo + 1
1734 n_act_virt(sigma_probe) = rtbse_env%last_active_mo - rtbse_env%n_occ(sigma_probe)
1735 n_ov(sigma_probe) = n_act_occ(sigma_probe)*n_act_virt(sigma_probe)
1736 off(sigma_probe) = n_ov_joint
1737 n_ov_joint = n_ov_joint + n_ov(sigma_probe)
1740 IF (rtbse_env%unit_nr > 0)
THEN
1741 WRITE (rtbse_env%unit_nr,
'(A)')
' RTBSE| ----- TDA Liouvillian diagnostic -----'
1742 WRITE (rtbse_env%unit_nr,
'(A,I0,A,I0)') &
1743 ' RTBSE| n_spin = ', rtbse_env%n_spin,
', joint N_OV = ', n_ov_joint
1744 WRITE (rtbse_env%unit_nr,
'(A)')
' RTBSE|'
1751 file_form=
"FORMATTED", &
1752 file_position=
"REWIND", &
1753 ignore_should_output=.true.)
1754 IF (eig_unit > 0)
THEN
1755 WRITE (eig_unit,
'(A)')
'# Joint spin-block TDA Liouvillian eigenvalues'
1756 IF (rtbse_env%n_spin == 1)
THEN
1757 WRITE (eig_unit,
'(A,I0,A,I0)')
'# n_spin = ', rtbse_env%n_spin,
', N_OV = ', n_ov(1)
1759 WRITE (eig_unit,
'(A,I0,A,I0,A,I0)')
'# n_spin = ', rtbse_env%n_spin, &
1760 ', N_OV(1) = ', n_ov(1),
', N_OV(2) = ', n_ov(2)
1770 DO sigma_probe = 1, rtbse_env%n_spin
1771 DO b = rtbse_env%n_occ(sigma_probe) + 1, rtbse_env%last_active_mo
1772 DO j = rtbse_env%first_active_mo, rtbse_env%n_occ(sigma_probe)
1773 k_local = (b - rtbse_env%n_occ(sigma_probe) - 1)*n_act_occ(sigma_probe) + &
1774 (j - rtbse_env%first_active_mo + 1)
1775 k_col = off(sigma_probe) + k_local
1777 DO sigma_out = 1, rtbse_env%n_spin
1778 CALL cp_cfm_set_all(rtbse_env%drho_probe(sigma_out), cmplx(0.0_dp, 0.0_dp, kind=
dp))
1781 j - rtbse_env%first_active_mo + 1, &
1782 b - rtbse_env%first_active_mo + 1, &
1783 cmplx(1.0_dp, 0.0_dp, kind=
dp))
1787 IF (rtbse_env%n_spin == 1)
THEN
1788 CALL apply_liouvillian_to_drho_spin(rtbse_env, rtbse_env%drho_probe(1), &
1789 rtbse_env%L_drho(1), 1)
1791 CALL apply_liouvillian_to_drho(rtbse_env, rtbse_env%drho_probe, rtbse_env%L_drho)
1795 DO sigma_out = 1, rtbse_env%n_spin
1796 ALLOCATE (ov_block(n_act_occ(sigma_out), n_act_virt(sigma_out)))
1798 start_row=1, start_col=n_act_occ(sigma_out) + 1, &
1799 n_rows=n_act_occ(sigma_out), n_cols=n_act_virt(sigma_out))
1801 reshape(ov_block, [n_ov(sigma_out), 1]), &
1802 start_row=off(sigma_out) + 1, start_col=k_col, &
1803 n_rows=n_ov(sigma_out), n_cols=1)
1804 DEALLOCATE (ov_block)
1815 cmplx(-1.0_dp, 0.0_dp, kind=
dp), rtbse_env%L_pairs)
1816 residual_max =
cp_cfm_norm(rtbse_env%eigvecs_pairs,
'M')
1817 IF (rtbse_env%unit_nr > 0)
THEN
1818 WRITE (rtbse_env%unit_nr,
'(A,ES16.6)') &
1819 ' RTBSE| Hermitian residual ||L - L^H||_max = ', residual_max
1820 WRITE (rtbse_env%unit_nr,
'(A)')
' RTBSE|'
1822 IF (residual_max > 1.0e-6_dp)
THEN
1823 cpabort(
"Liouvillian Hermitian residual > 1e-6 - check kernel signs / symmetry.")
1827 CALL cp_cfm_heevd(rtbse_env%L_pairs, rtbse_env%eigvecs_pairs, &
1828 rtbse_env%eigenvalues_liouvillian)
1831 IF (rtbse_env%unit_nr > 0)
THEN
1832 WRITE (rtbse_env%unit_nr,
'(A,T26,A,T59,A)') &
1833 ' RTBSE|',
"Excitation index n",
"Excitation energy (eV)"
1834 DO n = 1, n_ov_joint
1835 WRITE (rtbse_env%unit_nr,
'(A,T40,I4,T69,F12.4)') &
1836 ' RTBSE|', n, rtbse_env%eigenvalues_liouvillian(n)*
evolt
1838 WRITE (rtbse_env%unit_nr,
'(A)')
' RTBSE|'
1840 IF (eig_unit > 0)
THEN
1841 WRITE (eig_unit,
'(A)')
'# n Omega [a.u.] Omega [eV]'
1842 DO n = 1, n_ov_joint
1843 WRITE (eig_unit,
'(I5,4X,ES24.14E3,4X,ES24.14E3)') n, &
1844 rtbse_env%eigenvalues_liouvillian(n), &
1845 rtbse_env%eigenvalues_liouvillian(n)*
evolt
1851 DEALLOCATE (n_act_occ, n_act_virt, n_ov, off)
1853 CALL timestop(handle)
1854 END SUBROUTINE diagnose_tda_liouvillian
1871 SUBROUTINE diagnose_abba_liouvillian(rtbse_env)
1874 CHARACTER(len=*),
PARAMETER :: routinen =
'diagnose_ABBA_liouvillian'
1876 COMPLEX(kind=dp),
ALLOCATABLE,
DIMENSION(:, :) :: ov_block, vo_block
1877 COMPLEX(kind=dp),
DIMENSION(:, :),
POINTER :: b_local
1878 INTEGER :: b, eig_unit, handle, j, k_col, k_local, &
1879 n, n_ov_joint, sigma_out, sigma_probe
1880 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: n_act_occ, n_act_virt, n_ov, off
1881 REAL(kind=
dp) :: lambda_min_amb, residual_a, residual_b
1884 CALL timeset(routinen, handle)
1890 ALLOCATE (n_act_occ(rtbse_env%n_spin), n_act_virt(rtbse_env%n_spin), &
1891 n_ov(rtbse_env%n_spin), off(rtbse_env%n_spin))
1893 DO sigma_probe = 1, rtbse_env%n_spin
1894 n_act_occ(sigma_probe) = rtbse_env%n_occ(sigma_probe) - rtbse_env%first_active_mo + 1
1895 n_act_virt(sigma_probe) = rtbse_env%last_active_mo - rtbse_env%n_occ(sigma_probe)
1896 n_ov(sigma_probe) = n_act_occ(sigma_probe)*n_act_virt(sigma_probe)
1897 off(sigma_probe) = n_ov_joint
1898 n_ov_joint = n_ov_joint + n_ov(sigma_probe)
1901 IF (rtbse_env%unit_nr > 0)
THEN
1902 WRITE (rtbse_env%unit_nr,
'(A)')
' RTBSE| ----- ABBA Liouvillian diagnostic -----'
1903 WRITE (rtbse_env%unit_nr,
'(A,I0,A,I0)') &
1904 ' RTBSE| n_spin = ', rtbse_env%n_spin,
', joint N_OV = ', n_ov_joint
1905 WRITE (rtbse_env%unit_nr,
'(A)')
' RTBSE|'
1910 file_form=
"FORMATTED", &
1911 file_position=
"REWIND", &
1912 ignore_should_output=.true.)
1913 IF (eig_unit > 0)
THEN
1914 WRITE (eig_unit,
'(A)')
'# Joint spin-block ABBA Liouvillian eigenvalues'
1915 IF (rtbse_env%n_spin == 1)
THEN
1916 WRITE (eig_unit,
'(A,I0,A,I0)')
'# n_spin = ', rtbse_env%n_spin,
', N_OV = ', n_ov(1)
1918 WRITE (eig_unit,
'(A,I0,A,I0,A,I0)')
'# n_spin = ', rtbse_env%n_spin, &
1919 ', N_OV(1) = ', n_ov(1),
', N_OV(2) = ', n_ov(2)
1929 DO sigma_probe = 1, rtbse_env%n_spin
1930 DO b = rtbse_env%n_occ(sigma_probe) + 1, rtbse_env%last_active_mo
1931 DO j = rtbse_env%first_active_mo, rtbse_env%n_occ(sigma_probe)
1932 k_local = (b - rtbse_env%n_occ(sigma_probe) - 1)*n_act_occ(sigma_probe) + &
1933 (j - rtbse_env%first_active_mo + 1)
1934 k_col = off(sigma_probe) + k_local
1936 DO sigma_out = 1, rtbse_env%n_spin
1937 CALL cp_cfm_set_all(rtbse_env%drho_probe(sigma_out), cmplx(0.0_dp, 0.0_dp, kind=
dp))
1940 j - rtbse_env%first_active_mo + 1, &
1941 b - rtbse_env%first_active_mo + 1, &
1942 cmplx(1.0_dp, 0.0_dp, kind=
dp))
1944 IF (rtbse_env%n_spin == 1)
THEN
1945 CALL apply_liouvillian_to_drho_spin(rtbse_env, rtbse_env%drho_probe(1), &
1946 rtbse_env%L_drho(1), 1)
1948 CALL apply_liouvillian_to_drho(rtbse_env, rtbse_env%drho_probe, rtbse_env%L_drho)
1951 DO sigma_out = 1, rtbse_env%n_spin
1952 ALLOCATE (ov_block(n_act_occ(sigma_out), n_act_virt(sigma_out)))
1953 ALLOCATE (vo_block(n_act_virt(sigma_out), n_act_occ(sigma_out)))
1955 start_row=1, start_col=n_act_occ(sigma_out) + 1, &
1956 n_rows=n_act_occ(sigma_out), n_cols=n_act_virt(sigma_out))
1958 reshape(ov_block, [n_ov(sigma_out), 1]), &
1959 start_row=off(sigma_out) + 1, start_col=k_col, &
1960 n_rows=n_ov(sigma_out), n_cols=1)
1963 start_row=n_act_occ(sigma_out) + 1, start_col=1, &
1964 n_rows=n_act_virt(sigma_out), n_cols=n_act_occ(sigma_out))
1966 reshape(transpose(vo_block), [n_ov(sigma_out), 1]), &
1967 start_row=off(sigma_out) + 1, start_col=k_col, &
1968 n_rows=n_ov(sigma_out), n_cols=1)
1969 DEALLOCATE (ov_block, vo_block)
1977 b_local => rtbse_env%B_mat%local_data
1978 b_local = -conjg(b_local)
1983 cmplx(-1.0_dp, 0.0_dp, kind=
dp), rtbse_env%A_mat)
1984 residual_a =
cp_cfm_norm(rtbse_env%eigvecs_pairs,
'M')
1988 cmplx(-1.0_dp, 0.0_dp, kind=
dp), rtbse_env%B_mat)
1989 residual_b =
cp_cfm_norm(rtbse_env%eigvecs_pairs,
'M')
1991 IF (rtbse_env%unit_nr > 0)
THEN
1992 WRITE (rtbse_env%unit_nr,
'(A,ES16.6)') &
1993 ' RTBSE| Hermitian residual ||A - A^H||_max = ', residual_a
1994 WRITE (rtbse_env%unit_nr,
'(A,ES16.6)') &
1995 ' RTBSE| Symmetry residual ||B - B^T||_max = ', residual_b
1997 IF (residual_a > 1.0e-6_dp)
THEN
1998 cpabort(
"A is not Hermitian within 1e-6 - check kernel signs / symmetry.")
2000 IF (residual_b > 1.0e-6_dp)
THEN
2001 cpabort(
"B is not symmetric within 1e-6 - check kernel signs / symmetry.")
2007 cmplx(-1.0_dp, 0.0_dp, kind=
dp), rtbse_env%B_mat)
2010 cmplx(1.0_dp, 0.0_dp, kind=
dp), rtbse_env%B_mat)
2013 CALL cp_cfm_to_cfm(rtbse_env%AmB_scratch, rtbse_env%L_pairs)
2014 CALL cp_cfm_heevd(rtbse_env%L_pairs, rtbse_env%eigvecs_pairs, rtbse_env%eigenvalues_liouvillian)
2015 lambda_min_amb = rtbse_env%eigenvalues_liouvillian(1)
2016 IF (rtbse_env%unit_nr > 0)
THEN
2017 WRITE (rtbse_env%unit_nr,
'(A,ES16.6,A,F12.6,A)') &
2018 ' RTBSE| lambda_min(A - B) = ', &
2019 lambda_min_amb,
' a.u. (', lambda_min_amb*
evolt,
' eV)'
2022 IF (lambda_min_amb < 0.0_dp)
THEN
2023 CALL cp_abort(__location__, &
2024 "(A - B) not positive definite - this may hint at a triplet or "// &
2025 "charge-transfer instability of the reference state.")
2030 CALL cp_cfm_power(rtbse_env%AmB_scratch, threshold=0.0_dp, exponent=0.5_dp)
2033 CALL cp_cfm_gemm(
'N',
'N', n_ov_joint, n_ov_joint, n_ov_joint, &
2034 cmplx(1.0_dp, 0.0_dp, kind=
dp), &
2035 rtbse_env%AmB_scratch, rtbse_env%ApB_scratch, &
2036 cmplx(0.0_dp, 0.0_dp, kind=
dp), &
2038 CALL cp_cfm_gemm(
'N',
'N', n_ov_joint, n_ov_joint, n_ov_joint, &
2039 cmplx(1.0_dp, 0.0_dp, kind=
dp), &
2040 rtbse_env%B_mat, rtbse_env%AmB_scratch, &
2041 cmplx(0.0_dp, 0.0_dp, kind=
dp), &
2045 CALL cp_cfm_heevd(rtbse_env%L_pairs, rtbse_env%eigvecs_pairs, rtbse_env%eigenvalues_liouvillian)
2046 DO n = 1, n_ov_joint
2047 IF (rtbse_env%eigenvalues_liouvillian(n) < 0.0_dp)
THEN
2048 rtbse_env%eigenvalues_liouvillian(n) = 0.0_dp
2050 rtbse_env%eigenvalues_liouvillian(n) = sqrt(rtbse_env%eigenvalues_liouvillian(n))
2054 IF (rtbse_env%unit_nr > 0)
THEN
2055 WRITE (rtbse_env%unit_nr,
'(A)')
' RTBSE|'
2056 WRITE (rtbse_env%unit_nr,
'(A,T26,A,T59,A)') &
2057 ' RTBSE|',
"Excitation index n",
"Excitation energy (eV)"
2058 DO n = 1, n_ov_joint
2059 WRITE (rtbse_env%unit_nr,
'(A,T40,I4,T69,F12.4)') &
2060 ' RTBSE|', n, rtbse_env%eigenvalues_liouvillian(n)*
evolt
2062 WRITE (rtbse_env%unit_nr,
'(A)')
' RTBSE|'
2064 IF (eig_unit > 0)
THEN
2065 WRITE (eig_unit,
'(A)')
'# n Omega [a.u.] Omega [eV]'
2066 DO n = 1, n_ov_joint
2067 WRITE (eig_unit,
'(I5,4X,ES24.14E3,4X,ES24.14E3)') n, &
2068 rtbse_env%eigenvalues_liouvillian(n), &
2069 rtbse_env%eigenvalues_liouvillian(n)*
evolt
2075 DEALLOCATE (n_act_occ, n_act_virt, n_ov, off)
2077 CALL timestop(handle)
2078 END SUBROUTINE diagnose_abba_liouvillian
2088 SUBROUTINE transform_ao_to_mo_covariant_fm(rtbse_env, fm_ao, fm_mo, i_spin)
2091 INTEGER,
INTENT(IN) :: i_spin
2093 CHARACTER(len=*),
PARAMETER :: routinen =
'transform_ao_to_mo_covariant_fm'
2097 CALL timeset(routinen, handle)
2100 CALL parallel_gemm(
"N",
"N", rtbse_env%n_ao, rtbse_env%mo_active, rtbse_env%n_ao, &
2101 1.0_dp, fm_ao, rtbse_env%C_active(i_spin), &
2102 0.0_dp, rtbse_env%ao_mo_workspace(1))
2104 CALL parallel_gemm(
"T",
"N", rtbse_env%mo_active, rtbse_env%mo_active, rtbse_env%n_ao, &
2105 1.0_dp, rtbse_env%C_active(i_spin), rtbse_env%ao_mo_workspace(1), &
2108 CALL timestop(handle)
2109 END SUBROUTINE transform_ao_to_mo_covariant_fm
2119 SUBROUTINE transform_ao_to_mo_covariant_cfm(rtbse_env, fm_ao, fm_mo, i_spin)
2122 INTEGER,
INTENT(IN) :: i_spin
2124 CHARACTER(len=*),
PARAMETER :: routinen =
'transform_ao_to_mo_covariant_cfm'
2128 CALL timeset(routinen, handle)
2131 CALL cp_cfm_to_fm(msource=fm_ao, mtargetr=rtbse_env%real_workspace(1), &
2132 mtargeti=rtbse_env%real_workspace(2))
2134 CALL parallel_gemm(
"N",
"N", rtbse_env%n_ao, rtbse_env%mo_active, rtbse_env%n_ao, &
2135 1.0_dp, rtbse_env%real_workspace(1), rtbse_env%C_active(i_spin), &
2136 0.0_dp, rtbse_env%ao_mo_workspace(1))
2137 CALL parallel_gemm(
"T",
"N", rtbse_env%mo_active, rtbse_env%mo_active, rtbse_env%n_ao, &
2138 1.0_dp, rtbse_env%C_active(i_spin), rtbse_env%ao_mo_workspace(1), &
2139 0.0_dp, rtbse_env%real_workspace_mo(1))
2141 CALL parallel_gemm(
"N",
"N", rtbse_env%n_ao, rtbse_env%mo_active, rtbse_env%n_ao, &
2142 1.0_dp, rtbse_env%real_workspace(2), rtbse_env%C_active(i_spin), &
2143 0.0_dp, rtbse_env%ao_mo_workspace(1))
2144 CALL parallel_gemm(
"T",
"N", rtbse_env%mo_active, rtbse_env%mo_active, rtbse_env%n_ao, &
2145 1.0_dp, rtbse_env%C_active(i_spin), rtbse_env%ao_mo_workspace(1), &
2146 0.0_dp, rtbse_env%real_workspace_mo(2))
2148 CALL cp_fm_to_cfm(msourcer=rtbse_env%real_workspace_mo(1), &
2149 msourcei=rtbse_env%real_workspace_mo(2), &
2152 CALL timestop(handle)
2153 END SUBROUTINE transform_ao_to_mo_covariant_cfm
2163 SUBROUTINE transform_mo_to_ao_contravariant_cfm(rtbse_env, fm_mo, fm_ao, i_spin)
2166 INTEGER,
INTENT(IN) :: i_spin
2168 CHARACTER(len=*),
PARAMETER :: routinen =
'transform_mo_to_ao_contravariant_cfm'
2172 CALL timeset(routinen, handle)
2175 CALL cp_cfm_to_fm(msource=fm_mo, mtargetr=rtbse_env%real_workspace_mo(1), &
2176 mtargeti=rtbse_env%real_workspace_mo(2))
2178 CALL parallel_gemm(
"N",
"N", rtbse_env%n_ao, rtbse_env%mo_active, rtbse_env%mo_active, &
2179 1.0_dp, rtbse_env%C_active(i_spin), rtbse_env%real_workspace_mo(1), &
2180 0.0_dp, rtbse_env%ao_mo_workspace(1))
2181 CALL parallel_gemm(
"N",
"T", rtbse_env%n_ao, rtbse_env%n_ao, rtbse_env%mo_active, &
2182 1.0_dp, rtbse_env%ao_mo_workspace(1), rtbse_env%C_active(i_spin), &
2183 0.0_dp, rtbse_env%real_workspace(1))
2185 CALL parallel_gemm(
"N",
"N", rtbse_env%n_ao, rtbse_env%mo_active, rtbse_env%mo_active, &
2186 1.0_dp, rtbse_env%C_active(i_spin), rtbse_env%real_workspace_mo(2), &
2187 0.0_dp, rtbse_env%ao_mo_workspace(1))
2188 CALL parallel_gemm(
"N",
"T", rtbse_env%n_ao, rtbse_env%n_ao, rtbse_env%mo_active, &
2189 1.0_dp, rtbse_env%ao_mo_workspace(1), rtbse_env%C_active(i_spin), &
2190 0.0_dp, rtbse_env%real_workspace(2))
2192 CALL cp_fm_to_cfm(msourcer=rtbse_env%real_workspace(1), &
2193 msourcei=rtbse_env%real_workspace(2), mtarget=fm_ao)
2195 CALL timestop(handle)
2196 END SUBROUTINE transform_mo_to_ao_contravariant_cfm
2206 SUBROUTINE transform_mo_occupation_factor_diff_cfm(rtbse_env, cfm, i_spin)
2211 CHARACTER(len=*),
PARAMETER :: routinen =
'transform_mo_occupation_factor_diff_cfm'
2215 CALL timeset(routinen, handle)
2217 CALL cp_cfm_to_fm(msource=cfm, mtargetr=rtbse_env%real_workspace_mo(1), &
2218 mtargeti=rtbse_env%real_workspace_mo(2))
2220 CALL transform_mo_occupation_factor_diff_fm(rtbse_env, rtbse_env%real_workspace_mo(1), i_spin)
2222 CALL transform_mo_occupation_factor_diff_fm(rtbse_env, rtbse_env%real_workspace_mo(2), i_spin)
2224 CALL cp_fm_to_cfm(msourcer=rtbse_env%real_workspace_mo(1), &
2225 msourcei=rtbse_env%real_workspace_mo(2), &
2228 CALL timestop(handle)
2229 END SUBROUTINE transform_mo_occupation_factor_diff_cfm
2239 SUBROUTINE transform_mo_occupation_factor_diff_fm(rtbse_env, fm, i_spin)
2244 CHARACTER(len=*),
PARAMETER :: routinen =
'transform_mo_occupation_factor_diff_fm'
2246 INTEGER :: handle, i_global, i_global_mo, i_local, &
2247 j_global, j_global_mo, j_local, n_occ, &
2248 ncol_local, nrow_local, shift
2249 INTEGER,
DIMENSION(:),
POINTER :: col_indices, row_indices
2250 REAL(kind=
dp) :: occ_factor
2251 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: local_data
2253 CALL timeset(routinen, handle)
2255 n_occ = rtbse_env%n_occ(i_spin)
2257 shift = rtbse_env%first_active_mo - 1
2260 nrow_local=nrow_local, ncol_local=ncol_local, &
2261 row_indices=row_indices, col_indices=col_indices)
2263 local_data => fm%local_data
2265 DO i_local = 1, nrow_local
2266 i_global = row_indices(i_local)
2267 i_global_mo = i_global + shift
2268 DO j_local = 1, ncol_local
2269 j_global = col_indices(j_local)
2270 j_global_mo = j_global + shift
2272 IF (i_global_mo <= n_occ .AND. j_global_mo > n_occ)
THEN
2273 occ_factor = -1.0_dp
2274 ELSE IF (i_global_mo > n_occ .AND. j_global_mo <= n_occ)
THEN
2280 local_data(i_local, j_local) = occ_factor*local_data(i_local, j_local)
2284 CALL timestop(handle)
2285 END SUBROUTINE transform_mo_occupation_factor_diff_fm
2296 SUBROUTINE mask_mo_block_cfm(rtbse_env, cfm, i_spin, keep_OV, keep_ovvo)
2299 INTEGER,
INTENT(IN) :: i_spin
2300 LOGICAL,
INTENT(IN) :: keep_ov
2301 LOGICAL,
INTENT(IN),
OPTIONAL :: keep_ovvo
2303 CHARACTER(len=*),
PARAMETER :: routinen =
'mask_mo_block_cfm'
2305 COMPLEX(kind=dp),
DIMENSION(:, :),
POINTER :: local_data
2306 INTEGER :: handle, i_global, i_global_mo, i_local, &
2307 j_global, j_global_mo, j_local, n_occ, &
2308 ncol_local, nrow_local, shift
2309 INTEGER,
DIMENSION(:),
POINTER :: col_indices, row_indices
2310 LOGICAL :: keep, l_keep_ovvo
2312 CALL timeset(routinen, handle)
2314 l_keep_ovvo = .false.
2315 IF (
PRESENT(keep_ovvo)) l_keep_ovvo = keep_ovvo
2317 n_occ = rtbse_env%n_occ(i_spin)
2318 shift = rtbse_env%first_active_mo - 1
2321 nrow_local=nrow_local, ncol_local=ncol_local, &
2322 row_indices=row_indices, col_indices=col_indices)
2324 local_data => cfm%local_data
2326 DO i_local = 1, nrow_local
2327 i_global = row_indices(i_local)
2328 i_global_mo = i_global + shift
2329 DO j_local = 1, ncol_local
2330 j_global = col_indices(j_local)
2331 j_global_mo = j_global + shift
2332 IF (l_keep_ovvo)
THEN
2334 keep = ((i_global_mo <= n_occ) .NEQV. (j_global_mo <= n_occ))
2335 ELSE IF (keep_ov)
THEN
2336 keep = (i_global_mo <= n_occ .AND. j_global_mo > n_occ)
2338 keep = (i_global_mo > n_occ .AND. j_global_mo <= n_occ)
2340 IF (.NOT. keep) local_data(i_local, j_local) = cmplx(0.0_dp, 0.0_dp, kind=
dp)
2344 CALL timestop(handle)
2345 END SUBROUTINE mask_mo_block_cfm
2354 SUBROUTINE mask_mo_block_fm(rtbse_env, fm, i_spin, keep_OV)
2357 INTEGER,
INTENT(IN) :: i_spin
2358 LOGICAL,
INTENT(IN) :: keep_ov
2360 CHARACTER(len=*),
PARAMETER :: routinen =
'mask_mo_block_fm'
2362 INTEGER :: handle, i_global, i_global_mo, i_local, &
2363 j_global, j_global_mo, j_local, n_occ, &
2364 ncol_local, nrow_local, shift
2365 INTEGER,
DIMENSION(:),
POINTER :: col_indices, row_indices
2367 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: local_data
2369 CALL timeset(routinen, handle)
2371 n_occ = rtbse_env%n_occ(i_spin)
2372 shift = rtbse_env%first_active_mo - 1
2375 nrow_local=nrow_local, ncol_local=ncol_local, &
2376 row_indices=row_indices, col_indices=col_indices)
2378 local_data => fm%local_data
2380 DO i_local = 1, nrow_local
2381 i_global = row_indices(i_local)
2382 i_global_mo = i_global + shift
2383 DO j_local = 1, ncol_local
2384 j_global = col_indices(j_local)
2385 j_global_mo = j_global + shift
2387 keep = (i_global_mo <= n_occ .AND. j_global_mo > n_occ)
2389 keep = (i_global_mo > n_occ .AND. j_global_mo <= n_occ)
2391 IF (.NOT. keep) local_data(i_local, j_local) = 0.0_dp
2395 CALL timestop(handle)
2396 END SUBROUTINE mask_mo_block_fm
2409 SUBROUTINE rotate_rho_phase(rtbse_env, rho, i_spin, phase)
2412 INTEGER,
INTENT(IN) :: i_spin
2413 REAL(kind=
dp),
INTENT(IN) :: phase
2415 CHARACTER(len=*),
PARAMETER :: routinen =
'rotate_rho_phase'
2417 COMPLEX(kind=dp) :: phase_ov, phase_vo
2418 COMPLEX(kind=dp),
DIMENSION(:, :),
POINTER :: local_data
2419 INTEGER :: handle, i_global, i_global_mo, i_local, &
2420 j_global, j_global_mo, j_local, n_occ, &
2421 ncol_local, nrow_local, shift
2422 INTEGER,
DIMENSION(:),
POINTER :: col_indices, row_indices
2424 IF (rtbse_env%omega_shift == 0.0_dp)
RETURN
2426 CALL timeset(routinen, handle)
2428 n_occ = rtbse_env%n_occ(i_spin)
2429 shift = rtbse_env%first_active_mo - 1
2430 phase_ov = cmplx(cos(phase), sin(phase), kind=
dp)
2431 phase_vo = conjg(phase_ov)
2434 nrow_local=nrow_local, ncol_local=ncol_local, &
2435 row_indices=row_indices, col_indices=col_indices)
2436 local_data => rho%local_data
2438 DO i_local = 1, nrow_local
2439 i_global = row_indices(i_local)
2440 i_global_mo = i_global + shift
2441 DO j_local = 1, ncol_local
2442 j_global = col_indices(j_local)
2443 j_global_mo = j_global + shift
2444 IF (i_global_mo <= n_occ .AND. j_global_mo > n_occ)
THEN
2446 local_data(i_local, j_local) = phase_ov*local_data(i_local, j_local)
2447 ELSE IF (i_global_mo > n_occ .AND. j_global_mo <= n_occ)
THEN
2449 local_data(i_local, j_local) = phase_vo*local_data(i_local, j_local)
2454 CALL timestop(handle)
2455 END SUBROUTINE rotate_rho_phase
2468 SUBROUTINE build_rho_lab(rtbse_env, rho_in, t_phys, rho_lab)
2470 TYPE(
cp_cfm_type),
DIMENSION(:),
POINTER :: rho_in
2471 REAL(kind=
dp),
INTENT(IN) :: t_phys
2472 TYPE(
cp_cfm_type),
DIMENSION(:),
POINTER :: rho_lab
2474 CHARACTER(len=*),
PARAMETER :: routinen =
'build_rho_lab'
2476 INTEGER :: handle, i
2478 IF (rtbse_env%omega_shift == 0.0_dp .OR. .NOT.
ASSOCIATED(rtbse_env%rho_new_last))
THEN
2483 CALL timeset(routinen, handle)
2485 DO i = 1, rtbse_env%n_spin
2489 CALL rotate_rho_phase(rtbse_env, rtbse_env%rho_new_last(i), i, rtbse_env%omega_shift*t_phys)
2491 rho_lab => rtbse_env%rho_new_last
2493 CALL timestop(handle)
2494 END SUBROUTINE build_rho_lab
2506 SUBROUTINE apply_restart_basis_bridge(rtbse_env)
2509 CHARACTER(len=*),
PARAMETER :: routinen =
'apply_restart_basis_bridge'
2510 COMPLEX(kind=dp),
PARAMETER :: c_one = cmplx(1.0_dp, 0.0_dp, kind=
dp), &
2511 c_zero = cmplx(0.0_dp, 0.0_dp, kind=
dp)
2513 INTEGER :: handle, i, i_glob, i_mo, ii, j_glob, &
2514 j_mo, jj, n_flip, ncol_local, &
2516 INTEGER,
DIMENSION(:),
POINTER :: col_indices, row_indices
2518 REAL(kind=
dp) :: dev_ident, dev_offdiag, dev_ov, &
2520 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: u_diag
2521 REAL(kind=
dp),
CONTIGUOUS,
DIMENSION(:, :), &
2524 TYPE(
cp_fm_type),
DIMENSION(:),
POINTER :: c_old
2526 CALL timeset(routinen, handle)
2529 ALLOCATE (c_old(rtbse_env%n_spin))
2530 DO i = 1, rtbse_env%n_spin
2531 CALL cp_fm_create(c_old(i), rtbse_env%fm_struct_ao_mo_active)
2534 IF (.NOT. found)
THEN
2535 DO i = 1, rtbse_env%n_spin
2539 CALL timestop(handle)
2543 CALL cp_fm_create(sc_old, rtbse_env%fm_struct_ao_mo_active)
2544 ALLOCATE (u_diag(rtbse_env%mo_active))
2546 DO i = 1, rtbse_env%n_spin
2548 CALL parallel_gemm(
"N",
"N", rtbse_env%n_ao, rtbse_env%mo_active, rtbse_env%n_ao, &
2549 1.0_dp, rtbse_env%S_fm, c_old(i), 0.0_dp, sc_old)
2551 CALL parallel_gemm(
"T",
"N", rtbse_env%mo_active, rtbse_env%mo_active, rtbse_env%n_ao, &
2552 1.0_dp, rtbse_env%C_active(i), sc_old, 0.0_dp, rtbse_env%real_workspace_mo(1))
2556 n_flip = count(u_diag < 0.0_dp)
2557 CALL cp_fm_get_info(rtbse_env%real_workspace_mo(1), nrow_local=nrow_local, ncol_local=ncol_local, &
2558 row_indices=row_indices, col_indices=col_indices, local_data=u_data)
2559 dev_ident = 0.0_dp; dev_offdiag = 0.0_dp; dev_ov = 0.0_dp
2560 DO ii = 1, nrow_local
2561 i_glob = row_indices(ii)
2562 i_mo = i_glob + rtbse_env%first_active_mo - 1
2563 DO jj = 1, ncol_local
2564 j_glob = col_indices(jj)
2565 j_mo = j_glob + rtbse_env%first_active_mo - 1
2566 IF (i_glob == j_glob)
THEN
2567 dev_ident = max(dev_ident, abs(u_data(ii, jj) - 1.0_dp))
2569 dev_ident = max(dev_ident, abs(u_data(ii, jj)))
2570 dev_offdiag = max(dev_offdiag, abs(u_data(ii, jj)))
2572 IF ((i_mo <= rtbse_env%n_occ(i)) .NEQV. (j_mo <= rtbse_env%n_occ(i)))
THEN
2573 dev_ov = max(dev_ov, abs(u_data(ii, jj)))
2578 CALL parallel_gemm(
"T",
"N", rtbse_env%mo_active, rtbse_env%mo_active, rtbse_env%mo_active, &
2579 1.0_dp, rtbse_env%real_workspace_mo(1), rtbse_env%real_workspace_mo(1), &
2580 0.0_dp, rtbse_env%real_workspace_mo(2))
2581 CALL cp_fm_get_info(rtbse_env%real_workspace_mo(2), nrow_local=nrow_local, ncol_local=ncol_local, &
2582 row_indices=row_indices, col_indices=col_indices, local_data=u_data)
2583 dev_unitary = 0.0_dp
2584 DO ii = 1, nrow_local
2585 i_glob = row_indices(ii)
2586 DO jj = 1, ncol_local
2587 j_glob = col_indices(jj)
2588 dev_unitary = max(dev_unitary, abs(u_data(ii, jj) - merge(1.0_dp, 0.0_dp, i_glob == j_glob)))
2591 CALL rtbse_env%real_workspace_mo(1)%matrix_struct%para_env%max(dev_ident)
2592 CALL rtbse_env%real_workspace_mo(1)%matrix_struct%para_env%max(dev_offdiag)
2593 CALL rtbse_env%real_workspace_mo(1)%matrix_struct%para_env%max(dev_ov)
2594 CALL rtbse_env%real_workspace_mo(1)%matrix_struct%para_env%max(dev_unitary)
2596 IF (rtbse_env%unit_nr > 0)
THEN
2597 WRITE (rtbse_env%unit_nr,
'(A,I3,A)')
" RTBSE| Restart basis bridge U = C2^T S C1 (spin ", i,
"):"
2598 WRITE (rtbse_env%unit_nr,
'(A,ES12.3,A)')
" RTBSE| max |U - 1| ", dev_ident, &
2599 " (total gauge correction)"
2600 WRITE (rtbse_env%unit_nr,
'(A,I12)')
" RTBSE| sign flips (U_ii<0)", n_flip
2601 WRITE (rtbse_env%unit_nr,
'(A,ES12.3,A)')
" RTBSE| max offdiag |U_ij| ", dev_offdiag, &
2602 " (degenerate-subspace rotation)"
2603 WRITE (rtbse_env%unit_nr,
'(A,ES12.3,A)')
" RTBSE| max |U^T U - 1| ", dev_unitary, &
2604 " (representability loss)"
2605 WRITE (rtbse_env%unit_nr,
'(A,ES12.3,A)')
" RTBSE| max |U_OV| ", dev_ov, &
2606 " (occ/virt structure change)"
2608 IF (dev_unitary >= 1.0e-3_dp)
THEN
2609 CALL cp_abort(__location__, &
2610 "Restart basis bridge: active spaces of the two runs differ severely (|U^T U - 1| >= 1e-3)")
2612 IF (dev_unitary >= 1.0e-10_dp .AND. dev_unitary < 1.0e-3_dp)
THEN
2613 CALL cp_warn(__location__, &
2614 "Restart basis bridge: representability loss above 1e-10 - active windows differ slightly.")
2618 IF (dev_ov >= 1.0e-6_dp)
THEN
2619 CALL cp_warn(__location__, &
2620 "Restart basis bridge: occupied/virtual mixing above 1e-6 - occupation structure changed.")
2624 CALL cp_fm_to_cfm(msourcer=rtbse_env%real_workspace_mo(1), mtarget=rtbse_env%rho_workspace(1))
2625 CALL cp_cfm_gemm(
'N',
'N', rtbse_env%mo_active, rtbse_env%mo_active, rtbse_env%mo_active, &
2626 c_one, rtbse_env%rho_workspace(1), rtbse_env%rho(i), c_zero, rtbse_env%rho_workspace(2))
2627 CALL cp_cfm_gemm(
'N',
'C', rtbse_env%mo_active, rtbse_env%mo_active, rtbse_env%mo_active, &
2628 c_one, rtbse_env%rho_workspace(2), rtbse_env%rho_workspace(1), c_zero, rtbse_env%rho(i))
2633 DO i = 1, rtbse_env%n_spin
2637 CALL timestop(handle)
2638 END SUBROUTINE apply_restart_basis_bridge
2652 SUBROUTINE get_hartree_complex(rtbse_env, rho_cfm, v_cfm, ispin)
2656 INTEGER,
INTENT(IN) :: ispin
2658 CHARACTER(len=*),
PARAMETER :: routinen =
'get_hartree_complex'
2664 CALL timeset(routinen, handle)
2675 CALL cp_cfm_to_fm(msource=rho_cfm, mtargetr=rtbse_env%real_workspace(1))
2676 CALL cp_cfm_set_all(rtbse_env%sigma_complex_workspace(1), cmplx(0.0_dp, 0.0_dp, kind=
dp))
2677 CALL cp_fm_to_cfm(msourcer=rtbse_env%real_workspace(1), &
2678 mtarget=rtbse_env%sigma_complex_workspace(1))
2679 CALL get_hartree(rtbse_env, rtbse_env%sigma_complex_workspace(1), &
2680 rtbse_env%real_workspace(1))
2683 CALL cp_cfm_to_fm(msource=rho_cfm, mtargeti=rtbse_env%real_workspace(2))
2684 CALL cp_cfm_set_all(rtbse_env%sigma_complex_workspace(1), cmplx(0.0_dp, 0.0_dp, kind=
dp))
2685 CALL cp_fm_to_cfm(msourcer=rtbse_env%real_workspace(2), &
2686 mtarget=rtbse_env%sigma_complex_workspace(1))
2687 CALL get_hartree(rtbse_env, rtbse_env%sigma_complex_workspace(1), &
2688 rtbse_env%real_workspace(2))
2691 CALL cp_fm_to_cfm(msourcer=rtbse_env%real_workspace(1), &
2692 msourcei=rtbse_env%real_workspace(2), &
2695 CALL timestop(handle)
2696 END SUBROUTINE get_hartree_complex
2706 SUBROUTINE apply_delta_pulse_mo(rtbse_env)
2709 CHARACTER(len=*),
PARAMETER :: routinen =
'apply_delta_pulse_MO'
2711 INTEGER :: handle, i, k
2712 REAL(kind=
dp) :: intensity, metric
2713 REAL(kind=
dp),
DIMENSION(3) :: kvec
2715 CALL timeset(routinen, handle)
2718 IF (rtbse_env%unit_nr > 0)
WRITE (rtbse_env%unit_nr,
'(A28)')
' RTBSE| Applying delta pulse'
2720 intensity = -rtbse_env%dft_control%rtp_control%delta_pulse_scale
2722 kvec(:) = rtbse_env%dft_control%rtp_control%delta_pulse_direction(:)
2723 IF (rtbse_env%unit_nr > 0)
WRITE (rtbse_env%unit_nr,
'(A38,E14.4E3,E14.4E3,E14.4E3)') &
2724 " RTBSE| Delta pulse elements (a.u.) : ", intensity*kvec(:)
2726 DO i = 1, rtbse_env%n_spin
2730 kvec(k), rtbse_env%moments_field(k, i))
2733 CALL cp_fm_transpose(rtbse_env%real_workspace_mo(1), rtbse_env%real_workspace_mo(2))
2735 0.5_dp, rtbse_env%real_workspace_mo(2))
2737 CALL cp_fm_scale(intensity, rtbse_env%real_workspace_mo(1))
2738 CALL cp_fm_to_cfm(msourcei=rtbse_env%real_workspace_mo(1), mtarget=rtbse_env%ham_workspace(i))
2741 CALL propagate_density(rtbse_env, rtbse_env%ham_workspace, rtbse_env%rho, rtbse_env%rho_new)
2742 metric =
rho_metric(rtbse_env%rho_new, rtbse_env%rho, rtbse_env%n_spin)
2743 IF (rtbse_env%unit_nr > 0)
WRITE (rtbse_env%unit_nr, (
'(A42,E38.8E3)'))
" RTBSE| Metric difference after delta kick", metric
2745 DO i = 1, rtbse_env%n_spin
2749 CALL timestop(handle)
2750 END SUBROUTINE apply_delta_pulse_mo
2761 SUBROUTINE project_drho_to_ov(rtbse_env, cfm, i_spin)
2764 INTEGER,
INTENT(IN) :: i_spin
2766 COMPLEX(kind=dp),
DIMENSION(:, :),
POINTER :: local_data
2767 INTEGER :: i_global, i_global_mo, i_local, &
2768 j_global, j_global_mo, j_local, n_occ, &
2769 ncol_local, nrow_local, shift
2770 INTEGER,
DIMENSION(:),
POINTER :: col_indices, row_indices
2772 n_occ = rtbse_env%n_occ(i_spin)
2773 shift = rtbse_env%first_active_mo - 1
2776 nrow_local=nrow_local, ncol_local=ncol_local, &
2777 row_indices=row_indices, col_indices=col_indices)
2778 local_data => cfm%local_data
2781 DO j_local = 1, ncol_local
2782 j_global = col_indices(j_local)
2783 j_global_mo = j_global + shift
2784 DO i_local = 1, nrow_local
2785 i_global = row_indices(i_local)
2786 i_global_mo = i_global + shift
2787 IF ((i_global_mo <= n_occ .AND. j_global_mo <= n_occ) .OR. &
2788 (i_global_mo > n_occ .AND. j_global_mo > n_occ))
THEN
2789 local_data(i_local, j_local) = cmplx(0.0_dp, 0.0_dp, kind=
dp)
2793 END SUBROUTINE project_drho_to_ov
2805 SUBROUTINE get_electron_number_mo(rtbse_env, rho, electron_n_re, electron_n_im)
2808 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: electron_n_re, electron_n_im
2810 CHARACTER(len=*),
PARAMETER :: routinen =
'get_electron_number_MO'
2812 COMPLEX(kind=dp),
DIMENSION(:, :),
POINTER :: local_data
2813 INTEGER :: handle, i_global, i_local, j, j_global, &
2814 j_local, ncol_local, nrow_local
2815 INTEGER,
DIMENSION(:),
POINTER :: col_indices, row_indices
2817 CALL timeset(routinen, handle)
2818 electron_n_re(:) = 0.0_dp
2819 electron_n_im(:) = 0.0_dp
2820 DO j = 1, rtbse_env%n_spin
2822 nrow_local=nrow_local, &
2823 ncol_local=ncol_local, &
2824 row_indices=row_indices, &
2825 col_indices=col_indices)
2826 local_data => rho(j)%local_data
2828 DO i_local = 1, nrow_local
2829 i_global = row_indices(i_local)
2831 DO j_local = 1, ncol_local
2832 j_global = col_indices(j_local)
2833 IF (j_global == i_global)
THEN
2835 electron_n_re(j) = electron_n_re(j) + real(local_data(i_local, j_local), kind=
dp)
2836 electron_n_im(j) = electron_n_im(j) + aimag(local_data(i_local, j_local))
2842 CALL rho(j)%matrix_struct%para_env%sum(electron_n_re(j))
2843 CALL rho(j)%matrix_struct%para_env%sum(electron_n_im(j))
2845 electron_n_re(j) = electron_n_re(j)*rtbse_env%spin_degeneracy
2846 electron_n_im(j) = electron_n_im(j)*rtbse_env%spin_degeneracy
2849 CALL timestop(handle)
2850 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, plan)
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, all_images, minimum_image, neighbor_image, first_component)
...
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