61#include "./base/base_uses.f90"
67 CHARACTER(len=*),
PARAMETER,
PRIVATE :: moduleN =
'bse_main'
93 SUBROUTINE prepare_bse_env(bse_env, fm_S_ia_full, fm_S_ij_full, fm_S_ab_full, fm_Q, &
94 Eigenval, Eigenval_scf, homo, virtual, dimen_RI, dimen_RI_red, &
95 gw_corr_lev_occ, bse_lev_virt, qs_env, unit_nr)
98 TYPE(
cp_fm_type),
DIMENSION(:),
INTENT(IN) :: fm_s_ia_full, fm_s_ij_full, fm_s_ab_full
100 REAL(kind=
dp),
DIMENSION(:, :, :),
INTENT(IN) :: eigenval, eigenval_scf
101 INTEGER,
DIMENSION(:),
INTENT(IN) :: homo, virtual
102 INTEGER,
INTENT(IN) :: dimen_ri, dimen_ri_red, gw_corr_lev_occ
103 INTEGER,
DIMENSION(:),
INTENT(IN) :: bse_lev_virt
105 INTEGER,
INTENT(IN) :: unit_nr
107 CHARACTER(LEN=*),
PARAMETER :: routinen =
'prepare_bse_env'
109 INTEGER :: handle, ispin, n_window, nspins
110 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: n_mo, n_ov, offsets
111 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: eigenval_dft_spin, eigenval_qp_spin
116 CALL timeset(routinen, handle)
121 bse_section => bse_env%bse_section
125 bse_env%nspins = nspins
126 bse_env%dimen_RI = dimen_ri
127 bse_env%dimen_RI_red = dimen_ri_red
129 bse_env%gw_corr_lev_occ = gw_corr_lev_occ
130 ALLOCATE (bse_env%gw_corr_lev_virt(nspins))
131 bse_env%gw_corr_lev_virt(:) = bse_lev_virt(:)
134 bse_env%do_iterdiag = bse_env%bse_diag_method ==
bse_iterdiag
135 bse_env%do_fulldiag = bse_env%bse_diag_method ==
bse_fulldiag
136 bse_env%do_tda = bse_env%flag_tda ==
bse_tda .OR. bse_env%flag_tda ==
bse_both
137 bse_env%do_abba = bse_env%flag_tda ==
bse_abba .OR. bse_env%flag_tda ==
bse_both
144 bse_env%bse_debug_print = .true.
149 bse_env%para_env => fm_s_ia_full(1)%matrix_struct%para_env
150 CALL get_qs_env(qs_env, subsys=bse_env%subsys, pw_env=bse_env%pw_env, &
151 dft_control=bse_env%dft_control, mos=bse_env%mos, &
152 exstate_env=bse_env%exstate_env)
153 CALL bse_env%para_env%sync()
156 IF (bse_env%do_iterdiag)
THEN
157 cpabort(
"Iterative BSE is not yet available for open-shell references")
159 CALL cp_warn(__location__, &
160 "Open-shell (UKS/LSD) BSE is a recent addition and has not been "// &
161 "extensively validated. Verify results carefully before using them "// &
162 "for production calculations.")
166 ALLOCATE (n_mo(nspins))
167 n_mo(:) = homo(:) + virtual(:)
169 bse_env%bse_cutoff_empty, window, warn=.true.)
172 ALLOCATE (bse_env%homo_red(nspins), bse_env%virt_red(nspins), bse_env%homo_full(nspins))
173 ALLOCATE (bse_env%fm_S_ia(nspins), bse_env%fm_S_ij(nspins), bse_env%fm_S_ab(nspins))
174 bse_env%homo_full(:) = homo(:)
178 eigenval_scf(:, 1, ispin), eigenval(:, 1, ispin), &
179 eigenval_dft_spin, eigenval_qp_spin, homo(ispin), virtual(ispin), &
180 dimen_ri, unit_nr, ispin, bse_env, window, nspins == 1)
183 n_window =
SIZE(eigenval_qp_spin)
184 ALLOCATE (bse_env%eigenval_dft(n_window, nspins), bse_env%eigenval_qp(n_window, nspins))
186 bse_env%eigenval_dft(:, ispin) = eigenval_dft_spin(:)
187 bse_env%eigenval_qp(:, ispin) = eigenval_qp_spin(:)
188 DEALLOCATE (eigenval_dft_spin, eigenval_qp_spin)
190 ALLOCATE (n_ov(nspins), offsets(nspins))
192 DEALLOCATE (n_ov, offsets)
194 CALL invert_static_screening(fm_q, dimen_ri_red, bse_env%fm_eps_inv)
198 CALL get_multipoles_ao(qs_env, 1, bse_env%matrix_dipole_ao, bse_env%multipole_ref_point)
199 IF (bse_env%num_print_exc_descr /= 0 .AND. nspins == 1)
THEN
200 CALL get_multipoles_ao(qs_env, 2, bse_env%matrix_quadpole_ao, bse_env%multipole_ref_point)
203 CALL timestop(handle)
214 SUBROUTINE invert_static_screening(fm_Q, dimen_RI_red, fm_eps_inv)
217 INTEGER,
INTENT(IN) :: dimen_ri_red
220 CHARACTER(LEN=*),
PARAMETER :: routinen =
'invert_static_screening'
222 INTEGER :: handle, i_global, iib, info_chol, &
223 j_global, jjb, ncol_local, nrow_local
224 INTEGER,
DIMENSION(:),
POINTER :: col_indices, row_indices
227 CALL timeset(routinen, handle)
236 CALL cp_fm_get_info(matrix=fm_eps_inv, nrow_local=nrow_local, ncol_local=ncol_local, &
237 row_indices=row_indices, col_indices=col_indices)
238 DO jjb = 1, ncol_local
239 j_global = col_indices(jjb)
240 DO iib = 1, nrow_local
241 i_global = row_indices(iib)
242 IF (j_global == i_global .AND. i_global <= dimen_ri_red)
THEN
243 fm_eps_inv%local_data(iib, jjb) = fm_eps_inv%local_data(iib, jjb) + 1.0_dp
250 IF (info_chol /= 0)
THEN
251 CALL cp_abort(__location__,
'Cholesky decomposition failed for static polarization in BSE')
258 CALL timestop(handle)
260 END SUBROUTINE invert_static_screening
272 TYPE(
cp_fm_type),
DIMENSION(:),
INTENT(IN) :: mo_coeff
273 INTEGER,
INTENT(IN) :: unit_nr
275 CHARACTER(LEN=*),
PARAMETER :: routinen =
'bse_solve'
277 INTEGER :: handle, ispin, n_window, nspins
278 REAL(kind=
dp) :: diag_runtime_est
279 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: eigenval_joint
280 TYPE(
cp_fm_type) :: fm_a_bse, fm_b_bse, fm_c_bse, &
281 fm_inv_sqrt_a_minus_b, &
285 CALL timeset(routinen, handle)
287 nspins = bse_env%nspins
293 n_window =
SIZE(bse_env%eigenval_qp, 1)
294 ALLOCATE (eigenval_joint(n_window*nspins))
296 IF (bse_env%use_ks_energies)
THEN
297 eigenval_joint((ispin - 1)*n_window + 1:ispin*n_window) = bse_env%eigenval_dft(:, ispin)
299 eigenval_joint((ispin - 1)*n_window + 1:ispin*n_window) = bse_env%eigenval_qp(:, ispin)
304 ALLOCATE (bse_env%fm_S_bar_ia(nspins), bse_env%fm_S_bar_ij(nspins))
306 CALL screen_slabs(bse_env%fm_eps_inv, bse_env%fm_S_ij(ispin), bse_env%fm_S_ia(ispin), &
307 bse_env%dimen_RI_red, bse_env%homo_red(ispin), bse_env%virt_red(ispin), &
308 bse_env%fm_S_bar_ij(ispin), bse_env%fm_S_bar_ia(ispin))
312 IF (bse_env%do_iterdiag)
THEN
314 bse_env%homo_red, bse_env%virt_red, bse_env%homo_full, &
315 bse_env%dimen_RI, bse_env%do_tda, bse_env%do_abba, &
316 bse_env, mo_coeff, unit_nr)
319 IF (bse_env%do_fulldiag)
THEN
321 bse_env%para_env, diag_runtime_est)
322 CALL create_a_and_b(bse_env%fm_S_ia, bse_env%fm_S_ij, bse_env%fm_S_ab, &
323 bse_env%fm_S_bar_ia, bse_env%fm_S_bar_ij, fm_a_bse, fm_b_bse, &
324 bse_env%do_abba, eigenval_joint, unit_nr, bse_env%homo_red, &
325 bse_env%virt_red, bse_env%dimen_RI, bse_env)
326 IF (bse_env%do_abba)
THEN
328 fm_sqrt_a_minus_b, fm_inv_sqrt_a_minus_b, &
329 unit_nr, bse_env, diag_runtime_est)
332 tddfpt_control => bse_env%dft_control%tddfpt2_control
334 IF (bse_env%do_tda .AND. (.NOT. tddfpt_control%do_bse))
THEN
335 CALL diagonalize_a(fm_a_bse, bse_env%homo_red, bse_env%virt_red, bse_env%homo_full, &
336 unit_nr, diag_runtime_est, bse_env, mo_coeff)
339 IF (bse_env%do_abba)
THEN
340 CALL diagonalize_c(fm_c_bse, bse_env%homo_red, bse_env%virt_red, bse_env%homo_full, &
341 fm_sqrt_a_minus_b, fm_inv_sqrt_a_minus_b, &
342 unit_nr, diag_runtime_est, bse_env, mo_coeff)
347 DEALLOCATE (eigenval_joint)
349 IF (unit_nr > 0)
THEN
350 WRITE (unit_nr,
'(T2,A4,T7,A53)')
'BSE|',
'The BSE was successfully calculated. Have a nice day!'
353 CALL timestop(handle)
371 INTEGER,
INTENT(IN) :: unit_nr
373 CHARACTER(LEN=*),
PARAMETER :: routinen =
'bse_fulldiag_memory_check'
375 CHARACTER(LEN=16) :: bud_str, mem_str
376 CHARACTER(LEN=64) :: remedy
377 INTEGER :: handle, homo, ispin, n_ov_joint, nspins
378 LOGICAL :: from_free, over, skipped
379 REAL(kind=
dp) :: budget_gb, mem_avail_gb, mem_est_gb
382 CALL timeset(routinen, handle)
386 CALL bse_window_from_mos(mos, bse_env%bse_cutoff_occ, bse_env%bse_cutoff_empty, window, warn=.false.)
390 n_ov_joint = n_ov_joint + (homo - window%first_mo + 1)*(window%last_mo - homo)
394 REAL(para_env%num_pe, kind=
dp)
397 from_free = bse_env%memory_budget_gb < 0.0_dp
399 budget_gb = bse_env%memory_budget_gb
403 skipped = mem_avail_gb <= 0.0_dp
405 over = .NOT. skipped .AND. bse_env%memory_check /=
bse_memcheck_off .AND. mem_est_gb > budget_gb
407 IF (unit_nr > 0)
THEN
408 WRITE (unit_nr,
'(T2,A4)')
'BSE|'
409 WRITE (unit_nr,
'(T2,A4,T7,A)')
'BSE|',
'Early memory check for the full diagonalization'
410 WRITE (unit_nr,
'(T2,A4,T7,A,T71,I10)')
'BSE|',
'Transition pairs in the active window (DFT axis)', &
412 WRITE (unit_nr,
'(T2,A4,T7,A,T67,F14.3)')
'BSE|',
'Peak memory estimate per MPI rank (GB)', mem_est_gb
413 IF (.NOT. skipped)
THEN
414 WRITE (unit_nr,
'(T2,A4,T7,A,T67,F14.3)')
'BSE|',
'Memory budget per MPI rank (GB)', budget_gb
417 WRITE (unit_nr,
'(T2,A4,T7,A)')
'BSE|',
'Memory check: OFF'
418 ELSE IF (skipped)
THEN
419 WRITE (unit_nr,
'(T2,A4,T7,A)')
'BSE|',
'Memory check: skipped, free memory not detectable'
421 WRITE (unit_nr,
'(T2,A4,T7,A)')
'BSE|',
'Memory check: the estimate exceeds the budget'
423 WRITE (unit_nr,
'(T2,A4,T7,A)')
'BSE|',
'Memory check: within the budget'
425 WRITE (unit_nr,
'(T2,A4)')
'BSE|'
429 WRITE (mem_str,
'(F16.3)') mem_est_gb
430 WRITE (bud_str,
'(F16.3)') budget_gb
432 IF (nspins == 1)
THEN
433 remedy =
"more MPI ranks, a tighter window, ITERDIAG"
435 remedy =
"more MPI ranks, a tighter window"
437 SELECT CASE (bse_env%memory_check)
439 IF (unit_nr > 0)
CALL cp_warn(__location__, &
440 "BSE full diagonalization: the estimate of "//trim(adjustl(mem_str))// &
441 " GB per MPI rank exceeds the budget of "//trim(adjustl(bud_str))// &
442 " GB. Try one of: "//trim(remedy)//
".")
444 CALL cp_abort(__location__, &
445 "BSE full diagonalization: the estimate of "//trim(adjustl(mem_str))// &
446 " GB per MPI rank exceeds the budget of "//trim(adjustl(bud_str))// &
447 " GB. Try one of: "//trim(remedy)//
", MEMORY_CHECK WARN.")
451 CALL timestop(handle)
Routines for the full diagonalization of GW + Bethe-Salpeter for computing electronic excitations.
subroutine, public create_a_and_b(fm_s_ia, fm_s_ij, fm_s_ab, fm_s_bar_ia, fm_s_bar_ij, fm_a, fm_b, do_abba, eigenval, unit_nr, homo, virtual, dimen_ri, bse_env)
Explicit A, and B for ABBA, from the slabs the screening method contracts: the bare ones for TDHF and...
subroutine, public diagonalize_a(fm_a, homo, virtual, homo_irred, unit_nr, diag_est, bse_env, mo_coeff)
Solving hermitian eigenvalue equation A X^n = Ω^n X^n.
subroutine, public create_hermitian_form_of_abba(fm_a, fm_b, fm_c, fm_sqrt_a_minus_b, fm_inv_sqrt_a_minus_b, unit_nr, bse_env, diag_est)
Construct Matrix C=(A-B)^0.5 (A+B) (A-B)^0.5 to solve full BSE matrix as a hermitian problem (cf....
subroutine, public diagonalize_c(fm_c, homo, virtual, homo_irred, fm_sqrt_a_minus_b, fm_inv_sqrt_a_minus_b, unit_nr, diag_est, bse_env, mo_coeff)
Solving eigenvalue equation C Z^n = (Ω^n)^2 Z^n . Here, the eigenvectors Z^n relate to X^n via Eq....
Iterative solution of the Bethe-Salpeter equation: the block Davidson solvers on top of the matrix-fr...
subroutine, public solve_bse_iteratively(eigenval_reduced, homo_red_arr, virt_red_arr, homo, dimen_ri, do_tda, do_abba, bse_env, mo_coeff, unit_nr)
Lowest excitations of a closed-shell reference from the block Davidson solvers on top of the matrix-f...
Main routines for GW + Bethe-Salpeter for computing electronic excitations: a GW path prepares the BS...
subroutine, public bse_fulldiag_memory_check(bse_env, mos, para_env, unit_nr)
Early memory check for the full diagonalization, before any GW work: the window on the DFT axis gives...
subroutine, public bse_solve(bse_env, mo_coeff, unit_nr)
Solves the BSE on a prepared environment: input normalisation, the screened slabs from [1+Q(0)]^-1,...
subroutine, public prepare_bse_env(bse_env, fm_s_ia_full, fm_s_ij_full, fm_s_ab_full, fm_q, eigenval, eigenval_scf, homo, virtual, dimen_ri, dimen_ri_red, gw_corr_lev_occ, bse_lev_virt, qs_env, unit_nr)
Prepares the BSE environment from the old GW's slabs: run flags, the window on the DFT axis,...
Matrix-free application of the BSE matrices A and B to trial vectors from RI slabs that are sliced al...
real(kind=dp), parameter, public mem_fraction
Routines for printing information in context of the BSE calculation.
subroutine, public print_bse_start_flag(bse_tda, bse_abba, unit_nr)
...
The BSE environment: the settings of the &BSE section and the state a GW path prepares for the solver...
Auxiliary routines for GW + Bethe-Salpeter for computing electronic excitations.
subroutine, public truncate_bse_matrices(fm_s_ia_full, fm_s_ij_full, fm_s_ab_full, eigenval_scf, eigenval, eigenval_reduced_scf, eigenval_reduced_qp, homo, virtual, dimen_ri, unit_nr, ispin, bse_env, window, print_window)
Determines indices within the given energy cutoffs and truncates Eigenvalues and matrices.
subroutine, public estimate_bse_resources(n_ov_joint, unit_nr, bse_abba, para_env, diag_runtime_est)
Roughly estimates the needed runtime and memory during the BSE run.
subroutine, public adapt_bse_input_params(homo, virtual, unit_nr, bse_env)
Checks BSE input section and adapts them if necessary.
pure real(kind=dp) function, public fulldiag_memory_estimate_gb(n_ov_joint, do_abba)
Peak memory of the full diagonalization in GB, all ranks together: n_ov^2 doubles times the matrices ...
subroutine, public bse_window_from_dft(eigenval_scf, n_mo, homo, cutoff_occ, cutoff_empty, window, warn)
The active MO window on the DFT axis: one absolute MO range for every spin; when the spin windows dif...
subroutine, public get_bse_spin_block_layout(homo_red, virt_red, n_ov, offsets, n_ov_joint)
Spin-block layout for the open-shell (joint) BSE matrix: per-spin OV-pair counts and the block offset...
subroutine, public bse_window_from_mos(mos, cutoff_occ, cutoff_empty, window, warn)
The active MO window of bse_window_from_dft, from the DFT eigenvalues of the MO sets.
subroutine, public screen_slabs(fm_eps_inv, fm_s_ij, fm_s_ia, dimen_ri_red, homo, virtual, fm_s_bar_ij, fm_s_bar_ia)
The screened slabs \bar{B}^P_ij = sum_Q [1+Q(0)]^-1_PQ B^Q_ij and \bar{B}^P_ia = sum_Q [1+Q(0)]^-1_PQ...
Defines control structures, which contain the parameters and the settings for the DFT-based calculati...
Basic linear algebra operations for full matrices.
subroutine, public cp_fm_uplo_to_full(matrix, work, uplo)
given a triangular matrix according to uplo, computes the corresponding full matrix
various cholesky decomposition related routines
subroutine, public cp_fm_cholesky_invert(matrix, n, info_out)
used to replace the cholesky decomposition by the inverse
subroutine, public cp_fm_cholesky_decompose(matrix, n, info_out)
used to replace a symmetric positive def. matrix M with its cholesky decomposition U: M = U^T * U,...
represent a full matrix distributed on many processors
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_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, parameter, public debug_print_level
Defines the basic variable types.
integer, parameter, public dp
Interface to the message passing library MPI.
subroutine, public mp_mem_avail_per_rank_gb(comm, mem_avail_gb)
Memory that is currently free on the node, per MPI rank of that node, in GB.
Common selection and union operations for contiguous molecular-orbital windows.
subroutine, public get_qs_env(qs_env, atomic_kind_set, qs_kind_set, cell, super_cell, cell_ref, use_ref_cell, kpoints, dft_control, mos, sab_orb, sab_all, qmmm, qmmm_periodic, mimic, sac_ae, sac_ppl, sac_lri, sap_ppnl, sab_vdw, sab_scp, sap_oce, sab_lrc, sab_se, sab_xtbe, sab_tbe, sab_core, sab_xb, sab_xtb_pp, sab_xtb_nonbond, sab_almo, sab_kp, sab_kp_nosym, sab_cneo, particle_set, energy, force, matrix_h, matrix_h_im, matrix_ks, matrix_ks_im, matrix_vxc, run_rtp, rtp, matrix_h_kp, matrix_h_im_kp, matrix_ks_kp, matrix_ks_im_kp, matrix_vxc_kp, kinetic_kp, matrix_s_kp, matrix_w_kp, matrix_s_ri_aux_kp, matrix_s, matrix_s_ri_aux, matrix_w, matrix_p_mp2, matrix_p_mp2_admm, matrix_vhxc, rho, rho_xc, pw_env, ewald_env, ewald_pw, active_space, mpools, input, para_env, blacs_env, scf_control, rel_control, kinetic, qs_charges, vppl, xcint_weights, rho_core, rho_nlcc, rho_nlcc_g, ks_env, ks_qmmm_env, wf_history, scf_env, local_particles, local_molecules, distribution_2d, dbcsr_dist, molecule_kind_set, molecule_set, subsys, cp_subsys, oce, local_rho_set, rho_atom_set, task_list, task_list_soft, rho0_atom_set, rho0_mpole, rhoz_set, rhoz_cneo_set, ecoul_1c, rho0_s_rs, rho0_s_gs, rhoz_cneo_s_rs, rhoz_cneo_s_gs, do_kpoints, has_unit_metric, requires_mo_derivs, mo_derivs, mo_loc_history, nkind, natom, nelectron_total, nelectron_spin, efield, neighbor_list_id, linres_control, xas_env, virial, cp_ddapc_env, cp_ddapc_ewald, outer_scf_history, outer_scf_ihistory, x_data, et_coupling, dftb_potential, results, se_taper, se_store_int_env, se_nddo_mpole, se_nonbond_env, admm_env, lri_env, lri_density, exstate_env, ec_env, harris_env, dispersion_env, gcp_env, vee, rho_external, external_vxc, mask, mp2_env, bs_env, kg_env, wanniercentres, atprop, ls_scf_env, do_transport, transport_env, v_hartree_rspace, s_mstruct_changed, rho_changed, potential_changed, forces_up_to_date, mscfg_env, almo_scf_env, gradient_history, variable_history, embed_pot, spin_embed_pot, polar_env, mos_last_converged, eeq, rhs, do_rixs, tb_tblite)
Get the QUICKSTEP environment.
Definition and initialisation of the mo data type.
subroutine, public get_mo_set(mo_set, maxocc, homo, lfomo, nao, nelectron, n_el_f, nmo, eigenvalues, occupation_numbers, mo_coeff, mo_coeff_b, uniform_occupation, kts, mu, flexible_electron_count)
Get the components of a MO set data structure.
Calculates the moment integrals <a|r^m|b> and <a|r x d/dr|b>.
subroutine, public get_multipoles_ao(qs_env, n_moments, matrix_multipole, rpoint)
The AO multipoles M^k_µν = <φ_µ|(r - r_0)^k|φ_ν> of every order up to n_moments, on the block pattern...
Settings of the &BSE section (read_bse_section, re-read by prepare_bse_env, normalised in place by ad...
type of a logger, at the moment it contains just a print level starting at which level it should be l...
stores all the informations relevant to an mpi environment