52#include "./base/base_uses.f90"
58 CHARACTER(len=*),
PARAMETER,
PRIVATE :: moduleN =
'bse_properties'
68 REAL(kind=
dp),
DIMENSION(3) :: r_e = 0.0_dp, &
76 REAL(kind=
dp) :: sigma_e = 0.0_dp, &
78 cov_e_h_sum = 0.0_dp, &
80 diff_r_abs = 0.0_dp, &
81 diff_r_sqr = 0.0_dp, &
83 LOGICAL :: flag_tda = .false.
107 trans_mom_bse, oscill_str, polarizability_residues, &
108 mp2_env, homo_red, virtual_red, unit_nr, &
112 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:), &
113 INTENT(IN) :: exc_ens
114 TYPE(
cp_fm_type),
DIMENSION(3) :: fm_dipole_ai_trunc
115 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :, :), &
116 INTENT(OUT) :: trans_mom_bse
117 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:), &
118 INTENT(OUT) :: oscill_str
119 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :, :), &
120 INTENT(OUT) :: polarizability_residues
121 TYPE(
mp2_type),
INTENT(IN) :: mp2_env
122 INTEGER,
INTENT(IN) :: homo_red, virtual_red, unit_nr
123 TYPE(
cp_fm_type),
INTENT(IN),
OPTIONAL :: fm_eigvec_y
125 CHARACTER(LEN=*),
PARAMETER :: routinen =
'get_oscillator_strengths'
127 INTEGER :: handle, idir, jdir, n
129 fm_struct_trans_mom_bse
131 TYPE(
cp_fm_type),
DIMENSION(3) :: fm_dipole_mo_trunc_reordered, &
132 fm_dipole_per_dir, fm_trans_mom_bse
134 CALL timeset(routinen, handle)
136 CALL cp_fm_struct_create(fm_struct_dipole_mo_trunc_reordered, fm_eigvec_x%matrix_struct%para_env, &
137 fm_eigvec_x%matrix_struct%context, 1, homo_red*virtual_red)
139 fm_eigvec_x%matrix_struct%context, 1, homo_red*virtual_red)
146 CALL cp_fm_create(fm_dipole_mo_trunc_reordered(idir), matrix_struct=fm_struct_dipole_mo_trunc_reordered, &
147 name=
"dipoles_mo_reordered")
148 CALL cp_fm_set_all(fm_dipole_mo_trunc_reordered(idir), 0.0_dp)
149 CALL fm_general_add_bse(fm_dipole_mo_trunc_reordered(idir), fm_dipole_ai_trunc(idir), 1.0_dp, &
152 unit_nr, (/2, 4, 3, 1/), mp2_env)
157 CALL cp_fm_create(fm_trans_mom_bse(idir), matrix_struct=fm_struct_trans_mom_bse, &
158 name=
"excitonic_dipoles")
163 CALL cp_fm_create(fm_eigvec_xysum, matrix_struct=fm_eigvec_x%matrix_struct, name=
"excit_amplitude_sum")
166 IF (
PRESENT(fm_eigvec_y))
THEN
170 CALL parallel_gemm(
'N',
'N', 1, homo_red*virtual_red, homo_red*virtual_red, sqrt(2.0_dp), &
171 fm_dipole_mo_trunc_reordered(idir), fm_eigvec_xysum, 0.0_dp, fm_trans_mom_bse(idir))
175 ALLOCATE (oscill_str(homo_red*virtual_red))
176 ALLOCATE (trans_mom_bse(3, 1, homo_red*virtual_red))
177 ALLOCATE (polarizability_residues(3, 3, homo_red*virtual_red))
178 trans_mom_bse(:, :, :) = 0.0_dp
185 DO n = 1, homo_red*virtual_red
188 polarizability_residues(idir, jdir, n) = 2.0_dp*exc_ens(n)*trans_mom_bse(idir, 1, n)*trans_mom_bse(jdir, 1, n)
191 oscill_str(n) = 2.0_dp/3.0_dp*exc_ens(n)*sum(abs(trans_mom_bse(:, :, n))**2)
203 CALL timestop(handle)
220 info_approximation, unit_nr, mp2_env)
222 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:), &
223 INTENT(IN) :: oscill_str
224 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :, :), &
225 INTENT(IN) :: polarizability_residues
226 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:), &
227 INTENT(IN) :: exc_ens
228 CHARACTER(LEN=10) :: info_approximation
229 INTEGER,
INTENT(IN) :: unit_nr
230 TYPE(
mp2_type),
INTENT(INOUT) :: mp2_env
232 CHARACTER(LEN=*),
PARAMETER :: routinen =
'compute_absorption_spectrum'
234 CHARACTER(LEN=10) :: eta_str, width_eta_format_str
235 CHARACTER(LEN=40) :: file_name_crosssection, &
237 INTEGER :: handle, i, idir, j, jdir, k, num_steps, &
238 unit_nr_file, width_eta
239 REAL(kind=
dp) :: eta, freq_end, freq_start, freq_step, &
241 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: abs_cross_section, abs_spectrum
242 REAL(kind=
dp),
DIMENSION(:),
POINTER :: eta_list
245 CALL timeset(routinen, handle)
247 freq_step = mp2_env%bse%bse_spectrum_freq_step_size
248 freq_start = mp2_env%bse%bse_spectrum_freq_start
249 freq_end = mp2_env%bse%bse_spectrum_freq_end
250 eta_list => mp2_env%bse%bse_eta_spectrum_list
253 num_steps = nint((freq_end - freq_start)/freq_step) + 1
255 DO k = 1,
SIZE(eta_list)
259 width_eta = max(1, int(log10(eta)) + 1) + 4
260 WRITE (width_eta_format_str,
"(A2,I0,A3)")
'(F', width_eta,
'.3)'
261 WRITE (eta_str, width_eta_format_str) eta*
evolt
263 file_name_spectrum =
'BSE'//trim(adjustl(info_approximation))//
'eta='//trim(eta_str)//
'.spectrum'
264 file_name_crosssection =
'BSE'//trim(adjustl(info_approximation))//
'eta='//trim(eta_str)//
'.crosssection'
268 ALLOCATE (abs_spectrum(num_steps, 11))
269 abs_spectrum(:, :) = 0.0_dp
272 ALLOCATE (abs_cross_section(num_steps, 11))
273 abs_cross_section(:, :) = 0.0_dp
288 omega = freq_start + (i - 1)*freq_step
289 abs_spectrum(i, 1) = omega
290 DO j = 1,
SIZE(oscill_str)
291 abs_spectrum(i, 2) = abs_spectrum(i, 2) - oscill_str(j)* &
292 aimag(1/((omega + cmplx(0.0, eta, kind=
dp))**2 - exc_ens(j)**2))
297 abs_spectrum(i, 2 + (idir - 1)*3 + jdir) = abs_spectrum(i, 2 + (idir - 1)*3 + jdir) &
298 - polarizability_residues(idir, jdir, j)* &
299 aimag(1/((omega + cmplx(0.0, eta, kind=
dp))**2 - exc_ens(j)**2))
307 omega = abs_spectrum(i, 1)
308 abs_cross_section(i, 1) = omega
309 abs_cross_section(i, 2:) = 4.0_dp*
pi*abs_spectrum(i, 2:)*omega/
c_light_au
313 IF (mp2_env%bse%bse_debug_print)
THEN
314 IF (unit_nr > 0)
THEN
315 WRITE (unit_nr,
'(T2,A10,T13,A,T65,F16.4)')
'BSE|DEBUG|', &
316 'Averaged dynamical dipole polarizability at 8.2 eV:', &
318 WRITE (unit_nr,
'(T2,A10,T13,A,T65,F16.4)')
'BSE|DEBUG|', &
319 'Averaged photoabsorption cross section at 8.2 eV:', &
320 abs_cross_section(83, 2)
326 IF (logger%para_env%is_source())
THEN
332 IF (unit_nr_file > 0)
THEN
333 CALL open_file(file_name_crosssection, unit_number=unit_nr_file, &
334 file_status=
"UNKNOWN", file_action=
"WRITE")
335 WRITE (unit_nr_file,
'(A,A6)') σµµωπω
"# Photoabsorption cross section _{ '}() = -4/c * Im[ \sum_n "// &
336 Ωµµωη²Ω²
"[2 ^n d_^n d_'^n] / [(+i)- (^n)] ] from Bethe Salpeter equation for method ", &
337 trim(adjustl(info_approximation))
338 WRITE (unit_nr_file,
'(A20,1X,10(2X,A20,1X))')
"# Frequency (eV)", σω
"_{avg}()", σω
"_xx()", &
339 σω
"_xy()", σω
"_xz()", σω
"_yx()", σω
"_yy()", σω
"_yz()", σω
"_zx()", &
342 WRITE (unit_nr_file,
'(11(F20.8,1X))') abs_cross_section(i, 1)*
evolt, abs_cross_section(i, 2:11)
346 DEALLOCATE (abs_cross_section)
348 IF (unit_nr_file > 0)
THEN
349 CALL open_file(file_name_spectrum, unit_number=unit_nr_file, &
350 file_status=
"UNKNOWN", file_action=
"WRITE")
351 WRITE (unit_nr_file,
'(A,A6)') αµµω
"# Imaginary part of polarizability _{ '}() = -\sum_n "// &
352 Ωµµωη²Ω²
"[2 ^n d_^n d_'^n] / [(+i)- (^n)] from Bethe Salpeter equation for method ", &
353 trim(adjustl(info_approximation))
354 WRITE (unit_nr_file,
'(A20,1X,10(2X,A20,1X))')
"# Frequency (eV)", αω
"Im{_{avg}()}", αω
"Im{_xx()}", &
355 αω
"Im{_xy()}", αω
"Im{_xz()}", αω
"Im{_yx()}", αω
"Im{_yy()}", αω
"Im{_yz()}", αω
"Im{_zx()}", &
356 αω
"Im{_zy()}", αω
"Im{_zz()}"
358 WRITE (unit_nr_file,
'(11(F20.8,1X))') abs_spectrum(i, 1)*
evolt, abs_spectrum(i, 2:11)
362 DEALLOCATE (abs_spectrum)
365 IF (unit_nr > 0)
THEN
366 WRITE (unit_nr,
'(T2,A4)')
'BSE|'
367 WRITE (unit_nr,
'(T2,A4,T7,A,A)') &
368 'BSE|',
"Printed optical absorption spectrum to local files, e.g. "
369 WRITE (unit_nr,
'(T2,A4,T7,A)') &
370 'BSE|', file_name_spectrum
371 WRITE (unit_nr,
'(T2,A4,T7,A,A)') &
372 'BSE|',
"as well as photoabsorption cross section to, e.g. "
373 WRITE (unit_nr,
'(T2,A4,T7,A)') &
374 'BSE|', file_name_crosssection
375 WRITE (unit_nr,
'(T2,A4,T7,A52)') &
376 'BSE|',
"using the Eq. (7.51) from C. Ullrichs Book on TDDFT:"
377 WRITE (unit_nr,
'(T2,A4)')
'BSE|'
378 WRITE (unit_nr,
'(T2,A4,T10,A75)') &
379 'BSE|', αωωη²Ω²
"Im{_{avg}()} = -Im{\sum_{n=1}^{N_exc} \frac{f_n}{(+i) - (^n)}}"
380 WRITE (unit_nr,
'(T2,A4)')
'BSE|'
381 WRITE (unit_nr,
'(T2,A4,T7,A)') &
382 'BSE|',
"or for the full polarizability tensor:"
383 WRITE (unit_nr,
'(T2,A4,T10,A)') &
384 'BSE|', αµµωΩµµωη²Ω²
"_{ '}() = -\sum_n [2 ^n d_^n d_'^n] / [(+i)- (^n)]"
385 WRITE (unit_nr,
'(T2,A4)')
'BSE|'
386 WRITE (unit_nr,
'(T2,A4,T7,A)') &
387 'BSE|',
"as well as Eq. (7.48):"
388 WRITE (unit_nr,
'(T2,A4,T10,A)') &
389 'BSE|', σµµωπωαµµω
"_{ '}() = 4 Im{_{ '}()} / c"
390 WRITE (unit_nr,
'(T2,A4)')
'BSE|'
391 WRITE (unit_nr,
'(T2,A4,T7,A)') &
392 'BSE|', µ
"with transition moments d_^n, oscillator strengths f_n,"
393 WRITE (unit_nr,
'(T2,A4,T7,A)') &
394 'BSE|', Ω
"excitation energies ^n and the speed of light c."
395 WRITE (unit_nr,
'(T2,A4)')
'BSE|'
396 WRITE (unit_nr,
'(T2,A4,T7,A)') &
397 'BSE|',
"Please note that we adopt an additional minus sign for both quantities,"
398 WRITE (unit_nr,
'(T2,A4,T7,A)') &
399 'BSE|',
"due to the convention for charge vs particle density as done in MolGW:"
400 WRITE (unit_nr,
'(T2,A4,T7,A)') &
401 'BSE|',
"https://doi.org/10.1016/j.cpc.2016.06.019."
402 WRITE (unit_nr,
'(T2,A4)')
'BSE|'
405 CALL timestop(handle)
423 mo_coeff, homo, virtual, &
424 info_approximation, &
426 qs_env, unit_nr, mp2_env)
429 TYPE(
cp_fm_type),
INTENT(IN),
OPTIONAL :: fm_y
430 TYPE(
cp_fm_type),
DIMENSION(:),
INTENT(IN) :: mo_coeff
431 INTEGER,
INTENT(IN) :: homo, virtual
432 CHARACTER(LEN=10) :: info_approximation
433 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: oscill_str
435 INTEGER,
INTENT(IN) :: unit_nr
436 TYPE(
mp2_type),
INTENT(INOUT) :: mp2_env
438 CHARACTER(LEN=*),
PARAMETER :: routinen =
'calculate_NTOs'
440 CHARACTER(LEN=20),
DIMENSION(2) :: nto_name
441 INTEGER :: handle, homo_irred, i, i_nto, info_svd, &
442 j, n_exc, n_nto, nao_full, nao_trunc
443 INTEGER,
DIMENSION(:),
POINTER :: stride
444 LOGICAL :: append_cube, cube_file
445 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: eigval_svd_squ
446 REAL(kind=
dp),
DIMENSION(:),
POINTER :: eigval_svd
448 fm_struct_nto_holes, &
449 fm_struct_nto_particles, &
451 TYPE(
cp_fm_type) :: fm_eigvl, fm_eigvr_t, fm_m, fm_mo_coeff, fm_nto_coeff_holes, &
452 fm_nto_coeff_particles, fm_nto_set, fm_x_ia, fm_y_ai
453 TYPE(
mo_set_type),
ALLOCATABLE,
DIMENSION(:) :: nto_set
456 CALL timeset(routinen, handle)
461 nao_full = qs_env%mos(1)%nao
462 nao_trunc = homo + virtual
464 homo_irred = qs_env%mos(1)%homo
473 fm_x%matrix_struct%para_env, fm_x%matrix_struct%context, &
474 nao_trunc, nao_trunc)
476 fm_x%matrix_struct%para_env, fm_x%matrix_struct%context, &
479 fm_x%matrix_struct%para_env, fm_x%matrix_struct%context, &
482 fm_x%matrix_struct%para_env, fm_x%matrix_struct%context, &
485 CALL cp_fm_create(fm_mo_coeff, matrix_struct=fm_struct_mo_coeff, &
491 nao_full, nao_trunc, &
492 1, homo_irred - homo + 1, &
494 mo_coeff(1)%matrix_struct%context)
497 IF (unit_nr > 0)
THEN
498 WRITE (unit_nr,
'(T2,A4,T7,A)')
'BSE|', &
499 φχ
'The Natural Transition Orbital (NTO) pairs _I(r_e) and _I(r_h) for a fixed'
500 WRITE (unit_nr,
'(T2,A4,T7,A)')
'BSE|', &
501 'excitation index n are obtained by singular value decomposition of T'
502 WRITE (unit_nr,
'(T2,A4)')
'BSE|'
503 WRITE (unit_nr,
'(T2,A4,T15,A)')
'BSE|', &
505 IF (
PRESENT(fm_y))
THEN
506 WRITE (unit_nr,
'(T2,A4,T15,A)')
'BSE|', &
509 WRITE (unit_nr,
'(T2,A4,T15,A)')
'BSE|', &
512 WRITE (unit_nr,
'(T2,A4)')
'BSE|'
513 WRITE (unit_nr,
'(T2,A4,T15,A)')
'BSE|', &
515 WRITE (unit_nr,
'(T2,A4,T15,A)')
'BSE|', &
516 φψ
'_I(r_e) = \sum_p V_pI _p(r_e)'
517 WRITE (unit_nr,
'(T2,A4,T15,A)')
'BSE|', &
518 χψ
'_I(r_h) = \sum_p U_pI _p(r_e)'
519 WRITE (unit_nr,
'(T2,A4)')
'BSE|'
520 WRITE (unit_nr,
'(T2,A4,T7,A)')
'BSE|', &
521 'where we have introduced'
522 WRITE (unit_nr,
'(T2,A4)')
'BSE|'
523 WRITE (unit_nr,
'(T2,A4,T7,A,T20,A)') &
524 'BSE|', ψ
"_p:",
"occupied and virtual molecular orbitals,"
525 WRITE (unit_nr,
'(T2,A4,T7,A,T20,A)') &
526 'BSE|', φ
"_I(r_e):",
"NTO state for the electron,"
527 WRITE (unit_nr,
'(T2,A4,T7,A,T20,A)') &
528 'BSE|', χ
"_I(r_h):",
"NTO state for the hole,"
529 WRITE (unit_nr,
'(T2,A4,T7,A,T20,A)') &
530 'BSE|', Λ
":", λ
"diagonal matrix of NTO weights _I,"
531 WRITE (unit_nr,
'(T2,A4)')
'BSE|'
532 WRITE (unit_nr,
'(T2,A4,T7,A)')
'BSE|', &
533 "The NTOs are calculated with the following settings:"
534 WRITE (unit_nr,
'(T2,A4)')
'BSE|'
535 WRITE (unit_nr,
'(T2,A4,T7,A,T71,I10)')
'BSE|',
'Number of excitations, for which NTOs are computed', &
536 mp2_env%bse%num_print_exc_ntos
537 IF (mp2_env%bse%eps_nto_osc_str > 0.0_dp)
THEN
538 WRITE (unit_nr,
'(T2,A4,T7,A,T71,F10.3)')
'BSE|',
'Threshold for oscillator strength f^n', &
539 mp2_env%bse%eps_nto_osc_str
541 WRITE (unit_nr,
'(T2,A4,T7,A,T71,A10)')
'BSE|',
'Threshold for oscillator strength f^n', &
544 WRITE (unit_nr,
'(T2,A4,T7,A,T72,F10.3)')
'BSE|', λ
'Threshold for NTO weights (_I)^2', &
545 mp2_env%bse%eps_nto_eigval
549 IF (unit_nr > 0)
THEN
550 WRITE (unit_nr,
'(T2,A4)')
'BSE|'
551 IF (.NOT.
PRESENT(fm_y))
THEN
552 WRITE (unit_nr,
'(T2,A4,T7,A)')
'BSE|', &
553 'NTOs from solving the BSE within the TDA:'
555 WRITE (unit_nr,
'(T2,A4,T7,A)')
'BSE|', &
556 'NTOs from solving the BSE without the TDA:'
558 WRITE (unit_nr,
'(T2,A4)')
'BSE|'
559 WRITE (unit_nr,
'(T2,A4,T8,A12,T22,A8,T33,A14,T62,A)')
'BSE|', &
560 'Excitation n',
"TDA/ABBA",
"Index of NTO I", λ
'NTO weights (_I)^2'
563 DO j = 1, mp2_env%bse%num_print_exc_ntos
564 n_exc = mp2_env%bse%bse_nto_state_list_final(j)
566 IF (mp2_env%bse%eps_nto_osc_str > 0.0_dp)
THEN
568 IF (oscill_str(n_exc) < mp2_env%bse%eps_nto_osc_str)
THEN
570 IF (unit_nr > 0)
THEN
571 WRITE (unit_nr,
'(T2,A4)')
'BSE|'
572 WRITE (unit_nr,
'(T2,A4,T8,I12,T24,A6,T42,A39)')
'BSE|', &
573 n_exc, info_approximation,
"Skipped (Oscillator strength too small)"
580 name=
"single_part_trans_dm")
583 CALL cp_fm_create(fm_nto_coeff_holes, matrix_struct=fm_struct_nto_holes, &
584 name=
"nto_coeffs_holes")
587 CALL cp_fm_create(fm_nto_coeff_particles, matrix_struct=fm_struct_nto_particles, &
588 name=
"nto_coeffs_particles")
593 .false., unit_nr, mp2_env)
602 IF (
PRESENT(fm_y))
THEN
605 .true., unit_nr, mp2_env)
621 matrix_struct=fm_m%matrix_struct, &
622 name=
"LEFT_SINGULAR_MATRIX")
625 matrix_struct=fm_m%matrix_struct, &
626 name=
"RIGHT_SINGULAR_MATRIX")
629 ALLOCATE (eigval_svd(nao_trunc))
630 eigval_svd(:) = 0.0_dp
632 CALL cp_fm_svd(fm_m, fm_eigvl, fm_eigvr_t, eigval_svd, info_svd)
633 IF (info_svd /= 0)
THEN
634 IF (unit_nr > 0)
THEN
635 CALL cp_warn(__location__, &
636 "SVD for computation of NTOs not successful. "// &
637 "Skipping print of NTOs.")
638 IF (info_svd > 0)
THEN
639 CALL cp_warn(__location__, &
640 "PDGESVD detected heterogeneity. "// &
641 "Decreasing number of MPI ranks might solve this issue.")
650 ALLOCATE (eigval_svd_squ(nao_trunc))
651 eigval_svd_squ(:) = eigval_svd(:)**2
653 IF (.NOT.
PRESENT(fm_y))
THEN
654 IF (abs(sum(eigval_svd_squ) - 1) >= 1e-5)
THEN
655 cpwarn(
"Sum of NTO coefficients deviates from 1!")
661 CALL parallel_gemm(
"N",
"N", nao_full, nao_trunc, nao_trunc, 1.0_dp, fm_mo_coeff, fm_eigvl, 0.0_dp, &
665 CALL parallel_gemm(
"N",
"T", nao_full, nao_trunc, nao_trunc, 1.0_dp, fm_mo_coeff, fm_eigvr_t, 0.0_dp, &
666 fm_nto_coeff_particles)
674 nto_name(1) =
'Hole_coord'
675 nto_name(2) =
'Particle_coord'
676 ALLOCATE (nto_set(2))
679 DO i_nto = 1, nao_trunc
680 IF (eigval_svd_squ(i_nto) > mp2_env%bse%eps_nto_eigval)
THEN
688 IF (unit_nr > 0)
THEN
689 WRITE (unit_nr,
'(T2,A4)')
'BSE|'
691 WRITE (unit_nr,
'(T2,A4,T8,I12,T24,A6,T41,I6,T71,F10.5)')
'BSE|', &
692 n_exc, info_approximation, i_nto, eigval_svd_squ(i_nto)
700 CALL allocate_mo_set(nto_set(i), nao_trunc, n_nto, 0, 0.0_dp, 2.0_dp, 0.0_dp)
701 CALL init_mo_set(nto_set(i), fm_ref=fm_nto_set, name=nto_name(i))
707 CALL cp_fm_to_fm(fm_nto_coeff_holes, nto_set(1)%mo_coeff, ncol=n_nto)
708 CALL cp_fm_to_fm(fm_nto_coeff_particles, nto_set(2)%mo_coeff, ncol=n_nto)
717 stride, append_cube, nto_section)
722 DEALLOCATE (eigval_svd)
723 DEALLOCATE (eigval_svd_squ)
737 CALL timestop(handle)
754 fm_multipole_ij_trunc, fm_multipole_ab_trunc, &
755 fm_multipole_ai_trunc, &
756 i_exc, homo, virtual, &
760 DIMENSION(:) :: exc_descr
762 TYPE(
cp_fm_type),
ALLOCATABLE,
DIMENSION(:), &
763 INTENT(IN) :: fm_multipole_ij_trunc, &
764 fm_multipole_ab_trunc, &
765 fm_multipole_ai_trunc
766 INTEGER,
INTENT(IN) :: i_exc, homo, virtual
767 TYPE(
cp_fm_type),
INTENT(IN),
OPTIONAL :: fm_y_ia
769 CHARACTER(LEN=*),
PARAMETER :: routinen =
'get_exciton_descriptors'
771 INTEGER :: handle, i_dir
772 INTEGER,
DIMENSION(3) :: mask_quadrupole
774 REAL(kind=
dp) :: norm_x, norm_xpy, norm_y
775 REAL(kind=
dp),
DIMENSION(3) :: r_e_h_xx, r_e_h_xy, r_e_h_yx, r_e_h_yy, &
776 r_e_sq_x, r_e_sq_y, r_e_x, r_e_y, &
777 r_h_sq_x, r_h_sq_y, r_h_x, r_h_y
779 TYPE(
cp_fm_type) :: fm_work_ba, fm_work_ia, fm_work_ia_2
781 CALL timeset(routinen, handle)
782 IF (
PRESENT(fm_y_ia))
THEN
790 mask_quadrupole = (/4, 7, 9/)
793 context=fm_x_ia%matrix_struct%context, nrow_global=homo, ncol_global=virtual)
795 context=fm_x_ia%matrix_struct%context, nrow_global=virtual, ncol_global=virtual)
815 exc_descr(i_exc)%r_e(:) = 0.0_dp
816 exc_descr(i_exc)%r_h(:) = 0.0_dp
817 exc_descr(i_exc)%r_e_sq(:) = 0.0_dp
818 exc_descr(i_exc)%r_h_sq(:) = 0.0_dp
819 exc_descr(i_exc)%r_e_h(:) = 0.0_dp
821 exc_descr(i_exc)%flag_TDA = flag_tda
822 exc_descr(i_exc)%norm_XpY = 0.0_dp
828 IF (.NOT. flag_tda)
THEN
830 norm_xpy = norm_xpy + norm_y
833 exc_descr(i_exc)%norm_XpY = norm_xpy
839 r_h_x(i_dir) = r_h_x(i_dir)/norm_xpy
840 IF (.NOT. flag_tda)
THEN
843 r_h_y(i_dir) = r_h_y(i_dir)/norm_xpy
846 exc_descr(i_exc)%r_h(:) = r_h_x(:) + r_h_y(:)
852 r_e_x(i_dir) = r_e_x(i_dir)/norm_xpy
853 IF (.NOT. flag_tda)
THEN
856 r_e_y(i_dir) = r_e_y(i_dir)/norm_xpy
859 exc_descr(i_exc)%r_e(:) = r_e_x(:) + r_e_y(:)
865 fm_x_ia, r_h_sq_x(i_dir))
866 r_h_sq_x(i_dir) = r_h_sq_x(i_dir)/norm_xpy
867 IF (.NOT. flag_tda)
THEN
870 fm_multipole_ab_trunc(mask_quadrupole(i_dir)), r_h_sq_y(i_dir))
871 r_h_sq_y(i_dir) = r_h_sq_y(i_dir)/norm_xpy
874 exc_descr(i_exc)%r_h_sq(:) = r_h_sq_x(:) + r_h_sq_y(:)
880 fm_multipole_ab_trunc(mask_quadrupole(i_dir)), r_e_sq_x(i_dir))
881 r_e_sq_x(i_dir) = r_e_sq_x(i_dir)/norm_xpy
882 IF (.NOT. flag_tda)
THEN
885 fm_y_ia, r_e_sq_y(i_dir))
886 r_e_sq_y(i_dir) = r_e_sq_y(i_dir)/norm_xpy
889 exc_descr(i_exc)%r_e_sq(:) = r_e_sq_x(:) + r_e_sq_y(:)
902 CALL parallel_gemm(
"N",
"N", homo, virtual, virtual, 1.0_dp, &
903 fm_x_ia, fm_multipole_ab_trunc(i_dir), 0.0_dp, fm_work_ia)
906 fm_multipole_ij_trunc(i_dir), fm_work_ia, 0.0_dp, fm_work_ia_2)
908 CALL cp_fm_trace(fm_x_ia, fm_work_ia_2, r_e_h_xx(i_dir))
909 r_e_h_xx(i_dir) = r_e_h_xx(i_dir)/norm_xpy
910 IF (.NOT. flag_tda)
THEN
915 CALL parallel_gemm(
"N",
"N", homo, virtual, virtual, 1.0_dp, &
916 fm_y_ia, fm_multipole_ab_trunc(i_dir), 0.0_dp, fm_work_ia)
919 fm_multipole_ij_trunc(i_dir), fm_work_ia, 0.0_dp, fm_work_ia_2)
921 CALL cp_fm_trace(fm_y_ia, fm_work_ia_2, r_e_h_yy(i_dir))
922 r_e_h_yy(i_dir) = r_e_h_yy(i_dir)/norm_xpy
936 CALL parallel_gemm(
"T",
"T", virtual, virtual, homo, 1.0_dp, &
937 fm_y_ia, fm_multipole_ai_trunc(i_dir), 0.0_dp, fm_work_ba)
939 CALL parallel_gemm(
"T",
"N", homo, virtual, virtual, 1.0_dp, &
940 fm_multipole_ai_trunc(i_dir), fm_work_ba, 0.0_dp, fm_work_ia)
942 CALL cp_fm_trace(fm_work_ia, fm_x_ia, r_e_h_xy(i_dir))
943 r_e_h_xy(i_dir) = r_e_h_xy(i_dir)/norm_xpy
957 CALL parallel_gemm(
"T",
"T", virtual, virtual, homo, 1.0_dp, &
958 fm_x_ia, fm_multipole_ai_trunc(i_dir), 0.0_dp, fm_work_ba)
960 CALL parallel_gemm(
"T",
"N", homo, virtual, virtual, 1.0_dp, &
961 fm_multipole_ai_trunc(i_dir), fm_work_ba, 0.0_dp, fm_work_ia)
963 CALL cp_fm_trace(fm_work_ia, fm_y_ia, r_e_h_yx(i_dir))
964 r_e_h_yx(i_dir) = r_e_h_yx(i_dir)/norm_xpy
967 exc_descr(i_exc)%r_e_h(:) = r_e_h_xx(:) + r_e_h_xy(:) + r_e_h_yx(:) + r_e_h_yy(:)
974 exc_descr(i_exc)%diff_r_abs = sqrt(sum((exc_descr(i_exc)%r_h(:) - exc_descr(i_exc)%r_e(:))**2))
977 exc_descr(i_exc)%sigma_e = sqrt(sum(exc_descr(i_exc)%r_e_sq(:)) - sum(exc_descr(i_exc)%r_e(:)**2))
980 exc_descr(i_exc)%sigma_h = sqrt(sum(exc_descr(i_exc)%r_h_sq(:)) - sum(exc_descr(i_exc)%r_h(:)**2))
983 exc_descr(i_exc)%cov_e_h_sum = 0.0_dp
984 exc_descr(i_exc)%cov_e_h(:) = 0.0_dp
986 exc_descr(i_exc)%cov_e_h(i_dir) = exc_descr(i_exc)%r_e_h(i_dir) &
987 - exc_descr(i_exc)%r_e(i_dir)*exc_descr(i_exc)%r_h(i_dir)
988 exc_descr(i_exc)%cov_e_h_sum = exc_descr(i_exc)%cov_e_h_sum + &
989 exc_descr(i_exc)%r_e_h(i_dir) - exc_descr(i_exc)%r_e(i_dir)*exc_descr(i_exc)%r_h(i_dir)
993 exc_descr(i_exc)%diff_r_sqr = sqrt(exc_descr(i_exc)%diff_r_abs**2 + &
994 exc_descr(i_exc)%sigma_e**2 + exc_descr(i_exc)%sigma_h**2 &
995 - 2*exc_descr(i_exc)%cov_e_h_sum)
998 exc_descr(i_exc)%corr_e_h = exc_descr(i_exc)%cov_e_h_sum/(exc_descr(i_exc)%sigma_e*exc_descr(i_exc)%sigma_h)
1001 exc_descr(i_exc)%r_e_shift(:) = exc_descr(i_exc)%r_e(:)
1002 exc_descr(i_exc)%r_h_shift(:) = exc_descr(i_exc)%r_h(:)
1007 CALL timestop(handle)
Routines for computing excitonic properties, e.g. exciton diameter, from the BSE.
subroutine, public compute_absorption_spectrum(oscill_str, polarizability_residues, exc_ens, info_approximation, unit_nr, mp2_env)
Computes and returns absorption spectrum for the frequency range and broadening provided by the user....
subroutine, public get_oscillator_strengths(fm_eigvec_x, exc_ens, fm_dipole_ai_trunc, trans_mom_bse, oscill_str, polarizability_residues, mp2_env, homo_red, virtual_red, unit_nr, fm_eigvec_y)
Compute and return BSE dipoles d_r^n = sqrt(2) sum_ia < ψ_i | r | ψ_a > ( X_ia^n + Y_ia^n ) and oscil...
subroutine, public get_exciton_descriptors(exc_descr, fm_x_ia, fm_multipole_ij_trunc, fm_multipole_ab_trunc, fm_multipole_ai_trunc, i_exc, homo, virtual, fm_y_ia)
...
subroutine, public calculate_ntos(fm_x, fm_y, mo_coeff, homo, virtual, info_approximation, oscill_str, qs_env, unit_nr, mp2_env)
...
Auxiliary routines for GW + Bethe-Salpeter for computing electronic excitations.
subroutine, public trace_exciton_descr(fm_a, fm_b, fm_c, alpha)
Computes trace of form Tr{A^T B C} for exciton descriptors.
subroutine, public reshuffle_eigvec(fm_eigvec, fm_eigvec_reshuffled, homo, virtual, n_exc, do_transpose, unit_nr, mp2_env)
...
subroutine, public print_bse_nto_cubes(qs_env, mos, istate, info_approximation, stride, append_cube, print_section)
Borrowed from the tddfpt module with slight adaptions.
subroutine, public fm_general_add_bse(fm_out, fm_in, beta, nrow_secidx_in, ncol_secidx_in, nrow_secidx_out, ncol_secidx_out, unit_nr, reordering, mp2_env)
Adds and reorders full matrices with a combined index structure, e.g. adding W_ij,...
Utility routines to open and close files. Tracking of preconnections.
subroutine, public open_file(file_name, file_status, file_form, file_action, file_position, file_pad, unit_number, debug, skip_get_unit_number, file_access)
Opens the requested file using a free unit number.
subroutine, public close_file(unit_number, file_status, keep_preconnection)
Close an open file given by its logical unit number. Optionally, keep the file and unit preconnected.
basic linear algebra operations for full matrices
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....
used for collecting some of the diagonalization schemes available for cp_fm_type. cp_fm_power also mo...
subroutine, public cp_fm_svd(matrix_a, matrix_eigvl, matrix_eigvr_t, eigval, info)
decomposes a quadratic matrix into its singular value decomposition
represent the structure of a full matrix
subroutine, public cp_fm_struct_create(fmstruct, para_env, context, nrow_global, ncol_global, nrow_block, ncol_block, descriptor, first_p_pos, local_leading_dimension, template_fmstruct, square_blocks, force_block)
allocates and initializes a full matrix structure
subroutine, public cp_fm_struct_release(fmstruct)
releases a full matrix structure
represent a full matrix distributed on many processors
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_to_fm_submat(msource, mtarget, nrow, ncol, s_firstrow, s_firstcol, t_firstrow, t_firstcol)
copy just a part ot the matrix
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_get_submatrix(fm, target_m, start_row, start_col, n_rows, n_cols, transpose)
gets a submatrix of a full matrix op(target_m)(1:n_rows,1:n_cols) =fm(start_row:start_row+n_rows,...
subroutine, public cp_fm_create(matrix, matrix_struct, name, use_sp)
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 ...
recursive integer function, public cp_logger_get_default_unit_nr(logger, local, skip_not_ionode)
asks the default unit number of the given logger. try to use cp_logger_get_unit_nr
type(cp_logger_type) function, pointer, public cp_get_default_logger()
returns the default logger
Defines the basic variable types.
integer, parameter, public dp
Definition of mathematical constants and functions.
real(kind=dp), parameter, public pi
Types needed for MP2 calculations.
basic linear algebra operations for full matrixes
Definition of physical constants:
real(kind=dp), parameter, public c_light_au
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, 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, 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, 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, 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, ecoul_1c, rho0_s_rs, rho0_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)
Get the QUICKSTEP environment.
Definition and initialisation of the mo data type.
subroutine, public allocate_mo_set(mo_set, nao, nmo, nelectron, n_el_f, maxocc, flexible_electron_count)
Allocates a mo set and partially initializes it (nao,nmo,nelectron, and flexible_electron_count are v...
subroutine, public deallocate_mo_set(mo_set)
Deallocate a wavefunction data structure.
subroutine, public init_mo_set(mo_set, fm_pool, fm_ref, fm_struct, name)
initializes an allocated mo_set. eigenvalues, mo_coeff, occupation_numbers are valid only after this ...
keeps the information about the structure of a full matrix
type of a logger, at the moment it contains just a print level starting at which level it should be l...