Line data Source code
1 : !--------------------------------------------------------------------------------------------------!
2 : ! CP2K: A general program to perform molecular dynamics simulations !
3 : ! Copyright 2000-2026 CP2K developers group <https://cp2k.org> !
4 : ! !
5 : ! SPDX-License-Identifier: GPL-2.0-or-later !
6 : !--------------------------------------------------------------------------------------------------!
7 :
8 : ! **************************************************************************************************
9 : !> \brief
10 : !> \author Jan Wilhelm
11 : !> \date 07.2023
12 : ! **************************************************************************************************
13 : MODULE post_scf_bandstructure_utils
14 : USE atomic_kind_types, ONLY: atomic_kind_type,&
15 : get_atomic_kind,&
16 : get_atomic_kind_set
17 : USE cell_types, ONLY: cell_type,&
18 : get_cell,&
19 : pbc
20 : USE cp_blacs_env, ONLY: cp_blacs_env_type
21 : USE cp_cfm_basic_linalg, ONLY: cp_cfm_scale
22 : USE cp_cfm_cholesky, ONLY: cp_cfm_cholesky_decompose
23 : USE cp_cfm_diag, ONLY: cp_cfm_geeig,&
24 : cp_cfm_geeig_canon,&
25 : cp_cfm_heevd
26 : USE cp_cfm_types, ONLY: cp_cfm_create,&
27 : cp_cfm_get_info,&
28 : cp_cfm_release,&
29 : cp_cfm_set_all,&
30 : cp_cfm_to_cfm,&
31 : cp_cfm_to_fm,&
32 : cp_cfm_type,&
33 : cp_fm_to_cfm
34 : USE cp_control_types, ONLY: dft_control_type
35 : USE cp_dbcsr_api, ONLY: &
36 : dbcsr_create, dbcsr_deallocate_matrix, dbcsr_desymmetrize, dbcsr_p_type, dbcsr_set, &
37 : dbcsr_type, dbcsr_type_antisymmetric, dbcsr_type_no_symmetry, dbcsr_type_symmetric
38 : USE cp_dbcsr_cp2k_link, ONLY: cp_dbcsr_alloc_block_from_nbl
39 : USE cp_dbcsr_operations, ONLY: copy_dbcsr_to_fm,&
40 : copy_fm_to_dbcsr,&
41 : dbcsr_allocate_matrix_set,&
42 : dbcsr_deallocate_matrix_set
43 : USE cp_files, ONLY: close_file,&
44 : open_file
45 : USE cp_fm_diag, ONLY: cp_fm_geeig_canon
46 : USE cp_fm_struct, ONLY: cp_fm_struct_create,&
47 : cp_fm_struct_release,&
48 : cp_fm_struct_type
49 : USE cp_fm_types, ONLY: cp_fm_create,&
50 : cp_fm_get_diag,&
51 : cp_fm_get_info,&
52 : cp_fm_release,&
53 : cp_fm_set_all,&
54 : cp_fm_to_fm,&
55 : cp_fm_type
56 : USE cp_log_handling, ONLY: cp_logger_get_default_io_unit,&
57 : cp_to_string
58 : USE cp_parser_methods, ONLY: read_float_object
59 : USE input_constants, ONLY: int_ldos_z,&
60 : large_cell_Gamma,&
61 : large_cell_Gamma_ri_rs,&
62 : non_periodic_ri_rs,&
63 : small_cell_full_kp
64 : USE input_section_types, ONLY: section_vals_get,&
65 : section_vals_get_subs_vals,&
66 : section_vals_type,&
67 : section_vals_val_get
68 : USE kinds, ONLY: default_string_length,&
69 : dp,&
70 : max_line_length
71 : USE kpoint_methods, ONLY: kpoint_init_cell_index,&
72 : rskp_transform
73 : USE kpoint_types, ONLY: get_kpoint_info,&
74 : kpoint_create,&
75 : kpoint_type
76 : USE machine, ONLY: m_walltime
77 : USE mathconstants, ONLY: gaussi,&
78 : twopi,&
79 : z_one,&
80 : z_zero
81 : USE message_passing, ONLY: mp_para_env_type
82 : USE parallel_gemm_api, ONLY: parallel_gemm
83 : USE particle_types, ONLY: particle_type
84 : USE physcon, ONLY: angstrom,&
85 : evolt
86 : USE post_scf_bandstructure_types, ONLY: band_edges_type,&
87 : eps_qp_gap,&
88 : max_qp_gap,&
89 : post_scf_bandstructure_type
90 : USE pw_env_types, ONLY: pw_env_get,&
91 : pw_env_type
92 : USE pw_pool_types, ONLY: pw_pool_type
93 : USE pw_types, ONLY: pw_c1d_gs_type,&
94 : pw_r3d_rs_type
95 : USE qs_collocate_density, ONLY: calculate_rho_elec
96 : USE qs_environment_types, ONLY: get_qs_env,&
97 : qs_environment_type
98 : USE qs_ks_types, ONLY: qs_ks_env_type
99 : USE qs_mo_types, ONLY: get_mo_set,&
100 : mo_set_type
101 : USE qs_neighbor_list_types, ONLY: neighbor_list_set_p_type
102 : USE rpa_gw_im_time_util, ONLY: compute_weight_re_im,&
103 : get_atom_index_from_basis_function_index
104 : USE scf_control_types, ONLY: scf_control_type
105 : USE soc_pseudopotential_methods, ONLY: V_SOC_xyz_from_pseudopotential,&
106 : remove_soc_outside_energy_window_mo
107 : USE soc_pseudopotential_utils, ONLY: add_cfm_submat,&
108 : add_dbcsr_submat,&
109 : cfm_add_on_diag,&
110 : create_cfm_double,&
111 : get_cfm_submat
112 : USE string_utilities, ONLY: uppercase
113 : #include "base/base_uses.f90"
114 :
115 : IMPLICIT NONE
116 :
117 : PRIVATE
118 :
119 : PUBLIC :: create_and_init_bs_env, &
120 : eval_bandstructure_properties, cfm_ikp_from_fm_Gamma, &
121 : MIC_contribution_from_ikp, compute_xkp, kpoint_init_cell_index_simple, &
122 : rsmat_to_kp, soc, get_VBM_CBM_bandgaps, get_all_VBM_CBM_bandgaps
123 :
124 : CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'post_scf_bandstructure_utils'
125 :
126 : CONTAINS
127 :
128 : ! **************************************************************************************************
129 : !> \brief ...
130 : !> \param qs_env ...
131 : !> \param bs_env ...
132 : !> \param post_scf_bandstructure_section ...
133 : ! **************************************************************************************************
134 106 : SUBROUTINE create_and_init_bs_env(qs_env, bs_env, post_scf_bandstructure_section)
135 : TYPE(qs_environment_type), POINTER :: qs_env
136 : TYPE(post_scf_bandstructure_type), POINTER :: bs_env
137 : TYPE(section_vals_type), POINTER :: post_scf_bandstructure_section
138 :
139 : CHARACTER(LEN=*), PARAMETER :: routineN = 'create_and_init_bs_env'
140 :
141 : INTEGER :: handle
142 :
143 106 : CALL timeset(routineN, handle)
144 :
145 10388 : ALLOCATE (bs_env)
146 :
147 106 : CALL print_header(bs_env)
148 :
149 106 : CALL read_bandstructure_input_parameters(bs_env, post_scf_bandstructure_section, qs_env)
150 :
151 106 : CALL get_parameters_from_qs_env(qs_env, bs_env)
152 :
153 106 : CALL set_heuristic_parameters(bs_env)
154 :
155 194 : SELECT CASE (bs_env%small_cell_full_kp_or_large_cell_Gamma)
156 : CASE (large_cell_Gamma, large_cell_Gamma_ri_rs, non_periodic_ri_rs)
157 :
158 88 : CALL setup_kpoints_DOS_large_cell_Gamma(qs_env, bs_env, bs_env%kpoints_DOS)
159 :
160 88 : CALL allocate_and_fill_fm_ks_fm_s(qs_env, bs_env)
161 :
162 88 : CALL diagonalize_ks_matrix(bs_env)
163 :
164 88 : CALL check_positive_definite_overlap_mat(bs_env, qs_env)
165 :
166 : CASE (small_cell_full_kp)
167 :
168 18 : CALL setup_kpoints_scf_desymm(qs_env, bs_env, bs_env%kpoints_scf_desymm, .TRUE.)
169 18 : CALL setup_kpoints_scf_desymm(qs_env, bs_env, bs_env%kpoints_scf_desymm_2, .FALSE.)
170 :
171 18 : CALL setup_kpoints_DOS_small_cell_full_kp(bs_env, bs_env%kpoints_DOS)
172 :
173 18 : CALL allocate_and_fill_fm_ks_fm_s(qs_env, bs_env)
174 :
175 124 : CALL compute_cfm_mo_coeff_kp_and_eigenval_scf_kp(qs_env, bs_env)
176 :
177 : END SELECT
178 :
179 106 : CALL timestop(handle)
180 :
181 106 : END SUBROUTINE create_and_init_bs_env
182 :
183 : ! **************************************************************************************************
184 : !> \brief ...
185 : !> \param bs_env ...
186 : !> \param bs_sec ...
187 : !> \param qs_env ...
188 : ! **************************************************************************************************
189 106 : SUBROUTINE read_bandstructure_input_parameters(bs_env, bs_sec, qs_env)
190 : TYPE(post_scf_bandstructure_type), POINTER :: bs_env
191 : TYPE(section_vals_type), POINTER :: bs_sec
192 : TYPE(qs_environment_type), POINTER :: qs_env
193 :
194 : CHARACTER(LEN=*), PARAMETER :: routineN = 'read_bandstructure_input_parameters'
195 :
196 : CHARACTER(LEN=default_string_length) :: ustr
197 : CHARACTER(LEN=default_string_length), &
198 106 : DIMENSION(:), POINTER :: string_ptr
199 : CHARACTER(LEN=max_line_length) :: error_msg
200 : INTEGER :: handle, i, ikp
201 : REAL(KIND=dp), DIMENSION(3) :: kpptr
202 : REAL(KIND=dp), DIMENSION(3, 3) :: cart_hmat
203 : TYPE(cell_type), POINTER :: cell
204 : TYPE(section_vals_type), POINTER :: dos_pdos_sec, floquet_sec, gw_sec, &
205 : kp_bs_sec, ldos_sec, soc_sec
206 :
207 106 : CALL timeset(routineN, handle)
208 106 : NULLIFY (cell)
209 106 : CALL get_qs_env(qs_env=qs_env, cell=cell)
210 1378 : cart_hmat(:, :) = cell%hmat(:, :)
211 106 : IF (cell%input_cell_canonicalized) cart_hmat(:, :) = cell%input_hmat(:, :)
212 :
213 106 : NULLIFY (gw_sec)
214 106 : gw_sec => section_vals_get_subs_vals(bs_sec, "GW")
215 106 : CALL section_vals_get(gw_sec, explicit=bs_env%do_gw)
216 106 : CALL section_vals_val_get(gw_sec, "RI_RS", l_val=bs_env%do_gw_ri_rs)
217 :
218 106 : NULLIFY (soc_sec)
219 106 : soc_sec => section_vals_get_subs_vals(bs_sec, "SOC")
220 106 : CALL section_vals_get(soc_sec, explicit=bs_env%do_soc)
221 :
222 106 : CALL section_vals_val_get(soc_sec, "SOC_WINDOW_OCC", r_val=bs_env%soc_window_occ)
223 106 : CALL section_vals_val_get(soc_sec, "SOC_WINDOW_VIRT", r_val=bs_env%soc_window_virt)
224 106 : CALL section_vals_val_get(soc_sec, "SOC_WINDOW_SMEARING", r_val=bs_env%soc_window_smearing)
225 :
226 106 : NULLIFY (dos_pdos_sec)
227 106 : dos_pdos_sec => section_vals_get_subs_vals(bs_sec, "DOS")
228 106 : CALL section_vals_get(dos_pdos_sec, explicit=bs_env%do_dos_pdos)
229 :
230 106 : CALL section_vals_val_get(bs_sec, "DOS%KPOINTS", i_vals=bs_env%nkp_grid_DOS_input)
231 106 : CALL section_vals_val_get(bs_sec, "DOS%ENERGY_WINDOW", r_val=bs_env%energy_window_DOS)
232 106 : CALL section_vals_val_get(bs_sec, "DOS%ENERGY_STEP", r_val=bs_env%energy_step_DOS)
233 106 : CALL section_vals_val_get(bs_sec, "DOS%BROADENING", r_val=bs_env%broadening_DOS)
234 :
235 106 : NULLIFY (ldos_sec)
236 106 : ldos_sec => section_vals_get_subs_vals(bs_sec, "DOS%LDOS")
237 106 : CALL section_vals_get(ldos_sec, explicit=bs_env%do_ldos)
238 :
239 106 : CALL section_vals_val_get(ldos_sec, "INTEGRATION", i_val=bs_env%int_ldos_xyz)
240 106 : CALL section_vals_val_get(ldos_sec, "BIN_MESH", i_vals=bs_env%bin_mesh)
241 :
242 106 : NULLIFY (kp_bs_sec)
243 106 : kp_bs_sec => section_vals_get_subs_vals(bs_sec, "BANDSTRUCTURE_PATH")
244 106 : CALL section_vals_val_get(kp_bs_sec, "NPOINTS", i_val=bs_env%input_kp_bs_npoints)
245 106 : CALL section_vals_val_get(kp_bs_sec, "UNITS", c_val=ustr)
246 106 : CALL uppercase(ustr)
247 106 : CALL section_vals_val_get(kp_bs_sec, "SPECIAL_POINT", n_rep_val=bs_env%input_kp_bs_n_sp_pts)
248 :
249 106 : NULLIFY (floquet_sec)
250 106 : floquet_sec => section_vals_get_subs_vals(bs_sec, "FLOQUET")
251 106 : CALL section_vals_get(floquet_sec, explicit=bs_env%do_floquet)
252 106 : CALL section_vals_val_get(floquet_sec, "AMPLITUDE", r_val=bs_env%floquet_amplitude)
253 106 : CALL section_vals_val_get(floquet_sec, "FREQUENCY", r_val=bs_env%floquet_omega)
254 106 : CALL section_vals_val_get(floquet_sec, "POLARISATION", r_vals=bs_env%floquet_polarisation)
255 106 : CALL section_vals_val_get(floquet_sec, "PHASE_OFFSETS", r_vals=bs_env%floquet_phi)
256 106 : CALL section_vals_val_get(floquet_sec, "MAX_FLOQUET_INDEX", i_val=bs_env%max_floquet_index)
257 106 : CALL section_vals_val_get(floquet_sec, "EPS_FLOQUET", r_val=bs_env%eps_floquet)
258 106 : CALL section_vals_val_get(floquet_sec, "ENERGY_WINDOW", r_val=bs_env%energy_window_floquet)
259 106 : CALL section_vals_val_get(floquet_sec, "ENERGY_STEP", r_val=bs_env%energy_step_floquet)
260 106 : CALL section_vals_val_get(floquet_sec, "BROADENING", r_val=bs_env%broadening_floquet)
261 106 : CALL section_vals_val_get(floquet_sec, "MEM_FILL_FRACTION", r_val=bs_env%floquet_mem_fill_fraction)
262 106 : CALL section_vals_val_get(floquet_sec, "TEMPERATURE", r_val=bs_env%floquet_temperature)
263 106 : CALL section_vals_val_get(floquet_sec, "FLOQUET_DOS_FILE_NAME", c_val=bs_env%floquet_dos_file)
264 106 : CALL section_vals_val_get(floquet_sec, "QUASI_ENERGIES_FILE_NAME", c_val=bs_env%floquet_qe_file)
265 106 : CALL section_vals_val_get(floquet_sec, "FLOQUET_BS_FILE_NAME", c_val=bs_env%floquet_bs_file)
266 :
267 : ! read special points for band structure
268 216 : ALLOCATE (bs_env%xkp_special(3, bs_env%input_kp_bs_n_sp_pts))
269 116 : DO ikp = 1, bs_env%input_kp_bs_n_sp_pts
270 10 : CALL section_vals_val_get(kp_bs_sec, "SPECIAL_POINT", i_rep_val=ikp, c_vals=string_ptr)
271 10 : CPASSERT(SIZE(string_ptr(:), 1) == 4)
272 40 : DO i = 1, 3
273 30 : CALL read_float_object(string_ptr(i + 1), kpptr(i), error_msg)
274 40 : IF (LEN_TRIM(error_msg) > 0) CPABORT(TRIM(error_msg))
275 : END DO
276 106 : SELECT CASE (ustr)
277 : CASE ("B_VECTOR")
278 40 : bs_env%xkp_special(1:3, ikp) = kpptr(1:3)
279 : CASE ("CART_ANGSTROM")
280 : bs_env%xkp_special(1:3, ikp) = (kpptr(1)*cart_hmat(1, 1:3) + &
281 : kpptr(2)*cart_hmat(2, 1:3) + &
282 0 : kpptr(3)*cart_hmat(3, 1:3))/twopi*angstrom
283 : CASE ("CART_BOHR")
284 : bs_env%xkp_special(1:3, ikp) = (kpptr(1)*cart_hmat(1, 1:3) + &
285 : kpptr(2)*cart_hmat(2, 1:3) + &
286 0 : kpptr(3)*cart_hmat(3, 1:3))/twopi
287 : CASE DEFAULT
288 10 : CPABORT("Unknown unit <"//TRIM(ustr)//"> specified for k-point definition")
289 : END SELECT
290 : END DO
291 :
292 106 : CALL timestop(handle)
293 :
294 106 : END SUBROUTINE read_bandstructure_input_parameters
295 :
296 : ! **************************************************************************************************
297 : !> \brief ...
298 : !> \param bs_env ...
299 : ! **************************************************************************************************
300 106 : SUBROUTINE print_header(bs_env)
301 :
302 : TYPE(post_scf_bandstructure_type), POINTER :: bs_env
303 :
304 : CHARACTER(LEN=*), PARAMETER :: routineN = 'print_header'
305 :
306 : INTEGER :: handle, u
307 :
308 106 : CALL timeset(routineN, handle)
309 :
310 106 : bs_env%unit_nr = cp_logger_get_default_io_unit()
311 :
312 106 : u = bs_env%unit_nr
313 :
314 106 : IF (u > 0) THEN
315 53 : WRITE (u, '(T2,A)') ' '
316 53 : WRITE (u, '(T2,A)') REPEAT('-', 79)
317 53 : WRITE (u, '(T2,A,A78)') '-', '-'
318 53 : WRITE (u, '(T2,A,A51,A27)') '-', 'BANDSTRUCTURE CALCULATION', '-'
319 53 : WRITE (u, '(T2,A,A78)') '-', '-'
320 53 : WRITE (u, '(T2,A)') REPEAT('-', 79)
321 53 : WRITE (u, '(T2,A)') ' '
322 : END IF
323 :
324 106 : CALL timestop(handle)
325 :
326 106 : END SUBROUTINE print_header
327 :
328 : ! **************************************************************************************************
329 : !> \brief ...
330 : !> \param qs_env ...
331 : !> \param bs_env ...
332 : !> \param kpoints ...
333 : ! **************************************************************************************************
334 88 : SUBROUTINE setup_kpoints_DOS_large_cell_Gamma(qs_env, bs_env, kpoints)
335 :
336 : TYPE(qs_environment_type), POINTER :: qs_env
337 : TYPE(post_scf_bandstructure_type), POINTER :: bs_env
338 : TYPE(kpoint_type), POINTER :: kpoints
339 :
340 : CHARACTER(LEN=*), PARAMETER :: routineN = 'setup_kpoints_DOS_large_cell_Gamma'
341 :
342 : INTEGER :: handle, i_dim, i_kp_in_line, &
343 : i_special_kp, ikk, n_kp_in_line, &
344 : n_special_kp, nkp, nkp_only_bs, &
345 : nkp_only_DOS, u
346 : INTEGER, DIMENSION(3) :: nkp_grid, periodic
347 :
348 88 : CALL timeset(routineN, handle)
349 :
350 : ! routine adapted from mp2_integrals.F
351 88 : NULLIFY (kpoints)
352 88 : CALL kpoint_create(kpoints)
353 :
354 88 : kpoints%kp_scheme = "GENERAL"
355 :
356 88 : n_special_kp = bs_env%input_kp_bs_n_sp_pts
357 88 : n_kp_in_line = bs_env%input_kp_bs_npoints
358 :
359 352 : periodic(1:3) = bs_env%periodic(1:3)
360 :
361 352 : DO i_dim = 1, 3
362 :
363 264 : CPASSERT(periodic(i_dim) == 0 .OR. periodic(i_dim) == 1)
364 :
365 352 : IF (bs_env%nkp_grid_DOS_input(i_dim) < 0) THEN
366 246 : IF (periodic(i_dim) == 1) nkp_grid(i_dim) = 2
367 246 : IF (periodic(i_dim) == 0) nkp_grid(i_dim) = 1
368 : ELSE
369 18 : nkp_grid(i_dim) = bs_env%nkp_grid_DOS_input(i_dim)
370 : END IF
371 :
372 : END DO
373 :
374 : ! use the k <-> -k symmetry to reduce the number of kpoints
375 88 : IF (nkp_grid(1) > 1) THEN
376 4 : nkp_only_DOS = (nkp_grid(1) + 1)/2*nkp_grid(2)*nkp_grid(3)
377 84 : ELSE IF (nkp_grid(2) > 1) THEN
378 4 : nkp_only_DOS = nkp_grid(1)*(nkp_grid(2) + 1)/2*nkp_grid(3)
379 80 : ELSE IF (nkp_grid(3) > 1) THEN
380 2 : nkp_only_DOS = nkp_grid(1)*nkp_grid(2)*(nkp_grid(3) + 1)/2
381 : ELSE
382 78 : nkp_only_DOS = 1
383 : END IF
384 :
385 : ! we will compute the GW QP levels for all k's in the bandstructure path but also
386 : ! for all k-points from the SCF (e.g. for DOS or for self-consistent GW)
387 88 : IF (n_special_kp > 0) THEN
388 0 : nkp_only_bs = n_kp_in_line*(n_special_kp - 1) + 1
389 : ELSE
390 : nkp_only_bs = 0
391 : END IF
392 :
393 88 : nkp = nkp_only_DOS + nkp_only_bs
394 :
395 352 : kpoints%nkp_grid(1:3) = nkp_grid(1:3)
396 88 : kpoints%nkp = nkp
397 :
398 88 : bs_env%nkp_bs_and_DOS = nkp
399 88 : bs_env%nkp_only_bs = nkp_only_bs
400 88 : bs_env%nkp_only_DOS = nkp_only_DOS
401 :
402 440 : ALLOCATE (kpoints%xkp(3, nkp), kpoints%wkp(nkp))
403 184 : kpoints%wkp(1:nkp_only_DOS) = 1.0_dp/REAL(nkp_only_DOS, KIND=dp)
404 :
405 88 : CALL compute_xkp(kpoints%xkp, 1, nkp_only_DOS, nkp_grid)
406 :
407 88 : IF (n_special_kp > 0) THEN
408 0 : kpoints%xkp(1:3, nkp_only_DOS + 1) = bs_env%xkp_special(1:3, 1)
409 0 : ikk = nkp_only_DOS + 1
410 0 : DO i_special_kp = 2, n_special_kp
411 0 : DO i_kp_in_line = 1, n_kp_in_line
412 0 : ikk = ikk + 1
413 : kpoints%xkp(1:3, ikk) = bs_env%xkp_special(1:3, i_special_kp - 1) + &
414 : REAL(i_kp_in_line, KIND=dp)/REAL(n_kp_in_line, KIND=dp)* &
415 : (bs_env%xkp_special(1:3, i_special_kp) - &
416 0 : bs_env%xkp_special(1:3, i_special_kp - 1))
417 0 : kpoints%wkp(ikk) = 0.0_dp
418 : END DO
419 : END DO
420 : END IF
421 :
422 88 : CALL kpoint_init_cell_index_simple(kpoints, qs_env)
423 :
424 88 : u = bs_env%unit_nr
425 :
426 88 : IF (u > 0) THEN
427 44 : IF (nkp_only_bs > 0) THEN
428 : WRITE (u, FMT="(T2,1A,T77,I4)") &
429 0 : "Number of special k-points for the bandstructure", n_special_kp
430 0 : WRITE (u, FMT="(T2,1A,T77,I4)") "Number of k-points for the bandstructure", nkp
431 : WRITE (u, FMT="(T2,1A,T69,3I4)") &
432 0 : "K-point mesh for the density of states (DOS)", nkp_grid(1:3)
433 : ELSE
434 : WRITE (u, FMT="(T2,1A,T69,3I4)") &
435 44 : "K-point mesh for the density of states (DOS) and the self-energy", nkp_grid(1:3)
436 : END IF
437 : END IF
438 :
439 88 : CALL timestop(handle)
440 :
441 88 : END SUBROUTINE setup_kpoints_DOS_large_cell_Gamma
442 :
443 : ! **************************************************************************************************
444 : !> \brief ...
445 : !> \param qs_env ...
446 : !> \param bs_env ...
447 : !> \param kpoints ...
448 : !> \param do_print ...
449 : ! **************************************************************************************************
450 36 : SUBROUTINE setup_kpoints_scf_desymm(qs_env, bs_env, kpoints, do_print)
451 : TYPE(qs_environment_type), POINTER :: qs_env
452 : TYPE(post_scf_bandstructure_type), POINTER :: bs_env
453 : TYPE(kpoint_type), POINTER :: kpoints
454 :
455 : CHARACTER(LEN=*), PARAMETER :: routineN = 'setup_kpoints_scf_desymm'
456 :
457 : INTEGER :: handle, i_cell_x, i_dim, img, j_cell_y, &
458 : k_cell_z, nimages, nkp, u
459 : INTEGER, DIMENSION(3) :: cell_grid, cixd, nkp_grid
460 : TYPE(kpoint_type), POINTER :: kpoints_scf
461 :
462 : LOGICAL:: do_print
463 :
464 36 : CALL timeset(routineN, handle)
465 :
466 36 : NULLIFY (kpoints)
467 36 : CALL kpoint_create(kpoints)
468 :
469 36 : CALL get_qs_env(qs_env=qs_env, kpoints=kpoints_scf)
470 :
471 144 : nkp_grid(1:3) = kpoints_scf%nkp_grid(1:3)
472 36 : nkp = nkp_grid(1)*nkp_grid(2)*nkp_grid(3)
473 :
474 : ! we need in periodic directions at least 4 k-points in the SCF
475 144 : DO i_dim = 1, 3
476 144 : IF (bs_env%periodic(i_dim) == 1) THEN
477 72 : CPASSERT(nkp_grid(i_dim) >= 4)
478 : END IF
479 : END DO
480 :
481 36 : kpoints%kp_scheme = "GENERAL"
482 144 : kpoints%nkp_grid(1:3) = nkp_grid(1:3)
483 36 : kpoints%nkp = nkp
484 36 : bs_env%nkp_scf_desymm = nkp
485 :
486 108 : ALLOCATE (kpoints%xkp(1:3, nkp))
487 36 : CALL compute_xkp(kpoints%xkp, 1, nkp, nkp_grid)
488 :
489 108 : ALLOCATE (kpoints%wkp(nkp))
490 612 : kpoints%wkp(:) = 1.0_dp/REAL(nkp, KIND=dp)
491 :
492 : ! for example 4x3x6 kpoint grid -> 3x3x5 cell grid because we need the same number of
493 : ! neighbor cells on both sides of the unit cell
494 144 : cell_grid(1:3) = nkp_grid(1:3) - MODULO(nkp_grid(1:3) + 1, 2)
495 :
496 : ! cell index: for example for x: from -n_x/2 to +n_x/2, n_x: number of cells in x direction
497 144 : cixd(1:3) = cell_grid(1:3)/2
498 :
499 36 : nimages = cell_grid(1)*cell_grid(2)*cell_grid(3)
500 :
501 36 : bs_env%nimages_scf_desymm = nimages
502 144 : bs_env%cell_grid_scf_desymm(1:3) = cell_grid(1:3)
503 :
504 36 : IF (ASSOCIATED(kpoints%index_to_cell)) DEALLOCATE (kpoints%index_to_cell)
505 36 : IF (ASSOCIATED(kpoints%cell_to_index)) DEALLOCATE (kpoints%cell_to_index)
506 :
507 180 : ALLOCATE (kpoints%cell_to_index(-cixd(1):cixd(1), -cixd(2):cixd(2), -cixd(3):cixd(3)))
508 108 : ALLOCATE (kpoints%index_to_cell(3, nimages))
509 :
510 36 : img = 0
511 88 : DO i_cell_x = -cixd(1), cixd(1)
512 244 : DO j_cell_y = -cixd(2), cixd(2)
513 532 : DO k_cell_z = -cixd(3), cixd(3)
514 324 : img = img + 1
515 324 : kpoints%cell_to_index(i_cell_x, j_cell_y, k_cell_z) = img
516 1452 : kpoints%index_to_cell(1:3, img) = [i_cell_x, j_cell_y, k_cell_z]
517 : END DO
518 : END DO
519 : END DO
520 :
521 36 : u = bs_env%unit_nr
522 36 : IF (u > 0 .AND. do_print) THEN
523 9 : WRITE (u, FMT="(T2,A,I49)") "Number of cells for G, χ, W, Σ", nimages
524 : END IF
525 :
526 36 : CALL timestop(handle)
527 :
528 36 : END SUBROUTINE setup_kpoints_scf_desymm
529 :
530 : ! **************************************************************************************************
531 : !> \brief ...
532 : !> \param bs_env ...
533 : !> \param kpoints ...
534 : ! **************************************************************************************************
535 18 : SUBROUTINE setup_kpoints_DOS_small_cell_full_kp(bs_env, kpoints)
536 :
537 : TYPE(post_scf_bandstructure_type), POINTER :: bs_env
538 : TYPE(kpoint_type), POINTER :: kpoints
539 :
540 : CHARACTER(LEN=*), PARAMETER :: routineN = 'setup_kpoints_DOS_small_cell_full_kp'
541 :
542 : INTEGER :: handle, i_kp_in_line, i_special_kp, ikk, &
543 : n_kp_in_line, n_special_kp, nkp, &
544 : nkp_only_bs, nkp_scf_desymm, u
545 :
546 18 : CALL timeset(routineN, handle)
547 :
548 : ! routine adapted from mp2_integrals.F
549 18 : NULLIFY (kpoints)
550 18 : CALL kpoint_create(kpoints)
551 :
552 18 : n_special_kp = bs_env%input_kp_bs_n_sp_pts
553 18 : n_kp_in_line = bs_env%input_kp_bs_npoints
554 18 : nkp_scf_desymm = bs_env%nkp_scf_desymm
555 :
556 : ! we will compute the GW QP levels for all k's in the bandstructure path but also
557 : ! for all k-points from the SCF (e.g. for DOS or for self-consistent GW)
558 18 : IF (n_special_kp > 0) THEN
559 4 : nkp_only_bs = n_kp_in_line*(n_special_kp - 1) + 1
560 : ELSE
561 : nkp_only_bs = 0
562 : END IF
563 18 : nkp = nkp_only_bs + nkp_scf_desymm
564 :
565 54 : ALLOCATE (kpoints%xkp(3, nkp))
566 54 : ALLOCATE (kpoints%wkp(nkp))
567 :
568 18 : kpoints%nkp = nkp
569 :
570 18 : bs_env%nkp_bs_and_DOS = nkp
571 18 : bs_env%nkp_only_bs = nkp_only_bs
572 18 : bs_env%nkp_only_DOS = nkp_scf_desymm
573 :
574 2340 : kpoints%xkp(1:3, 1:nkp_scf_desymm) = bs_env%kpoints_scf_desymm%xkp(1:3, 1:nkp_scf_desymm)
575 306 : kpoints%wkp(1:nkp_scf_desymm) = 1.0_dp/REAL(nkp_scf_desymm, KIND=dp)
576 :
577 18 : IF (n_special_kp > 0) THEN
578 32 : kpoints%xkp(1:3, nkp_scf_desymm + 1) = bs_env%xkp_special(1:3, 1)
579 4 : ikk = nkp_scf_desymm + 1
580 10 : DO i_special_kp = 2, n_special_kp
581 70 : DO i_kp_in_line = 1, n_kp_in_line
582 60 : ikk = ikk + 1
583 : kpoints%xkp(1:3, ikk) = bs_env%xkp_special(1:3, i_special_kp - 1) + &
584 : REAL(i_kp_in_line, KIND=dp)/REAL(n_kp_in_line, KIND=dp)* &
585 : (bs_env%xkp_special(1:3, i_special_kp) - &
586 480 : bs_env%xkp_special(1:3, i_special_kp - 1))
587 66 : kpoints%wkp(ikk) = 0.0_dp
588 : END DO
589 : END DO
590 : END IF
591 :
592 18 : IF (ASSOCIATED(kpoints%index_to_cell)) DEALLOCATE (kpoints%index_to_cell)
593 :
594 54 : ALLOCATE (kpoints%index_to_cell(3, bs_env%nimages_scf_desymm))
595 1332 : kpoints%index_to_cell(:, :) = bs_env%kpoints_scf_desymm%index_to_cell(:, :)
596 :
597 18 : u = bs_env%unit_nr
598 :
599 18 : IF (u > 0) THEN
600 9 : WRITE (u, FMT="(T2,1A,T77,I4)") "Number of special k-points for the bandstructure", &
601 18 : n_special_kp
602 9 : WRITE (u, FMT="(T2,1A,T77,I4)") "Number of k-points for the bandstructure", nkp
603 : END IF
604 :
605 18 : CALL timestop(handle)
606 :
607 18 : END SUBROUTINE setup_kpoints_DOS_small_cell_full_kp
608 :
609 : ! **************************************************************************************************
610 : !> \brief ...
611 : !> \param qs_env ...
612 : !> \param bs_env ...
613 : ! **************************************************************************************************
614 18 : SUBROUTINE compute_cfm_mo_coeff_kp_and_eigenval_scf_kp(qs_env, bs_env)
615 : TYPE(qs_environment_type), POINTER :: qs_env
616 : TYPE(post_scf_bandstructure_type), POINTER :: bs_env
617 :
618 : CHARACTER(LEN=*), PARAMETER :: routineN = 'compute_cfm_mo_coeff_kp_and_eigenval_scf_kp'
619 :
620 : INTEGER :: handle, ikp, ispin, nkp_bs_and_DOS
621 18 : INTEGER, DIMENSION(:, :, :), POINTER :: cell_to_index_scf
622 : REAL(KIND=dp) :: CBM, VBM
623 : REAL(KIND=dp), DIMENSION(3) :: xkp
624 : TYPE(cp_cfm_type) :: cfm_ks, cfm_mos, cfm_s
625 18 : TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: matrix_ks, matrix_s
626 : TYPE(kpoint_type), POINTER :: kpoints_scf
627 : TYPE(neighbor_list_set_p_type), DIMENSION(:), &
628 18 : POINTER :: sab_nl
629 :
630 18 : CALL timeset(routineN, handle)
631 :
632 : CALL get_qs_env(qs_env, &
633 : matrix_ks_kp=matrix_ks, &
634 : matrix_s_kp=matrix_s, &
635 18 : kpoints=kpoints_scf)
636 :
637 18 : NULLIFY (sab_nl)
638 18 : CALL get_kpoint_info(kpoints_scf, sab_nl=sab_nl, cell_to_index=cell_to_index_scf)
639 :
640 18 : CALL cp_cfm_create(cfm_ks, bs_env%cfm_work_mo%matrix_struct)
641 18 : CALL cp_cfm_create(cfm_s, bs_env%cfm_work_mo%matrix_struct)
642 18 : CALL cp_cfm_create(cfm_mos, bs_env%cfm_work_mo%matrix_struct)
643 :
644 : ! nkp_bs_and_DOS contains desymmetrized k-point mesh from SCF and k-points from GW bandstructure
645 18 : nkp_bs_and_DOS = bs_env%nkp_bs_and_DOS
646 :
647 90 : ALLOCATE (bs_env%eigenval_G0W0(bs_env%n_ao, nkp_bs_and_DOS, bs_env%n_spin))
648 90 : ALLOCATE (bs_env%eigenval_HF(bs_env%n_ao, nkp_bs_and_DOS, bs_env%n_spin))
649 442 : ALLOCATE (bs_env%cfm_mo_coeff_kp(nkp_bs_and_DOS, bs_env%n_spin))
650 442 : ALLOCATE (bs_env%cfm_ks_kp(nkp_bs_and_DOS, bs_env%n_spin))
651 406 : ALLOCATE (bs_env%cfm_s_kp(nkp_bs_and_DOS))
652 370 : DO ikp = 1, nkp_bs_and_DOS
653 704 : DO ispin = 1, bs_env%n_spin
654 352 : CALL cp_cfm_create(bs_env%cfm_mo_coeff_kp(ikp, ispin), bs_env%cfm_work_mo%matrix_struct)
655 704 : CALL cp_cfm_create(bs_env%cfm_ks_kp(ikp, ispin), bs_env%cfm_work_mo%matrix_struct)
656 : END DO
657 370 : CALL cp_cfm_create(bs_env%cfm_s_kp(ikp), bs_env%cfm_work_mo%matrix_struct)
658 : END DO
659 :
660 36 : DO ispin = 1, bs_env%n_spin
661 370 : DO ikp = 1, nkp_bs_and_DOS
662 :
663 1408 : xkp(1:3) = bs_env%kpoints_DOS%xkp(1:3, ikp)
664 :
665 : ! h^KS^R -> h^KS(k)
666 352 : CALL rsmat_to_kp(matrix_ks, ispin, xkp, cell_to_index_scf, sab_nl, bs_env, cfm_ks)
667 :
668 : ! S^R -> S(k)
669 352 : CALL rsmat_to_kp(matrix_s, 1, xkp, cell_to_index_scf, sab_nl, bs_env, cfm_s)
670 :
671 : ! we store the complex KS matrix as fm matrix because the infrastructure for fm is
672 : ! much nicer compared to cfm
673 352 : CALL cp_cfm_to_cfm(cfm_ks, bs_env%cfm_ks_kp(ikp, ispin))
674 352 : CALL cp_cfm_to_cfm(cfm_s, bs_env%cfm_s_kp(ikp))
675 :
676 : ! Diagonalize KS-matrix via Rothaan-Hall equation:
677 : ! H^KS(k) C(k) = S(k) C(k) ε(k)
678 : CALL cp_cfm_geeig_canon(cfm_ks, cfm_s, cfm_mos, &
679 : bs_env%eigenval_scf(:, ikp, ispin), &
680 352 : bs_env%cfm_work_mo, bs_env%eps_eigval_mat_s)
681 :
682 : ! we store the complex MO coeff as fm matrix because the infrastructure for fm is
683 : ! much nicer compared to cfm
684 370 : CALL cp_cfm_to_cfm(cfm_mos, bs_env%cfm_mo_coeff_kp(ikp, ispin))
685 :
686 : END DO
687 :
688 370 : VBM = MAXVAL(bs_env%eigenval_scf(bs_env%n_occ(ispin), :, ispin))
689 370 : CBM = MINVAL(bs_env%eigenval_scf(bs_env%n_occ(ispin) + 1, :, ispin))
690 :
691 36 : bs_env%e_fermi(ispin) = 0.5_dp*(VBM + CBM)
692 :
693 : END DO
694 :
695 18 : CALL get_VBM_CBM_bandgaps(bs_env%band_edges_scf, bs_env%eigenval_scf, bs_env)
696 :
697 18 : CALL cp_cfm_release(cfm_ks)
698 18 : CALL cp_cfm_release(cfm_s)
699 18 : CALL cp_cfm_release(cfm_mos)
700 :
701 18 : CALL timestop(handle)
702 :
703 36 : END SUBROUTINE compute_cfm_mo_coeff_kp_and_eigenval_scf_kp
704 :
705 : ! **************************************************************************************************
706 : !> \brief ...
707 : !> \param mat_rs ...
708 : !> \param ispin ...
709 : !> \param xkp ...
710 : !> \param cell_to_index_scf ...
711 : !> \param sab_nl ...
712 : !> \param bs_env ...
713 : !> \param cfm_kp ...
714 : !> \param imag_rs_mat ...
715 : ! **************************************************************************************************
716 1976 : SUBROUTINE rsmat_to_kp(mat_rs, ispin, xkp, cell_to_index_scf, sab_nl, bs_env, cfm_kp, imag_rs_mat)
717 : TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: mat_rs
718 : INTEGER :: ispin
719 : REAL(KIND=dp), DIMENSION(3) :: xkp
720 : INTEGER, DIMENSION(:, :, :), POINTER :: cell_to_index_scf
721 : TYPE(neighbor_list_set_p_type), DIMENSION(:), &
722 : POINTER :: sab_nl
723 : TYPE(post_scf_bandstructure_type), POINTER :: bs_env
724 : TYPE(cp_cfm_type) :: cfm_kp
725 : LOGICAL, OPTIONAL :: imag_rs_mat
726 :
727 : CHARACTER(LEN=*), PARAMETER :: routineN = 'rsmat_to_kp'
728 :
729 : INTEGER :: handle
730 : LOGICAL :: imag_rs_mat_private
731 : TYPE(dbcsr_type), POINTER :: cmat, nsmat, rmat
732 :
733 1976 : CALL timeset(routineN, handle)
734 :
735 1976 : ALLOCATE (rmat, cmat, nsmat)
736 :
737 1976 : imag_rs_mat_private = .FALSE.
738 1976 : IF (PRESENT(imag_rs_mat)) imag_rs_mat_private = imag_rs_mat
739 :
740 954 : IF (imag_rs_mat_private) THEN
741 954 : CALL dbcsr_create(rmat, template=mat_rs(1, 1)%matrix, matrix_type=dbcsr_type_antisymmetric)
742 954 : CALL dbcsr_create(cmat, template=mat_rs(1, 1)%matrix, matrix_type=dbcsr_type_symmetric)
743 : ELSE
744 1022 : CALL dbcsr_create(rmat, template=mat_rs(1, 1)%matrix, matrix_type=dbcsr_type_symmetric)
745 1022 : CALL dbcsr_create(cmat, template=mat_rs(1, 1)%matrix, matrix_type=dbcsr_type_antisymmetric)
746 : END IF
747 1976 : CALL dbcsr_create(nsmat, template=mat_rs(1, 1)%matrix, matrix_type=dbcsr_type_no_symmetry)
748 1976 : CALL cp_dbcsr_alloc_block_from_nbl(rmat, sab_nl)
749 1976 : CALL cp_dbcsr_alloc_block_from_nbl(cmat, sab_nl)
750 :
751 1976 : CALL dbcsr_set(rmat, 0.0_dp)
752 1976 : CALL dbcsr_set(cmat, 0.0_dp)
753 : CALL rskp_transform(rmatrix=rmat, cmatrix=cmat, rsmat=mat_rs, ispin=ispin, &
754 1976 : xkp=xkp, cell_to_index=cell_to_index_scf, sab_nl=sab_nl)
755 :
756 1976 : CALL dbcsr_desymmetrize(rmat, nsmat)
757 1976 : CALL copy_dbcsr_to_fm(nsmat, bs_env%fm_work_mo(1))
758 1976 : CALL dbcsr_desymmetrize(cmat, nsmat)
759 1976 : CALL copy_dbcsr_to_fm(nsmat, bs_env%fm_work_mo(2))
760 1976 : CALL cp_fm_to_cfm(bs_env%fm_work_mo(1), bs_env%fm_work_mo(2), cfm_kp)
761 :
762 1976 : CALL dbcsr_deallocate_matrix(rmat)
763 1976 : CALL dbcsr_deallocate_matrix(cmat)
764 1976 : CALL dbcsr_deallocate_matrix(nsmat)
765 :
766 1976 : CALL timestop(handle)
767 :
768 1976 : END SUBROUTINE rsmat_to_kp
769 :
770 : ! **************************************************************************************************
771 : !> \brief ...
772 : !> \param bs_env ...
773 : ! **************************************************************************************************
774 88 : SUBROUTINE diagonalize_ks_matrix(bs_env)
775 : TYPE(post_scf_bandstructure_type), POINTER :: bs_env
776 :
777 : CHARACTER(LEN=*), PARAMETER :: routineN = 'diagonalize_ks_matrix'
778 :
779 : INTEGER :: handle, ikp, ispin
780 : REAL(KIND=dp) :: CBM, VBM
781 :
782 88 : CALL timeset(routineN, handle)
783 :
784 352 : ALLOCATE (bs_env%eigenval_scf_Gamma(bs_env%n_ao, bs_env%n_spin))
785 :
786 190 : DO ispin = 1, bs_env%n_spin
787 :
788 : ! use work matrices because the matrices are overwritten in cp_fm_geeig_canon
789 102 : CALL cp_fm_to_fm(bs_env%fm_ks_Gamma(ispin), bs_env%fm_work_mo(1))
790 102 : CALL cp_fm_to_fm(bs_env%fm_s_Gamma, bs_env%fm_work_mo(2))
791 :
792 : ! diagonalize the Kohn-Sham matrix to obtain MO coefficients and SCF eigenvalues
793 : ! (at the Gamma-point)
794 : CALL cp_fm_geeig_canon(bs_env%fm_work_mo(1), &
795 : bs_env%fm_work_mo(2), &
796 : bs_env%fm_mo_coeff_Gamma(ispin), &
797 : bs_env%eigenval_scf_Gamma(:, ispin), &
798 : bs_env%fm_work_mo(3), &
799 102 : bs_env%eps_eigval_mat_s)
800 :
801 102 : VBM = bs_env%eigenval_scf_Gamma(bs_env%n_occ(ispin), ispin)
802 102 : CBM = bs_env%eigenval_scf_Gamma(bs_env%n_occ(ispin) + 1, ispin)
803 :
804 102 : bs_env%band_edges_scf_Gamma(ispin)%VBM = VBM
805 102 : bs_env%band_edges_scf_Gamma(ispin)%CBM = CBM
806 190 : bs_env%e_fermi(ispin) = 0.5_dp*(VBM + CBM)
807 :
808 : END DO
809 :
810 88 : CALL timestop(handle)
811 :
812 : ! Gamma-only path for molecules: eigenval_scf is filled here from the Gamma eigenvalues
813 190 : DO ispin = 1, bs_env%n_spin
814 304 : DO ikp = 1, bs_env%nkp_bs_and_DOS
815 1420 : bs_env%eigenval_scf(:, ikp, ispin) = bs_env%eigenval_scf_Gamma(:, ispin)
816 : END DO
817 : END DO
818 :
819 88 : END SUBROUTINE diagonalize_ks_matrix
820 :
821 : ! **************************************************************************************************
822 : !> \brief ...
823 : !> \param bs_env ...
824 : !> \param qs_env ...
825 : ! **************************************************************************************************
826 88 : SUBROUTINE check_positive_definite_overlap_mat(bs_env, qs_env)
827 : TYPE(post_scf_bandstructure_type), POINTER :: bs_env
828 : TYPE(qs_environment_type), POINTER :: qs_env
829 :
830 : CHARACTER(LEN=*), PARAMETER :: routineN = 'check_positive_definite_overlap_mat'
831 :
832 : INTEGER :: handle, ikp, info, u
833 : TYPE(cp_cfm_type) :: cfm_s_ikp
834 :
835 88 : CALL timeset(routineN, handle)
836 :
837 184 : DO ikp = 1, bs_env%kpoints_DOS%nkp
838 :
839 : ! get S_µν(k_i) from S_µν(k=0)
840 : CALL cfm_ikp_from_fm_Gamma(cfm_s_ikp, bs_env%fm_s_Gamma, &
841 96 : ikp, qs_env, bs_env%kpoints_DOS, "ORB")
842 :
843 : ! check whether S_µν(k_i) is positive definite
844 96 : CALL cp_cfm_cholesky_decompose(matrix=cfm_s_ikp, n=bs_env%n_ao, info_out=info)
845 :
846 : ! check if Cholesky decomposition failed (Cholesky decomposition only works for
847 : ! positive definite matrices
848 184 : IF (info /= 0) THEN
849 0 : u = bs_env%unit_nr
850 :
851 0 : IF (u > 0) THEN
852 0 : WRITE (u, FMT="(T2,A)") ""
853 : WRITE (u, FMT="(T2,A)") "ERROR: The Cholesky decomposition "// &
854 0 : "of the k-point overlap matrix failed. This is"
855 : WRITE (u, FMT="(T2,A)") "because the algorithm is "// &
856 0 : "only correct in the limit of large cells. The cell of "
857 : WRITE (u, FMT="(T2,A)") "the calculation is too small. "// &
858 0 : "Use MULTIPLE_UNIT_CELL to create a larger cell "
859 0 : WRITE (u, FMT="(T2,A)") "and to prevent this error."
860 : END IF
861 :
862 0 : CALL bs_env%para_env%sync()
863 0 : CPABORT("Please see information on the error above.")
864 :
865 : END IF ! Cholesky decomposition failed
866 :
867 : END DO ! ikp
868 :
869 88 : CALL cp_cfm_release(cfm_s_ikp)
870 :
871 88 : CALL timestop(handle)
872 :
873 88 : END SUBROUTINE check_positive_definite_overlap_mat
874 :
875 : ! **************************************************************************************************
876 : !> \brief ...
877 : !> \param qs_env ...
878 : !> \param bs_env ...
879 : ! **************************************************************************************************
880 212 : SUBROUTINE get_parameters_from_qs_env(qs_env, bs_env)
881 : TYPE(qs_environment_type), POINTER :: qs_env
882 : TYPE(post_scf_bandstructure_type), POINTER :: bs_env
883 :
884 : CHARACTER(LEN=*), PARAMETER :: routineN = 'get_parameters_from_qs_env'
885 :
886 : INTEGER :: color_sub, handle, homo, n_ao, n_atom, u
887 : INTEGER, DIMENSION(3) :: periodic
888 : REAL(KIND=dp), DIMENSION(3, 3) :: hmat
889 : TYPE(cell_type), POINTER :: cell
890 : TYPE(dft_control_type), POINTER :: dft_control
891 106 : TYPE(mo_set_type), DIMENSION(:), POINTER :: mos
892 : TYPE(mp_para_env_type), POINTER :: para_env
893 106 : TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
894 : TYPE(scf_control_type), POINTER :: scf_control
895 : TYPE(section_vals_type), POINTER :: input
896 :
897 106 : CALL timeset(routineN, handle)
898 :
899 : CALL get_qs_env(qs_env, &
900 : dft_control=dft_control, &
901 : scf_control=scf_control, &
902 106 : mos=mos)
903 :
904 106 : bs_env%n_spin = dft_control%nspins
905 106 : IF (bs_env%n_spin == 1) bs_env%spin_degeneracy = 2.0_dp
906 106 : IF (bs_env%n_spin == 2) bs_env%spin_degeneracy = 1.0_dp
907 :
908 106 : CALL get_mo_set(mo_set=mos(1), nao=n_ao, homo=homo)
909 106 : bs_env%n_ao = n_ao
910 318 : bs_env%n_occ(1:2) = homo
911 318 : bs_env%n_vir(1:2) = n_ao - homo
912 :
913 106 : IF (bs_env%n_spin == 2) THEN
914 14 : CALL get_mo_set(mo_set=mos(2), homo=homo)
915 14 : bs_env%n_occ(2) = homo
916 14 : bs_env%n_vir(2) = n_ao - homo
917 : END IF
918 :
919 106 : bs_env%eps_eigval_mat_s = scf_control%eps_eigval
920 :
921 : ! get para_env from qs_env (bs_env%para_env is identical to para_env in qs_env)
922 106 : CALL get_qs_env(qs_env, para_env=para_env)
923 106 : color_sub = 0
924 106 : ALLOCATE (bs_env%para_env)
925 106 : CALL bs_env%para_env%from_split(para_env, color_sub)
926 :
927 106 : CALL get_qs_env(qs_env, particle_set=particle_set)
928 :
929 106 : n_atom = SIZE(particle_set)
930 106 : bs_env%n_atom = n_atom
931 :
932 106 : CALL get_qs_env(qs_env=qs_env, cell=cell)
933 106 : CALL get_cell(cell=cell, periodic=periodic, h=hmat)
934 424 : bs_env%periodic(1:3) = periodic(1:3)
935 1378 : bs_env%hmat(1:3, 1:3) = hmat
936 106 : bs_env%nimages_scf = dft_control%nimages
937 106 : IF (dft_control%nimages == 1) THEN
938 88 : IF (bs_env%do_gw_ri_rs) THEN
939 80 : IF (ANY(periodic /= 0)) THEN
940 0 : bs_env%small_cell_full_kp_or_large_cell_Gamma = large_cell_Gamma_ri_rs
941 : ELSE
942 20 : bs_env%small_cell_full_kp_or_large_cell_Gamma = non_periodic_ri_rs
943 : END IF
944 : ELSE
945 68 : bs_env%small_cell_full_kp_or_large_cell_Gamma = large_cell_Gamma
946 : END IF
947 18 : ELSE IF (dft_control%nimages > 1) THEN
948 18 : IF (bs_env%do_gw_ri_rs) THEN
949 0 : CPABORT("RI-RS Not Implemented for K-point Calculations")
950 : ELSE
951 18 : bs_env%small_cell_full_kp_or_large_cell_Gamma = small_cell_full_kp
952 : END IF
953 : ELSE
954 0 : CPABORT("Wrong number of cells from DFT calculation.")
955 : END IF
956 :
957 106 : u = bs_env%unit_nr
958 :
959 : ! Marek : Get and save the rtp method
960 106 : CALL get_qs_env(qs_env=qs_env, input=input)
961 106 : CALL section_vals_val_get(input, "DFT%REAL_TIME_PROPAGATION%RTBSE%_SECTION_PARAMETERS_", i_val=bs_env%rtp_method)
962 :
963 106 : IF (u > 0) THEN
964 53 : WRITE (u, FMT="(T2,2A,T73,I8)") "Number of occupied molecular orbitals (MOs) ", &
965 106 : "= Number of occupied bands", homo
966 53 : WRITE (u, FMT="(T2,2A,T73,I8)") "Number of unoccupied (= virtual) MOs ", &
967 106 : "= Number of unoccupied bands", n_ao - homo
968 53 : WRITE (u, FMT="(T2,A,T73,I8)") "Number of Gaussian basis functions for MOs", n_ao
969 53 : IF (bs_env%small_cell_full_kp_or_large_cell_Gamma == small_cell_full_kp) THEN
970 9 : WRITE (u, FMT="(T2,2A,T73,I8)") "Number of cells considered in the DFT ", &
971 18 : "calculation", bs_env%nimages_scf
972 : END IF
973 : END IF
974 :
975 106 : CALL timestop(handle)
976 :
977 106 : END SUBROUTINE get_parameters_from_qs_env
978 :
979 : ! **************************************************************************************************
980 : !> \brief ...
981 : !> \param bs_env ...
982 : ! **************************************************************************************************
983 106 : SUBROUTINE set_heuristic_parameters(bs_env)
984 : TYPE(post_scf_bandstructure_type), POINTER :: bs_env
985 :
986 : CHARACTER(LEN=*), PARAMETER :: routineN = 'set_heuristic_parameters'
987 :
988 : INTEGER :: handle
989 :
990 106 : CALL timeset(routineN, handle)
991 :
992 106 : bs_env%n_bins_max_for_printing = 5000
993 :
994 106 : CALL timestop(handle)
995 :
996 106 : END SUBROUTINE set_heuristic_parameters
997 :
998 : ! **************************************************************************************************
999 : !> \brief ...
1000 : !> \param qs_env ...
1001 : !> \param bs_env ...
1002 : ! **************************************************************************************************
1003 106 : SUBROUTINE allocate_and_fill_fm_ks_fm_s(qs_env, bs_env)
1004 : TYPE(qs_environment_type), POINTER :: qs_env
1005 : TYPE(post_scf_bandstructure_type), POINTER :: bs_env
1006 :
1007 : CHARACTER(LEN=*), PARAMETER :: routineN = 'allocate_and_fill_fm_ks_fm_s'
1008 :
1009 : INTEGER :: handle, i_work, ispin
1010 : TYPE(cp_blacs_env_type), POINTER :: blacs_env
1011 : TYPE(cp_fm_struct_type), POINTER :: fm_struct
1012 106 : TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: matrix_ks, matrix_s
1013 : TYPE(mp_para_env_type), POINTER :: para_env
1014 :
1015 106 : CALL timeset(routineN, handle)
1016 :
1017 : CALL get_qs_env(qs_env, &
1018 : para_env=para_env, &
1019 : blacs_env=blacs_env, &
1020 : matrix_ks_kp=matrix_ks, &
1021 106 : matrix_s_kp=matrix_s)
1022 :
1023 106 : NULLIFY (fm_struct)
1024 : CALL cp_fm_struct_create(fm_struct, context=blacs_env, nrow_global=bs_env%n_ao, &
1025 106 : ncol_global=bs_env%n_ao, para_env=para_env)
1026 :
1027 530 : DO i_work = 1, SIZE(bs_env%fm_work_mo)
1028 530 : CALL cp_fm_create(bs_env%fm_work_mo(i_work), fm_struct)
1029 : END DO
1030 :
1031 106 : CALL cp_cfm_create(bs_env%cfm_work_mo, fm_struct)
1032 106 : CALL cp_cfm_create(bs_env%cfm_work_mo_2, fm_struct)
1033 :
1034 106 : CALL cp_fm_create(bs_env%fm_s_Gamma, fm_struct)
1035 106 : CALL copy_dbcsr_to_fm(matrix_s(1, 1)%matrix, bs_env%fm_s_Gamma)
1036 :
1037 226 : DO ispin = 1, bs_env%n_spin
1038 120 : CALL cp_fm_create(bs_env%fm_ks_Gamma(ispin), fm_struct)
1039 120 : CALL copy_dbcsr_to_fm(matrix_ks(ispin, 1)%matrix, bs_env%fm_ks_Gamma(ispin))
1040 226 : CALL cp_fm_create(bs_env%fm_mo_coeff_Gamma(ispin), fm_struct)
1041 : END DO
1042 :
1043 106 : CALL cp_fm_struct_release(fm_struct)
1044 :
1045 106 : NULLIFY (bs_env%mat_ao_ao%matrix)
1046 106 : ALLOCATE (bs_env%mat_ao_ao%matrix)
1047 : CALL dbcsr_create(bs_env%mat_ao_ao%matrix, template=matrix_s(1, 1)%matrix, &
1048 106 : matrix_type=dbcsr_type_no_symmetry)
1049 :
1050 530 : ALLOCATE (bs_env%eigenval_scf(bs_env%n_ao, bs_env%nkp_bs_and_DOS, bs_env%n_spin))
1051 :
1052 106 : CALL timestop(handle)
1053 :
1054 106 : END SUBROUTINE allocate_and_fill_fm_ks_fm_s
1055 :
1056 : ! **************************************************************************************************
1057 : !> \brief ...
1058 : !> \param qs_env ...
1059 : !> \param bs_env ...
1060 : ! **************************************************************************************************
1061 106 : SUBROUTINE eval_bandstructure_properties(qs_env, bs_env)
1062 : TYPE(qs_environment_type), POINTER :: qs_env
1063 : TYPE(post_scf_bandstructure_type), POINTER :: bs_env
1064 :
1065 : CHARACTER(LEN=*), PARAMETER :: routineN = 'eval_bandstructure_properties'
1066 :
1067 : INTEGER :: handle, homo, homo_1, homo_2, &
1068 : homo_spinor, ikp, ikp_for_file, ispin, &
1069 : n_ao, n_E, nkind, nkp
1070 : LOGICAL :: is_bandstruc_kpoint, print_DOS_kpoints, &
1071 : print_ikp
1072 : REAL(KIND=dp) :: broadening, E_max, E_max_G0W0, E_min, &
1073 : E_min_G0W0, E_total_window, &
1074 : energy_step_DOS, energy_window_DOS, t1
1075 106 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:) :: DOS_G0W0, DOS_G0W0_SOC, DOS_scf, DOS_scf_SOC, &
1076 106 : eigenval, eigenval_spinor, eigenval_spinor_G0W0, eigenval_spinor_no_SOC
1077 106 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: PDOS_G0W0, PDOS_G0W0_SOC, PDOS_scf, &
1078 106 : PDOS_scf_SOC, proj_mo_on_kind
1079 106 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :) :: LDOS_G0W0_2d, LDOS_scf_2d, &
1080 106 : LDOS_scf_2d_SOC
1081 : TYPE(band_edges_type) :: band_edges_G0W0, band_edges_G0W0_SOC, &
1082 : band_edges_scf, band_edges_scf_guess, &
1083 : band_edges_scf_SOC
1084 : TYPE(cp_cfm_type) :: cfm_ks_ikp, cfm_ks_ikp_spinor, cfm_mos_ikp_spinor, cfm_s_ikp, &
1085 : cfm_s_ikp_copy, cfm_s_ikp_spinor, cfm_s_ikp_spinor_copy, cfm_SOC_ikp_spinor, &
1086 : cfm_spinor_wf_ikp, cfm_work_ikp, cfm_work_ikp_spinor
1087 318 : TYPE(cp_cfm_type), DIMENSION(2) :: cfm_mos_ikp
1088 :
1089 106 : CALL timeset(routineN, handle)
1090 :
1091 106 : n_ao = bs_env%n_ao
1092 :
1093 106 : energy_window_DOS = bs_env%energy_window_DOS
1094 106 : energy_step_DOS = bs_env%energy_step_DOS
1095 106 : broadening = bs_env%broadening_DOS
1096 :
1097 : ! if we have done GW or a full kpoint SCF, we already have the band edges
1098 106 : IF (bs_env%do_gw .OR. &
1099 : bs_env%small_cell_full_kp_or_large_cell_Gamma == small_cell_full_kp) THEN
1100 106 : band_edges_scf = bs_env%band_edges_scf
1101 106 : band_edges_scf_guess = band_edges_scf
1102 : ELSE
1103 :
1104 0 : IF (bs_env%n_spin == 1) THEN
1105 0 : homo = bs_env%n_occ(1)
1106 0 : band_edges_scf_guess%VBM = bs_env%eigenval_scf_Gamma(homo, 1)
1107 0 : band_edges_scf_guess%CBM = bs_env%eigenval_scf_Gamma(homo + 1, 1)
1108 : ELSE
1109 0 : homo_1 = bs_env%n_occ(1)
1110 0 : homo_2 = bs_env%n_occ(2)
1111 : band_edges_scf_guess%VBM = MAX(bs_env%eigenval_scf_Gamma(homo_1, 1), &
1112 0 : bs_env%eigenval_scf_Gamma(homo_2, 2))
1113 : band_edges_scf_guess%CBM = MIN(bs_env%eigenval_scf_Gamma(homo_1 + 1, 1), &
1114 0 : bs_env%eigenval_scf_Gamma(homo_2 + 1, 2))
1115 : END IF
1116 :
1117 : ! initialization
1118 0 : band_edges_scf%VBM = -1000.0_dp
1119 0 : band_edges_scf%CBM = 1000.0_dp
1120 0 : band_edges_scf%DBG = 1000.0_dp
1121 : END IF
1122 :
1123 106 : E_min = band_edges_scf_guess%VBM - 0.5_dp*energy_window_DOS
1124 106 : E_max = band_edges_scf_guess%CBM + 0.5_dp*energy_window_DOS
1125 :
1126 106 : IF (bs_env%do_gw) THEN
1127 104 : band_edges_G0W0 = bs_env%band_edges_G0W0
1128 104 : E_min_G0W0 = band_edges_G0W0%VBM - 0.5_dp*energy_window_DOS
1129 104 : E_max_G0W0 = band_edges_G0W0%CBM + 0.5_dp*energy_window_DOS
1130 104 : E_min = MIN(E_min, E_min_G0W0)
1131 104 : E_max = MAX(E_max, E_max_G0W0)
1132 : END IF
1133 :
1134 106 : E_total_window = E_max - E_min
1135 :
1136 106 : n_E = INT(E_total_window/energy_step_DOS)
1137 :
1138 106 : CALL get_qs_env(qs_env, nkind=nkind)
1139 :
1140 424 : ALLOCATE (proj_mo_on_kind(n_ao, nkind))
1141 106 : proj_mo_on_kind(:, :) = 0.0_dp
1142 :
1143 318 : ALLOCATE (eigenval(n_ao))
1144 318 : ALLOCATE (eigenval_spinor(2*n_ao))
1145 212 : ALLOCATE (eigenval_spinor_no_SOC(2*n_ao))
1146 212 : ALLOCATE (eigenval_spinor_G0W0(2*n_ao))
1147 :
1148 106 : IF (bs_env%do_dos_pdos) THEN
1149 :
1150 60 : ALLOCATE (DOS_scf(n_E))
1151 20 : DOS_scf(:) = 0.0_dp
1152 80 : ALLOCATE (PDOS_scf(n_E, nkind))
1153 20 : PDOS_scf(:, :) = 0.0_dp
1154 :
1155 20 : IF (bs_env%do_soc) THEN
1156 :
1157 32 : ALLOCATE (DOS_scf_SOC(n_E))
1158 16 : DOS_scf_SOC(:) = 0.0_dp
1159 48 : ALLOCATE (PDOS_scf_SOC(n_E, nkind))
1160 16 : PDOS_scf_SOC(:, :) = 0.0_dp
1161 :
1162 : END IF
1163 :
1164 20 : IF (bs_env%do_gw) THEN
1165 :
1166 40 : ALLOCATE (DOS_G0W0(n_E))
1167 20 : DOS_G0W0(:) = 0.0_dp
1168 60 : ALLOCATE (PDOS_G0W0(n_E, nkind))
1169 20 : PDOS_G0W0(:, :) = 0.0_dp
1170 :
1171 20 : IF (bs_env%do_soc) THEN
1172 :
1173 32 : ALLOCATE (DOS_G0W0_SOC(n_E))
1174 16 : DOS_G0W0_SOC(:) = 0.0_dp
1175 48 : ALLOCATE (PDOS_G0W0_SOC(n_E, nkind))
1176 16 : PDOS_G0W0_SOC(:, :) = 0.0_dp
1177 :
1178 : END IF
1179 : END IF
1180 : END IF
1181 :
1182 106 : CALL cp_cfm_create(cfm_mos_ikp(1), bs_env%fm_ks_Gamma(1)%matrix_struct)
1183 106 : CALL cp_cfm_create(cfm_mos_ikp(2), bs_env%fm_ks_Gamma(1)%matrix_struct)
1184 106 : CALL cp_cfm_create(cfm_work_ikp, bs_env%fm_ks_Gamma(1)%matrix_struct)
1185 106 : CALL cp_cfm_create(cfm_s_ikp_copy, bs_env%fm_ks_Gamma(1)%matrix_struct)
1186 :
1187 106 : IF (bs_env%do_soc) THEN
1188 :
1189 22 : CALL cp_cfm_create(cfm_mos_ikp_spinor, bs_env%cfm_SOC_spinor_ao(1)%matrix_struct)
1190 22 : CALL cp_cfm_create(cfm_work_ikp_spinor, bs_env%cfm_SOC_spinor_ao(1)%matrix_struct)
1191 22 : CALL cp_cfm_create(cfm_s_ikp_spinor_copy, bs_env%cfm_SOC_spinor_ao(1)%matrix_struct)
1192 22 : CALL cp_cfm_create(cfm_ks_ikp_spinor, bs_env%cfm_SOC_spinor_ao(1)%matrix_struct)
1193 22 : CALL cp_cfm_create(cfm_SOC_ikp_spinor, bs_env%cfm_SOC_spinor_ao(1)%matrix_struct)
1194 22 : CALL cp_cfm_create(cfm_s_ikp_spinor, bs_env%cfm_SOC_spinor_ao(1)%matrix_struct)
1195 22 : CALL cp_cfm_create(cfm_spinor_wf_ikp, bs_env%cfm_SOC_spinor_ao(1)%matrix_struct)
1196 :
1197 22 : homo_spinor = bs_env%n_occ(1) + bs_env%n_occ(bs_env%n_spin)
1198 :
1199 22 : band_edges_scf_SOC%VBM = -1000.0_dp
1200 22 : band_edges_scf_SOC%CBM = 1000.0_dp
1201 22 : band_edges_scf_SOC%DBG = 1000.0_dp
1202 :
1203 22 : IF (bs_env%do_gw) THEN
1204 22 : band_edges_G0W0_SOC%VBM = -1000.0_dp
1205 22 : band_edges_G0W0_SOC%CBM = 1000.0_dp
1206 22 : band_edges_G0W0_SOC%DBG = 1000.0_dp
1207 : END IF
1208 :
1209 22 : IF (bs_env%unit_nr > 0) THEN
1210 11 : WRITE (bs_env%unit_nr, '(A)') ''
1211 11 : IF (bs_env%soc_window_occ > 0.0_dp) THEN
1212 3 : WRITE (bs_env%unit_nr, '(T2,A,T71,F10.2)') 'SOC requested, SOC energy window occ (eV):', &
1213 6 : bs_env%soc_window_occ*evolt
1214 : ELSE
1215 8 : WRITE (bs_env%unit_nr, '(T2,A,T71,A10)') 'SOC requested, SOC energy window occ (eV):', &
1216 16 : ' no window'
1217 : END IF
1218 11 : IF (bs_env%soc_window_virt > 0.0_dp) THEN
1219 3 : WRITE (bs_env%unit_nr, '(T2,A,T71,F10.2)') 'SOC requested, SOC energy window virt (eV):', &
1220 6 : bs_env%soc_window_virt*evolt
1221 : ELSE
1222 8 : WRITE (bs_env%unit_nr, '(T2,A,T71,A10)') 'SOC requested, SOC energy window virt (eV):', &
1223 16 : ' no window'
1224 : END IF
1225 11 : IF (bs_env%soc_window_occ > 0.0_dp .OR. bs_env%soc_window_virt > 0.0_dp) THEN
1226 4 : WRITE (bs_env%unit_nr, '(T2,A,T71,F10.2)') 'SOC requested, SOC window smearing (eV):', &
1227 8 : bs_env%soc_window_smearing*evolt
1228 : END IF
1229 : END IF
1230 : END IF
1231 :
1232 106 : IF (bs_env%do_ldos) THEN
1233 2 : CPASSERT(bs_env%int_ldos_xyz == int_ldos_z)
1234 : END IF
1235 :
1236 106 : IF (bs_env%unit_nr > 0) THEN
1237 53 : WRITE (bs_env%unit_nr, '(A)') ''
1238 : END IF
1239 :
1240 106 : IF (bs_env%small_cell_full_kp_or_large_cell_Gamma == small_cell_full_kp) THEN
1241 18 : CALL cp_cfm_create(cfm_ks_ikp, bs_env%cfm_ks_kp(1, 1)%matrix_struct)
1242 18 : CALL cp_cfm_create(cfm_s_ikp, bs_env%cfm_ks_kp(1, 1)%matrix_struct)
1243 : END IF
1244 :
1245 554 : DO ikp = 1, bs_env%nkp_bs_and_DOS
1246 :
1247 448 : t1 = m_walltime()
1248 :
1249 914 : DO ispin = 1, bs_env%n_spin
1250 :
1251 580 : SELECT CASE (bs_env%small_cell_full_kp_or_large_cell_Gamma)
1252 : CASE (large_cell_Gamma, large_cell_Gamma_ri_rs, non_periodic_ri_rs)
1253 :
1254 : ! 1. get H^KS_µν(k_i) from H^KS_µν(k=0)
1255 : CALL cfm_ikp_from_fm_Gamma(cfm_ks_ikp, bs_env%fm_ks_Gamma(ispin), &
1256 114 : ikp, qs_env, bs_env%kpoints_DOS, "ORB")
1257 :
1258 : ! 2. get S_µν(k_i) from S_µν(k=0)
1259 : CALL cfm_ikp_from_fm_Gamma(cfm_s_ikp, bs_env%fm_s_Gamma, &
1260 114 : ikp, qs_env, bs_env%kpoints_DOS, "ORB")
1261 114 : CALL cp_cfm_to_cfm(cfm_s_ikp, cfm_s_ikp_copy)
1262 :
1263 : ! 3. Diagonalize (Roothaan-Hall): H_KS(k_i)*C(k_i) = S(k_i)*C(k_i)*ϵ(k_i)
1264 : CALL cp_cfm_geeig(cfm_ks_ikp, cfm_s_ikp_copy, cfm_mos_ikp(ispin), &
1265 114 : eigenval, cfm_work_ikp)
1266 :
1267 : CASE (small_cell_full_kp)
1268 :
1269 : ! 1. get H^KS_µν(k_i)
1270 352 : CALL cp_cfm_to_cfm(bs_env%cfm_ks_kp(ikp, ispin), cfm_ks_ikp)
1271 :
1272 : ! 2. get S_µν(k_i)
1273 352 : CALL cp_cfm_to_cfm(bs_env%cfm_s_kp(ikp), cfm_s_ikp)
1274 :
1275 : ! 3. get C_µn(k_i) and ϵ_n(k_i)
1276 352 : CALL cp_cfm_to_cfm(bs_env%cfm_mo_coeff_kp(ikp, ispin), cfm_mos_ikp(ispin))
1277 5072 : eigenval(:) = bs_env%eigenval_scf(:, ikp, ispin)
1278 :
1279 : END SELECT
1280 :
1281 : ! 4. Projection p_nk^A of MO ψ_nk(r) on atom type A (inspired by Mulliken charge)
1282 : ! p_nk^A = sum_µ^A,ν C*_µ^A,n(k) S_µ^A,ν(k) C_ν,n(k)
1283 466 : CALL compute_proj_mo_on_kind(proj_mo_on_kind, qs_env, cfm_mos_ikp(ispin), cfm_s_ikp)
1284 :
1285 : ! 5. DOS and PDOS
1286 466 : IF (bs_env%do_dos_pdos) THEN
1287 : CALL add_to_DOS_PDOS(DOS_scf, PDOS_scf, eigenval, ikp, bs_env, n_E, E_min, &
1288 234 : proj_mo_on_kind)
1289 :
1290 234 : IF (bs_env%do_gw) THEN
1291 : CALL add_to_DOS_PDOS(DOS_G0W0, PDOS_G0W0, bs_env%eigenval_G0W0(:, ikp, ispin), &
1292 234 : ikp, bs_env, n_E, E_min, proj_mo_on_kind)
1293 : END IF
1294 : END IF
1295 :
1296 466 : IF (bs_env%do_ldos) THEN
1297 : CALL add_to_LDOS_2d(LDOS_scf_2d, qs_env, ikp, bs_env, cfm_mos_ikp(ispin), &
1298 2 : eigenval(:), band_edges_scf_guess)
1299 :
1300 2 : IF (bs_env%do_gw) THEN
1301 : CALL add_to_LDOS_2d(LDOS_G0W0_2d, qs_env, ikp, bs_env, cfm_mos_ikp(ispin), &
1302 2 : bs_env%eigenval_G0W0(:, ikp, 1), band_edges_G0W0)
1303 : END IF
1304 :
1305 : END IF
1306 :
1307 466 : homo = bs_env%n_occ(ispin)
1308 :
1309 466 : band_edges_scf%VBM = MAX(band_edges_scf%VBM, eigenval(homo))
1310 466 : band_edges_scf%CBM = MIN(band_edges_scf%CBM, eigenval(homo + 1))
1311 914 : band_edges_scf%DBG = MIN(band_edges_scf%DBG, eigenval(homo + 1) - eigenval(homo))
1312 :
1313 : END DO ! spin
1314 :
1315 : ! now the same with spin-orbit coupling
1316 448 : IF (bs_env%do_soc) THEN
1317 :
1318 : ! only print eigenvalues of DOS k-points in case no bandstructure path has been given
1319 328 : print_DOS_kpoints = (bs_env%nkp_only_bs <= 0)
1320 : ! in kpoints_DOS, the last nkp_only_bs are bandstructure k-points
1321 328 : is_bandstruc_kpoint = (ikp > bs_env%nkp_only_DOS)
1322 328 : print_ikp = print_DOS_kpoints .OR. is_bandstruc_kpoint
1323 :
1324 328 : IF (print_DOS_kpoints) THEN
1325 234 : nkp = bs_env%nkp_only_DOS
1326 234 : ikp_for_file = ikp
1327 : ELSE
1328 94 : nkp = bs_env%nkp_only_bs
1329 94 : ikp_for_file = ikp - bs_env%nkp_only_DOS
1330 : END IF
1331 :
1332 : ! compute DFT+SOC eigenvalues; based on these, compute band edges, DOS and LDOS
1333 : CALL SOC_ev(bs_env, qs_env, ikp, bs_env%eigenval_scf, &
1334 : E_min, cfm_mos_ikp, DOS_scf_SOC, PDOS_scf_SOC, &
1335 328 : band_edges_scf_SOC, eigenval_spinor, cfm_spinor_wf_ikp)
1336 :
1337 328 : IF (.NOT. bs_env%do_gw .AND. print_ikp) THEN
1338 0 : CALL write_SOC_eigenvalues(eigenval_spinor, ikp_for_file, ikp, bs_env)
1339 : END IF
1340 :
1341 328 : IF (bs_env%do_ldos) THEN
1342 : CALL add_to_LDOS_2d(LDOS_scf_2d_SOC, qs_env, ikp, bs_env, cfm_spinor_wf_ikp, &
1343 2 : eigenval_spinor, band_edges_scf_guess, .TRUE., cfm_work_ikp)
1344 : END IF
1345 :
1346 328 : IF (bs_env%do_gw) THEN
1347 :
1348 : ! compute G0W0+SOC eigenvalues; based on these, compute band edges, DOS and LDOS
1349 : CALL SOC_ev(bs_env, qs_env, ikp, bs_env%eigenval_G0W0, &
1350 : E_min, cfm_mos_ikp, DOS_G0W0_SOC, PDOS_G0W0_SOC, &
1351 328 : band_edges_G0W0_SOC, eigenval_spinor_G0W0, cfm_spinor_wf_ikp)
1352 :
1353 328 : IF (print_ikp) THEN
1354 : ! write SCF+SOC and G0W0+SOC eigenvalues to file
1355 : ! SCF_and_G0W0_band_structure_for_kpoint_<ikp>_+_SOC
1356 : CALL write_SOC_eigenvalues(eigenval_spinor, ikp_for_file, ikp, bs_env, &
1357 296 : eigenval_spinor_G0W0)
1358 : END IF
1359 :
1360 : END IF ! do_gw
1361 :
1362 : END IF ! do_soc
1363 :
1364 554 : IF (bs_env%unit_nr > 0 .AND. m_walltime() - t1 > 20.0_dp) THEN
1365 : WRITE (bs_env%unit_nr, '(T2,A,T43,I5,A,I3,A,F7.1,A)') &
1366 0 : 'Compute DOS, LDOS for k-point ', ikp, ' /', bs_env%nkp_bs_and_DOS, &
1367 0 : ', Execution time', m_walltime() - t1, ' s'
1368 : END IF
1369 :
1370 : END DO ! ikp_DOS
1371 :
1372 106 : band_edges_scf%IDBG = band_edges_scf%CBM - band_edges_scf%VBM
1373 106 : IF (bs_env%do_soc) THEN
1374 22 : band_edges_scf_SOC%IDBG = band_edges_scf_SOC%CBM - band_edges_scf_SOC%VBM
1375 22 : IF (bs_env%do_gw) THEN
1376 22 : band_edges_G0W0_SOC%IDBG = band_edges_G0W0_SOC%CBM - band_edges_G0W0_SOC%VBM
1377 : END IF
1378 : END IF
1379 :
1380 106 : CALL write_band_edges(band_edges_scf, "SCF", bs_env)
1381 106 : IF (bs_env%do_dos_pdos) THEN
1382 20 : CALL write_dos_pdos(DOS_scf, PDOS_scf, bs_env, qs_env, "SCF", E_min, band_edges_scf%VBM)
1383 : END IF
1384 106 : IF (bs_env%do_ldos) THEN
1385 2 : CALL print_LDOS_main(LDOS_scf_2d, bs_env, band_edges_scf, "SCF")
1386 : END IF
1387 :
1388 106 : IF (bs_env%do_soc) THEN
1389 22 : CALL write_band_edges(band_edges_scf_SOC, "SCF+SOC", bs_env)
1390 22 : IF (bs_env%do_dos_pdos) THEN
1391 : CALL write_dos_pdos(DOS_scf_SOC, PDOS_scf_SOC, bs_env, qs_env, "SCF_SOC", &
1392 16 : E_min, band_edges_scf_SOC%VBM)
1393 : END IF
1394 22 : IF (bs_env%do_ldos) THEN
1395 : ! argument band_edges_scf is actually correct because the non-SOC band edges
1396 : ! have been used as reference in add_to_LDOS_2d
1397 : CALL print_LDOS_main(LDOS_scf_2d_SOC, bs_env, band_edges_scf, &
1398 2 : "SCF_SOC")
1399 : END IF
1400 : END IF
1401 :
1402 106 : IF (bs_env%do_gw) THEN
1403 104 : CALL write_band_edges(band_edges_G0W0, "G0W0", bs_env)
1404 104 : CALL write_band_edges(bs_env%band_edges_HF, "Hartree-Fock with SCF orbitals", bs_env)
1405 104 : IF (bs_env%do_dos_pdos) THEN
1406 : CALL write_dos_pdos(DOS_G0W0, PDOS_G0W0, bs_env, qs_env, "G0W0", E_min, &
1407 20 : band_edges_G0W0%VBM)
1408 : END IF
1409 104 : IF (bs_env%do_ldos) THEN
1410 2 : CALL print_LDOS_main(LDOS_G0W0_2d, bs_env, band_edges_G0W0, "G0W0")
1411 : END IF
1412 : END IF
1413 :
1414 106 : IF (bs_env%do_soc .AND. bs_env%do_gw) THEN
1415 22 : CALL write_band_edges(band_edges_G0W0_SOC, "G0W0+SOC", bs_env)
1416 22 : IF (bs_env%do_dos_pdos) THEN
1417 : CALL write_dos_pdos(DOS_G0W0_SOC, PDOS_G0W0_SOC, bs_env, qs_env, "G0W0_SOC", E_min, &
1418 16 : band_edges_G0W0_SOC%VBM)
1419 : END IF
1420 : END IF
1421 :
1422 106 : CALL cp_cfm_release(cfm_s_ikp)
1423 106 : CALL cp_cfm_release(cfm_ks_ikp)
1424 106 : CALL cp_cfm_release(cfm_mos_ikp(1))
1425 106 : CALL cp_cfm_release(cfm_mos_ikp(2))
1426 106 : CALL cp_cfm_release(cfm_work_ikp)
1427 106 : CALL cp_cfm_release(cfm_s_ikp_copy)
1428 :
1429 106 : CALL cp_cfm_release(cfm_s_ikp_spinor)
1430 106 : CALL cp_cfm_release(cfm_ks_ikp_spinor)
1431 106 : CALL cp_cfm_release(cfm_SOC_ikp_spinor)
1432 106 : CALL cp_cfm_release(cfm_mos_ikp_spinor)
1433 106 : CALL cp_cfm_release(cfm_work_ikp_spinor)
1434 106 : CALL cp_cfm_release(cfm_s_ikp_spinor_copy)
1435 106 : CALL cp_cfm_release(cfm_spinor_wf_ikp)
1436 :
1437 106 : CALL timestop(handle)
1438 :
1439 424 : END SUBROUTINE eval_bandstructure_properties
1440 :
1441 : ! **************************************************************************************************
1442 : !> \brief ...
1443 : !> \param LDOS_2d ...
1444 : !> \param bs_env ...
1445 : !> \param band_edges ...
1446 : !> \param scf_gw_soc ...
1447 : ! **************************************************************************************************
1448 6 : SUBROUTINE print_LDOS_main(LDOS_2d, bs_env, band_edges, scf_gw_soc)
1449 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :) :: LDOS_2d
1450 : TYPE(post_scf_bandstructure_type), POINTER :: bs_env
1451 : TYPE(band_edges_type) :: band_edges
1452 : CHARACTER(LEN=*) :: scf_gw_soc
1453 :
1454 : CHARACTER(LEN=*), PARAMETER :: routineN = 'print_LDOS_main'
1455 :
1456 : INTEGER :: handle, i_x, i_x_bin, i_x_end, i_x_end_bin, i_x_end_glob, i_x_start, &
1457 : i_x_start_bin, i_x_start_glob, i_y, i_y_bin, i_y_end, i_y_end_bin, i_y_end_glob, &
1458 : i_y_start, i_y_start_bin, i_y_start_glob, n_E
1459 6 : INTEGER, ALLOCATABLE, DIMENSION(:, :) :: n_sum_for_bins
1460 : INTEGER, DIMENSION(2) :: bin_mesh
1461 : LOGICAL :: do_xy_bins
1462 : REAL(KIND=dp) :: E_min, energy_step, energy_window
1463 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :) :: LDOS_2d_bins
1464 :
1465 6 : CALL timeset(routineN, handle)
1466 :
1467 6 : n_E = SIZE(LDOS_2d, 3)
1468 :
1469 6 : energy_window = bs_env%energy_window_DOS
1470 6 : energy_step = bs_env%energy_step_DOS
1471 6 : E_min = band_edges%VBM - 0.5_dp*energy_window
1472 :
1473 18 : bin_mesh(1:2) = bs_env%bin_mesh(1:2)
1474 6 : do_xy_bins = (bin_mesh(1) > 0 .AND. bin_mesh(2) > 0)
1475 :
1476 6 : i_x_start = LBOUND(LDOS_2d, 1)
1477 6 : i_x_end = UBOUND(LDOS_2d, 1)
1478 6 : i_y_start = LBOUND(LDOS_2d, 2)
1479 6 : i_y_end = UBOUND(LDOS_2d, 2)
1480 :
1481 6 : IF (do_xy_bins) THEN
1482 6 : i_x_start_bin = 1
1483 6 : i_x_end_bin = bin_mesh(1)
1484 6 : i_y_start_bin = 1
1485 6 : i_y_end_bin = bin_mesh(2)
1486 : ELSE
1487 : i_x_start_bin = i_x_start
1488 : i_x_end_bin = i_x_end
1489 : i_y_start_bin = i_y_start
1490 : i_y_end_bin = i_y_end
1491 : END IF
1492 :
1493 30 : ALLOCATE (LDOS_2d_bins(i_x_start_bin:i_x_end_bin, i_y_start_bin:i_y_end_bin, n_E))
1494 6 : LDOS_2d_bins(:, :, :) = 0.0_dp
1495 :
1496 6 : IF (do_xy_bins) THEN
1497 :
1498 6 : i_x_start_glob = i_x_start
1499 6 : i_x_end_glob = i_x_end
1500 6 : i_y_start_glob = i_y_start
1501 6 : i_y_end_glob = i_y_end
1502 :
1503 6 : CALL bs_env%para_env%min(i_x_start_glob)
1504 6 : CALL bs_env%para_env%max(i_x_end_glob)
1505 6 : CALL bs_env%para_env%min(i_y_start_glob)
1506 6 : CALL bs_env%para_env%max(i_y_end_glob)
1507 :
1508 24 : ALLOCATE (n_sum_for_bins(bin_mesh(1), bin_mesh(2)), SOURCE=0)
1509 :
1510 : ! transform interval [i_x_start, i_x_end] to [1, bin_mesh(1)] (and same for y)
1511 390 : DO i_y = i_y_start, i_y_end
1512 4230 : DO i_x = i_x_start, i_x_end
1513 3840 : i_x_bin = bin_mesh(1)*(i_x - i_x_start_glob)/(i_x_end_glob - i_x_start_glob + 1) + 1
1514 3840 : i_y_bin = bin_mesh(2)*(i_y - i_y_start_glob)/(i_y_end_glob - i_y_start_glob + 1) + 1
1515 : LDOS_2d_bins(i_x_bin, i_y_bin, :) = LDOS_2d_bins(i_x_bin, i_y_bin, :) + &
1516 1073920 : LDOS_2d(i_x, i_y, :)
1517 4224 : n_sum_for_bins(i_x_bin, i_y_bin) = n_sum_for_bins(i_x_bin, i_y_bin) + 1
1518 : END DO
1519 : END DO
1520 :
1521 6 : CALL bs_env%para_env%sum(LDOS_2d_bins)
1522 6 : CALL bs_env%para_env%sum(n_sum_for_bins)
1523 :
1524 : ! divide by number of terms in the sum so we have the average LDOS(x,y,E)
1525 30 : DO i_y_bin = 1, bin_mesh(2)
1526 126 : DO i_x_bin = 1, bin_mesh(1)
1527 : LDOS_2d_bins(i_x_bin, i_y_bin, :) = LDOS_2d_bins(i_x_bin, i_y_bin, :)/ &
1528 26872 : REAL(n_sum_for_bins(i_x_bin, i_y_bin), KIND=dp)
1529 : END DO
1530 : END DO
1531 :
1532 : ELSE
1533 :
1534 0 : LDOS_2d_bins(:, :, :) = LDOS_2d(:, :, :)
1535 :
1536 : END IF
1537 :
1538 6 : IF (bin_mesh(1)*bin_mesh(2) < bs_env%n_bins_max_for_printing) THEN
1539 6 : CALL print_LDOS_2d_bins(LDOS_2d_bins, bs_env, E_min, scf_gw_soc)
1540 : ELSE
1541 0 : CPWARN("The number of bins for the LDOS is too large. Decrease BIN_MESH.")
1542 : END IF
1543 :
1544 6 : CALL timestop(handle)
1545 :
1546 12 : END SUBROUTINE print_LDOS_main
1547 :
1548 : ! **************************************************************************************************
1549 : !> \brief ...
1550 : !> \param LDOS_2d_bins ...
1551 : !> \param bs_env ...
1552 : !> \param E_min ...
1553 : !> \param scf_gw_soc ...
1554 : ! **************************************************************************************************
1555 6 : SUBROUTINE print_LDOS_2d_bins(LDOS_2d_bins, bs_env, E_min, scf_gw_soc)
1556 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :) :: LDOS_2d_bins
1557 : TYPE(post_scf_bandstructure_type), POINTER :: bs_env
1558 : REAL(KIND=dp) :: E_min
1559 : CHARACTER(LEN=*) :: scf_gw_soc
1560 :
1561 : CHARACTER(LEN=*), PARAMETER :: routineN = 'print_LDOS_2d_bins'
1562 :
1563 : CHARACTER(LEN=18) :: print_format
1564 : CHARACTER(LEN=4) :: print_format_1, print_format_2
1565 : CHARACTER(len=default_string_length) :: fname
1566 : INTEGER :: handle, i_E, i_x, i_x_end, i_x_start, &
1567 : i_y, i_y_end, i_y_start, iunit, n_E, &
1568 : n_x, n_y
1569 : REAL(KIND=dp) :: energy
1570 : REAL(KIND=dp), DIMENSION(3) :: coord, idx
1571 :
1572 6 : CALL timeset(routineN, handle)
1573 :
1574 6 : i_x_start = LBOUND(LDOS_2d_bins, 1)
1575 6 : i_x_end = UBOUND(LDOS_2d_bins, 1)
1576 6 : i_y_start = LBOUND(LDOS_2d_bins, 2)
1577 6 : i_y_end = UBOUND(LDOS_2d_bins, 2)
1578 6 : n_E = SIZE(LDOS_2d_bins, 3)
1579 :
1580 6 : n_x = i_x_end - i_x_start + 1
1581 6 : n_y = i_y_end - i_y_start + 1
1582 :
1583 6 : IF (bs_env%para_env%is_source()) THEN
1584 :
1585 15 : DO i_y = i_y_start, i_y_end
1586 63 : DO i_x = i_x_start, i_x_end
1587 :
1588 48 : idx(1) = (REAL(i_x, KIND=dp) - 0.5_dp)/REAL(n_x, KIND=dp)
1589 48 : idx(2) = (REAL(i_y, KIND=dp) - 0.5_dp)/REAL(n_y, KIND=dp)
1590 48 : idx(3) = 0.0_dp
1591 624 : coord(1:3) = MATMUL(bs_env%hmat, idx)
1592 :
1593 48 : CALL get_print_format(coord(1), print_format_1)
1594 48 : CALL get_print_format(coord(2), print_format_2)
1595 :
1596 48 : print_format = "(3A,"//print_format_1//",A,"//print_format_2//",A)"
1597 :
1598 48 : WRITE (fname, print_format) "LDOS_", scf_gw_soc, &
1599 96 : "_at_x_", coord(1)*angstrom, '_A_and_y_', coord(2)*angstrom, '_A'
1600 :
1601 : CALL open_file(TRIM(fname), unit_number=iunit, file_status="REPLACE", &
1602 48 : file_action="WRITE")
1603 :
1604 48 : WRITE (iunit, "(2A)") " Energy E (eV) average LDOS(x,y,E) (1/(eV*Å^2), ", &
1605 96 : "integrated over z, averaged inside bin)"
1606 :
1607 13424 : DO i_E = 1, n_E
1608 13376 : energy = E_min + i_E*bs_env%energy_step_DOS
1609 13376 : WRITE (iunit, "(2F17.3)") energy*evolt, &
1610 : LDOS_2d_bins(i_x, i_y, i_E)* &
1611 26800 : bs_env%unit_ldos_int_z_inv_Ang2_eV
1612 : END DO
1613 :
1614 60 : CALL close_file(iunit)
1615 :
1616 : END DO
1617 : END DO
1618 :
1619 : END IF
1620 :
1621 6 : CALL timestop(handle)
1622 :
1623 6 : END SUBROUTINE print_LDOS_2d_bins
1624 :
1625 : ! **************************************************************************************************
1626 : !> \brief ...
1627 : !> \param coord ...
1628 : !> \param print_format ...
1629 : ! **************************************************************************************************
1630 96 : SUBROUTINE get_print_format(coord, print_format)
1631 : REAL(KIND=dp) :: coord
1632 : CHARACTER(LEN=4) :: print_format
1633 :
1634 : CHARACTER(LEN=*), PARAMETER :: routineN = 'get_print_format'
1635 :
1636 : INTEGER :: handle
1637 :
1638 96 : CALL timeset(routineN, handle)
1639 :
1640 96 : IF (coord < -10000/angstrom) THEN
1641 0 : print_format = "F9.2"
1642 96 : ELSE IF (coord < -1000/angstrom) THEN
1643 0 : print_format = "F8.2"
1644 96 : ELSE IF (coord < -100/angstrom) THEN
1645 0 : print_format = "F7.2"
1646 96 : ELSE IF (coord < -10/angstrom) THEN
1647 0 : print_format = "F6.2"
1648 96 : ELSE IF (coord < -1/angstrom) THEN
1649 0 : print_format = "F5.2"
1650 96 : ELSE IF (coord < 10/angstrom) THEN
1651 96 : print_format = "F4.2"
1652 0 : ELSE IF (coord < 100/angstrom) THEN
1653 0 : print_format = "F5.2"
1654 0 : ELSE IF (coord < 1000/angstrom) THEN
1655 0 : print_format = "F6.2"
1656 0 : ELSE IF (coord < 10000/angstrom) THEN
1657 0 : print_format = "F7.2"
1658 : ELSE
1659 0 : print_format = "F8.2"
1660 : END IF
1661 :
1662 96 : CALL timestop(handle)
1663 :
1664 96 : END SUBROUTINE get_print_format
1665 :
1666 : ! **************************************************************************************************
1667 : !> \brief ...
1668 : !> \param bs_env ...
1669 : !> \param qs_env ...
1670 : !> \param ikp ...
1671 : !> \param eigenval_no_SOC ...
1672 : !> \param E_min ...
1673 : !> \param cfm_mos_ikp ...
1674 : !> \param DOS ...
1675 : !> \param PDOS ...
1676 : !> \param band_edges ...
1677 : !> \param eigenval_spinor ...
1678 : !> \param cfm_spinor_wf_ikp ...
1679 : ! **************************************************************************************************
1680 656 : SUBROUTINE SOC_ev(bs_env, qs_env, ikp, eigenval_no_SOC, E_min, cfm_mos_ikp, &
1681 : DOS, PDOS, band_edges, eigenval_spinor, cfm_spinor_wf_ikp)
1682 :
1683 : TYPE(post_scf_bandstructure_type), POINTER :: bs_env
1684 : TYPE(qs_environment_type), POINTER :: qs_env
1685 : INTEGER :: ikp
1686 : REAL(KIND=dp), DIMENSION(:, :, :) :: eigenval_no_SOC
1687 : REAL(KIND=dp) :: E_min
1688 : TYPE(cp_cfm_type), DIMENSION(2) :: cfm_mos_ikp
1689 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:) :: DOS
1690 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: PDOS
1691 : TYPE(band_edges_type) :: band_edges
1692 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:) :: eigenval_spinor
1693 : TYPE(cp_cfm_type) :: cfm_spinor_wf_ikp
1694 :
1695 : CHARACTER(LEN=*), PARAMETER :: routineN = 'SOC_ev'
1696 :
1697 : INTEGER :: handle, homo_spinor, n_ao, n_E, nkind
1698 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:) :: eigenval_spinor_no_SOC
1699 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: proj_mo_on_kind_spinor
1700 : TYPE(cp_cfm_type) :: cfm_eigenvec_ikp_spinor, &
1701 : cfm_ks_ikp_spinor, cfm_mos_ikp_spinor, &
1702 : cfm_SOC_ikp_spinor, cfm_work_ikp_spinor
1703 :
1704 : !TYPE(band_edges_type) :: band_edges_no_SOC
1705 :
1706 656 : CALL timeset(routineN, handle)
1707 :
1708 656 : n_ao = bs_env%n_ao
1709 656 : homo_spinor = bs_env%n_occ(1) + bs_env%n_occ(bs_env%n_spin)
1710 656 : CALL get_qs_env(qs_env, nkind=nkind)
1711 :
1712 656 : CALL cp_cfm_create(cfm_ks_ikp_spinor, bs_env%cfm_SOC_spinor_ao(1)%matrix_struct)
1713 656 : CALL cp_cfm_create(cfm_SOC_ikp_spinor, bs_env%cfm_SOC_spinor_ao(1)%matrix_struct)
1714 656 : CALL cp_cfm_create(cfm_mos_ikp_spinor, bs_env%cfm_SOC_spinor_ao(1)%matrix_struct)
1715 656 : CALL cp_cfm_create(cfm_work_ikp_spinor, bs_env%cfm_SOC_spinor_ao(1)%matrix_struct)
1716 656 : CALL cp_cfm_create(cfm_eigenvec_ikp_spinor, bs_env%cfm_SOC_spinor_ao(1)%matrix_struct)
1717 :
1718 1968 : ALLOCATE (eigenval_spinor_no_SOC(2*n_ao))
1719 2624 : ALLOCATE (proj_mo_on_kind_spinor(2*n_ao, nkind))
1720 : ! PDOS not yet implemented -> projection is just zero -> PDOS is zero
1721 656 : proj_mo_on_kind_spinor(:, :) = 0.0_dp
1722 :
1723 : ! 1. get V^SOC_µν,σσ'(k_i)
1724 676 : SELECT CASE (bs_env%small_cell_full_kp_or_large_cell_Gamma)
1725 : CASE (large_cell_Gamma, large_cell_Gamma_ri_rs, non_periodic_ri_rs)
1726 :
1727 : ! 1. get V^SOC_µν,σσ'(k_i) from V^SOC_µν,σσ'(k=0)
1728 : CALL cfm_ikp_from_cfm_spinor_Gamma(cfm_SOC_ikp_spinor, &
1729 : bs_env%cfm_SOC_spinor_ao(1), &
1730 : bs_env%fm_s_Gamma%matrix_struct, &
1731 20 : ikp, qs_env, bs_env%kpoints_DOS, "ORB")
1732 :
1733 : CASE (small_cell_full_kp)
1734 :
1735 : ! 1. V^SOC_µν,σσ'(k_i) already there
1736 656 : CALL cp_cfm_to_cfm(bs_env%cfm_SOC_spinor_ao(ikp), cfm_SOC_ikp_spinor)
1737 :
1738 : END SELECT
1739 :
1740 : ! 2. V^SOC_nn',σσ'(k_i) = sum_µν C^*_µn,σ(k_i) V^SOC_µν,σσ'(k_i) C_νn'(k_i),
1741 : ! C_µn,σ(k_i): MO coefficiencts from diagonalizing KS-matrix h^KS_nn',σσ'(k_i)
1742 :
1743 : ! 2.1 build matrix C_µn,σ(k_i)
1744 656 : CALL cp_cfm_set_all(cfm_mos_ikp_spinor, z_zero)
1745 656 : CALL add_cfm_submat(cfm_mos_ikp_spinor, cfm_mos_ikp(1), 1, 1)
1746 656 : CALL add_cfm_submat(cfm_mos_ikp_spinor, cfm_mos_ikp(bs_env%n_spin), n_ao + 1, n_ao + 1)
1747 :
1748 : ! 2.2 work_nν,σσ' = sum_µ C^*_µn,σ(k_i) V^SOC_µν,σσ'(k_i)
1749 : CALL parallel_gemm('C', 'N', 2*n_ao, 2*n_ao, 2*n_ao, z_one, &
1750 : cfm_mos_ikp_spinor, cfm_SOC_ikp_spinor, &
1751 656 : z_zero, cfm_work_ikp_spinor)
1752 :
1753 : ! 2.3 V^SOC_nn',σσ'(k_i) = sum_ν work_nν,σσ' C_νn'(k_i)
1754 : CALL parallel_gemm('N', 'N', 2*n_ao, 2*n_ao, 2*n_ao, z_one, &
1755 : cfm_work_ikp_spinor, cfm_mos_ikp_spinor, &
1756 656 : z_zero, cfm_ks_ikp_spinor)
1757 :
1758 : ! 3. remove SOC outside of energy window (otherwise, numerical problems arise
1759 : ! because energetically low semicore states and energetically very high
1760 : ! unbound states couple to the states around the Fermi level)
1761 8800 : eigenval_spinor_no_SOC(1:n_ao) = eigenval_no_SOC(1:n_ao, ikp, 1)
1762 8800 : eigenval_spinor_no_SOC(n_ao + 1:) = eigenval_no_SOC(1:n_ao, ikp, bs_env%n_spin)
1763 656 : IF (bs_env%soc_window_occ > 0.0_dp .OR. bs_env%soc_window_virt > 0.0_dp) THEN
1764 : CALL remove_soc_outside_energy_window_mo(cfm_ks_ikp_spinor, &
1765 : bs_env%soc_window_virt, &
1766 : bs_env%soc_window_smearing, &
1767 : eigenval_spinor_no_SOC, &
1768 256 : bs_env%e_fermi(1))
1769 :
1770 : END IF
1771 :
1772 : ! 4. h^G0W0+SOC_nn',σσ'(k_i) = ε_nσ^G0W0(k_i) δ_nn' δ_σσ' + V^SOC_nn',σσ'(k_i)
1773 656 : CALL cfm_add_on_diag(cfm_ks_ikp_spinor, eigenval_spinor_no_SOC)
1774 :
1775 : ! 5. diagonalize h^G0W0+SOC_nn',σσ'(k_i) to get eigenvalues
1776 656 : CALL cp_cfm_heevd(cfm_ks_ikp_spinor, cfm_eigenvec_ikp_spinor, eigenval_spinor)
1777 :
1778 : ! 6. DOS from spinors, no PDOS
1779 656 : IF (bs_env%do_dos_pdos) THEN
1780 452 : n_E = SIZE(DOS)
1781 : CALL add_to_DOS_PDOS(DOS, PDOS, eigenval_spinor, &
1782 452 : ikp, bs_env, n_E, E_min, proj_mo_on_kind_spinor)
1783 : END IF
1784 :
1785 : ! 7. valence band max. (VBM), conduction band min. (CBM) and direct bandgap (DBG)
1786 656 : band_edges%VBM = MAX(band_edges%VBM, eigenval_spinor(homo_spinor))
1787 656 : band_edges%CBM = MIN(band_edges%CBM, eigenval_spinor(homo_spinor + 1))
1788 : band_edges%DBG = MIN(band_edges%DBG, eigenval_spinor(homo_spinor + 1) &
1789 656 : - eigenval_spinor(homo_spinor))
1790 :
1791 : ! 8. spinor wavefunctions:
1792 : CALL parallel_gemm('N', 'N', 2*n_ao, 2*n_ao, 2*n_ao, z_one, &
1793 : cfm_mos_ikp_spinor, cfm_eigenvec_ikp_spinor, &
1794 656 : z_zero, cfm_spinor_wf_ikp)
1795 :
1796 656 : CALL cp_cfm_release(cfm_ks_ikp_spinor)
1797 656 : CALL cp_cfm_release(cfm_SOC_ikp_spinor)
1798 656 : CALL cp_cfm_release(cfm_work_ikp_spinor)
1799 656 : CALL cp_cfm_release(cfm_eigenvec_ikp_spinor)
1800 656 : CALL cp_cfm_release(cfm_mos_ikp_spinor)
1801 :
1802 656 : CALL timestop(handle)
1803 :
1804 1968 : END SUBROUTINE SOC_ev
1805 :
1806 : ! **************************************************************************************************
1807 : !> \brief ...
1808 : !> \param DOS ...
1809 : !> \param PDOS ...
1810 : !> \param eigenval ...
1811 : !> \param ikp ...
1812 : !> \param bs_env ...
1813 : !> \param n_E ...
1814 : !> \param E_min ...
1815 : !> \param proj_mo_on_kind ...
1816 : ! **************************************************************************************************
1817 920 : SUBROUTINE add_to_DOS_PDOS(DOS, PDOS, eigenval, ikp, bs_env, n_E, E_min, proj_mo_on_kind)
1818 :
1819 : REAL(KIND=dp), DIMENSION(:) :: DOS
1820 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: PDOS
1821 : REAL(KIND=dp), DIMENSION(:) :: eigenval
1822 : INTEGER :: ikp
1823 : TYPE(post_scf_bandstructure_type), POINTER :: bs_env
1824 : INTEGER :: n_E
1825 : REAL(KIND=dp) :: E_min
1826 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: proj_mo_on_kind
1827 :
1828 : CHARACTER(LEN=*), PARAMETER :: routineN = 'add_to_DOS_PDOS'
1829 :
1830 : INTEGER :: handle, i_E, i_kind, i_mo, n_mo, nkind
1831 : REAL(KIND=dp) :: broadening, energy, energy_step_DOS, wkp
1832 :
1833 920 : CALL timeset(routineN, handle)
1834 :
1835 920 : energy_step_DOS = bs_env%energy_step_DOS
1836 920 : broadening = bs_env%broadening_DOS
1837 :
1838 920 : n_mo = SIZE(eigenval)
1839 920 : nkind = SIZE(proj_mo_on_kind, 2)
1840 :
1841 : ! normalize to closed-shell / open-shell
1842 920 : wkp = bs_env%kpoints_DOS%wkp(ikp)*bs_env%spin_degeneracy
1843 2072664 : DO i_E = 1, n_E
1844 2071744 : energy = E_min + i_E*energy_step_DOS
1845 45624244 : DO i_mo = 1, n_mo
1846 : ! DOS
1847 43551580 : DOS(i_E) = DOS(i_E) + wkp*Gaussian(energy - eigenval(i_mo), broadening)
1848 :
1849 : ! PDOS
1850 132726484 : DO i_kind = 1, nkind
1851 130654740 : IF (proj_mo_on_kind(i_mo, i_kind) > 0.0_dp) THEN
1852 : PDOS(i_E, i_kind) = PDOS(i_E, i_kind) + &
1853 : proj_mo_on_kind(i_mo, i_kind)*wkp* &
1854 27026364 : Gaussian(energy - eigenval(i_mo), broadening)
1855 : END IF
1856 : END DO
1857 : END DO
1858 : END DO
1859 :
1860 920 : CALL timestop(handle)
1861 :
1862 920 : END SUBROUTINE add_to_DOS_PDOS
1863 :
1864 : ! **************************************************************************************************
1865 : !> \brief ...
1866 : !> \param LDOS_2d ...
1867 : !> \param qs_env ...
1868 : !> \param ikp ...
1869 : !> \param bs_env ...
1870 : !> \param cfm_mos_ikp ...
1871 : !> \param eigenval ...
1872 : !> \param band_edges ...
1873 : !> \param do_spinor ...
1874 : !> \param cfm_non_spinor ...
1875 : ! **************************************************************************************************
1876 6 : SUBROUTINE add_to_LDOS_2d(LDOS_2d, qs_env, ikp, bs_env, cfm_mos_ikp, eigenval, &
1877 : band_edges, do_spinor, cfm_non_spinor)
1878 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :) :: LDOS_2d
1879 : TYPE(qs_environment_type), POINTER :: qs_env
1880 : INTEGER :: ikp
1881 : TYPE(post_scf_bandstructure_type), POINTER :: bs_env
1882 : TYPE(cp_cfm_type) :: cfm_mos_ikp
1883 : REAL(KIND=dp), DIMENSION(:) :: eigenval
1884 : TYPE(band_edges_type) :: band_edges
1885 : LOGICAL, OPTIONAL :: do_spinor
1886 : TYPE(cp_cfm_type), OPTIONAL :: cfm_non_spinor
1887 :
1888 : CHARACTER(LEN=*), PARAMETER :: routineN = 'add_to_LDOS_2d'
1889 :
1890 : INTEGER :: handle, i_E, i_x_end, i_x_start, i_y_end, i_y_start, i_z, i_z_end, i_z_start, &
1891 : j_col, j_mo, n_E, n_mo, n_z, ncol_local, nimages, z_end_global, z_start_global
1892 6 : INTEGER, DIMENSION(:), POINTER :: col_indices
1893 : LOGICAL :: is_any_weight_non_zero, my_do_spinor
1894 : REAL(KIND=dp) :: broadening, E_max, E_min, &
1895 : E_total_window, energy, energy_step, &
1896 : energy_window, spin_degeneracy, weight
1897 : TYPE(cp_cfm_type) :: cfm_weighted_dm_ikp, cfm_work
1898 : TYPE(cp_fm_type) :: fm_non_spinor, fm_weighted_dm_MIC
1899 6 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: weighted_dm_MIC
1900 : TYPE(dft_control_type), POINTER :: dft_control
1901 : TYPE(pw_c1d_gs_type) :: rho_g
1902 : TYPE(pw_env_type), POINTER :: pw_env
1903 : TYPE(pw_pool_type), POINTER :: auxbas_pw_pool
1904 : TYPE(pw_r3d_rs_type) :: LDOS_3d
1905 : TYPE(qs_ks_env_type), POINTER :: ks_env
1906 :
1907 6 : CALL timeset(routineN, handle)
1908 :
1909 6 : my_do_spinor = .FALSE.
1910 6 : IF (PRESENT(do_spinor)) my_do_spinor = do_spinor
1911 :
1912 6 : CALL get_qs_env(qs_env, ks_env=ks_env, pw_env=pw_env, dft_control=dft_control)
1913 :
1914 : ! previously, dft_control%nimages set to # neighbor cells, revert for Γ-only KS matrix
1915 6 : nimages = dft_control%nimages
1916 6 : dft_control%nimages = bs_env%nimages_scf
1917 :
1918 6 : energy_window = bs_env%energy_window_DOS
1919 6 : energy_step = bs_env%energy_step_DOS
1920 6 : broadening = bs_env%broadening_DOS
1921 :
1922 6 : E_min = band_edges%VBM - 0.5_dp*energy_window
1923 6 : E_max = band_edges%CBM + 0.5_dp*energy_window
1924 6 : E_total_window = E_max - E_min
1925 :
1926 6 : n_E = INT(E_total_window/energy_step)
1927 :
1928 6 : CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool)
1929 :
1930 6 : CALL auxbas_pw_pool%create_pw(LDOS_3d)
1931 6 : CALL auxbas_pw_pool%create_pw(rho_g)
1932 :
1933 6 : i_x_start = LBOUND(LDOS_3d%array, 1)
1934 6 : i_x_end = UBOUND(LDOS_3d%array, 1)
1935 6 : i_y_start = LBOUND(LDOS_3d%array, 2)
1936 6 : i_y_end = UBOUND(LDOS_3d%array, 2)
1937 6 : i_z_start = LBOUND(LDOS_3d%array, 3)
1938 6 : i_z_end = UBOUND(LDOS_3d%array, 3)
1939 :
1940 6 : z_start_global = i_z_start
1941 6 : z_end_global = i_z_end
1942 :
1943 6 : CALL bs_env%para_env%min(z_start_global)
1944 6 : CALL bs_env%para_env%max(z_end_global)
1945 6 : n_z = z_end_global - z_start_global + 1
1946 :
1947 36 : IF (ANY(ABS(bs_env%hmat(1:2, 3)) > 1.0E-6_dp) .OR. ANY(ABS(bs_env%hmat(3, 1:2)) > 1.0E-6_dp)) THEN
1948 0 : CPABORT("Please choose a cell that has 90° angles to the z-direction.")
1949 : END IF
1950 : ! for integration, we need the dz and the conversion from H -> eV and a_Bohr -> Å
1951 6 : bs_env%unit_ldos_int_z_inv_Ang2_eV = bs_env%hmat(3, 3)/REAL(n_z, KIND=dp)/evolt/angstrom**2
1952 :
1953 6 : IF (ikp == 1) THEN
1954 30 : ALLOCATE (LDOS_2d(i_x_start:i_x_end, i_y_start:i_y_end, n_E))
1955 6 : LDOS_2d(:, :, :) = 0.0_dp
1956 : END IF
1957 :
1958 6 : CALL cp_cfm_create(cfm_work, cfm_mos_ikp%matrix_struct)
1959 6 : CALL cp_cfm_create(cfm_weighted_dm_ikp, cfm_mos_ikp%matrix_struct)
1960 6 : CALL cp_fm_create(fm_weighted_dm_MIC, cfm_mos_ikp%matrix_struct)
1961 6 : IF (my_do_spinor) THEN
1962 2 : CALL cp_fm_create(fm_non_spinor, cfm_non_spinor%matrix_struct)
1963 : END IF
1964 :
1965 : CALL cp_cfm_get_info(matrix=cfm_mos_ikp, &
1966 : ncol_global=n_mo, &
1967 : ncol_local=ncol_local, &
1968 6 : col_indices=col_indices)
1969 :
1970 6 : NULLIFY (weighted_dm_MIC)
1971 6 : CALL dbcsr_allocate_matrix_set(weighted_dm_MIC, 1)
1972 6 : ALLOCATE (weighted_dm_MIC(1)%matrix)
1973 : CALL dbcsr_create(weighted_dm_MIC(1)%matrix, template=bs_env%mat_ao_ao%matrix, &
1974 6 : matrix_type=dbcsr_type_symmetric)
1975 :
1976 1678 : DO i_E = 1, n_E
1977 :
1978 1672 : energy = E_min + i_E*energy_step
1979 :
1980 1672 : is_any_weight_non_zero = .FALSE.
1981 :
1982 20950 : DO j_col = 1, ncol_local
1983 :
1984 19278 : j_mo = col_indices(j_col)
1985 :
1986 19278 : IF (my_do_spinor) THEN
1987 : spin_degeneracy = 1.0_dp
1988 : ELSE
1989 10818 : spin_degeneracy = bs_env%spin_degeneracy
1990 : END IF
1991 :
1992 19278 : weight = Gaussian(energy - eigenval(j_mo), broadening)*spin_degeneracy
1993 :
1994 144099 : cfm_work%local_data(:, j_col) = cfm_mos_ikp%local_data(:, j_col)*weight
1995 :
1996 20950 : IF (weight > 1.0E-5_dp) is_any_weight_non_zero = .TRUE.
1997 :
1998 : END DO
1999 :
2000 1672 : CALL bs_env%para_env%sync()
2001 1672 : CALL bs_env%para_env%sum(is_any_weight_non_zero)
2002 1672 : CALL bs_env%para_env%sync()
2003 :
2004 : ! cycle if there are no states at the energy i_E
2005 1678 : IF (is_any_weight_non_zero) THEN
2006 :
2007 : CALL parallel_gemm('N', 'C', n_mo, n_mo, n_mo, z_one, &
2008 24 : cfm_mos_ikp, cfm_work, z_zero, cfm_weighted_dm_ikp)
2009 :
2010 24 : IF (my_do_spinor) THEN
2011 :
2012 : ! contribution from up,up to fm_non_spinor
2013 8 : CALL get_cfm_submat(cfm_non_spinor, cfm_weighted_dm_ikp, 1, 1)
2014 8 : CALL cp_fm_set_all(fm_non_spinor, 0.0_dp)
2015 : CALL MIC_contribution_from_ikp(bs_env, qs_env, fm_non_spinor, &
2016 : cfm_non_spinor, ikp, bs_env%kpoints_DOS, &
2017 8 : "ORB", bs_env%kpoints_DOS%wkp(ikp))
2018 :
2019 : ! add contribution from down,down to fm_non_spinor
2020 8 : CALL get_cfm_submat(cfm_non_spinor, cfm_weighted_dm_ikp, n_mo/2, n_mo/2)
2021 : CALL MIC_contribution_from_ikp(bs_env, qs_env, fm_non_spinor, &
2022 : cfm_non_spinor, ikp, bs_env%kpoints_DOS, &
2023 8 : "ORB", bs_env%kpoints_DOS%wkp(ikp))
2024 : CALL copy_fm_to_dbcsr(fm_non_spinor, weighted_dm_MIC(1)%matrix, &
2025 8 : keep_sparsity=.FALSE.)
2026 : ELSE
2027 16 : CALL cp_fm_set_all(fm_weighted_dm_MIC, 0.0_dp)
2028 : CALL MIC_contribution_from_ikp(bs_env, qs_env, fm_weighted_dm_MIC, &
2029 : cfm_weighted_dm_ikp, ikp, bs_env%kpoints_DOS, &
2030 16 : "ORB", bs_env%kpoints_DOS%wkp(ikp))
2031 : CALL copy_fm_to_dbcsr(fm_weighted_dm_MIC, weighted_dm_MIC(1)%matrix, &
2032 16 : keep_sparsity=.FALSE.)
2033 : END IF
2034 :
2035 338424 : LDOS_3d%array(:, :, :) = 0.0_dp
2036 :
2037 : CALL calculate_rho_elec(matrix_p_kp=weighted_dm_MIC, &
2038 : rho=LDOS_3d, &
2039 : rho_gspace=rho_g, &
2040 24 : ks_env=ks_env)
2041 :
2042 504 : DO i_z = i_z_start, i_z_end
2043 338424 : LDOS_2d(:, :, i_E) = LDOS_2d(:, :, i_E) + LDOS_3d%array(:, :, i_z)
2044 : END DO
2045 :
2046 : END IF
2047 :
2048 : END DO
2049 :
2050 : ! set back nimages
2051 6 : dft_control%nimages = nimages
2052 :
2053 6 : CALL auxbas_pw_pool%give_back_pw(LDOS_3d)
2054 6 : CALL auxbas_pw_pool%give_back_pw(rho_g)
2055 :
2056 6 : CALL cp_cfm_release(cfm_work)
2057 6 : CALL cp_cfm_release(cfm_weighted_dm_ikp)
2058 :
2059 6 : CALL cp_fm_release(fm_weighted_dm_MIC)
2060 :
2061 6 : CALL dbcsr_deallocate_matrix_set(weighted_dm_MIC)
2062 :
2063 6 : IF (my_do_spinor) THEN
2064 2 : CALL cp_fm_release(fm_non_spinor)
2065 : END IF
2066 :
2067 6 : CALL timestop(handle)
2068 :
2069 6 : END SUBROUTINE add_to_LDOS_2d
2070 :
2071 : ! **************************************************************************************************
2072 : !> \brief ...
2073 : !> \param eigenval_spinor ...
2074 : !> \param ikp_for_file ...
2075 : !> \param ikp ...
2076 : !> \param bs_env ...
2077 : !> \param eigenval_spinor_G0W0 ...
2078 : ! **************************************************************************************************
2079 296 : SUBROUTINE write_SOC_eigenvalues(eigenval_spinor, ikp_for_file, ikp, bs_env, eigenval_spinor_G0W0)
2080 :
2081 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:) :: eigenval_spinor
2082 : INTEGER :: ikp_for_file, ikp
2083 : TYPE(post_scf_bandstructure_type), POINTER :: bs_env
2084 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:), OPTIONAL :: eigenval_spinor_G0W0
2085 :
2086 : CHARACTER(LEN=*), PARAMETER :: routineN = 'write_SOC_eigenvalues'
2087 :
2088 : CHARACTER(len=3) :: occ_vir
2089 : CHARACTER(LEN=default_string_length) :: fname
2090 : INTEGER :: handle, i_mo, iunit, n_occ_spinor
2091 :
2092 296 : CALL timeset(routineN, handle)
2093 :
2094 296 : fname = "bandstructure_SCF_and_G0W0_plus_SOC"
2095 :
2096 296 : IF (bs_env%para_env%is_source()) THEN
2097 :
2098 148 : IF (ikp_for_file == 1) THEN
2099 : CALL open_file(TRIM(fname), unit_number=iunit, file_status="REPLACE", &
2100 11 : file_action="WRITE")
2101 : ELSE
2102 : CALL open_file(TRIM(fname), unit_number=iunit, file_status="OLD", &
2103 137 : file_action="WRITE", file_position="APPEND")
2104 : END IF
2105 :
2106 148 : WRITE (iunit, "(A)") " "
2107 148 : WRITE (iunit, "(A10,I7,A25,3F10.4)") "kpoint: ", ikp_for_file, "coordinate: ", &
2108 740 : bs_env%kpoints_DOS%xkp(:, ikp)
2109 148 : WRITE (iunit, "(A)") " "
2110 :
2111 148 : IF (PRESENT(eigenval_spinor_G0W0)) THEN
2112 : ! SCF+SOC and G0W0+SOC eigenvalues
2113 148 : WRITE (iunit, "(A5,A12,2A22)") "n", "k", "ϵ_nk^DFT+SOC (eV)", "ϵ_nk^G0W0+SOC (eV)"
2114 : ELSE
2115 : ! SCF+SOC eigenvalues only
2116 0 : WRITE (iunit, "(A5,A12,A22)") "n", "k", "ϵ_nk^DFT+SOC (eV)"
2117 : END IF
2118 :
2119 148 : n_occ_spinor = bs_env%n_occ(1) + bs_env%n_occ(bs_env%n_spin)
2120 :
2121 3932 : DO i_mo = 1, SIZE(eigenval_spinor)
2122 3784 : IF (i_mo <= n_occ_spinor) occ_vir = 'occ'
2123 3784 : IF (i_mo > n_occ_spinor) occ_vir = 'vir'
2124 3932 : IF (PRESENT(eigenval_spinor_G0W0)) THEN
2125 : ! SCF+SOC and G0W0+SOC eigenvalues
2126 3784 : WRITE (iunit, "(I5,3A,I5,4F16.3,2F17.3)") i_mo, ' (', occ_vir, ') ', &
2127 7568 : ikp_for_file, eigenval_spinor(i_mo)*evolt, eigenval_spinor_G0W0(i_mo)*evolt
2128 : ELSE
2129 : ! SCF+SOC eigenvalues only
2130 0 : WRITE (iunit, "(I5,3A,I5,4F16.3,F17.3)") i_mo, ' (', occ_vir, ') ', &
2131 0 : ikp_for_file, eigenval_spinor(i_mo)*evolt
2132 : END IF
2133 : END DO
2134 :
2135 148 : CALL close_file(iunit)
2136 :
2137 : END IF
2138 :
2139 296 : CALL timestop(handle)
2140 :
2141 296 : END SUBROUTINE write_SOC_eigenvalues
2142 :
2143 : ! **************************************************************************************************
2144 : !> \brief ...
2145 : !> \param int_number ...
2146 : !> \return ...
2147 : ! **************************************************************************************************
2148 0 : PURE FUNCTION count_digits(int_number)
2149 :
2150 : INTEGER, INTENT(IN) :: int_number
2151 : INTEGER :: count_digits
2152 :
2153 : INTEGER :: digitCount, tempInt
2154 :
2155 0 : digitCount = 0
2156 :
2157 0 : tempInt = int_number
2158 :
2159 0 : DO WHILE (tempInt /= 0)
2160 0 : tempInt = tempInt/10
2161 0 : digitCount = digitCount + 1
2162 : END DO
2163 :
2164 0 : count_digits = digitCount
2165 :
2166 0 : END FUNCTION count_digits
2167 :
2168 : ! **************************************************************************************************
2169 : !> \brief ...
2170 : !> \param band_edges ...
2171 : !> \param scf_gw_soc ...
2172 : !> \param bs_env ...
2173 : ! **************************************************************************************************
2174 358 : SUBROUTINE write_band_edges(band_edges, scf_gw_soc, bs_env)
2175 :
2176 : TYPE(band_edges_type) :: band_edges
2177 : CHARACTER(LEN=*) :: scf_gw_soc
2178 : TYPE(post_scf_bandstructure_type), POINTER :: bs_env
2179 :
2180 : CHARACTER(LEN=*), PARAMETER :: routineN = 'write_band_edges'
2181 :
2182 : CHARACTER(LEN=17) :: print_format
2183 : INTEGER :: handle, u
2184 :
2185 358 : CALL timeset(routineN, handle)
2186 :
2187 : ! print format
2188 358 : print_format = "(T2,2A,T61,F20.3)"
2189 :
2190 358 : u = bs_env%unit_nr
2191 358 : IF (u > 0) THEN
2192 179 : WRITE (u, '(T2,A)') ''
2193 179 : WRITE (u, print_format) scf_gw_soc, ' valence band maximum (eV):', band_edges%VBM*evolt
2194 179 : WRITE (u, print_format) scf_gw_soc, ' conduction band minimum (eV):', band_edges%CBM*evolt
2195 179 : WRITE (u, print_format) scf_gw_soc, ' indirect band gap (eV):', band_edges%IDBG*evolt
2196 179 : WRITE (u, print_format) scf_gw_soc, ' direct band gap (eV):', band_edges%DBG*evolt
2197 : END IF
2198 :
2199 358 : CALL timestop(handle)
2200 :
2201 358 : END SUBROUTINE write_band_edges
2202 :
2203 : ! **************************************************************************************************
2204 : !> \brief ...
2205 : !> \param DOS ...
2206 : !> \param PDOS ...
2207 : !> \param bs_env ...
2208 : !> \param qs_env ...
2209 : !> \param scf_gw_soc ...
2210 : !> \param E_min ...
2211 : !> \param E_VBM ...
2212 : ! **************************************************************************************************
2213 72 : SUBROUTINE write_dos_pdos(DOS, PDOS, bs_env, qs_env, scf_gw_soc, E_min, E_VBM)
2214 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:) :: DOS
2215 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: PDOS
2216 : TYPE(post_scf_bandstructure_type), POINTER :: bs_env
2217 : TYPE(qs_environment_type), POINTER :: qs_env
2218 : CHARACTER(LEN=*) :: scf_gw_soc
2219 : REAL(KIND=dp) :: E_min, E_VBM
2220 :
2221 : CHARACTER(LEN=*), PARAMETER :: routineN = 'write_dos_pdos'
2222 :
2223 : CHARACTER(LEN=3), DIMENSION(100) :: elements
2224 : CHARACTER(LEN=default_string_length) :: atom_name, fname, output_string
2225 : INTEGER :: handle, i_E, i_kind, iatom, iunit, n_A, &
2226 : n_E, nkind
2227 : REAL(KIND=dp) :: energy
2228 72 : TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
2229 :
2230 72 : CALL timeset(routineN, handle)
2231 :
2232 72 : WRITE (fname, "(3A)") "DOS_PDOS_", scf_gw_soc, ".out"
2233 :
2234 72 : n_E = SIZE(PDOS, 1)
2235 72 : nkind = SIZE(PDOS, 2)
2236 72 : CALL get_qs_env(qs_env, particle_set=particle_set)
2237 :
2238 72 : IF (bs_env%para_env%is_source()) THEN
2239 :
2240 36 : CALL open_file(TRIM(fname), unit_number=iunit, file_status="REPLACE", file_action="WRITE")
2241 :
2242 36 : n_A = 2 + nkind
2243 :
2244 140 : DO iatom = 1, bs_env%n_atom
2245 : CALL get_atomic_kind(atomic_kind=particle_set(iatom)%atomic_kind, &
2246 104 : kind_number=i_kind, name=atom_name)
2247 140 : elements(i_kind) = atom_name(1:3)
2248 : END DO
2249 :
2250 36 : WRITE (output_string, "(A,I1,A)") "(", n_A, "A)"
2251 :
2252 36 : WRITE (iunit, TRIM(output_string)) "Energy-E_F (eV) DOS (1/eV) PDOS (1/eV) ", &
2253 72 : " of atom type ", elements(1:nkind)
2254 :
2255 36 : WRITE (output_string, "(A,I1,A)") "(", n_A, "F13.5)"
2256 :
2257 73686 : DO i_E = 1, n_E
2258 : ! energy is relative to valence band maximum => - E_VBM
2259 73650 : energy = E_min + i_E*bs_env%energy_step_DOS - E_VBM
2260 220986 : WRITE (iunit, TRIM(output_string)) energy*evolt, DOS(i_E)/evolt, PDOS(i_E, :)/evolt
2261 : END DO
2262 :
2263 36 : CALL close_file(iunit)
2264 :
2265 : END IF
2266 :
2267 72 : CALL timestop(handle)
2268 :
2269 72 : END SUBROUTINE write_dos_pdos
2270 :
2271 : ! **************************************************************************************************
2272 : !> \brief ...
2273 : !> \param energy ...
2274 : !> \param broadening ...
2275 : !> \return ...
2276 : ! **************************************************************************************************
2277 70597222 : PURE FUNCTION Gaussian(energy, broadening)
2278 :
2279 : REAL(KIND=dp), INTENT(IN) :: energy, broadening
2280 : REAL(KIND=dp) :: Gaussian
2281 :
2282 70597222 : IF (ABS(energy) < 5*broadening) THEN
2283 111792 : Gaussian = 1.0_dp/broadening/SQRT(twopi)*EXP(-0.5_dp*energy**2/broadening**2)
2284 : ELSE
2285 : Gaussian = 0.0_dp
2286 : END IF
2287 :
2288 70597222 : END FUNCTION Gaussian
2289 :
2290 : ! **************************************************************************************************
2291 : !> \brief ...
2292 : !> \param proj_mo_on_kind ...
2293 : !> \param qs_env ...
2294 : !> \param cfm_mos ...
2295 : !> \param cfm_s ...
2296 : ! **************************************************************************************************
2297 466 : SUBROUTINE compute_proj_mo_on_kind(proj_mo_on_kind, qs_env, cfm_mos, cfm_s)
2298 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: proj_mo_on_kind
2299 : TYPE(qs_environment_type), POINTER :: qs_env
2300 : TYPE(cp_cfm_type) :: cfm_mos, cfm_s
2301 :
2302 : CHARACTER(LEN=*), PARAMETER :: routineN = 'compute_proj_mo_on_kind'
2303 :
2304 : INTEGER :: handle, i_atom, i_global, i_kind, i_row, &
2305 : j_col, n_ao, n_mo, ncol_local, nkind, &
2306 : nrow_local
2307 466 : INTEGER, ALLOCATABLE, DIMENSION(:) :: atom_from_bf, kind_of
2308 466 : INTEGER, DIMENSION(:), POINTER :: col_indices, row_indices
2309 466 : TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set
2310 : TYPE(cp_cfm_type) :: cfm_proj, cfm_s_i_kind, cfm_work
2311 : TYPE(cp_fm_type) :: fm_proj_im, fm_proj_re
2312 :
2313 466 : CALL timeset(routineN, handle)
2314 :
2315 466 : CALL get_qs_env(qs_env, atomic_kind_set=atomic_kind_set, nkind=nkind)
2316 466 : CALL get_atomic_kind_set(atomic_kind_set, kind_of=kind_of)
2317 :
2318 : CALL cp_cfm_get_info(matrix=cfm_mos, &
2319 : nrow_global=n_mo, &
2320 : nrow_local=nrow_local, &
2321 : ncol_local=ncol_local, &
2322 : row_indices=row_indices, &
2323 466 : col_indices=col_indices)
2324 :
2325 466 : n_ao = qs_env%bs_env%n_ao
2326 :
2327 1398 : ALLOCATE (atom_from_bf(n_ao))
2328 466 : CALL get_atom_index_from_basis_function_index(qs_env, atom_from_bf, n_ao, "ORB")
2329 :
2330 466 : proj_mo_on_kind(:, :) = 0.0_dp
2331 :
2332 466 : CALL cp_cfm_create(cfm_s_i_kind, cfm_s%matrix_struct)
2333 466 : CALL cp_cfm_create(cfm_work, cfm_s%matrix_struct)
2334 466 : CALL cp_cfm_create(cfm_proj, cfm_s%matrix_struct)
2335 466 : CALL cp_fm_create(fm_proj_re, cfm_s%matrix_struct)
2336 466 : CALL cp_fm_create(fm_proj_im, cfm_s%matrix_struct)
2337 :
2338 1286 : DO i_kind = 1, nkind
2339 :
2340 820 : CALL cp_cfm_to_cfm(cfm_s, cfm_s_i_kind)
2341 :
2342 : ! set entries in overlap matrix to zero which do not belong to atoms of i_kind
2343 10676 : DO j_col = 1, ncol_local
2344 74010 : DO i_row = 1, nrow_local
2345 :
2346 63334 : i_global = row_indices(i_row)
2347 :
2348 63334 : IF (i_global <= n_ao) THEN
2349 63334 : i_atom = atom_from_bf(i_global)
2350 0 : ELSE IF (i_global <= 2*n_ao) THEN
2351 0 : i_atom = atom_from_bf(i_global - n_ao)
2352 : ELSE
2353 0 : CPABORT("Wrong indices.")
2354 : END IF
2355 :
2356 73190 : IF (i_kind /= kind_of(i_atom)) THEN
2357 28849 : cfm_s_i_kind%local_data(i_row, j_col) = z_zero
2358 : END IF
2359 :
2360 : END DO
2361 : END DO
2362 :
2363 : CALL parallel_gemm('N', 'N', n_mo, n_mo, n_mo, z_one, &
2364 820 : cfm_s_i_kind, cfm_mos, z_zero, cfm_work)
2365 : CALL parallel_gemm('C', 'N', n_mo, n_mo, n_mo, z_one, &
2366 820 : cfm_mos, cfm_work, z_zero, cfm_proj)
2367 :
2368 820 : CALL cp_cfm_to_fm(cfm_proj, fm_proj_re, fm_proj_im)
2369 :
2370 820 : CALL cp_fm_get_diag(fm_proj_im, proj_mo_on_kind(:, i_kind))
2371 1286 : CALL cp_fm_get_diag(fm_proj_re, proj_mo_on_kind(:, i_kind))
2372 :
2373 : END DO ! i_kind
2374 :
2375 466 : CALL cp_cfm_release(cfm_s_i_kind)
2376 466 : CALL cp_cfm_release(cfm_work)
2377 466 : CALL cp_cfm_release(cfm_proj)
2378 466 : CALL cp_fm_release(fm_proj_re)
2379 466 : CALL cp_fm_release(fm_proj_im)
2380 :
2381 466 : CALL timestop(handle)
2382 :
2383 1864 : END SUBROUTINE compute_proj_mo_on_kind
2384 :
2385 : ! **************************************************************************************************
2386 : !> \brief ...
2387 : !> \param cfm_spinor_ikp ...
2388 : !> \param cfm_spinor_Gamma ...
2389 : !> \param fm_struct_non_spinor ...
2390 : !> \param ikp ...
2391 : !> \param qs_env ...
2392 : !> \param kpoints ...
2393 : !> \param basis_type ...
2394 : ! **************************************************************************************************
2395 120 : SUBROUTINE cfm_ikp_from_cfm_spinor_Gamma(cfm_spinor_ikp, cfm_spinor_Gamma, fm_struct_non_spinor, &
2396 : ikp, qs_env, kpoints, basis_type)
2397 : TYPE(cp_cfm_type) :: cfm_spinor_ikp, cfm_spinor_Gamma
2398 : TYPE(cp_fm_struct_type), POINTER :: fm_struct_non_spinor
2399 : INTEGER :: ikp
2400 : TYPE(qs_environment_type), POINTER :: qs_env
2401 : TYPE(kpoint_type), POINTER :: kpoints
2402 : CHARACTER(LEN=*) :: basis_type
2403 :
2404 : CHARACTER(LEN=*), PARAMETER :: routineN = 'cfm_ikp_from_cfm_spinor_Gamma'
2405 :
2406 : INTEGER :: handle, i_block, i_offset, j_block, &
2407 : j_offset, n_ao
2408 : TYPE(cp_cfm_type) :: cfm_non_spinor_Gamma, cfm_non_spinor_ikp
2409 : TYPE(cp_fm_type) :: fm_non_spinor_Gamma_im, &
2410 : fm_non_spinor_Gamma_re
2411 :
2412 20 : CALL timeset(routineN, handle)
2413 :
2414 20 : CALL cp_cfm_create(cfm_non_spinor_Gamma, fm_struct_non_spinor)
2415 20 : CALL cp_cfm_create(cfm_non_spinor_ikp, fm_struct_non_spinor)
2416 20 : CALL cp_fm_create(fm_non_spinor_Gamma_re, fm_struct_non_spinor)
2417 20 : CALL cp_fm_create(fm_non_spinor_Gamma_im, fm_struct_non_spinor)
2418 :
2419 20 : CALL cp_cfm_get_info(cfm_non_spinor_Gamma, nrow_global=n_ao)
2420 :
2421 20 : CALL cp_cfm_set_all(cfm_spinor_ikp, z_zero)
2422 :
2423 60 : DO i_block = 0, 1
2424 140 : DO j_block = 0, 1
2425 80 : i_offset = i_block*n_ao + 1
2426 80 : j_offset = j_block*n_ao + 1
2427 80 : CALL get_cfm_submat(cfm_non_spinor_Gamma, cfm_spinor_Gamma, i_offset, j_offset)
2428 80 : CALL cp_cfm_to_fm(cfm_non_spinor_Gamma, fm_non_spinor_Gamma_re, fm_non_spinor_Gamma_im)
2429 :
2430 : ! transform real part of Gamma-point matrix to ikp
2431 : CALL cfm_ikp_from_fm_Gamma(cfm_non_spinor_ikp, fm_non_spinor_Gamma_re, &
2432 80 : ikp, qs_env, kpoints, basis_type)
2433 80 : CALL add_cfm_submat(cfm_spinor_ikp, cfm_non_spinor_ikp, i_offset, j_offset)
2434 :
2435 : ! transform imag part of Gamma-point matrix to ikp
2436 : CALL cfm_ikp_from_fm_Gamma(cfm_non_spinor_ikp, fm_non_spinor_Gamma_im, &
2437 80 : ikp, qs_env, kpoints, basis_type)
2438 120 : CALL add_cfm_submat(cfm_spinor_ikp, cfm_non_spinor_ikp, i_offset, j_offset, gaussi)
2439 :
2440 : END DO
2441 : END DO
2442 :
2443 20 : CALL cp_cfm_release(cfm_non_spinor_Gamma)
2444 20 : CALL cp_cfm_release(cfm_non_spinor_ikp)
2445 20 : CALL cp_fm_release(fm_non_spinor_Gamma_re)
2446 20 : CALL cp_fm_release(fm_non_spinor_Gamma_im)
2447 :
2448 20 : CALL timestop(handle)
2449 :
2450 20 : END SUBROUTINE cfm_ikp_from_cfm_spinor_Gamma
2451 :
2452 : ! **************************************************************************************************
2453 : !> \brief ...
2454 : !> \param cfm_ikp ...
2455 : !> \param fm_Gamma ...
2456 : !> \param ikp ...
2457 : !> \param qs_env ...
2458 : !> \param kpoints ...
2459 : !> \param basis_type ...
2460 : ! **************************************************************************************************
2461 7076 : SUBROUTINE cfm_ikp_from_fm_Gamma(cfm_ikp, fm_Gamma, ikp, qs_env, kpoints, basis_type)
2462 : TYPE(cp_cfm_type) :: cfm_ikp
2463 : TYPE(cp_fm_type) :: fm_Gamma
2464 : INTEGER :: ikp
2465 : TYPE(qs_environment_type), POINTER :: qs_env
2466 : TYPE(kpoint_type), POINTER :: kpoints
2467 : CHARACTER(LEN=*) :: basis_type
2468 :
2469 : CHARACTER(LEN=*), PARAMETER :: routineN = 'cfm_ikp_from_fm_Gamma'
2470 :
2471 : INTEGER :: col_global, handle, i_atom, i_atom_old, i_cell, i_mic_cell, i_row, j_atom, &
2472 : j_atom_old, j_cell, j_col, n_bf, ncol_local, nrow_local, num_cells, row_global
2473 7076 : INTEGER, ALLOCATABLE, DIMENSION(:) :: atom_from_bf
2474 7076 : INTEGER, DIMENSION(:), POINTER :: col_indices, row_indices
2475 7076 : INTEGER, DIMENSION(:, :), POINTER :: index_to_cell
2476 : LOGICAL :: i_cell_is_the_minimum_image_cell
2477 : REAL(KIND=dp) :: abs_rab_cell_i, abs_rab_cell_j, arg
2478 : REAL(KIND=dp), DIMENSION(3) :: cell_vector, cell_vector_j, rab_cell_i, &
2479 : rab_cell_j
2480 : REAL(KIND=dp), DIMENSION(3, 3) :: hmat
2481 : TYPE(cell_type), POINTER :: cell
2482 7076 : TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
2483 :
2484 7076 : CALL timeset(routineN, handle)
2485 :
2486 7076 : IF (.NOT. ASSOCIATED(cfm_ikp%local_data)) THEN
2487 2860 : CALL cp_cfm_create(cfm_ikp, fm_Gamma%matrix_struct)
2488 : END IF
2489 7076 : CALL cp_cfm_set_all(cfm_ikp, z_zero)
2490 :
2491 : CALL cp_fm_get_info(matrix=fm_Gamma, &
2492 : nrow_local=nrow_local, &
2493 : ncol_local=ncol_local, &
2494 : row_indices=row_indices, &
2495 7076 : col_indices=col_indices)
2496 :
2497 : ! get number of basis functions (bf) for different basis sets
2498 7076 : IF (basis_type == "ORB") THEN
2499 4656 : n_bf = qs_env%bs_env%n_ao
2500 2420 : ELSE IF (basis_type == "RI_AUX") THEN
2501 2420 : n_bf = qs_env%bs_env%n_RI
2502 : ELSE
2503 0 : CPABORT("Only ORB and RI_AUX basis implemented.")
2504 : END IF
2505 :
2506 21228 : ALLOCATE (atom_from_bf(n_bf))
2507 7076 : CALL get_atom_index_from_basis_function_index(qs_env, atom_from_bf, n_bf, basis_type)
2508 :
2509 7076 : NULLIFY (cell, particle_set)
2510 7076 : CALL get_qs_env(qs_env, cell=cell, particle_set=particle_set)
2511 7076 : CALL get_cell(cell=cell, h=hmat)
2512 :
2513 7076 : index_to_cell => kpoints%index_to_cell
2514 :
2515 7076 : num_cells = SIZE(index_to_cell, 2)
2516 7076 : i_atom_old = 0
2517 7076 : j_atom_old = 0
2518 :
2519 107916 : DO j_col = 1, ncol_local
2520 1398502 : DO i_row = 1, nrow_local
2521 :
2522 1290586 : row_global = row_indices(i_row)
2523 1290586 : col_global = col_indices(j_col)
2524 :
2525 1290586 : i_atom = atom_from_bf(row_global)
2526 1290586 : j_atom = atom_from_bf(col_global)
2527 :
2528 : ! we only need to check for new MIC cell for new i_atom-j_atom pair
2529 1290586 : IF (i_atom /= i_atom_old .OR. j_atom /= j_atom_old) THEN
2530 756984 : DO i_cell = 1, num_cells
2531 :
2532 : ! only check nearest neigbors
2533 1871888 : IF (ANY(ABS(index_to_cell(1:3, i_cell)) > 1)) CYCLE
2534 :
2535 6033280 : cell_vector(1:3) = MATMUL(hmat, REAL(index_to_cell(1:3, i_cell), dp))
2536 :
2537 : rab_cell_i(1:3) = pbc(particle_set(i_atom)%r(1:3), cell) - &
2538 1508320 : (pbc(particle_set(j_atom)%r(1:3), cell) + cell_vector(1:3))
2539 377080 : abs_rab_cell_i = SQRT(rab_cell_i(1)**2 + rab_cell_i(2)**2 + rab_cell_i(3)**2)
2540 :
2541 : ! minimum image convention
2542 377080 : i_cell_is_the_minimum_image_cell = .TRUE.
2543 3796088 : DO j_cell = 1, num_cells
2544 54704128 : cell_vector_j(1:3) = MATMUL(hmat, REAL(index_to_cell(1:3, j_cell), dp))
2545 : rab_cell_j(1:3) = pbc(particle_set(i_atom)%r(1:3), cell) - &
2546 13676032 : (pbc(particle_set(j_atom)%r(1:3), cell) + cell_vector_j(1:3))
2547 3419008 : abs_rab_cell_j = SQRT(rab_cell_j(1)**2 + rab_cell_j(2)**2 + rab_cell_j(3)**2)
2548 :
2549 3796088 : IF (abs_rab_cell_i > abs_rab_cell_j + 1.0E-6_dp) THEN
2550 676826 : i_cell_is_the_minimum_image_cell = .FALSE.
2551 : END IF
2552 : END DO
2553 :
2554 573312 : IF (i_cell_is_the_minimum_image_cell) THEN
2555 196232 : i_mic_cell = i_cell
2556 : END IF
2557 :
2558 : END DO ! i_cell
2559 : END IF
2560 :
2561 : arg = REAL(index_to_cell(1, i_mic_cell), dp)*kpoints%xkp(1, ikp) + &
2562 : REAL(index_to_cell(2, i_mic_cell), dp)*kpoints%xkp(2, ikp) + &
2563 1290586 : REAL(index_to_cell(3, i_mic_cell), dp)*kpoints%xkp(3, ikp)
2564 :
2565 : cfm_ikp%local_data(i_row, j_col) = COS(twopi*arg)*fm_Gamma%local_data(i_row, j_col)*z_one + &
2566 1290586 : SIN(twopi*arg)*fm_Gamma%local_data(i_row, j_col)*gaussi
2567 :
2568 1290586 : j_atom_old = j_atom
2569 1391426 : i_atom_old = i_atom
2570 :
2571 : END DO ! j_col
2572 : END DO ! i_row
2573 :
2574 7076 : CALL timestop(handle)
2575 :
2576 21228 : END SUBROUTINE cfm_ikp_from_fm_Gamma
2577 :
2578 : ! **************************************************************************************************
2579 : !> \brief ...
2580 : !> \param bs_env ...
2581 : !> \param qs_env ...
2582 : !> \param fm_W_MIC_freq_j ...
2583 : !> \param cfm_W_ikp_freq_j ...
2584 : !> \param ikp ...
2585 : !> \param kpoints ...
2586 : !> \param basis_type ...
2587 : !> \param wkp_ext ...
2588 : ! **************************************************************************************************
2589 2484 : SUBROUTINE MIC_contribution_from_ikp(bs_env, qs_env, fm_W_MIC_freq_j, &
2590 : cfm_W_ikp_freq_j, ikp, kpoints, basis_type, wkp_ext)
2591 : TYPE(post_scf_bandstructure_type), POINTER :: bs_env
2592 : TYPE(qs_environment_type), POINTER :: qs_env
2593 : TYPE(cp_fm_type) :: fm_W_MIC_freq_j
2594 : TYPE(cp_cfm_type) :: cfm_W_ikp_freq_j
2595 : INTEGER, INTENT(IN) :: ikp
2596 : TYPE(kpoint_type), POINTER :: kpoints
2597 : CHARACTER(LEN=*) :: basis_type
2598 : REAL(KIND=dp), OPTIONAL :: wkp_ext
2599 :
2600 : CHARACTER(LEN=*), PARAMETER :: routineN = 'MIC_contribution_from_ikp'
2601 :
2602 : INTEGER :: handle, i_bf, iatom, iatom_old, irow, &
2603 : j_bf, jatom, jatom_old, jcol, n_bf, &
2604 : ncol_local, nrow_local, num_cells
2605 2484 : INTEGER, ALLOCATABLE, DIMENSION(:) :: atom_from_bf_index
2606 2484 : INTEGER, DIMENSION(:), POINTER :: col_indices, row_indices
2607 2484 : INTEGER, DIMENSION(:, :), POINTER :: index_to_cell
2608 : REAL(KIND=dp) :: contribution, weight_im, weight_re, &
2609 : wkp_of_ikp
2610 : REAL(KIND=dp), DIMENSION(3, 3) :: hmat
2611 2484 : REAL(KIND=dp), DIMENSION(:), POINTER :: wkp
2612 2484 : REAL(KIND=dp), DIMENSION(:, :), POINTER :: xkp
2613 : TYPE(cell_type), POINTER :: cell
2614 2484 : TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
2615 :
2616 2484 : CALL timeset(routineN, handle)
2617 :
2618 : ! get number of basis functions (bf) for different basis sets
2619 2484 : IF (basis_type == "ORB") THEN
2620 32 : n_bf = qs_env%bs_env%n_ao
2621 2452 : ELSE IF (basis_type == "RI_AUX") THEN
2622 2452 : n_bf = qs_env%bs_env%n_RI
2623 : ELSE
2624 0 : CPABORT("Only ORB and RI_AUX basis implemented.")
2625 : END IF
2626 :
2627 7452 : ALLOCATE (atom_from_bf_index(n_bf))
2628 2484 : CALL get_atom_index_from_basis_function_index(qs_env, atom_from_bf_index, n_bf, basis_type)
2629 :
2630 2484 : NULLIFY (cell, particle_set)
2631 2484 : CALL get_qs_env(qs_env, cell=cell, particle_set=particle_set)
2632 2484 : CALL get_cell(cell=cell, h=hmat)
2633 :
2634 : CALL cp_cfm_get_info(matrix=cfm_W_ikp_freq_j, &
2635 : nrow_local=nrow_local, &
2636 : ncol_local=ncol_local, &
2637 : row_indices=row_indices, &
2638 2484 : col_indices=col_indices)
2639 :
2640 2484 : CALL get_kpoint_info(kpoints, xkp=xkp, wkp=wkp)
2641 2484 : index_to_cell => kpoints%index_to_cell
2642 2484 : num_cells = SIZE(index_to_cell, 2)
2643 :
2644 2484 : iatom_old = 0
2645 2484 : jatom_old = 0
2646 :
2647 56384 : DO jcol = 1, ncol_local
2648 1066438 : DO irow = 1, nrow_local
2649 :
2650 1010054 : i_bf = row_indices(irow)
2651 1010054 : j_bf = col_indices(jcol)
2652 :
2653 1010054 : iatom = atom_from_bf_index(i_bf)
2654 1010054 : jatom = atom_from_bf_index(j_bf)
2655 :
2656 1010054 : IF (PRESENT(wkp_ext)) THEN
2657 3496 : wkp_of_ikp = wkp_ext
2658 : ELSE
2659 1040270 : SELECT CASE (bs_env%l_RI(i_bf) + bs_env%l_RI(j_bf))
2660 : CASE (0)
2661 : ! both RI functions are s-functions, k-extrapolation for 2D and 3D
2662 33712 : wkp_of_ikp = wkp(ikp)
2663 : CASE (1)
2664 : ! one function is an s-function, the other a p-function, k-extrapolation for 3D
2665 144552 : wkp_of_ikp = bs_env%wkp_s_p(ikp)
2666 : CASE DEFAULT
2667 : ! for any other matrix element of W, there is no need for extrapolation
2668 1006558 : wkp_of_ikp = bs_env%wkp_no_extra(ikp)
2669 : END SELECT
2670 : END IF
2671 :
2672 1010054 : IF (iatom /= iatom_old .OR. jatom /= jatom_old) THEN
2673 :
2674 : CALL compute_weight_re_im(weight_re, weight_im, &
2675 : num_cells, iatom, jatom, xkp(1:3, ikp), wkp_of_ikp, &
2676 104552 : cell, index_to_cell, hmat, particle_set)
2677 :
2678 104552 : iatom_old = iatom
2679 104552 : jatom_old = jatom
2680 :
2681 : END IF
2682 :
2683 : contribution = weight_re*REAL(cfm_W_ikp_freq_j%local_data(irow, jcol)) + &
2684 1010054 : weight_im*AIMAG(cfm_W_ikp_freq_j%local_data(irow, jcol))
2685 :
2686 : fm_W_MIC_freq_j%local_data(irow, jcol) = fm_W_MIC_freq_j%local_data(irow, jcol) &
2687 1063954 : + contribution
2688 :
2689 : END DO
2690 : END DO
2691 :
2692 2484 : CALL timestop(handle)
2693 :
2694 7452 : END SUBROUTINE MIC_contribution_from_ikp
2695 :
2696 : ! **************************************************************************************************
2697 : !> \brief ...
2698 : !> \param xkp ...
2699 : !> \param ikp_start ...
2700 : !> \param ikp_end ...
2701 : !> \param grid ...
2702 : ! **************************************************************************************************
2703 124 : SUBROUTINE compute_xkp(xkp, ikp_start, ikp_end, grid)
2704 :
2705 : REAL(KIND=dp), DIMENSION(:, :), POINTER :: xkp
2706 : INTEGER :: ikp_start, ikp_end
2707 : INTEGER, DIMENSION(3) :: grid
2708 :
2709 : CHARACTER(LEN=*), PARAMETER :: routineN = 'compute_xkp'
2710 :
2711 : INTEGER :: handle, i, ix, iy, iz
2712 :
2713 124 : CALL timeset(routineN, handle)
2714 :
2715 124 : i = ikp_start
2716 276 : DO ix = 1, grid(1)
2717 620 : DO iy = 1, grid(2)
2718 1186 : DO iz = 1, grid(3)
2719 :
2720 690 : IF (i > ikp_end) CYCLE
2721 :
2722 672 : xkp(1, i) = REAL(2*ix - grid(1) - 1, KIND=dp)/(2._dp*REAL(grid(1), KIND=dp))
2723 672 : xkp(2, i) = REAL(2*iy - grid(2) - 1, KIND=dp)/(2._dp*REAL(grid(2), KIND=dp))
2724 672 : xkp(3, i) = REAL(2*iz - grid(3) - 1, KIND=dp)/(2._dp*REAL(grid(3), KIND=dp))
2725 1034 : i = i + 1
2726 :
2727 : END DO
2728 : END DO
2729 : END DO
2730 :
2731 124 : CALL timestop(handle)
2732 :
2733 124 : END SUBROUTINE compute_xkp
2734 :
2735 : ! **************************************************************************************************
2736 : !> \brief ...
2737 : !> \param kpoints ...
2738 : !> \param qs_env ...
2739 : ! **************************************************************************************************
2740 176 : SUBROUTINE kpoint_init_cell_index_simple(kpoints, qs_env)
2741 :
2742 : TYPE(kpoint_type), POINTER :: kpoints
2743 : TYPE(qs_environment_type), POINTER :: qs_env
2744 :
2745 : CHARACTER(LEN=*), PARAMETER :: routineN = 'kpoint_init_cell_index_simple'
2746 :
2747 : INTEGER :: handle, nimages
2748 : TYPE(mp_para_env_type), POINTER :: para_env
2749 : TYPE(neighbor_list_set_p_type), DIMENSION(:), &
2750 88 : POINTER :: sab_orb
2751 :
2752 88 : CALL timeset(routineN, handle)
2753 :
2754 88 : NULLIFY (para_env, sab_orb)
2755 88 : CALL get_qs_env(qs_env=qs_env, para_env=para_env, sab_orb=sab_orb)
2756 88 : CALL kpoint_init_cell_index(kpoints, sab_orb, para_env, nimages)
2757 :
2758 88 : CALL timestop(handle)
2759 :
2760 88 : END SUBROUTINE kpoint_init_cell_index_simple
2761 :
2762 : ! **************************************************************************************************
2763 : !> \brief ...
2764 : !> \param qs_env ...
2765 : !> \param bs_env ...
2766 : ! **************************************************************************************************
2767 22 : SUBROUTINE soc(qs_env, bs_env)
2768 : TYPE(qs_environment_type), POINTER :: qs_env
2769 : TYPE(post_scf_bandstructure_type), POINTER :: bs_env
2770 :
2771 : CHARACTER(LEN=*), PARAMETER :: routineN = 'soc'
2772 :
2773 : INTEGER :: handle
2774 :
2775 22 : CALL timeset(routineN, handle)
2776 :
2777 : ! V^SOC_µν^(α),R = ħ/2 < ϕ_µ cell O | sum_ℓ ΔV_ℓ^SO(r,r') L^(α) | ϕ_ν cell R>, α = x,y,z
2778 : ! see Hartwigsen, Goedecker, Hutter, Eq.(18), (19) (doi.org/10.1103/PhysRevB.58.3641)
2779 22 : CALL V_SOC_xyz_from_pseudopotential(qs_env, bs_env%mat_V_SOC_xyz)
2780 :
2781 : ! Calculate H^SOC_µν,σσ'(k) = sum_α V^SOC_µν^(α)(k)*Pauli-matrix^(α)_σσ'
2782 : ! see Hartwigsen, Goedecker, Hutter, Eq.(18) (doi.org/10.1103/PhysRevB.58.3641)
2783 28 : SELECT CASE (bs_env%small_cell_full_kp_or_large_cell_Gamma)
2784 : CASE (large_cell_Gamma, large_cell_Gamma_ri_rs, non_periodic_ri_rs)
2785 :
2786 : ! H^SOC_µν,σσ' = sum_α V^SOC_µν^(α)*Pauli-matrix^(α)_σσ'
2787 6 : CALL H_KS_spinor_Gamma(bs_env)
2788 :
2789 : CASE (small_cell_full_kp)
2790 :
2791 : ! V^SOC_µν^(α),R -> V^SOC_µν^(α)(k); then calculate spinor H^SOC_µν,σσ'(k) (see above)
2792 22 : CALL H_KS_spinor_kp(qs_env, bs_env)
2793 :
2794 : END SELECT
2795 :
2796 22 : CALL timestop(handle)
2797 :
2798 22 : END SUBROUTINE soc
2799 :
2800 : ! **************************************************************************************************
2801 : !> \brief ...
2802 : !> \param bs_env ...
2803 : ! **************************************************************************************************
2804 6 : SUBROUTINE H_KS_spinor_Gamma(bs_env)
2805 :
2806 : TYPE(post_scf_bandstructure_type), POINTER :: bs_env
2807 :
2808 : CHARACTER(LEN=*), PARAMETER :: routineN = 'H_KS_spinor_Gamma'
2809 :
2810 : INTEGER :: handle, nao, s
2811 : TYPE(cp_fm_struct_type), POINTER :: str
2812 :
2813 6 : CALL timeset(routineN, handle)
2814 :
2815 6 : CALL cp_fm_get_info(bs_env%fm_ks_Gamma(1), nrow_global=nao)
2816 :
2817 12 : ALLOCATE (bs_env%cfm_SOC_spinor_ao(1))
2818 6 : CALL create_cfm_double(bs_env%cfm_SOC_spinor_ao(1), fm_orig=bs_env%fm_ks_Gamma(1))
2819 6 : CALL cp_cfm_set_all(bs_env%cfm_SOC_spinor_ao(1), z_zero)
2820 :
2821 6 : str => bs_env%fm_ks_Gamma(1)%matrix_struct
2822 :
2823 6 : s = nao + 1
2824 :
2825 : ! careful: inside add_dbcsr_submat, mat_V_SOC_xyz is multiplied by i because the real matrix
2826 : ! mat_V_SOC_xyz is antisymmetric as V_SOC matrix is purely imaginary and Hermitian
2827 : ! V_x * sigma_x: sigma_x = ((0,1),(1,0))
2828 : ! ud block (1,s): +i*V_x
2829 : CALL add_dbcsr_submat(bs_env%cfm_SOC_spinor_ao(1), bs_env%mat_V_SOC_xyz(1, 1)%matrix, &
2830 6 : str, 1, s, z_one, .FALSE.)
2831 : ! du block (s,1): +i*V_x
2832 : CALL add_dbcsr_submat(bs_env%cfm_SOC_spinor_ao(1), bs_env%mat_V_SOC_xyz(1, 1)%matrix, &
2833 6 : str, s, 1, z_one, .FALSE.)
2834 :
2835 : ! V_y * sigma_y: sigma_y = ((0,-i),(i,0))
2836 : ! ud block (1,s): i*(i*V_y) = -V_y (extra gaussi factor)
2837 : CALL add_dbcsr_submat(bs_env%cfm_SOC_spinor_ao(1), bs_env%mat_V_SOC_xyz(2, 1)%matrix, &
2838 6 : str, 1, s, gaussi, .FALSE.)
2839 : ! du block (s,1): -i*(i*V_y) = +V_y (extra -gaussi factor)
2840 : CALL add_dbcsr_submat(bs_env%cfm_SOC_spinor_ao(1), bs_env%mat_V_SOC_xyz(2, 1)%matrix, &
2841 6 : str, s, 1, -gaussi, .FALSE.)
2842 :
2843 : ! V_z * sigma_z: sigma_z = ((1,0),(0,-1))
2844 : ! uu block (1,1): +i*V_z
2845 : CALL add_dbcsr_submat(bs_env%cfm_SOC_spinor_ao(1), bs_env%mat_V_SOC_xyz(3, 1)%matrix, &
2846 6 : str, 1, 1, z_one, .FALSE.)
2847 : ! dd block (s,s): -i*V_z
2848 : CALL add_dbcsr_submat(bs_env%cfm_SOC_spinor_ao(1), bs_env%mat_V_SOC_xyz(3, 1)%matrix, &
2849 6 : str, s, s, -z_one, .FALSE.)
2850 :
2851 6 : CALL timestop(handle)
2852 :
2853 6 : END SUBROUTINE H_KS_spinor_Gamma
2854 :
2855 : ! **************************************************************************************************
2856 : !> \brief ...
2857 : !> \param qs_env ...
2858 : !> \param bs_env ...
2859 : ! **************************************************************************************************
2860 32 : SUBROUTINE H_KS_spinor_kp(qs_env, bs_env)
2861 : TYPE(qs_environment_type), POINTER :: qs_env
2862 : TYPE(post_scf_bandstructure_type), POINTER :: bs_env
2863 :
2864 : CHARACTER(LEN=*), PARAMETER :: routineN = 'H_KS_spinor_kp'
2865 :
2866 : INTEGER :: handle, i_dim, ikp, n_spin, &
2867 : nkp_bs_and_DOS, s
2868 16 : INTEGER, DIMENSION(:, :, :), POINTER :: cell_to_index_scf
2869 : REAL(KIND=dp), DIMENSION(3) :: xkp
2870 : TYPE(cp_cfm_type) :: cfm_V_SOC_xyz_ikp
2871 : TYPE(cp_fm_struct_type), POINTER :: str
2872 : TYPE(kpoint_type), POINTER :: kpoints_scf
2873 : TYPE(neighbor_list_set_p_type), DIMENSION(:), &
2874 16 : POINTER :: sab_nl
2875 :
2876 16 : CALL timeset(routineN, handle)
2877 :
2878 16 : nkp_bs_and_DOS = bs_env%nkp_bs_and_DOS
2879 16 : n_spin = bs_env%n_spin
2880 16 : s = bs_env%n_ao + 1
2881 16 : str => bs_env%cfm_ks_kp(1, 1)%matrix_struct
2882 :
2883 16 : CALL cp_cfm_create(cfm_V_SOC_xyz_ikp, bs_env%cfm_work_mo%matrix_struct)
2884 :
2885 16 : CALL alloc_cfm_double_array_1d(bs_env%cfm_SOC_spinor_ao, bs_env%cfm_ks_kp(1, 1), nkp_bs_and_DOS)
2886 :
2887 16 : CALL get_qs_env(qs_env, kpoints=kpoints_scf)
2888 :
2889 16 : NULLIFY (sab_nl)
2890 16 : CALL get_kpoint_info(kpoints_scf, sab_nl=sab_nl, cell_to_index=cell_to_index_scf)
2891 :
2892 64 : DO i_dim = 1, 3
2893 :
2894 1018 : DO ikp = 1, nkp_bs_and_DOS
2895 :
2896 3816 : xkp(1:3) = bs_env%kpoints_DOS%xkp(1:3, ikp)
2897 :
2898 954 : CALL cp_cfm_set_all(cfm_V_SOC_xyz_ikp, z_zero)
2899 :
2900 : CALL rsmat_to_kp(bs_env%mat_V_SOC_xyz, i_dim, xkp, cell_to_index_scf, &
2901 954 : sab_nl, bs_env, cfm_V_SOC_xyz_ikp, imag_rs_mat=.TRUE.)
2902 :
2903 : ! multiply V_SOC with i because bs_env%mat_V_SOC_xyz stores imag. part (real part = 0)
2904 954 : CALL cp_cfm_scale(gaussi, cfm_V_SOC_xyz_ikp)
2905 :
2906 48 : SELECT CASE (i_dim)
2907 : CASE (1)
2908 : ! add V^SOC_x * σ_x for σ_x = ( (0,1) (1,0) )
2909 318 : CALL add_cfm_submat(bs_env%cfm_SOC_spinor_ao(ikp), cfm_V_SOC_xyz_ikp, 1, s)
2910 318 : CALL add_cfm_submat(bs_env%cfm_SOC_spinor_ao(ikp), cfm_V_SOC_xyz_ikp, s, 1)
2911 : CASE (2)
2912 : ! add V^SOC_y * σ_y for σ_y = ( (0,-i) (i,0) )
2913 318 : CALL cp_cfm_scale(gaussi, cfm_V_SOC_xyz_ikp)
2914 318 : CALL add_cfm_submat(bs_env%cfm_SOC_spinor_ao(ikp), cfm_V_SOC_xyz_ikp, 1, s)
2915 318 : CALL cp_cfm_scale(-z_one, cfm_V_SOC_xyz_ikp)
2916 318 : CALL add_cfm_submat(bs_env%cfm_SOC_spinor_ao(ikp), cfm_V_SOC_xyz_ikp, s, 1)
2917 : CASE (3)
2918 : ! add V^SOC_z * σ_z for σ_z = ( (1,0) (0,1) )
2919 318 : CALL add_cfm_submat(bs_env%cfm_SOC_spinor_ao(ikp), cfm_V_SOC_xyz_ikp, 1, 1)
2920 318 : CALL cp_cfm_scale(-z_one, cfm_V_SOC_xyz_ikp)
2921 1272 : CALL add_cfm_submat(bs_env%cfm_SOC_spinor_ao(ikp), cfm_V_SOC_xyz_ikp, s, s)
2922 : END SELECT
2923 :
2924 : END DO
2925 :
2926 : END DO ! ikp
2927 :
2928 16 : CALL cp_cfm_release(cfm_V_SOC_xyz_ikp)
2929 :
2930 16 : CALL timestop(handle)
2931 :
2932 16 : END SUBROUTINE H_KS_spinor_kp
2933 :
2934 : ! **************************************************************************************************
2935 : !> \brief ...
2936 : !> \param cfm_array ...
2937 : !> \param cfm_template ...
2938 : !> \param n ...
2939 : ! **************************************************************************************************
2940 16 : SUBROUTINE alloc_cfm_double_array_1d(cfm_array, cfm_template, n)
2941 : TYPE(cp_cfm_type), ALLOCATABLE, DIMENSION(:) :: cfm_array
2942 : TYPE(cp_cfm_type) :: cfm_template
2943 : INTEGER :: n
2944 :
2945 : CHARACTER(LEN=*), PARAMETER :: routineN = 'alloc_cfm_double_array_1d'
2946 :
2947 : INTEGER :: handle, i
2948 :
2949 16 : CALL timeset(routineN, handle)
2950 :
2951 366 : ALLOCATE (cfm_array(n))
2952 334 : DO i = 1, n
2953 318 : CALL create_cfm_double(cfm_array(i), cfm_orig=cfm_template)
2954 334 : CALL cp_cfm_set_all(cfm_array(i), z_zero)
2955 : END DO
2956 :
2957 16 : CALL timestop(handle)
2958 :
2959 16 : END SUBROUTINE alloc_cfm_double_array_1d
2960 :
2961 : ! **************************************************************************************************
2962 : !> \brief ...
2963 : !> \param bs_env ...
2964 : ! **************************************************************************************************
2965 104 : SUBROUTINE get_all_VBM_CBM_bandgaps(bs_env)
2966 :
2967 : TYPE(post_scf_bandstructure_type), POINTER :: bs_env
2968 :
2969 : CHARACTER(LEN=*), PARAMETER :: routineN = 'get_all_VBM_CBM_bandgaps'
2970 :
2971 : INTEGER :: handle
2972 :
2973 104 : CALL timeset(routineN, handle)
2974 :
2975 104 : CALL get_VBM_CBM_bandgaps(bs_env%band_edges_scf, bs_env%eigenval_scf, bs_env)
2976 104 : CALL get_VBM_CBM_bandgaps(bs_env%band_edges_G0W0, bs_env%eigenval_G0W0, bs_env)
2977 104 : CALL get_VBM_CBM_bandgaps(bs_env%band_edges_HF, bs_env%eigenval_HF, bs_env)
2978 :
2979 104 : CALL check_qp_gap_sanity(bs_env)
2980 :
2981 104 : CALL timestop(handle)
2982 :
2983 104 : END SUBROUTINE get_all_VBM_CBM_bandgaps
2984 :
2985 : ! **************************************************************************************************
2986 : !> \brief Warn if the G0W0 fundamental band gap is inverted or implausibly large, i.e. if the
2987 : !> quasiparticle solve has produced a spectrum that cannot be physical.
2988 : !> \param bs_env ...
2989 : ! **************************************************************************************************
2990 104 : SUBROUTINE check_qp_gap_sanity(bs_env)
2991 :
2992 : TYPE(post_scf_bandstructure_type), POINTER :: bs_env
2993 :
2994 : REAL(KIND=dp) :: gap, gap_scf
2995 :
2996 104 : gap = bs_env%band_edges_G0W0%IDBG
2997 104 : gap_scf = bs_env%band_edges_scf%IDBG
2998 :
2999 : ! requiring a healthy SCF gap keeps the inversion test from firing on a genuine metal
3000 104 : IF (gap < -eps_qp_gap .AND. gap_scf > eps_qp_gap) THEN
3001 : CALL cp_warn(__LOCATION__, &
3002 : "G0W0 band gap is negative ("// &
3003 : TRIM(ADJUSTL(cp_to_string(gap*evolt, '(F12.3)')))//" eV): the quasiparticle "// &
3004 0 : "spectrum is inverted. Check numerical parameters.")
3005 104 : ELSE IF (ABS(gap) > max_qp_gap) THEN
3006 : CALL cp_warn(__LOCATION__, &
3007 : "G0W0 band gap is implausibly large ("// &
3008 : TRIM(ADJUSTL(cp_to_string(gap*evolt, '(F12.3)')))//" eV): the quasiparticle "// &
3009 0 : "solve has likely diverged. Check numerical parameters.")
3010 : END IF
3011 :
3012 104 : END SUBROUTINE check_qp_gap_sanity
3013 :
3014 : ! **************************************************************************************************
3015 : !> \brief ...
3016 : !> \param band_edges ...
3017 : !> \param ev ...
3018 : !> \param bs_env ...
3019 : ! **************************************************************************************************
3020 330 : SUBROUTINE get_VBM_CBM_bandgaps(band_edges, ev, bs_env)
3021 : TYPE(band_edges_type) :: band_edges
3022 : REAL(KIND=dp), DIMENSION(:, :, :) :: ev
3023 : TYPE(post_scf_bandstructure_type), POINTER :: bs_env
3024 :
3025 : CHARACTER(LEN=*), PARAMETER :: routineN = 'get_VBM_CBM_bandgaps'
3026 :
3027 : INTEGER :: handle, homo, homo_1, homo_2, ikp, &
3028 : ispin, lumo, lumo_1, lumo_2, n_mo
3029 : REAL(KIND=dp) :: E_DBG_at_ikp
3030 :
3031 330 : CALL timeset(routineN, handle)
3032 :
3033 330 : n_mo = bs_env%n_ao
3034 :
3035 330 : band_edges%DBG = 1000.0_dp
3036 :
3037 618 : SELECT CASE (bs_env%n_spin)
3038 : CASE (1)
3039 288 : homo = bs_env%n_occ(1)
3040 288 : lumo = homo + 1
3041 7490 : band_edges%VBM = MAXVAL(ev(1:homo, :, 1))
3042 14850 : band_edges%CBM = MINVAL(ev(homo + 1:n_mo, :, 1))
3043 : CASE (2)
3044 42 : homo_1 = bs_env%n_occ(1)
3045 42 : lumo_1 = homo_1 + 1
3046 42 : homo_2 = bs_env%n_occ(2)
3047 42 : lumo_2 = homo_2 + 1
3048 462 : band_edges%VBM = MAX(MAXVAL(ev(1:homo_1, :, 1)), MAXVAL(ev(1:homo_2, :, 2)))
3049 966 : band_edges%CBM = MIN(MINVAL(ev(homo_1 + 1:n_mo, :, 1)), MINVAL(ev(homo_2 + 1:n_mo, :, 2)))
3050 : CASE DEFAULT
3051 330 : CPABORT("Error with number of spins.")
3052 : END SELECT
3053 :
3054 330 : band_edges%IDBG = band_edges%CBM - band_edges%VBM
3055 :
3056 702 : DO ispin = 1, bs_env%n_spin
3057 :
3058 372 : homo = bs_env%n_occ(ispin)
3059 :
3060 2350 : DO ikp = 1, bs_env%nkp_bs_and_DOS
3061 :
3062 21460 : E_DBG_at_ikp = -MAXVAL(ev(1:homo, ikp, ispin)) + MINVAL(ev(homo + 1:n_mo, ikp, ispin))
3063 :
3064 2020 : IF (E_DBG_at_ikp < band_edges%DBG) band_edges%DBG = E_DBG_at_ikp
3065 :
3066 : END DO
3067 :
3068 : END DO
3069 :
3070 330 : CALL timestop(handle)
3071 :
3072 330 : END SUBROUTINE get_VBM_CBM_bandgaps
3073 :
3074 : END MODULE post_scf_bandstructure_utils
|