(git:ed6f26b)
Loading...
Searching...
No Matches
post_scf_bandstructure_utils.F
Go to the documentation of this file.
1!--------------------------------------------------------------------------------------------------!
2! CP2K: A general program to perform molecular dynamics simulations !
3! Copyright 2000-2025 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! **************************************************************************************************
17 USE cell_types, ONLY: cell_type,&
18 get_cell,&
19 pbc
23 USE cp_cfm_diag, ONLY: cp_cfm_geeig,&
26 USE cp_cfm_types, ONLY: cp_cfm_create,&
35 USE cp_dbcsr_api, ONLY: &
37 dbcsr_type, dbcsr_type_antisymmetric, dbcsr_type_no_symmetry, dbcsr_type_symmetric
43 USE cp_files, ONLY: close_file,&
49 USE cp_fm_types, ONLY: cp_fm_create,&
58 USE input_constants, ONLY: int_ldos_z,&
65 USE kinds, ONLY: default_string_length,&
66 dp,&
70 USE kpoint_types, ONLY: get_kpoint_info,&
73 USE machine, ONLY: m_walltime
74 USE mathconstants, ONLY: gaussi,&
75 twopi,&
76 z_one,&
77 z_zero
81 USE physcon, ONLY: angstrom,&
82 evolt
85 USE pw_env_types, ONLY: pw_env_get,&
88 USE pw_types, ONLY: pw_c1d_gs_type,&
94 USE qs_mo_types, ONLY: get_mo_set,&
107#include "base/base_uses.f90"
108
109 IMPLICIT NONE
110
111 PRIVATE
112
113 PUBLIC :: create_and_init_bs_env, &
117
118 CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'post_scf_bandstructure_utils'
119
120CONTAINS
121
122! **************************************************************************************************
123!> \brief ...
124!> \param qs_env ...
125!> \param bs_env ...
126!> \param post_scf_bandstructure_section ...
127! **************************************************************************************************
128 SUBROUTINE create_and_init_bs_env(qs_env, bs_env, post_scf_bandstructure_section)
129 TYPE(qs_environment_type), POINTER :: qs_env
130 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
131 TYPE(section_vals_type), POINTER :: post_scf_bandstructure_section
132
133 CHARACTER(LEN=*), PARAMETER :: routinen = 'create_and_init_bs_env'
134
135 INTEGER :: handle
136
137 CALL timeset(routinen, handle)
138
139 ALLOCATE (bs_env)
140
141 CALL print_header(bs_env)
142
143 CALL read_bandstructure_input_parameters(bs_env, post_scf_bandstructure_section)
144
145 CALL get_parameters_from_qs_env(qs_env, bs_env)
146
147 CALL set_heuristic_parameters(bs_env)
148
149 SELECT CASE (bs_env%small_cell_full_kp_or_large_cell_Gamma)
150 CASE (large_cell_gamma)
151
152 CALL setup_kpoints_dos_large_cell_gamma(qs_env, bs_env, bs_env%kpoints_DOS)
153
154 CALL allocate_and_fill_fm_ks_fm_s(qs_env, bs_env)
155
156 CALL diagonalize_ks_matrix(bs_env)
157
158 CALL check_positive_definite_overlap_mat(bs_env, qs_env)
159
160 CASE (small_cell_full_kp)
161
162 CALL setup_kpoints_scf_desymm(qs_env, bs_env, bs_env%kpoints_scf_desymm, .true.)
163 CALL setup_kpoints_scf_desymm(qs_env, bs_env, bs_env%kpoints_scf_desymm_2, .false.)
164
165 CALL setup_kpoints_dos_small_cell_full_kp(bs_env, bs_env%kpoints_DOS)
166
167 CALL allocate_and_fill_fm_ks_fm_s(qs_env, bs_env)
168
169 CALL compute_cfm_mo_coeff_kp_and_eigenval_scf_kp(qs_env, bs_env)
170
171 END SELECT
172
173 CALL timestop(handle)
174
175 END SUBROUTINE create_and_init_bs_env
176
177! **************************************************************************************************
178!> \brief ...
179!> \param bs_env ...
180!> \param bs_sec ...
181! **************************************************************************************************
182 SUBROUTINE read_bandstructure_input_parameters(bs_env, bs_sec)
183 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
184 TYPE(section_vals_type), POINTER :: bs_sec
185
186 CHARACTER(LEN=*), PARAMETER :: routinen = 'read_bandstructure_input_parameters'
187
188 CHARACTER(LEN=default_string_length), &
189 DIMENSION(:), POINTER :: string_ptr
190 CHARACTER(LEN=max_line_length) :: error_msg
191 INTEGER :: handle, i, ikp
192 TYPE(section_vals_type), POINTER :: gw_sec, kp_bs_sec, ldos_sec, soc_sec
193
194 CALL timeset(routinen, handle)
195
196 NULLIFY (gw_sec)
197 gw_sec => section_vals_get_subs_vals(bs_sec, "GW")
198 CALL section_vals_get(gw_sec, explicit=bs_env%do_gw)
199
200 NULLIFY (soc_sec)
201 soc_sec => section_vals_get_subs_vals(bs_sec, "SOC")
202 CALL section_vals_get(soc_sec, explicit=bs_env%do_soc)
203
204 CALL section_vals_val_get(soc_sec, "ENERGY_WINDOW", r_val=bs_env%energy_window_soc)
205
206 CALL section_vals_val_get(bs_sec, "DOS%KPOINTS", i_vals=bs_env%nkp_grid_DOS_input)
207 CALL section_vals_val_get(bs_sec, "DOS%ENERGY_WINDOW", r_val=bs_env%energy_window_DOS)
208 CALL section_vals_val_get(bs_sec, "DOS%ENERGY_STEP", r_val=bs_env%energy_step_DOS)
209 CALL section_vals_val_get(bs_sec, "DOS%BROADENING", r_val=bs_env%broadening_DOS)
210
211 NULLIFY (ldos_sec)
212 ldos_sec => section_vals_get_subs_vals(bs_sec, "DOS%LDOS")
213 CALL section_vals_get(ldos_sec, explicit=bs_env%do_ldos)
214
215 CALL section_vals_val_get(ldos_sec, "INTEGRATION", i_val=bs_env%int_ldos_xyz)
216 CALL section_vals_val_get(ldos_sec, "BIN_MESH", i_vals=bs_env%bin_mesh)
217
218 NULLIFY (kp_bs_sec)
219 kp_bs_sec => section_vals_get_subs_vals(bs_sec, "BANDSTRUCTURE_PATH")
220 CALL section_vals_val_get(kp_bs_sec, "NPOINTS", i_val=bs_env%input_kp_bs_npoints)
221 CALL section_vals_val_get(kp_bs_sec, "SPECIAL_POINT", n_rep_val=bs_env%input_kp_bs_n_sp_pts)
222
223 ! read special points for band structure
224 ALLOCATE (bs_env%xkp_special(3, bs_env%input_kp_bs_n_sp_pts))
225 DO ikp = 1, bs_env%input_kp_bs_n_sp_pts
226 CALL section_vals_val_get(kp_bs_sec, "SPECIAL_POINT", i_rep_val=ikp, c_vals=string_ptr)
227 cpassert(SIZE(string_ptr(:), 1) == 4)
228 DO i = 1, 3
229 CALL read_float_object(string_ptr(i + 1), bs_env%xkp_special(i, ikp), error_msg)
230 IF (len_trim(error_msg) > 0) cpabort(trim(error_msg))
231 END DO
232 END DO
233
234 CALL timestop(handle)
235
236 END SUBROUTINE read_bandstructure_input_parameters
237
238! **************************************************************************************************
239!> \brief ...
240!> \param bs_env ...
241! **************************************************************************************************
242 SUBROUTINE print_header(bs_env)
243
244 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
245
246 CHARACTER(LEN=*), PARAMETER :: routinen = 'print_header'
247
248 INTEGER :: handle, u
249
250 CALL timeset(routinen, handle)
251
252 bs_env%unit_nr = cp_logger_get_default_io_unit()
253
254 u = bs_env%unit_nr
255
256 IF (u > 0) THEN
257 WRITE (u, '(T2,A)') ' '
258 WRITE (u, '(T2,A)') repeat('-', 79)
259 WRITE (u, '(T2,A,A78)') '-', '-'
260 WRITE (u, '(T2,A,A51,A27)') '-', 'BANDSTRUCTURE CALCULATION', '-'
261 WRITE (u, '(T2,A,A78)') '-', '-'
262 WRITE (u, '(T2,A)') repeat('-', 79)
263 WRITE (u, '(T2,A)') ' '
264 END IF
265
266 CALL timestop(handle)
267
268 END SUBROUTINE print_header
269
270! **************************************************************************************************
271!> \brief ...
272!> \param qs_env ...
273!> \param bs_env ...
274!> \param kpoints ...
275! **************************************************************************************************
276 SUBROUTINE setup_kpoints_dos_large_cell_gamma(qs_env, bs_env, kpoints)
277
278 TYPE(qs_environment_type), POINTER :: qs_env
279 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
280 TYPE(kpoint_type), POINTER :: kpoints
281
282 CHARACTER(LEN=*), PARAMETER :: routinen = 'setup_kpoints_DOS_large_cell_Gamma'
283
284 INTEGER :: handle, i_dim, i_kp_in_line, &
285 i_special_kp, ikk, n_kp_in_line, &
286 n_special_kp, nkp, nkp_only_bs, &
287 nkp_only_dos, u
288 INTEGER, DIMENSION(3) :: nkp_grid, periodic
289
290 CALL timeset(routinen, handle)
291
292 ! routine adapted from mp2_integrals.F
293 NULLIFY (kpoints)
294 CALL kpoint_create(kpoints)
295
296 kpoints%kp_scheme = "GENERAL"
297
298 n_special_kp = bs_env%input_kp_bs_n_sp_pts
299 n_kp_in_line = bs_env%input_kp_bs_npoints
300
301 periodic(1:3) = bs_env%periodic(1:3)
302
303 DO i_dim = 1, 3
304
305 cpassert(periodic(i_dim) == 0 .OR. periodic(i_dim) == 1)
306
307 IF (bs_env%nkp_grid_DOS_input(i_dim) < 0) THEN
308 IF (periodic(i_dim) == 1) nkp_grid(i_dim) = 2
309 IF (periodic(i_dim) == 0) nkp_grid(i_dim) = 1
310 ELSE
311 nkp_grid(i_dim) = bs_env%nkp_grid_DOS_input(i_dim)
312 END IF
313
314 END DO
315
316 ! use the k <-> -k symmetry to reduce the number of kpoints
317 IF (nkp_grid(1) > 1) THEN
318 nkp_only_dos = (nkp_grid(1) + 1)/2*nkp_grid(2)*nkp_grid(3)
319 ELSE IF (nkp_grid(2) > 1) THEN
320 nkp_only_dos = nkp_grid(1)*(nkp_grid(2) + 1)/2*nkp_grid(3)
321 ELSE IF (nkp_grid(3) > 1) THEN
322 nkp_only_dos = nkp_grid(1)*nkp_grid(2)*(nkp_grid(3) + 1)/2
323 ELSE
324 nkp_only_dos = 1
325 END IF
326
327 ! we will compute the GW QP levels for all k's in the bandstructure path but also
328 ! for all k-points from the SCF (e.g. for DOS or for self-consistent GW)
329 IF (n_special_kp > 0) THEN
330 nkp_only_bs = n_kp_in_line*(n_special_kp - 1) + 1
331 ELSE
332 nkp_only_bs = 0
333 END IF
334
335 nkp = nkp_only_dos + nkp_only_bs
336
337 kpoints%nkp_grid(1:3) = nkp_grid(1:3)
338 kpoints%nkp = nkp
339
340 bs_env%nkp_bs_and_DOS = nkp
341 bs_env%nkp_only_bs = nkp_only_bs
342 bs_env%nkp_only_DOS = nkp_only_dos
343
344 ALLOCATE (kpoints%xkp(3, nkp), kpoints%wkp(nkp))
345 kpoints%wkp(1:nkp_only_dos) = 1.0_dp/real(nkp_only_dos, kind=dp)
346
347 CALL compute_xkp(kpoints%xkp, 1, nkp_only_dos, nkp_grid)
348
349 IF (n_special_kp > 0) THEN
350 kpoints%xkp(1:3, nkp_only_dos + 1) = bs_env%xkp_special(1:3, 1)
351 ikk = nkp_only_dos + 1
352 DO i_special_kp = 2, n_special_kp
353 DO i_kp_in_line = 1, n_kp_in_line
354 ikk = ikk + 1
355 kpoints%xkp(1:3, ikk) = bs_env%xkp_special(1:3, i_special_kp - 1) + &
356 REAL(i_kp_in_line, kind=dp)/real(n_kp_in_line, kind=dp)* &
357 (bs_env%xkp_special(1:3, i_special_kp) - &
358 bs_env%xkp_special(1:3, i_special_kp - 1))
359 kpoints%wkp(ikk) = 0.0_dp
360 END DO
361 END DO
362 END IF
363
364 CALL kpoint_init_cell_index_simple(kpoints, qs_env)
365
366 u = bs_env%unit_nr
367
368 IF (u > 0) THEN
369 IF (nkp_only_bs > 0) THEN
370 WRITE (u, fmt="(T2,1A,T77,I4)") &
371 "Number of special k-points for the bandstructure", n_special_kp
372 WRITE (u, fmt="(T2,1A,T77,I4)") "Number of k-points for the bandstructure", nkp
373 WRITE (u, fmt="(T2,1A,T69,3I4)") &
374 "K-point mesh for the density of states (DOS)", nkp_grid(1:3)
375 ELSE
376 WRITE (u, fmt="(T2,1A,T69,3I4)") &
377 "K-point mesh for the density of states (DOS) and the self-energy", nkp_grid(1:3)
378 END IF
379 END IF
380
381 CALL timestop(handle)
382
383 END SUBROUTINE setup_kpoints_dos_large_cell_gamma
384
385! **************************************************************************************************
386!> \brief ...
387!> \param qs_env ...
388!> \param bs_env ...
389!> \param kpoints ...
390!> \param do_print ...
391! **************************************************************************************************
392 SUBROUTINE setup_kpoints_scf_desymm(qs_env, bs_env, kpoints, do_print)
393 TYPE(qs_environment_type), POINTER :: qs_env
394 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
395 TYPE(kpoint_type), POINTER :: kpoints
396
397 CHARACTER(LEN=*), PARAMETER :: routinen = 'setup_kpoints_scf_desymm'
398
399 INTEGER :: handle, i_cell_x, i_dim, img, j_cell_y, &
400 k_cell_z, nimages, nkp, u
401 INTEGER, DIMENSION(3) :: cell_grid, cixd, nkp_grid
402 TYPE(kpoint_type), POINTER :: kpoints_scf
403
404 LOGICAL:: do_print
405
406 CALL timeset(routinen, handle)
407
408 NULLIFY (kpoints)
409 CALL kpoint_create(kpoints)
410
411 CALL get_qs_env(qs_env=qs_env, kpoints=kpoints_scf)
412
413 nkp_grid(1:3) = kpoints_scf%nkp_grid(1:3)
414 nkp = nkp_grid(1)*nkp_grid(2)*nkp_grid(3)
415
416 ! we need in periodic directions at least 4 k-points in the SCF
417 DO i_dim = 1, 3
418 IF (bs_env%periodic(i_dim) == 1) THEN
419 cpassert(nkp_grid(i_dim) .GE. 4)
420 END IF
421 END DO
422
423 kpoints%kp_scheme = "GENERAL"
424 kpoints%nkp_grid(1:3) = nkp_grid(1:3)
425 kpoints%nkp = nkp
426 bs_env%nkp_scf_desymm = nkp
427
428 ALLOCATE (kpoints%xkp(1:3, nkp))
429 CALL compute_xkp(kpoints%xkp, 1, nkp, nkp_grid)
430
431 ALLOCATE (kpoints%wkp(nkp))
432 kpoints%wkp(:) = 1.0_dp/real(nkp, kind=dp)
433
434 ! for example 4x3x6 kpoint grid -> 3x3x5 cell grid because we need the same number of
435 ! neighbor cells on both sides of the unit cell
436 cell_grid(1:3) = nkp_grid(1:3) - modulo(nkp_grid(1:3) + 1, 2)
437
438 ! cell index: for example for x: from -n_x/2 to +n_x/2, n_x: number of cells in x direction
439 cixd(1:3) = cell_grid(1:3)/2
440
441 nimages = cell_grid(1)*cell_grid(2)*cell_grid(3)
442
443 bs_env%nimages_scf_desymm = nimages
444 bs_env%cell_grid_scf_desymm(1:3) = cell_grid(1:3)
445
446 IF (ASSOCIATED(kpoints%index_to_cell)) DEALLOCATE (kpoints%index_to_cell)
447 IF (ASSOCIATED(kpoints%cell_to_index)) DEALLOCATE (kpoints%cell_to_index)
448
449 ALLOCATE (kpoints%cell_to_index(-cixd(1):cixd(1), -cixd(2):cixd(2), -cixd(3):cixd(3)))
450 ALLOCATE (kpoints%index_to_cell(nimages, 3))
451
452 img = 0
453 DO i_cell_x = -cixd(1), cixd(1)
454 DO j_cell_y = -cixd(2), cixd(2)
455 DO k_cell_z = -cixd(3), cixd(3)
456 img = img + 1
457 kpoints%cell_to_index(i_cell_x, j_cell_y, k_cell_z) = img
458 kpoints%index_to_cell(img, 1:3) = (/i_cell_x, j_cell_y, k_cell_z/)
459 END DO
460 END DO
461 END DO
462
463 u = bs_env%unit_nr
464 IF (u > 0 .AND. do_print) THEN
465 WRITE (u, fmt="(T2,A,I49)") χΣ"Number of cells for G, , W, ", nimages
466 END IF
467
468 CALL timestop(handle)
469
470 END SUBROUTINE setup_kpoints_scf_desymm
471
472! **************************************************************************************************
473!> \brief ...
474!> \param bs_env ...
475!> \param kpoints ...
476! **************************************************************************************************
477 SUBROUTINE setup_kpoints_dos_small_cell_full_kp(bs_env, kpoints)
478
479 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
480 TYPE(kpoint_type), POINTER :: kpoints
481
482 CHARACTER(LEN=*), PARAMETER :: routinen = 'setup_kpoints_DOS_small_cell_full_kp'
483
484 INTEGER :: handle, i_kp_in_line, i_special_kp, ikk, &
485 n_kp_in_line, n_special_kp, nkp, &
486 nkp_only_bs, nkp_scf_desymm, u
487
488 CALL timeset(routinen, handle)
489
490 ! routine adapted from mp2_integrals.F
491 NULLIFY (kpoints)
492 CALL kpoint_create(kpoints)
493
494 n_special_kp = bs_env%input_kp_bs_n_sp_pts
495 n_kp_in_line = bs_env%input_kp_bs_npoints
496 nkp_scf_desymm = bs_env%nkp_scf_desymm
497
498 ! we will compute the GW QP levels for all k's in the bandstructure path but also
499 ! for all k-points from the SCF (e.g. for DOS or for self-consistent GW)
500 IF (n_special_kp > 0) THEN
501 nkp_only_bs = n_kp_in_line*(n_special_kp - 1) + 1
502 ELSE
503 nkp_only_bs = 0
504 END IF
505 nkp = nkp_only_bs + nkp_scf_desymm
506
507 ALLOCATE (kpoints%xkp(3, nkp))
508 ALLOCATE (kpoints%wkp(nkp))
509
510 kpoints%nkp = nkp
511
512 bs_env%nkp_bs_and_DOS = nkp
513 bs_env%nkp_only_bs = nkp_only_bs
514 bs_env%nkp_only_DOS = nkp_scf_desymm
515
516 kpoints%xkp(1:3, 1:nkp_scf_desymm) = bs_env%kpoints_scf_desymm%xkp(1:3, 1:nkp_scf_desymm)
517 kpoints%wkp(1:nkp_scf_desymm) = 1.0_dp/real(nkp_scf_desymm, kind=dp)
518
519 IF (n_special_kp > 0) THEN
520 kpoints%xkp(1:3, nkp_scf_desymm + 1) = bs_env%xkp_special(1:3, 1)
521 ikk = nkp_scf_desymm + 1
522 DO i_special_kp = 2, n_special_kp
523 DO i_kp_in_line = 1, n_kp_in_line
524 ikk = ikk + 1
525 kpoints%xkp(1:3, ikk) = bs_env%xkp_special(1:3, i_special_kp - 1) + &
526 REAL(i_kp_in_line, kind=dp)/real(n_kp_in_line, kind=dp)* &
527 (bs_env%xkp_special(1:3, i_special_kp) - &
528 bs_env%xkp_special(1:3, i_special_kp - 1))
529 kpoints%wkp(ikk) = 0.0_dp
530 END DO
531 END DO
532 END IF
533
534 IF (ASSOCIATED(kpoints%index_to_cell)) DEALLOCATE (kpoints%index_to_cell)
535
536 ALLOCATE (kpoints%index_to_cell(bs_env%nimages_scf_desymm, 3))
537 kpoints%index_to_cell(:, :) = bs_env%kpoints_scf_desymm%index_to_cell(:, :)
538
539 u = bs_env%unit_nr
540
541 IF (u > 0) THEN
542 WRITE (u, fmt="(T2,1A,T77,I4)") "Number of special k-points for the bandstructure", &
543 n_special_kp
544 WRITE (u, fmt="(T2,1A,T77,I4)") "Number of k-points for the bandstructure", nkp
545 END IF
546
547 CALL timestop(handle)
548
549 END SUBROUTINE setup_kpoints_dos_small_cell_full_kp
550
551! **************************************************************************************************
552!> \brief ...
553!> \param qs_env ...
554!> \param bs_env ...
555! **************************************************************************************************
556 SUBROUTINE compute_cfm_mo_coeff_kp_and_eigenval_scf_kp(qs_env, bs_env)
557 TYPE(qs_environment_type), POINTER :: qs_env
558 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
559
560 CHARACTER(LEN=*), PARAMETER :: routinen = 'compute_cfm_mo_coeff_kp_and_eigenval_scf_kp'
561
562 INTEGER :: handle, ikp, ispin, nkp_bs_and_dos
563 INTEGER, DIMENSION(:, :, :), POINTER :: cell_to_index_scf
564 REAL(kind=dp) :: cbm, vbm
565 REAL(kind=dp), DIMENSION(3) :: xkp
566 TYPE(cp_cfm_type) :: cfm_ks, cfm_mos, cfm_s
567 TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: matrix_ks, matrix_s
568 TYPE(kpoint_type), POINTER :: kpoints_scf
569 TYPE(neighbor_list_set_p_type), DIMENSION(:), &
570 POINTER :: sab_nl
571
572 CALL timeset(routinen, handle)
573
574 CALL get_qs_env(qs_env, &
575 matrix_ks_kp=matrix_ks, &
576 matrix_s_kp=matrix_s, &
577 kpoints=kpoints_scf)
578
579 NULLIFY (sab_nl)
580 CALL get_kpoint_info(kpoints_scf, sab_nl=sab_nl, cell_to_index=cell_to_index_scf)
581
582 CALL cp_cfm_create(cfm_ks, bs_env%cfm_work_mo%matrix_struct)
583 CALL cp_cfm_create(cfm_s, bs_env%cfm_work_mo%matrix_struct)
584 CALL cp_cfm_create(cfm_mos, bs_env%cfm_work_mo%matrix_struct)
585
586 ! nkp_bs_and_DOS contains desymmetrized k-point mesh from SCF and k-points from GW bandstructure
587 nkp_bs_and_dos = bs_env%nkp_bs_and_DOS
588
589 ALLOCATE (bs_env%eigenval_G0W0(bs_env%n_ao, nkp_bs_and_dos, bs_env%n_spin))
590 ALLOCATE (bs_env%eigenval_HF(bs_env%n_ao, nkp_bs_and_dos, bs_env%n_spin))
591 ALLOCATE (bs_env%cfm_mo_coeff_kp(nkp_bs_and_dos, bs_env%n_spin))
592 ALLOCATE (bs_env%cfm_ks_kp(nkp_bs_and_dos, bs_env%n_spin))
593 ALLOCATE (bs_env%cfm_s_kp(nkp_bs_and_dos))
594 DO ikp = 1, nkp_bs_and_dos
595 DO ispin = 1, bs_env%n_spin
596 CALL cp_cfm_create(bs_env%cfm_mo_coeff_kp(ikp, ispin), bs_env%cfm_work_mo%matrix_struct)
597 CALL cp_cfm_create(bs_env%cfm_ks_kp(ikp, ispin), bs_env%cfm_work_mo%matrix_struct)
598 END DO
599 CALL cp_cfm_create(bs_env%cfm_s_kp(ikp), bs_env%cfm_work_mo%matrix_struct)
600 END DO
601
602 DO ispin = 1, bs_env%n_spin
603 DO ikp = 1, nkp_bs_and_dos
604
605 xkp(1:3) = bs_env%kpoints_DOS%xkp(1:3, ikp)
606
607 ! h^KS^R -> h^KS(k)
608 CALL rsmat_to_kp(matrix_ks, ispin, xkp, cell_to_index_scf, sab_nl, bs_env, cfm_ks)
609
610 ! S^R -> S(k)
611 CALL rsmat_to_kp(matrix_s, 1, xkp, cell_to_index_scf, sab_nl, bs_env, cfm_s)
612
613 ! we store the complex KS matrix as fm matrix because the infrastructure for fm is
614 ! much nicer compared to cfm
615 CALL cp_cfm_to_cfm(cfm_ks, bs_env%cfm_ks_kp(ikp, ispin))
616 CALL cp_cfm_to_cfm(cfm_s, bs_env%cfm_s_kp(ikp))
617
618 ! Diagonalize KS-matrix via Rothaan-Hall equation:
619 ! H^KS(k) C(k) = S(k) C(k) ε(k)
620 CALL cp_cfm_geeig_canon(cfm_ks, cfm_s, cfm_mos, &
621 bs_env%eigenval_scf(:, ikp, ispin), &
622 bs_env%cfm_work_mo, bs_env%eps_eigval_mat_s)
623
624 ! we store the complex MO coeff as fm matrix because the infrastructure for fm is
625 ! much nicer compared to cfm
626 CALL cp_cfm_to_cfm(cfm_mos, bs_env%cfm_mo_coeff_kp(ikp, ispin))
627
628 END DO
629
630 vbm = maxval(bs_env%eigenval_scf(bs_env%n_occ(ispin), :, ispin))
631 cbm = minval(bs_env%eigenval_scf(bs_env%n_occ(ispin) + 1, :, ispin))
632
633 bs_env%e_fermi(ispin) = 0.5_dp*(vbm + cbm)
634
635 END DO
636
637 CALL get_vbm_cbm_bandgaps(bs_env%band_edges_scf, bs_env%eigenval_scf, bs_env)
638
639 CALL cp_cfm_release(cfm_ks)
640 CALL cp_cfm_release(cfm_s)
641 CALL cp_cfm_release(cfm_mos)
642
643 CALL timestop(handle)
644
645 END SUBROUTINE compute_cfm_mo_coeff_kp_and_eigenval_scf_kp
646
647! **************************************************************************************************
648!> \brief ...
649!> \param mat_rs ...
650!> \param ispin ...
651!> \param xkp ...
652!> \param cell_to_index_scf ...
653!> \param sab_nl ...
654!> \param bs_env ...
655!> \param cfm_kp ...
656!> \param imag_rs_mat ...
657! **************************************************************************************************
658 SUBROUTINE rsmat_to_kp(mat_rs, ispin, xkp, cell_to_index_scf, sab_nl, bs_env, cfm_kp, imag_rs_mat)
659 TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: mat_rs
660 INTEGER :: ispin
661 REAL(kind=dp), DIMENSION(3) :: xkp
662 INTEGER, DIMENSION(:, :, :), POINTER :: cell_to_index_scf
663 TYPE(neighbor_list_set_p_type), DIMENSION(:), &
664 POINTER :: sab_nl
665 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
666 TYPE(cp_cfm_type) :: cfm_kp
667 LOGICAL, OPTIONAL :: imag_rs_mat
668
669 CHARACTER(LEN=*), PARAMETER :: routinen = 'rsmat_to_kp'
670
671 INTEGER :: handle
672 LOGICAL :: imag_rs_mat_private
673 TYPE(dbcsr_type), POINTER :: cmat, nsmat, rmat
674
675 CALL timeset(routinen, handle)
676
677 ALLOCATE (rmat, cmat, nsmat)
678
679 imag_rs_mat_private = .false.
680 IF (PRESENT(imag_rs_mat)) imag_rs_mat_private = imag_rs_mat
681
682 IF (imag_rs_mat_private) THEN
683 CALL dbcsr_create(rmat, template=mat_rs(1, 1)%matrix, matrix_type=dbcsr_type_antisymmetric)
684 CALL dbcsr_create(cmat, template=mat_rs(1, 1)%matrix, matrix_type=dbcsr_type_symmetric)
685 ELSE
686 CALL dbcsr_create(rmat, template=mat_rs(1, 1)%matrix, matrix_type=dbcsr_type_symmetric)
687 CALL dbcsr_create(cmat, template=mat_rs(1, 1)%matrix, matrix_type=dbcsr_type_antisymmetric)
688 END IF
689 CALL dbcsr_create(nsmat, template=mat_rs(1, 1)%matrix, matrix_type=dbcsr_type_no_symmetry)
690 CALL cp_dbcsr_alloc_block_from_nbl(rmat, sab_nl)
691 CALL cp_dbcsr_alloc_block_from_nbl(cmat, sab_nl)
692
693 CALL dbcsr_set(rmat, 0.0_dp)
694 CALL dbcsr_set(cmat, 0.0_dp)
695 CALL rskp_transform(rmatrix=rmat, cmatrix=cmat, rsmat=mat_rs, ispin=ispin, &
696 xkp=xkp, cell_to_index=cell_to_index_scf, sab_nl=sab_nl)
697
698 CALL dbcsr_desymmetrize(rmat, nsmat)
699 CALL copy_dbcsr_to_fm(nsmat, bs_env%fm_work_mo(1))
700 CALL dbcsr_desymmetrize(cmat, nsmat)
701 CALL copy_dbcsr_to_fm(nsmat, bs_env%fm_work_mo(2))
702 CALL cp_fm_to_cfm(bs_env%fm_work_mo(1), bs_env%fm_work_mo(2), cfm_kp)
703
704 CALL dbcsr_deallocate_matrix(rmat)
705 CALL dbcsr_deallocate_matrix(cmat)
706 CALL dbcsr_deallocate_matrix(nsmat)
707
708 CALL timestop(handle)
709
710 END SUBROUTINE rsmat_to_kp
711
712! **************************************************************************************************
713!> \brief ...
714!> \param bs_env ...
715! **************************************************************************************************
716 SUBROUTINE diagonalize_ks_matrix(bs_env)
717 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
718
719 CHARACTER(LEN=*), PARAMETER :: routinen = 'diagonalize_ks_matrix'
720
721 INTEGER :: handle, ispin
722 REAL(kind=dp) :: cbm, vbm
723
724 CALL timeset(routinen, handle)
725
726 ALLOCATE (bs_env%eigenval_scf_Gamma(bs_env%n_ao, bs_env%n_spin))
727
728 DO ispin = 1, bs_env%n_spin
729
730 ! use work matrices because the matrices are overwritten in cp_fm_geeig_canon
731 CALL cp_fm_to_fm(bs_env%fm_ks_Gamma(ispin), bs_env%fm_work_mo(1))
732 CALL cp_fm_to_fm(bs_env%fm_s_Gamma, bs_env%fm_work_mo(2))
733
734 ! diagonalize the Kohn-Sham matrix to obtain MO coefficients and SCF eigenvalues
735 ! (at the Gamma-point)
736 CALL cp_fm_geeig_canon(bs_env%fm_work_mo(1), &
737 bs_env%fm_work_mo(2), &
738 bs_env%fm_mo_coeff_Gamma(ispin), &
739 bs_env%eigenval_scf_Gamma(:, ispin), &
740 bs_env%fm_work_mo(3), &
741 bs_env%eps_eigval_mat_s)
742
743 vbm = bs_env%eigenval_scf_Gamma(bs_env%n_occ(ispin), ispin)
744 cbm = bs_env%eigenval_scf_Gamma(bs_env%n_occ(ispin) + 1, ispin)
745
746 bs_env%band_edges_scf_Gamma(ispin)%VBM = vbm
747 bs_env%band_edges_scf_Gamma(ispin)%CBM = cbm
748 bs_env%e_fermi(ispin) = 0.5_dp*(vbm + cbm)
749
750 END DO
751
752 CALL timestop(handle)
753
754 END SUBROUTINE diagonalize_ks_matrix
755
756! **************************************************************************************************
757!> \brief ...
758!> \param bs_env ...
759!> \param qs_env ...
760! **************************************************************************************************
761 SUBROUTINE check_positive_definite_overlap_mat(bs_env, qs_env)
762 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
763 TYPE(qs_environment_type), POINTER :: qs_env
764
765 CHARACTER(LEN=*), PARAMETER :: routinen = 'check_positive_definite_overlap_mat'
766
767 INTEGER :: handle, ikp, info, u
768 TYPE(cp_cfm_type) :: cfm_s_ikp
769
770 CALL timeset(routinen, handle)
771
772 DO ikp = 1, bs_env%kpoints_DOS%nkp
773
774 ! get S_µν(k_i) from S_µν(k=0)
775 CALL cfm_ikp_from_fm_gamma(cfm_s_ikp, bs_env%fm_s_Gamma, &
776 ikp, qs_env, bs_env%kpoints_DOS, "ORB")
777
778 ! check whether S_µν(k_i) is positive definite
779 CALL cp_cfm_cholesky_decompose(matrix=cfm_s_ikp, n=bs_env%n_ao, info_out=info)
780
781 ! check if Cholesky decomposition failed (Cholesky decomposition only works for
782 ! positive definite matrices
783 IF (info .NE. 0) THEN
784 u = bs_env%unit_nr
785
786 IF (u > 0) THEN
787 WRITE (u, fmt="(T2,A)") ""
788 WRITE (u, fmt="(T2,A)") "ERROR: The Cholesky decomposition "// &
789 "of the k-point overlap matrix failed. This is"
790 WRITE (u, fmt="(T2,A)") "because the algorithm is "// &
791 "only correct in the limit of large cells. The cell of "
792 WRITE (u, fmt="(T2,A)") "the calculation is too small. "// &
793 "Use MULTIPLE_UNIT_CELL to create a larger cell "
794 WRITE (u, fmt="(T2,A)") "and to prevent this error."
795 END IF
796
797 CALL bs_env%para_env%sync()
798 cpabort("Please see information on the error above.")
799
800 END IF ! Cholesky decomposition failed
801
802 END DO ! ikp
803
804 CALL cp_cfm_release(cfm_s_ikp)
805
806 CALL timestop(handle)
807
808 END SUBROUTINE check_positive_definite_overlap_mat
809
810! **************************************************************************************************
811!> \brief ...
812!> \param qs_env ...
813!> \param bs_env ...
814! **************************************************************************************************
815 SUBROUTINE get_parameters_from_qs_env(qs_env, bs_env)
816 TYPE(qs_environment_type), POINTER :: qs_env
817 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
818
819 CHARACTER(LEN=*), PARAMETER :: routinen = 'get_parameters_from_qs_env'
820
821 INTEGER :: color_sub, handle, homo, n_ao, n_atom, u
822 INTEGER, DIMENSION(3) :: periodic
823 REAL(kind=dp), DIMENSION(3, 3) :: hmat
824 TYPE(cell_type), POINTER :: cell
825 TYPE(dft_control_type), POINTER :: dft_control
826 TYPE(mo_set_type), DIMENSION(:), POINTER :: mos
827 TYPE(mp_para_env_type), POINTER :: para_env
828 TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
829 TYPE(scf_control_type), POINTER :: scf_control
830 TYPE(section_vals_type), POINTER :: input
831
832 CALL timeset(routinen, handle)
833
834 CALL get_qs_env(qs_env, &
835 dft_control=dft_control, &
836 scf_control=scf_control, &
837 mos=mos)
838
839 bs_env%n_spin = dft_control%nspins
840 IF (bs_env%n_spin == 1) bs_env%spin_degeneracy = 2.0_dp
841 IF (bs_env%n_spin == 2) bs_env%spin_degeneracy = 1.0_dp
842
843 CALL get_mo_set(mo_set=mos(1), nao=n_ao, homo=homo)
844 bs_env%n_ao = n_ao
845 bs_env%n_occ(1:2) = homo
846 bs_env%n_vir(1:2) = n_ao - homo
847
848 IF (bs_env%n_spin == 2) THEN
849 CALL get_mo_set(mo_set=mos(2), homo=homo)
850 bs_env%n_occ(2) = homo
851 bs_env%n_vir(2) = n_ao - homo
852 END IF
853
854 bs_env%eps_eigval_mat_s = scf_control%eps_eigval
855
856 ! get para_env from qs_env (bs_env%para_env is identical to para_env in qs_env)
857 CALL get_qs_env(qs_env, para_env=para_env)
858 color_sub = 0
859 ALLOCATE (bs_env%para_env)
860 CALL bs_env%para_env%from_split(para_env, color_sub)
861
862 CALL get_qs_env(qs_env, particle_set=particle_set)
863
864 n_atom = SIZE(particle_set)
865 bs_env%n_atom = n_atom
866
867 CALL get_qs_env(qs_env=qs_env, cell=cell)
868 CALL get_cell(cell=cell, periodic=periodic, h=hmat)
869 bs_env%periodic(1:3) = periodic(1:3)
870 bs_env%hmat(1:3, 1:3) = hmat
871 bs_env%nimages_scf = dft_control%nimages
872 IF (dft_control%nimages == 1) THEN
873 bs_env%small_cell_full_kp_or_large_cell_Gamma = large_cell_gamma
874 ELSE IF (dft_control%nimages > 1) THEN
875 bs_env%small_cell_full_kp_or_large_cell_Gamma = small_cell_full_kp
876 ELSE
877 cpabort("Wrong number of cells from DFT calculation.")
878 END IF
879
880 u = bs_env%unit_nr
881
882 ! Marek : Get and save the rtp method
883 CALL get_qs_env(qs_env=qs_env, input=input)
884 CALL section_vals_val_get(input, "DFT%REAL_TIME_PROPAGATION%RTBSE%_SECTION_PARAMETERS_", i_val=bs_env%rtp_method)
885
886 IF (u > 0) THEN
887 WRITE (u, fmt="(T2,2A,T73,I8)") "Number of occupied molecular orbitals (MOs) ", &
888 "= Number of occupied bands", homo
889 WRITE (u, fmt="(T2,2A,T73,I8)") "Number of unoccupied (= virtual) MOs ", &
890 "= Number of unoccupied bands", n_ao - homo
891 WRITE (u, fmt="(T2,A,T73,I8)") "Number of Gaussian basis functions for MOs", n_ao
892 IF (bs_env%small_cell_full_kp_or_large_cell_Gamma == small_cell_full_kp) THEN
893 WRITE (u, fmt="(T2,2A,T73,I8)") "Number of cells considered in the DFT ", &
894 "calculation", bs_env%nimages_scf
895 END IF
896 END IF
897
898 CALL timestop(handle)
899
900 END SUBROUTINE get_parameters_from_qs_env
901
902! **************************************************************************************************
903!> \brief ...
904!> \param bs_env ...
905! **************************************************************************************************
906 SUBROUTINE set_heuristic_parameters(bs_env)
907 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
908
909 CHARACTER(LEN=*), PARAMETER :: routinen = 'set_heuristic_parameters'
910
911 INTEGER :: handle
912
913 CALL timeset(routinen, handle)
914
915 bs_env%n_bins_max_for_printing = 5000
916
917 CALL timestop(handle)
918
919 END SUBROUTINE set_heuristic_parameters
920
921! **************************************************************************************************
922!> \brief ...
923!> \param qs_env ...
924!> \param bs_env ...
925! **************************************************************************************************
926 SUBROUTINE allocate_and_fill_fm_ks_fm_s(qs_env, bs_env)
927 TYPE(qs_environment_type), POINTER :: qs_env
928 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
929
930 CHARACTER(LEN=*), PARAMETER :: routinen = 'allocate_and_fill_fm_ks_fm_s'
931
932 INTEGER :: handle, i_work, ispin
933 TYPE(cp_blacs_env_type), POINTER :: blacs_env
934 TYPE(cp_fm_struct_type), POINTER :: fm_struct
935 TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: matrix_ks, matrix_s
936 TYPE(mp_para_env_type), POINTER :: para_env
937
938 CALL timeset(routinen, handle)
939
940 CALL get_qs_env(qs_env, &
941 para_env=para_env, &
942 blacs_env=blacs_env, &
943 matrix_ks_kp=matrix_ks, &
944 matrix_s_kp=matrix_s)
945
946 NULLIFY (fm_struct)
947 CALL cp_fm_struct_create(fm_struct, context=blacs_env, nrow_global=bs_env%n_ao, &
948 ncol_global=bs_env%n_ao, para_env=para_env)
949
950 DO i_work = 1, SIZE(bs_env%fm_work_mo)
951 CALL cp_fm_create(bs_env%fm_work_mo(i_work), fm_struct)
952 END DO
953
954 CALL cp_cfm_create(bs_env%cfm_work_mo, fm_struct)
955 CALL cp_cfm_create(bs_env%cfm_work_mo_2, fm_struct)
956
957 CALL cp_fm_create(bs_env%fm_s_Gamma, fm_struct)
958 CALL copy_dbcsr_to_fm(matrix_s(1, 1)%matrix, bs_env%fm_s_Gamma)
959
960 DO ispin = 1, bs_env%n_spin
961 CALL cp_fm_create(bs_env%fm_ks_Gamma(ispin), fm_struct)
962 CALL copy_dbcsr_to_fm(matrix_ks(ispin, 1)%matrix, bs_env%fm_ks_Gamma(ispin))
963 CALL cp_fm_create(bs_env%fm_mo_coeff_Gamma(ispin), fm_struct)
964 END DO
965
966 CALL cp_fm_struct_release(fm_struct)
967
968 NULLIFY (bs_env%mat_ao_ao%matrix)
969 ALLOCATE (bs_env%mat_ao_ao%matrix)
970 CALL dbcsr_create(bs_env%mat_ao_ao%matrix, template=matrix_s(1, 1)%matrix, &
971 matrix_type=dbcsr_type_no_symmetry)
972
973 ALLOCATE (bs_env%eigenval_scf(bs_env%n_ao, bs_env%nkp_bs_and_DOS, bs_env%n_spin))
974
975 CALL timestop(handle)
976
977 END SUBROUTINE allocate_and_fill_fm_ks_fm_s
978
979! **************************************************************************************************
980!> \brief ...
981!> \param qs_env ...
982!> \param bs_env ...
983! **************************************************************************************************
984 SUBROUTINE dos_pdos_ldos(qs_env, bs_env)
985 TYPE(qs_environment_type), POINTER :: qs_env
986 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
987
988 CHARACTER(LEN=*), PARAMETER :: routinen = 'dos_pdos_ldos'
989
990 INTEGER :: handle, homo, homo_1, homo_2, &
991 homo_spinor, ikp, ikp_for_file, ispin, &
992 n_ao, n_e, nkind, nkp
993 LOGICAL :: is_bandstruc_kpoint, print_dos_kpoints, &
994 print_ikp
995 REAL(kind=dp) :: broadening, e_max, e_max_g0w0, e_min, &
996 e_min_g0w0, e_total_window, &
997 energy_step_dos, energy_window_dos, t1
998 REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: dos_g0w0, dos_g0w0_soc, dos_scf, dos_scf_soc, &
999 eigenval, eigenval_spinor, eigenval_spinor_g0w0, eigenval_spinor_no_soc
1000 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :) :: pdos_g0w0, pdos_g0w0_soc, pdos_scf, &
1001 pdos_scf_soc, proj_mo_on_kind
1002 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :, :) :: ldos_g0w0_2d, ldos_scf_2d, &
1003 ldos_scf_2d_soc
1004 TYPE(band_edges_type) :: band_edges_g0w0, band_edges_g0w0_soc, &
1005 band_edges_scf, band_edges_scf_guess, &
1006 band_edges_scf_soc
1007 TYPE(cp_cfm_type) :: cfm_ks_ikp, cfm_ks_ikp_spinor, cfm_mos_ikp_spinor, cfm_s_ikp, &
1008 cfm_s_ikp_copy, cfm_s_ikp_spinor, cfm_s_ikp_spinor_copy, cfm_soc_ikp_spinor, &
1009 cfm_spinor_wf_ikp, cfm_work_ikp, cfm_work_ikp_spinor
1010 TYPE(cp_cfm_type), DIMENSION(2) :: cfm_mos_ikp
1011
1012 CALL timeset(routinen, handle)
1013
1014 n_ao = bs_env%n_ao
1015
1016 energy_window_dos = bs_env%energy_window_DOS
1017 energy_step_dos = bs_env%energy_step_DOS
1018 broadening = bs_env%broadening_DOS
1019
1020 ! if we have done GW or a full kpoint SCF, we already have the band edges
1021 IF (bs_env%do_gw .OR. &
1022 bs_env%small_cell_full_kp_or_large_cell_Gamma == small_cell_full_kp) THEN
1023 band_edges_scf = bs_env%band_edges_scf
1024 band_edges_scf_guess = band_edges_scf
1025 ELSE
1026
1027 IF (bs_env%n_spin == 1) THEN
1028 homo = bs_env%n_occ(1)
1029 band_edges_scf_guess%VBM = bs_env%eigenval_scf_Gamma(homo, 1)
1030 band_edges_scf_guess%CBM = bs_env%eigenval_scf_Gamma(homo + 1, 1)
1031 ELSE
1032 homo_1 = bs_env%n_occ(1)
1033 homo_2 = bs_env%n_occ(2)
1034 band_edges_scf_guess%VBM = max(bs_env%eigenval_scf_Gamma(homo_1, 1), &
1035 bs_env%eigenval_scf_Gamma(homo_2, 2))
1036 band_edges_scf_guess%CBM = min(bs_env%eigenval_scf_Gamma(homo_1 + 1, 1), &
1037 bs_env%eigenval_scf_Gamma(homo_2 + 1, 2))
1038 END IF
1039
1040 ! initialization
1041 band_edges_scf%VBM = -1000.0_dp
1042 band_edges_scf%CBM = 1000.0_dp
1043 band_edges_scf%DBG = 1000.0_dp
1044 END IF
1045
1046 e_min = band_edges_scf_guess%VBM - 0.5_dp*energy_window_dos
1047 e_max = band_edges_scf_guess%CBM + 0.5_dp*energy_window_dos
1048
1049 IF (bs_env%do_gw) THEN
1050 band_edges_g0w0 = bs_env%band_edges_G0W0
1051 e_min_g0w0 = band_edges_g0w0%VBM - 0.5_dp*energy_window_dos
1052 e_max_g0w0 = band_edges_g0w0%CBM + 0.5_dp*energy_window_dos
1053 e_min = min(e_min, e_min_g0w0)
1054 e_max = max(e_max, e_max_g0w0)
1055 END IF
1056
1057 e_total_window = e_max - e_min
1058
1059 n_e = int(e_total_window/energy_step_dos)
1060
1061 ALLOCATE (dos_scf(n_e))
1062 dos_scf(:) = 0.0_dp
1063 ALLOCATE (dos_scf_soc(n_e))
1064 dos_scf_soc(:) = 0.0_dp
1065
1066 CALL get_qs_env(qs_env, nkind=nkind)
1067
1068 ALLOCATE (pdos_scf(n_e, nkind))
1069 pdos_scf(:, :) = 0.0_dp
1070 ALLOCATE (pdos_scf_soc(n_e, nkind))
1071 pdos_scf_soc(:, :) = 0.0_dp
1072
1073 ALLOCATE (proj_mo_on_kind(n_ao, nkind))
1074 proj_mo_on_kind(:, :) = 0.0_dp
1075
1076 ALLOCATE (eigenval(n_ao))
1077 ALLOCATE (eigenval_spinor(2*n_ao))
1078 ALLOCATE (eigenval_spinor_no_soc(2*n_ao))
1079 ALLOCATE (eigenval_spinor_g0w0(2*n_ao))
1080
1081 IF (bs_env%do_gw) THEN
1082
1083 ALLOCATE (dos_g0w0(n_e))
1084 dos_g0w0(:) = 0.0_dp
1085 ALLOCATE (dos_g0w0_soc(n_e))
1086 dos_g0w0_soc(:) = 0.0_dp
1087
1088 ALLOCATE (pdos_g0w0(n_e, nkind))
1089 pdos_g0w0(:, :) = 0.0_dp
1090 ALLOCATE (pdos_g0w0_soc(n_e, nkind))
1091 pdos_g0w0_soc(:, :) = 0.0_dp
1092
1093 END IF
1094
1095 CALL cp_cfm_create(cfm_mos_ikp(1), bs_env%fm_ks_Gamma(1)%matrix_struct)
1096 CALL cp_cfm_create(cfm_mos_ikp(2), bs_env%fm_ks_Gamma(1)%matrix_struct)
1097 CALL cp_cfm_create(cfm_work_ikp, bs_env%fm_ks_Gamma(1)%matrix_struct)
1098 CALL cp_cfm_create(cfm_s_ikp_copy, bs_env%fm_ks_Gamma(1)%matrix_struct)
1099
1100 IF (bs_env%do_soc) THEN
1101
1102 CALL cp_cfm_create(cfm_mos_ikp_spinor, bs_env%cfm_SOC_spinor_ao(1)%matrix_struct)
1103 CALL cp_cfm_create(cfm_work_ikp_spinor, bs_env%cfm_SOC_spinor_ao(1)%matrix_struct)
1104 CALL cp_cfm_create(cfm_s_ikp_spinor_copy, bs_env%cfm_SOC_spinor_ao(1)%matrix_struct)
1105 CALL cp_cfm_create(cfm_ks_ikp_spinor, bs_env%cfm_SOC_spinor_ao(1)%matrix_struct)
1106 CALL cp_cfm_create(cfm_soc_ikp_spinor, bs_env%cfm_SOC_spinor_ao(1)%matrix_struct)
1107 CALL cp_cfm_create(cfm_s_ikp_spinor, bs_env%cfm_SOC_spinor_ao(1)%matrix_struct)
1108 CALL cp_cfm_create(cfm_spinor_wf_ikp, bs_env%cfm_SOC_spinor_ao(1)%matrix_struct)
1109
1110 homo_spinor = bs_env%n_occ(1) + bs_env%n_occ(bs_env%n_spin)
1111
1112 band_edges_scf_soc%VBM = -1000.0_dp
1113 band_edges_scf_soc%CBM = 1000.0_dp
1114 band_edges_scf_soc%DBG = 1000.0_dp
1115
1116 IF (bs_env%do_gw) THEN
1117 band_edges_g0w0_soc%VBM = -1000.0_dp
1118 band_edges_g0w0_soc%CBM = 1000.0_dp
1119 band_edges_g0w0_soc%DBG = 1000.0_dp
1120 END IF
1121
1122 IF (bs_env%unit_nr > 0) THEN
1123 WRITE (bs_env%unit_nr, '(A)') ''
1124 WRITE (bs_env%unit_nr, '(T2,A,F43.1,A)') 'SOC requested, SOC energy window:', &
1125 bs_env%energy_window_soc*evolt, ' eV'
1126 END IF
1127
1128 END IF
1129
1130 IF (bs_env%do_ldos) THEN
1131 cpassert(bs_env%int_ldos_xyz == int_ldos_z)
1132 END IF
1133
1134 IF (bs_env%unit_nr > 0) THEN
1135 WRITE (bs_env%unit_nr, '(A)') ''
1136 END IF
1137
1138 IF (bs_env%small_cell_full_kp_or_large_cell_Gamma == small_cell_full_kp) THEN
1139 CALL cp_cfm_create(cfm_ks_ikp, bs_env%cfm_ks_kp(1, 1)%matrix_struct)
1140 CALL cp_cfm_create(cfm_s_ikp, bs_env%cfm_ks_kp(1, 1)%matrix_struct)
1141 END IF
1142
1143 DO ikp = 1, bs_env%nkp_bs_and_DOS
1144
1145 t1 = m_walltime()
1146
1147 DO ispin = 1, bs_env%n_spin
1148
1149 SELECT CASE (bs_env%small_cell_full_kp_or_large_cell_Gamma)
1150 CASE (large_cell_gamma)
1151
1152 ! 1. get H^KS_µν(k_i) from H^KS_µν(k=0)
1153 CALL cfm_ikp_from_fm_gamma(cfm_ks_ikp, bs_env%fm_ks_Gamma(ispin), &
1154 ikp, qs_env, bs_env%kpoints_DOS, "ORB")
1155
1156 ! 2. get S_µν(k_i) from S_µν(k=0)
1157 CALL cfm_ikp_from_fm_gamma(cfm_s_ikp, bs_env%fm_s_Gamma, &
1158 ikp, qs_env, bs_env%kpoints_DOS, "ORB")
1159 CALL cp_cfm_to_cfm(cfm_s_ikp, cfm_s_ikp_copy)
1160
1161 ! 3. Diagonalize (Roothaan-Hall): H_KS(k_i)*C(k_i) = S(k_i)*C(k_i)*ϵ(k_i)
1162 CALL cp_cfm_geeig(cfm_ks_ikp, cfm_s_ikp_copy, cfm_mos_ikp(ispin), &
1163 eigenval, cfm_work_ikp)
1164
1165 CASE (small_cell_full_kp)
1166
1167 ! 1. get H^KS_µν(k_i)
1168 CALL cp_cfm_to_cfm(bs_env%cfm_ks_kp(ikp, ispin), cfm_ks_ikp)
1169
1170 ! 2. get S_µν(k_i)
1171 CALL cp_cfm_to_cfm(bs_env%cfm_s_kp(ikp), cfm_s_ikp)
1172
1173 ! 3. get C_µn(k_i) and ϵ_n(k_i)
1174 CALL cp_cfm_to_cfm(bs_env%cfm_mo_coeff_kp(ikp, ispin), cfm_mos_ikp(ispin))
1175 eigenval(:) = bs_env%eigenval_scf(:, ikp, ispin)
1176
1177 END SELECT
1178
1179 ! 4. Projection p_nk^A of MO ψ_nk(r) on atom type A (inspired by Mulliken charge)
1180 ! p_nk^A = sum_µ^A,ν C*_µ^A,n(k) S_µ^A,ν(k) C_ν,n(k)
1181 CALL compute_proj_mo_on_kind(proj_mo_on_kind, qs_env, cfm_mos_ikp(ispin), cfm_s_ikp)
1182
1183 ! 5. DOS and PDOS
1184 CALL add_to_dos_pdos(dos_scf, pdos_scf, eigenval, ikp, bs_env, n_e, e_min, &
1185 proj_mo_on_kind)
1186 IF (bs_env%do_gw) THEN
1187 CALL add_to_dos_pdos(dos_g0w0, pdos_g0w0, bs_env%eigenval_G0W0(:, ikp, ispin), &
1188 ikp, bs_env, n_e, e_min, proj_mo_on_kind)
1189 END IF
1190
1191 IF (bs_env%do_ldos) THEN
1192 CALL add_to_ldos_2d(ldos_scf_2d, qs_env, ikp, bs_env, cfm_mos_ikp(ispin), &
1193 eigenval(:), band_edges_scf_guess)
1194
1195 IF (bs_env%do_gw) THEN
1196 CALL add_to_ldos_2d(ldos_g0w0_2d, qs_env, ikp, bs_env, cfm_mos_ikp(ispin), &
1197 bs_env%eigenval_G0W0(:, ikp, 1), band_edges_g0w0)
1198 END IF
1199
1200 END IF
1201
1202 homo = bs_env%n_occ(ispin)
1203
1204 band_edges_scf%VBM = max(band_edges_scf%VBM, eigenval(homo))
1205 band_edges_scf%CBM = min(band_edges_scf%CBM, eigenval(homo + 1))
1206 band_edges_scf%DBG = min(band_edges_scf%DBG, eigenval(homo + 1) - eigenval(homo))
1207
1208 END DO ! spin
1209
1210 ! now the same with spin-orbit coupling
1211 IF (bs_env%do_soc) THEN
1212
1213 ! only print eigenvalues of DOS k-points in case no bandstructure path has been given
1214 print_dos_kpoints = (bs_env%nkp_only_bs .LE. 0)
1215 ! in kpoints_DOS, the last nkp_only_bs are bandstructure k-points
1216 is_bandstruc_kpoint = (ikp > bs_env%nkp_only_DOS)
1217 print_ikp = print_dos_kpoints .OR. is_bandstruc_kpoint
1218
1219 IF (print_dos_kpoints) THEN
1220 nkp = bs_env%nkp_only_DOS
1221 ikp_for_file = ikp
1222 ELSE
1223 nkp = bs_env%nkp_only_bs
1224 ikp_for_file = ikp - bs_env%nkp_only_DOS
1225 END IF
1226
1227 ! compute DFT+SOC eigenvalues; based on these, compute band edges, DOS and LDOS
1228 CALL soc_ev(bs_env, qs_env, ikp, bs_env%eigenval_scf, band_edges_scf, &
1229 e_min, cfm_mos_ikp, dos_scf_soc, pdos_scf_soc, &
1230 band_edges_scf_soc, eigenval_spinor, cfm_spinor_wf_ikp)
1231
1232 IF (.NOT. bs_env%do_gw .AND. print_ikp) THEN
1233 CALL write_soc_eigenvalues(eigenval_spinor, ikp_for_file, ikp, bs_env)
1234 END IF
1235
1236 IF (bs_env%do_ldos) THEN
1237 CALL add_to_ldos_2d(ldos_scf_2d_soc, qs_env, ikp, bs_env, cfm_spinor_wf_ikp, &
1238 eigenval_spinor, band_edges_scf_guess, .true., cfm_work_ikp)
1239 END IF
1240
1241 IF (bs_env%do_gw) THEN
1242
1243 ! compute G0W0+SOC eigenvalues; based on these, compute band edges, DOS and LDOS
1244 CALL soc_ev(bs_env, qs_env, ikp, bs_env%eigenval_G0W0, band_edges_g0w0, &
1245 e_min, cfm_mos_ikp, dos_g0w0_soc, pdos_g0w0_soc, &
1246 band_edges_g0w0_soc, eigenval_spinor_g0w0, cfm_spinor_wf_ikp)
1247
1248 IF (print_ikp) THEN
1249 ! write SCF+SOC and G0W0+SOC eigenvalues to file
1250 ! SCF_and_G0W0_band_structure_for_kpoint_<ikp>_+_SOC
1251 CALL write_soc_eigenvalues(eigenval_spinor, ikp_for_file, ikp, bs_env, &
1252 eigenval_spinor_g0w0)
1253 END IF
1254
1255 END IF ! do_gw
1256
1257 END IF ! do_soc
1258
1259 IF (bs_env%unit_nr > 0 .AND. m_walltime() - t1 > 20.0_dp) THEN
1260 WRITE (bs_env%unit_nr, '(T2,A,T43,I5,A,I3,A,F7.1,A)') &
1261 'Compute DOS, LDOS for k-point ', ikp, ' /', bs_env%nkp_bs_and_DOS, &
1262 ', Execution time', m_walltime() - t1, ' s'
1263 END IF
1264
1265 END DO ! ikp_DOS
1266
1267 band_edges_scf%IDBG = band_edges_scf%CBM - band_edges_scf%VBM
1268 IF (bs_env%do_soc) THEN
1269 band_edges_scf_soc%IDBG = band_edges_scf_soc%CBM - band_edges_scf_soc%VBM
1270 IF (bs_env%do_gw) THEN
1271 band_edges_g0w0_soc%IDBG = band_edges_g0w0_soc%CBM - band_edges_g0w0_soc%VBM
1272 END IF
1273 END IF
1274
1275 CALL write_band_edges(band_edges_scf, "SCF", bs_env)
1276 CALL write_dos_pdos(dos_scf, pdos_scf, bs_env, qs_env, "SCF", e_min, band_edges_scf%VBM)
1277 IF (bs_env%do_ldos) THEN
1278 CALL print_ldos_main(ldos_scf_2d, bs_env, band_edges_scf, "SCF")
1279 END IF
1280
1281 IF (bs_env%do_soc) THEN
1282 CALL write_band_edges(band_edges_scf_soc, "SCF+SOC", bs_env)
1283 CALL write_dos_pdos(dos_scf_soc, pdos_scf_soc, bs_env, qs_env, "SCF_SOC", &
1284 e_min, band_edges_scf_soc%VBM)
1285 IF (bs_env%do_ldos) THEN
1286 ! argument band_edges_scf is actually correct because the non-SOC band edges
1287 ! have been used as reference in add_to_LDOS_2d
1288 CALL print_ldos_main(ldos_scf_2d_soc, bs_env, band_edges_scf, &
1289 "SCF_SOC")
1290 END IF
1291 END IF
1292
1293 IF (bs_env%do_gw) THEN
1294 CALL write_band_edges(band_edges_g0w0, "G0W0", bs_env)
1295 CALL write_band_edges(bs_env%band_edges_HF, "Hartree-Fock with SCF orbitals", bs_env)
1296 CALL write_dos_pdos(dos_g0w0, pdos_g0w0, bs_env, qs_env, "G0W0", e_min, &
1297 band_edges_g0w0%VBM)
1298 IF (bs_env%do_ldos) THEN
1299 CALL print_ldos_main(ldos_g0w0_2d, bs_env, band_edges_g0w0, "G0W0")
1300 END IF
1301 END IF
1302
1303 IF (bs_env%do_soc .AND. bs_env%do_gw) THEN
1304 CALL write_band_edges(band_edges_g0w0_soc, "G0W0+SOC", bs_env)
1305 CALL write_dos_pdos(dos_g0w0_soc, pdos_g0w0_soc, bs_env, qs_env, "G0W0_SOC", e_min, &
1306 band_edges_g0w0_soc%VBM)
1307 END IF
1308
1309 CALL cp_cfm_release(cfm_s_ikp)
1310 CALL cp_cfm_release(cfm_ks_ikp)
1311 CALL cp_cfm_release(cfm_mos_ikp(1))
1312 CALL cp_cfm_release(cfm_mos_ikp(2))
1313 CALL cp_cfm_release(cfm_work_ikp)
1314 CALL cp_cfm_release(cfm_s_ikp_copy)
1315
1316 CALL cp_cfm_release(cfm_s_ikp_spinor)
1317 CALL cp_cfm_release(cfm_ks_ikp_spinor)
1318 CALL cp_cfm_release(cfm_soc_ikp_spinor)
1319 CALL cp_cfm_release(cfm_mos_ikp_spinor)
1320 CALL cp_cfm_release(cfm_work_ikp_spinor)
1321 CALL cp_cfm_release(cfm_s_ikp_spinor_copy)
1322 CALL cp_cfm_release(cfm_spinor_wf_ikp)
1323
1324 CALL timestop(handle)
1325
1326 END SUBROUTINE dos_pdos_ldos
1327
1328! **************************************************************************************************
1329!> \brief ...
1330!> \param LDOS_2d ...
1331!> \param bs_env ...
1332!> \param band_edges ...
1333!> \param scf_gw_soc ...
1334! **************************************************************************************************
1335 SUBROUTINE print_ldos_main(LDOS_2d, bs_env, band_edges, scf_gw_soc)
1336 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :, :) :: ldos_2d
1337 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
1338 TYPE(band_edges_type) :: band_edges
1339 CHARACTER(LEN=*) :: scf_gw_soc
1340
1341 CHARACTER(LEN=*), PARAMETER :: routinen = 'print_LDOS_main'
1342
1343 INTEGER :: handle, i_x, i_x_bin, i_x_end, i_x_end_bin, i_x_end_glob, i_x_start, &
1344 i_x_start_bin, i_x_start_glob, i_y, i_y_bin, i_y_end, i_y_end_bin, i_y_end_glob, &
1345 i_y_start, i_y_start_bin, i_y_start_glob, n_e
1346 INTEGER, ALLOCATABLE, DIMENSION(:, :) :: n_sum_for_bins
1347 INTEGER, DIMENSION(2) :: bin_mesh
1348 LOGICAL :: do_xy_bins
1349 REAL(kind=dp) :: e_min, energy_step, energy_window
1350 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :, :) :: ldos_2d_bins
1351
1352 CALL timeset(routinen, handle)
1353
1354 n_e = SIZE(ldos_2d, 3)
1355
1356 energy_window = bs_env%energy_window_DOS
1357 energy_step = bs_env%energy_step_DOS
1358 e_min = band_edges%VBM - 0.5_dp*energy_window
1359
1360 bin_mesh(1:2) = bs_env%bin_mesh(1:2)
1361 do_xy_bins = (bin_mesh(1) > 0 .AND. bin_mesh(2) > 0)
1362
1363 i_x_start = lbound(ldos_2d, 1)
1364 i_x_end = ubound(ldos_2d, 1)
1365 i_y_start = lbound(ldos_2d, 2)
1366 i_y_end = ubound(ldos_2d, 2)
1367
1368 IF (do_xy_bins) THEN
1369 i_x_start_bin = 1
1370 i_x_end_bin = bin_mesh(1)
1371 i_y_start_bin = 1
1372 i_y_end_bin = bin_mesh(2)
1373 ELSE
1374 i_x_start_bin = i_x_start
1375 i_x_end_bin = i_x_end
1376 i_y_start_bin = i_y_start
1377 i_y_end_bin = i_y_end
1378 END IF
1379
1380 ALLOCATE (ldos_2d_bins(i_x_start_bin:i_x_end_bin, i_y_start_bin:i_y_end_bin, n_e))
1381 ldos_2d_bins(:, :, :) = 0.0_dp
1382
1383 IF (do_xy_bins) THEN
1384
1385 i_x_start_glob = i_x_start
1386 i_x_end_glob = i_x_end
1387 i_y_start_glob = i_y_start
1388 i_y_end_glob = i_y_end
1389
1390 CALL bs_env%para_env%min(i_x_start_glob)
1391 CALL bs_env%para_env%max(i_x_end_glob)
1392 CALL bs_env%para_env%min(i_y_start_glob)
1393 CALL bs_env%para_env%max(i_y_end_glob)
1394
1395 ALLOCATE (n_sum_for_bins(bin_mesh(1), bin_mesh(2)))
1396 n_sum_for_bins(:, :) = 0
1397
1398 ! transform interval [i_x_start, i_x_end] to [1, bin_mesh(1)] (and same for y)
1399 DO i_x = i_x_start, i_x_end
1400 DO i_y = i_y_start, i_y_end
1401 i_x_bin = bin_mesh(1)*(i_x - i_x_start_glob)/(i_x_end_glob - i_x_start_glob + 1) + 1
1402 i_y_bin = bin_mesh(2)*(i_y - i_y_start_glob)/(i_y_end_glob - i_y_start_glob + 1) + 1
1403 ldos_2d_bins(i_x_bin, i_y_bin, :) = ldos_2d_bins(i_x_bin, i_y_bin, :) + &
1404 ldos_2d(i_x, i_y, :)
1405 n_sum_for_bins(i_x_bin, i_y_bin) = n_sum_for_bins(i_x_bin, i_y_bin) + 1
1406 END DO
1407 END DO
1408
1409 CALL bs_env%para_env%sum(ldos_2d_bins)
1410 CALL bs_env%para_env%sum(n_sum_for_bins)
1411
1412 ! divide by number of terms in the sum so we have the average LDOS(x,y,E)
1413 DO i_x_bin = 1, bin_mesh(1)
1414 DO i_y_bin = 1, bin_mesh(2)
1415 ldos_2d_bins(i_x_bin, i_y_bin, :) = ldos_2d_bins(i_x_bin, i_y_bin, :)/ &
1416 REAL(n_sum_for_bins(i_x_bin, i_y_bin), kind=dp)
1417 END DO
1418 END DO
1419
1420 ELSE
1421
1422 ldos_2d_bins(:, :, :) = ldos_2d(:, :, :)
1423
1424 END IF
1425
1426 IF (bin_mesh(1)*bin_mesh(2) < bs_env%n_bins_max_for_printing) THEN
1427 CALL print_ldos_2d_bins(ldos_2d_bins, bs_env, e_min, scf_gw_soc)
1428 ELSE
1429 cpwarn("The number of bins for the LDOS is too large. Decrease BIN_MESH.")
1430 END IF
1431
1432 CALL timestop(handle)
1433
1434 END SUBROUTINE print_ldos_main
1435
1436! **************************************************************************************************
1437!> \brief ...
1438!> \param LDOS_2d_bins ...
1439!> \param bs_env ...
1440!> \param E_min ...
1441!> \param scf_gw_soc ...
1442! **************************************************************************************************
1443 SUBROUTINE print_ldos_2d_bins(LDOS_2d_bins, bs_env, E_min, scf_gw_soc)
1444 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :, :) :: ldos_2d_bins
1445 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
1446 REAL(kind=dp) :: e_min
1447 CHARACTER(LEN=*) :: scf_gw_soc
1448
1449 CHARACTER(LEN=*), PARAMETER :: routinen = 'print_LDOS_2d_bins'
1450
1451 CHARACTER(LEN=18) :: print_format
1452 CHARACTER(LEN=4) :: print_format_1, print_format_2
1453 CHARACTER(len=default_string_length) :: fname
1454 INTEGER :: handle, i_e, i_x, i_x_end, i_x_start, &
1455 i_y, i_y_end, i_y_start, iunit, n_e, &
1456 n_x, n_y
1457 REAL(kind=dp) :: energy
1458 REAL(kind=dp), DIMENSION(3) :: coord, idx
1459
1460 CALL timeset(routinen, handle)
1461
1462 i_x_start = lbound(ldos_2d_bins, 1)
1463 i_x_end = ubound(ldos_2d_bins, 1)
1464 i_y_start = lbound(ldos_2d_bins, 2)
1465 i_y_end = ubound(ldos_2d_bins, 2)
1466 n_e = SIZE(ldos_2d_bins, 3)
1467
1468 n_x = i_x_end - i_x_start + 1
1469 n_y = i_y_end - i_y_start + 1
1470
1471 IF (bs_env%para_env%is_source()) THEN
1472
1473 DO i_x = i_x_start, i_x_end
1474 DO i_y = i_y_start, i_y_end
1475
1476 idx(1) = (real(i_x, kind=dp) - 0.5_dp)/real(n_x, kind=dp)
1477 idx(2) = (real(i_y, kind=dp) - 0.5_dp)/real(n_y, kind=dp)
1478 idx(3) = 0.0_dp
1479 coord(1:3) = matmul(bs_env%hmat, idx)
1480
1481 CALL get_print_format(coord(1), print_format_1)
1482 CALL get_print_format(coord(2), print_format_2)
1483
1484 print_format = "(3A,"//print_format_1//",A,"//print_format_2//",A)"
1485
1486 WRITE (fname, print_format) "LDOS_", scf_gw_soc, &
1487 "_at_x_", coord(1)*angstrom, '_A_and_y_', coord(2)*angstrom, '_A'
1488
1489 CALL open_file(trim(fname), unit_number=iunit, file_status="REPLACE", &
1490 file_action="WRITE")
1491
1492 WRITE (iunit, "(2A)") Å" Energy E (eV) average LDOS(x,y,E) (1/(eV*^2), ", &
1493 "integrated over z, averaged inside bin)"
1494
1495 DO i_e = 1, n_e
1496 energy = e_min + i_e*bs_env%energy_step_DOS
1497 WRITE (iunit, "(2F17.3)") energy*evolt, &
1498 ldos_2d_bins(i_x, i_y, i_e)* &
1499 bs_env%unit_ldos_int_z_inv_Ang2_eV
1500 END DO
1501
1502 CALL close_file(iunit)
1503
1504 END DO
1505 END DO
1506
1507 END IF
1508
1509 CALL timestop(handle)
1510
1511 END SUBROUTINE print_ldos_2d_bins
1512
1513! **************************************************************************************************
1514!> \brief ...
1515!> \param coord ...
1516!> \param print_format ...
1517! **************************************************************************************************
1518 SUBROUTINE get_print_format(coord, print_format)
1519 REAL(kind=dp) :: coord
1520 CHARACTER(LEN=4) :: print_format
1521
1522 CHARACTER(LEN=*), PARAMETER :: routinen = 'get_print_format'
1523
1524 INTEGER :: handle
1525
1526 CALL timeset(routinen, handle)
1527
1528 IF (coord < -10000/angstrom) THEN
1529 print_format = "F9.2"
1530 ELSE IF (coord < -1000/angstrom) THEN
1531 print_format = "F8.2"
1532 ELSE IF (coord < -100/angstrom) THEN
1533 print_format = "F7.2"
1534 ELSE IF (coord < -10/angstrom) THEN
1535 print_format = "F6.2"
1536 ELSE IF (coord < -1/angstrom) THEN
1537 print_format = "F5.2"
1538 ELSE IF (coord < 10/angstrom) THEN
1539 print_format = "F4.2"
1540 ELSE IF (coord < 100/angstrom) THEN
1541 print_format = "F5.2"
1542 ELSE IF (coord < 1000/angstrom) THEN
1543 print_format = "F6.2"
1544 ELSE IF (coord < 10000/angstrom) THEN
1545 print_format = "F7.2"
1546 ELSE
1547 print_format = "F8.2"
1548 END IF
1549
1550 CALL timestop(handle)
1551
1552 END SUBROUTINE get_print_format
1553
1554! **************************************************************************************************
1555!> \brief ...
1556!> \param bs_env ...
1557!> \param qs_env ...
1558!> \param ikp ...
1559!> \param eigenval_no_SOC ...
1560!> \param band_edges_no_SOC ...
1561!> \param E_min ...
1562!> \param cfm_mos_ikp ...
1563!> \param DOS ...
1564!> \param PDOS ...
1565!> \param band_edges ...
1566!> \param eigenval_spinor ...
1567!> \param cfm_spinor_wf_ikp ...
1568! **************************************************************************************************
1569 SUBROUTINE soc_ev(bs_env, qs_env, ikp, eigenval_no_SOC, band_edges_no_SOC, E_min, cfm_mos_ikp, &
1570 DOS, PDOS, band_edges, eigenval_spinor, cfm_spinor_wf_ikp)
1571
1572 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
1573 TYPE(qs_environment_type), POINTER :: qs_env
1574 INTEGER :: ikp
1575 REAL(kind=dp), DIMENSION(:, :, :) :: eigenval_no_soc
1576 TYPE(band_edges_type) :: band_edges_no_soc
1577 REAL(kind=dp) :: e_min
1578 TYPE(cp_cfm_type), DIMENSION(2) :: cfm_mos_ikp
1579 REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: dos
1580 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :) :: pdos
1581 TYPE(band_edges_type) :: band_edges
1582 REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: eigenval_spinor
1583 TYPE(cp_cfm_type) :: cfm_spinor_wf_ikp
1584
1585 CHARACTER(LEN=*), PARAMETER :: routinen = 'SOC_ev'
1586
1587 INTEGER :: handle, homo_spinor, n_ao, n_e, nkind
1588 REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: eigenval_spinor_no_soc
1589 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :) :: proj_mo_on_kind_spinor
1590 TYPE(cp_cfm_type) :: cfm_eigenvec_ikp_spinor, &
1591 cfm_ks_ikp_spinor, cfm_mos_ikp_spinor, &
1592 cfm_soc_ikp_spinor, cfm_work_ikp_spinor
1593
1594 CALL timeset(routinen, handle)
1595
1596 n_ao = bs_env%n_ao
1597 homo_spinor = bs_env%n_occ(1) + bs_env%n_occ(bs_env%n_spin)
1598 n_e = SIZE(dos)
1599 nkind = SIZE(pdos, 2)
1600
1601 CALL cp_cfm_create(cfm_ks_ikp_spinor, bs_env%cfm_SOC_spinor_ao(1)%matrix_struct)
1602 CALL cp_cfm_create(cfm_soc_ikp_spinor, bs_env%cfm_SOC_spinor_ao(1)%matrix_struct)
1603 CALL cp_cfm_create(cfm_mos_ikp_spinor, bs_env%cfm_SOC_spinor_ao(1)%matrix_struct)
1604 CALL cp_cfm_create(cfm_work_ikp_spinor, bs_env%cfm_SOC_spinor_ao(1)%matrix_struct)
1605 CALL cp_cfm_create(cfm_eigenvec_ikp_spinor, bs_env%cfm_SOC_spinor_ao(1)%matrix_struct)
1606
1607 ALLOCATE (eigenval_spinor_no_soc(2*n_ao))
1608 ALLOCATE (proj_mo_on_kind_spinor(2*n_ao, nkind))
1609 ! PDOS not yet implemented -> projection is just zero -> PDOS is zero
1610 proj_mo_on_kind_spinor(:, :) = 0.0_dp
1611
1612 ! 1. get V^SOC_µν,σσ'(k_i)
1613 SELECT CASE (bs_env%small_cell_full_kp_or_large_cell_Gamma)
1614 CASE (large_cell_gamma)
1615
1616 ! 1. get V^SOC_µν,σσ'(k_i) from V^SOC_µν,σσ'(k=0)
1617 CALL cfm_ikp_from_cfm_spinor_gamma(cfm_soc_ikp_spinor, &
1618 bs_env%cfm_SOC_spinor_ao(1), &
1619 bs_env%fm_s_Gamma%matrix_struct, &
1620 ikp, qs_env, bs_env%kpoints_DOS, "ORB")
1621
1622 CASE (small_cell_full_kp)
1623
1624 ! 1. V^SOC_µν,σσ'(k_i) already there
1625 CALL cp_cfm_to_cfm(bs_env%cfm_SOC_spinor_ao(ikp), cfm_soc_ikp_spinor)
1626
1627 END SELECT
1628
1629 ! 2. V^SOC_nn',σσ'(k_i) = sum_µν C^*_µn,σ(k_i) V^SOC_µν,σσ'(k_i) C_νn'(k_i),
1630 ! C_µn,σ(k_i): MO coefficiencts from diagonalizing KS-matrix h^KS_nn',σσ'(k_i)
1631
1632 ! 2.1 build matrix C_µn,σ(k_i)
1633 CALL cp_cfm_set_all(cfm_mos_ikp_spinor, z_zero)
1634 CALL add_cfm_submat(cfm_mos_ikp_spinor, cfm_mos_ikp(1), 1, 1)
1635 CALL add_cfm_submat(cfm_mos_ikp_spinor, cfm_mos_ikp(bs_env%n_spin), n_ao + 1, n_ao + 1)
1636
1637 ! 2.2 work_nν,σσ' = sum_µ C^*_µn,σ(k_i) V^SOC_µν,σσ'(k_i)
1638 CALL parallel_gemm('C', 'N', 2*n_ao, 2*n_ao, 2*n_ao, z_one, &
1639 cfm_mos_ikp_spinor, cfm_soc_ikp_spinor, &
1640 z_zero, cfm_work_ikp_spinor)
1641
1642 ! 2.3 V^SOC_nn',σσ'(k_i) = sum_ν work_nν,σσ' C_νn'(k_i)
1643 CALL parallel_gemm('N', 'N', 2*n_ao, 2*n_ao, 2*n_ao, z_one, &
1644 cfm_work_ikp_spinor, cfm_mos_ikp_spinor, &
1645 z_zero, cfm_ks_ikp_spinor)
1646
1647 ! 3. remove SOC outside of energy window (otherwise, numerical problems arise
1648 ! because energetically low semicore states and energetically very high
1649 ! unbound states couple to the states around the Fermi level)
1650 eigenval_spinor_no_soc(1:n_ao) = eigenval_no_soc(1:n_ao, ikp, 1)
1651 eigenval_spinor_no_soc(n_ao + 1:) = eigenval_no_soc(1:n_ao, ikp, bs_env%n_spin)
1652 IF (bs_env%energy_window_soc > 0.0_dp) THEN
1653 CALL remove_soc_outside_energy_window_mo(cfm_ks_ikp_spinor, &
1654 bs_env%energy_window_soc, &
1655 eigenval_spinor_no_soc, &
1656 band_edges_no_soc%VBM, &
1657 band_edges_no_soc%CBM)
1658 END IF
1659
1660 ! 4. h^G0W0+SOC_nn',σσ'(k_i) = ε_nσ^G0W0(k_i) δ_nn' δ_σσ' + V^SOC_nn',σσ'(k_i)
1661 CALL cfm_add_on_diag(cfm_ks_ikp_spinor, eigenval_spinor_no_soc)
1662
1663 ! 5. diagonalize h^G0W0+SOC_nn',σσ'(k_i) to get eigenvalues
1664 CALL cp_cfm_heevd(cfm_ks_ikp_spinor, cfm_eigenvec_ikp_spinor, eigenval_spinor)
1665
1666 ! 6. DOS from spinors, no PDOS
1667 CALL add_to_dos_pdos(dos, pdos, eigenval_spinor, &
1668 ikp, bs_env, n_e, e_min, proj_mo_on_kind_spinor)
1669
1670 ! 7. valence band max. (VBM), conduction band min. (CBM) and direct bandgap (DBG)
1671 band_edges%VBM = max(band_edges%VBM, eigenval_spinor(homo_spinor))
1672 band_edges%CBM = min(band_edges%CBM, eigenval_spinor(homo_spinor + 1))
1673 band_edges%DBG = min(band_edges%DBG, eigenval_spinor(homo_spinor + 1) &
1674 - eigenval_spinor(homo_spinor))
1675
1676 ! 8. spinor wavefunctions:
1677 CALL parallel_gemm('N', 'N', 2*n_ao, 2*n_ao, 2*n_ao, z_one, &
1678 cfm_mos_ikp_spinor, cfm_eigenvec_ikp_spinor, &
1679 z_zero, cfm_spinor_wf_ikp)
1680
1681 CALL cp_cfm_release(cfm_ks_ikp_spinor)
1682 CALL cp_cfm_release(cfm_soc_ikp_spinor)
1683 CALL cp_cfm_release(cfm_work_ikp_spinor)
1684 CALL cp_cfm_release(cfm_eigenvec_ikp_spinor)
1685 CALL cp_cfm_release(cfm_mos_ikp_spinor)
1686
1687 CALL timestop(handle)
1688
1689 END SUBROUTINE soc_ev
1690
1691! **************************************************************************************************
1692!> \brief ...
1693!> \param DOS ...
1694!> \param PDOS ...
1695!> \param eigenval ...
1696!> \param ikp ...
1697!> \param bs_env ...
1698!> \param n_E ...
1699!> \param E_min ...
1700!> \param proj_mo_on_kind ...
1701! **************************************************************************************************
1702 SUBROUTINE add_to_dos_pdos(DOS, PDOS, eigenval, ikp, bs_env, n_E, E_min, proj_mo_on_kind)
1703
1704 REAL(kind=dp), DIMENSION(:) :: dos
1705 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :) :: pdos
1706 REAL(kind=dp), DIMENSION(:) :: eigenval
1707 INTEGER :: ikp
1708 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
1709 INTEGER :: n_e
1710 REAL(kind=dp) :: e_min
1711 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :) :: proj_mo_on_kind
1712
1713 CHARACTER(LEN=*), PARAMETER :: routinen = 'add_to_DOS_PDOS'
1714
1715 INTEGER :: handle, i_e, i_kind, i_mo, n_mo, nkind
1716 REAL(kind=dp) :: broadening, energy, energy_step_dos, wkp
1717
1718 CALL timeset(routinen, handle)
1719
1720 energy_step_dos = bs_env%energy_step_DOS
1721 broadening = bs_env%broadening_DOS
1722
1723 n_mo = SIZE(eigenval)
1724 nkind = SIZE(proj_mo_on_kind, 2)
1725
1726 ! normalize to closed-shell / open-shell
1727 wkp = bs_env%kpoints_DOS%wkp(ikp)*bs_env%spin_degeneracy
1728 DO i_e = 1, n_e
1729 energy = e_min + i_e*energy_step_dos
1730 DO i_mo = 1, n_mo
1731 ! DOS
1732 dos(i_e) = dos(i_e) + wkp*gaussian(energy - eigenval(i_mo), broadening)
1733
1734 ! PDOS
1735 DO i_kind = 1, nkind
1736 IF (proj_mo_on_kind(i_mo, i_kind) > 0.0_dp) THEN
1737 pdos(i_e, i_kind) = pdos(i_e, i_kind) + &
1738 proj_mo_on_kind(i_mo, i_kind)*wkp* &
1739 gaussian(energy - eigenval(i_mo), broadening)
1740 END IF
1741 END DO
1742 END DO
1743 END DO
1744
1745 CALL timestop(handle)
1746
1747 END SUBROUTINE add_to_dos_pdos
1748
1749! **************************************************************************************************
1750!> \brief ...
1751!> \param LDOS_2d ...
1752!> \param qs_env ...
1753!> \param ikp ...
1754!> \param bs_env ...
1755!> \param cfm_mos_ikp ...
1756!> \param eigenval ...
1757!> \param band_edges ...
1758!> \param do_spinor ...
1759!> \param cfm_non_spinor ...
1760! **************************************************************************************************
1761 SUBROUTINE add_to_ldos_2d(LDOS_2d, qs_env, ikp, bs_env, cfm_mos_ikp, eigenval, &
1762 band_edges, do_spinor, cfm_non_spinor)
1763 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :, :) :: ldos_2d
1764 TYPE(qs_environment_type), POINTER :: qs_env
1765 INTEGER :: ikp
1766 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
1767 TYPE(cp_cfm_type) :: cfm_mos_ikp
1768 REAL(kind=dp), DIMENSION(:) :: eigenval
1769 TYPE(band_edges_type) :: band_edges
1770 LOGICAL, OPTIONAL :: do_spinor
1771 TYPE(cp_cfm_type), OPTIONAL :: cfm_non_spinor
1772
1773 CHARACTER(LEN=*), PARAMETER :: routinen = 'add_to_LDOS_2d'
1774
1775 INTEGER :: handle, i_e, i_x_end, i_x_start, i_y_end, i_y_start, i_z, i_z_end, i_z_start, &
1776 j_col, j_mo, n_e, n_mo, n_z, ncol_local, nimages, z_end_global, z_start_global
1777 INTEGER, DIMENSION(:), POINTER :: col_indices
1778 LOGICAL :: is_any_weight_non_zero, my_do_spinor
1779 REAL(kind=dp) :: broadening, e_max, e_min, &
1780 e_total_window, energy, energy_step, &
1781 energy_window, spin_degeneracy, weight
1782 TYPE(cp_cfm_type) :: cfm_weighted_dm_ikp, cfm_work
1783 TYPE(cp_fm_type) :: fm_non_spinor, fm_weighted_dm_mic
1784 TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: weighted_dm_mic
1785 TYPE(dft_control_type), POINTER :: dft_control
1786 TYPE(pw_c1d_gs_type) :: rho_g
1787 TYPE(pw_env_type), POINTER :: pw_env
1788 TYPE(pw_pool_type), POINTER :: auxbas_pw_pool
1789 TYPE(pw_r3d_rs_type) :: ldos_3d
1790 TYPE(qs_ks_env_type), POINTER :: ks_env
1791
1792 CALL timeset(routinen, handle)
1793
1794 my_do_spinor = .false.
1795 IF (PRESENT(do_spinor)) my_do_spinor = do_spinor
1796
1797 CALL get_qs_env(qs_env, ks_env=ks_env, pw_env=pw_env, dft_control=dft_control)
1798
1799 ! previously, dft_control%nimages set to # neighbor cells, revert for Γ-only KS matrix
1800 nimages = dft_control%nimages
1801 dft_control%nimages = bs_env%nimages_scf
1802
1803 energy_window = bs_env%energy_window_DOS
1804 energy_step = bs_env%energy_step_DOS
1805 broadening = bs_env%broadening_DOS
1806
1807 e_min = band_edges%VBM - 0.5_dp*energy_window
1808 e_max = band_edges%CBM + 0.5_dp*energy_window
1809 e_total_window = e_max - e_min
1810
1811 n_e = int(e_total_window/energy_step)
1812
1813 CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool)
1814
1815 CALL auxbas_pw_pool%create_pw(ldos_3d)
1816 CALL auxbas_pw_pool%create_pw(rho_g)
1817
1818 i_x_start = lbound(ldos_3d%array, 1)
1819 i_x_end = ubound(ldos_3d%array, 1)
1820 i_y_start = lbound(ldos_3d%array, 2)
1821 i_y_end = ubound(ldos_3d%array, 2)
1822 i_z_start = lbound(ldos_3d%array, 3)
1823 i_z_end = ubound(ldos_3d%array, 3)
1824
1825 z_start_global = i_z_start
1826 z_end_global = i_z_end
1827
1828 CALL bs_env%para_env%min(z_start_global)
1829 CALL bs_env%para_env%max(z_end_global)
1830 n_z = z_end_global - z_start_global + 1
1831
1832 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)) &
1833 cpabort(°"Please choose a cell that has 90 angles to the z-direction.")
1834 ! for integration, we need the dz and the conversion from H -> eV and a_Bohr -> Å
1835 bs_env%unit_ldos_int_z_inv_Ang2_eV = bs_env%hmat(3, 3)/real(n_z, kind=dp)/evolt/angstrom**2
1836
1837 IF (ikp == 1) THEN
1838 ALLOCATE (ldos_2d(i_x_start:i_x_end, i_y_start:i_y_end, n_e))
1839 ldos_2d(:, :, :) = 0.0_dp
1840 END IF
1841
1842 CALL cp_cfm_create(cfm_work, cfm_mos_ikp%matrix_struct)
1843 CALL cp_cfm_create(cfm_weighted_dm_ikp, cfm_mos_ikp%matrix_struct)
1844 CALL cp_fm_create(fm_weighted_dm_mic, cfm_mos_ikp%matrix_struct)
1845 IF (my_do_spinor) THEN
1846 CALL cp_fm_create(fm_non_spinor, cfm_non_spinor%matrix_struct)
1847 END IF
1848
1849 CALL cp_cfm_get_info(matrix=cfm_mos_ikp, &
1850 ncol_global=n_mo, &
1851 ncol_local=ncol_local, &
1852 col_indices=col_indices)
1853
1854 NULLIFY (weighted_dm_mic)
1855 CALL dbcsr_allocate_matrix_set(weighted_dm_mic, 1)
1856 ALLOCATE (weighted_dm_mic(1)%matrix)
1857 CALL dbcsr_create(weighted_dm_mic(1)%matrix, template=bs_env%mat_ao_ao%matrix, &
1858 matrix_type=dbcsr_type_symmetric)
1859
1860 DO i_e = 1, n_e
1861
1862 energy = e_min + i_e*energy_step
1863
1864 is_any_weight_non_zero = .false.
1865
1866 DO j_col = 1, ncol_local
1867
1868 j_mo = col_indices(j_col)
1869
1870 IF (my_do_spinor) THEN
1871 spin_degeneracy = 1.0_dp
1872 ELSE
1873 spin_degeneracy = bs_env%spin_degeneracy
1874 END IF
1875
1876 weight = gaussian(energy - eigenval(j_mo), broadening)*spin_degeneracy
1877
1878 cfm_work%local_data(:, j_col) = cfm_mos_ikp%local_data(:, j_col)*weight
1879
1880 IF (weight > 1.0e-5_dp) is_any_weight_non_zero = .true.
1881
1882 END DO
1883
1884 CALL bs_env%para_env%sync()
1885 CALL bs_env%para_env%sum(is_any_weight_non_zero)
1886 CALL bs_env%para_env%sync()
1887
1888 ! cycle if there are no states at the energy i_E
1889 IF (is_any_weight_non_zero) THEN
1890
1891 CALL parallel_gemm('N', 'C', n_mo, n_mo, n_mo, z_one, &
1892 cfm_mos_ikp, cfm_work, z_zero, cfm_weighted_dm_ikp)
1893
1894 IF (my_do_spinor) THEN
1895
1896 ! contribution from up,up to fm_non_spinor
1897 CALL get_cfm_submat(cfm_non_spinor, cfm_weighted_dm_ikp, 1, 1)
1898 CALL cp_fm_set_all(fm_non_spinor, 0.0_dp)
1899 CALL mic_contribution_from_ikp(bs_env, qs_env, fm_non_spinor, &
1900 cfm_non_spinor, ikp, bs_env%kpoints_DOS, &
1901 "ORB", bs_env%kpoints_DOS%wkp(ikp))
1902
1903 ! add contribution from down,down to fm_non_spinor
1904 CALL get_cfm_submat(cfm_non_spinor, cfm_weighted_dm_ikp, n_mo/2, n_mo/2)
1905 CALL mic_contribution_from_ikp(bs_env, qs_env, fm_non_spinor, &
1906 cfm_non_spinor, ikp, bs_env%kpoints_DOS, &
1907 "ORB", bs_env%kpoints_DOS%wkp(ikp))
1908 CALL copy_fm_to_dbcsr(fm_non_spinor, weighted_dm_mic(1)%matrix, &
1909 keep_sparsity=.false.)
1910 ELSE
1911 CALL cp_fm_set_all(fm_weighted_dm_mic, 0.0_dp)
1912 CALL mic_contribution_from_ikp(bs_env, qs_env, fm_weighted_dm_mic, &
1913 cfm_weighted_dm_ikp, ikp, bs_env%kpoints_DOS, &
1914 "ORB", bs_env%kpoints_DOS%wkp(ikp))
1915 CALL copy_fm_to_dbcsr(fm_weighted_dm_mic, weighted_dm_mic(1)%matrix, &
1916 keep_sparsity=.false.)
1917 END IF
1918
1919 ldos_3d%array(:, :, :) = 0.0_dp
1920
1921 CALL calculate_rho_elec(matrix_p_kp=weighted_dm_mic, &
1922 rho=ldos_3d, &
1923 rho_gspace=rho_g, &
1924 ks_env=ks_env)
1925
1926 DO i_z = i_z_start, i_z_end
1927 ldos_2d(:, :, i_e) = ldos_2d(:, :, i_e) + ldos_3d%array(:, :, i_z)
1928 END DO
1929
1930 END IF
1931
1932 END DO
1933
1934 ! set back nimages
1935 dft_control%nimages = nimages
1936
1937 CALL auxbas_pw_pool%give_back_pw(ldos_3d)
1938 CALL auxbas_pw_pool%give_back_pw(rho_g)
1939
1940 CALL cp_cfm_release(cfm_work)
1941 CALL cp_cfm_release(cfm_weighted_dm_ikp)
1942
1943 CALL cp_fm_release(fm_weighted_dm_mic)
1944
1945 CALL dbcsr_deallocate_matrix_set(weighted_dm_mic)
1946
1947 IF (my_do_spinor) THEN
1948 CALL cp_fm_release(fm_non_spinor)
1949 END IF
1950
1951 CALL timestop(handle)
1952
1953 END SUBROUTINE add_to_ldos_2d
1954
1955! **************************************************************************************************
1956!> \brief ...
1957!> \param eigenval_spinor ...
1958!> \param ikp_for_file ...
1959!> \param ikp ...
1960!> \param bs_env ...
1961!> \param eigenval_spinor_G0W0 ...
1962! **************************************************************************************************
1963 SUBROUTINE write_soc_eigenvalues(eigenval_spinor, ikp_for_file, ikp, bs_env, eigenval_spinor_G0W0)
1964
1965 REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: eigenval_spinor
1966 INTEGER :: ikp_for_file, ikp
1967 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
1968 REAL(kind=dp), ALLOCATABLE, DIMENSION(:), OPTIONAL :: eigenval_spinor_g0w0
1969
1970 CHARACTER(LEN=*), PARAMETER :: routinen = 'write_SOC_eigenvalues'
1971
1972 CHARACTER(len=3) :: occ_vir
1973 CHARACTER(LEN=default_string_length) :: fname
1974 INTEGER :: handle, i_mo, iunit, n_occ_spinor
1975
1976 CALL timeset(routinen, handle)
1977
1978 fname = "bandstructure_SCF_and_G0W0_plus_SOC"
1979
1980 IF (bs_env%para_env%is_source()) THEN
1981
1982 IF (ikp_for_file == 1) THEN
1983 CALL open_file(trim(fname), unit_number=iunit, file_status="REPLACE", &
1984 file_action="WRITE")
1985 ELSE
1986 CALL open_file(trim(fname), unit_number=iunit, file_status="OLD", &
1987 file_action="WRITE", file_position="APPEND")
1988 END IF
1989
1990 WRITE (iunit, "(A)") " "
1991 WRITE (iunit, "(A10,I7,A25,3F10.4)") "kpoint: ", ikp_for_file, "coordinate: ", &
1992 bs_env%kpoints_DOS%xkp(:, ikp)
1993 WRITE (iunit, "(A)") " "
1994
1995 IF (PRESENT(eigenval_spinor_g0w0)) THEN
1996 ! SCF+SOC and G0W0+SOC eigenvalues
1997 WRITE (iunit, "(A5,A12,2A22)") "n", "k", ϵ"_nk^DFT+SOC (eV)", ϵ"_nk^G0W0+SOC (eV)"
1998 ELSE
1999 ! SCF+SOC eigenvalues only
2000 WRITE (iunit, "(A5,A12,A22)") "n", "k", ϵ"_nk^DFT+SOC (eV)"
2001 END IF
2002
2003 n_occ_spinor = bs_env%n_occ(1) + bs_env%n_occ(bs_env%n_spin)
2004
2005 DO i_mo = 1, SIZE(eigenval_spinor)
2006 IF (i_mo .LE. n_occ_spinor) occ_vir = 'occ'
2007 IF (i_mo > n_occ_spinor) occ_vir = 'vir'
2008 IF (PRESENT(eigenval_spinor_g0w0)) THEN
2009 ! SCF+SOC and G0W0+SOC eigenvalues
2010 WRITE (iunit, "(I5,3A,I5,4F16.3,2F17.3)") i_mo, ' (', occ_vir, ') ', &
2011 ikp_for_file, eigenval_spinor(i_mo)*evolt, eigenval_spinor_g0w0(i_mo)*evolt
2012 ELSE
2013 ! SCF+SOC eigenvalues only
2014 WRITE (iunit, "(I5,3A,I5,4F16.3,F17.3)") i_mo, ' (', occ_vir, ') ', &
2015 ikp_for_file, eigenval_spinor(i_mo)*evolt
2016 END IF
2017 END DO
2018
2019 CALL close_file(iunit)
2020
2021 END IF
2022
2023 CALL timestop(handle)
2024
2025 END SUBROUTINE write_soc_eigenvalues
2026
2027! **************************************************************************************************
2028!> \brief ...
2029!> \param int_number ...
2030!> \return ...
2031! **************************************************************************************************
2032 PURE FUNCTION count_digits(int_number)
2033
2034 INTEGER, INTENT(IN) :: int_number
2035 INTEGER :: count_digits
2036
2037 INTEGER :: digitcount, tempint
2038
2039 digitcount = 0
2040
2041 tempint = int_number
2042
2043 DO WHILE (tempint /= 0)
2044 tempint = tempint/10
2045 digitcount = digitcount + 1
2046 END DO
2047
2048 count_digits = digitcount
2049
2050 END FUNCTION count_digits
2051
2052! **************************************************************************************************
2053!> \brief ...
2054!> \param band_edges ...
2055!> \param scf_gw_soc ...
2056!> \param bs_env ...
2057! **************************************************************************************************
2058 SUBROUTINE write_band_edges(band_edges, scf_gw_soc, bs_env)
2059
2060 TYPE(band_edges_type) :: band_edges
2061 CHARACTER(LEN=*) :: scf_gw_soc
2062 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
2063
2064 CHARACTER(LEN=*), PARAMETER :: routinen = 'write_band_edges'
2065
2066 CHARACTER(LEN=17) :: print_format
2067 INTEGER :: handle, u
2068
2069 CALL timeset(routinen, handle)
2070
2071 ! print format
2072 print_format = "(T2,2A,T61,F20.3)"
2073
2074 u = bs_env%unit_nr
2075 IF (u > 0) THEN
2076 WRITE (u, '(T2,A)') ''
2077 WRITE (u, print_format) scf_gw_soc, ' valence band maximum (eV):', band_edges%VBM*evolt
2078 WRITE (u, print_format) scf_gw_soc, ' conduction band minimum (eV):', band_edges%CBM*evolt
2079 WRITE (u, print_format) scf_gw_soc, ' indirect band gap (eV):', band_edges%IDBG*evolt
2080 WRITE (u, print_format) scf_gw_soc, ' direct band gap (eV):', band_edges%DBG*evolt
2081 END IF
2082
2083 CALL timestop(handle)
2084
2085 END SUBROUTINE write_band_edges
2086
2087! **************************************************************************************************
2088!> \brief ...
2089!> \param DOS ...
2090!> \param PDOS ...
2091!> \param bs_env ...
2092!> \param qs_env ...
2093!> \param scf_gw_soc ...
2094!> \param E_min ...
2095!> \param E_VBM ...
2096! **************************************************************************************************
2097 SUBROUTINE write_dos_pdos(DOS, PDOS, bs_env, qs_env, scf_gw_soc, E_min, E_VBM)
2098 REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: dos
2099 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :) :: pdos
2100 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
2101 TYPE(qs_environment_type), POINTER :: qs_env
2102 CHARACTER(LEN=*) :: scf_gw_soc
2103 REAL(kind=dp) :: e_min, e_vbm
2104
2105 CHARACTER(LEN=*), PARAMETER :: routinen = 'write_dos_pdos'
2106
2107 CHARACTER(LEN=3), DIMENSION(100) :: elements
2108 CHARACTER(LEN=default_string_length) :: atom_name, fname, output_string
2109 INTEGER :: handle, i_e, i_kind, iatom, iunit, n_a, &
2110 n_e, nkind
2111 REAL(kind=dp) :: energy
2112 TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
2113
2114 CALL timeset(routinen, handle)
2115
2116 WRITE (fname, "(3A)") "DOS_PDOS_", scf_gw_soc, ".out"
2117
2118 n_e = SIZE(pdos, 1)
2119 nkind = SIZE(pdos, 2)
2120 CALL get_qs_env(qs_env, particle_set=particle_set)
2121
2122 IF (bs_env%para_env%is_source()) THEN
2123
2124 CALL open_file(trim(fname), unit_number=iunit, file_status="REPLACE", file_action="WRITE")
2125
2126 n_a = 2 + nkind
2127
2128 DO iatom = 1, bs_env%n_atom
2129 CALL get_atomic_kind(atomic_kind=particle_set(iatom)%atomic_kind, &
2130 kind_number=i_kind, name=atom_name)
2131 elements(i_kind) = atom_name
2132 END DO
2133
2134 WRITE (output_string, "(A,I1,A)") "(", n_a, "A)"
2135
2136 WRITE (iunit, trim(output_string)) "Energy-E_F (eV) DOS (1/eV) PDOS (1/eV) ", &
2137 " of atom type ", elements(1:nkind)
2138
2139 WRITE (output_string, "(A,I1,A)") "(", n_a, "F13.5)"
2140
2141 DO i_e = 1, n_e
2142 ! energy is relative to valence band maximum => - E_VBM
2143 energy = e_min + i_e*bs_env%energy_step_DOS - e_vbm
2144 WRITE (iunit, trim(output_string)) energy*evolt, dos(i_e)/evolt, pdos(i_e, :)/evolt
2145 END DO
2146
2147 CALL close_file(iunit)
2148
2149 END IF
2150
2151 CALL timestop(handle)
2152
2153 END SUBROUTINE write_dos_pdos
2154
2155! **************************************************************************************************
2156!> \brief ...
2157!> \param energy ...
2158!> \param broadening ...
2159!> \return ...
2160! **************************************************************************************************
2161 PURE FUNCTION gaussian(energy, broadening)
2162
2163 REAL(kind=dp), INTENT(IN) :: energy, broadening
2164 REAL(kind=dp) :: gaussian
2165
2166 IF (abs(energy) < 5*broadening) THEN
2167 gaussian = 1.0_dp/broadening/sqrt(twopi)*exp(-0.5_dp*energy**2/broadening**2)
2168 ELSE
2169 gaussian = 0.0_dp
2170 END IF
2171
2172 END FUNCTION
2173
2174! **************************************************************************************************
2175!> \brief ...
2176!> \param proj_mo_on_kind ...
2177!> \param qs_env ...
2178!> \param cfm_mos ...
2179!> \param cfm_s ...
2180! **************************************************************************************************
2181 SUBROUTINE compute_proj_mo_on_kind(proj_mo_on_kind, qs_env, cfm_mos, cfm_s)
2182 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :) :: proj_mo_on_kind
2183 TYPE(qs_environment_type), POINTER :: qs_env
2184 TYPE(cp_cfm_type) :: cfm_mos, cfm_s
2185
2186 CHARACTER(LEN=*), PARAMETER :: routinen = 'compute_proj_mo_on_kind'
2187
2188 INTEGER :: handle, i_atom, i_global, i_kind, i_row, &
2189 j_col, n_ao, n_mo, ncol_local, nkind, &
2190 nrow_local
2191 INTEGER, ALLOCATABLE, DIMENSION(:) :: atom_from_bf, kind_of
2192 INTEGER, DIMENSION(:), POINTER :: col_indices, row_indices
2193 TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set
2194 TYPE(cp_cfm_type) :: cfm_proj, cfm_s_i_kind, cfm_work
2195 TYPE(cp_fm_type) :: fm_proj_im, fm_proj_re
2196
2197 CALL timeset(routinen, handle)
2198
2199 CALL get_qs_env(qs_env, atomic_kind_set=atomic_kind_set, nkind=nkind)
2200 CALL get_atomic_kind_set(atomic_kind_set, kind_of=kind_of)
2201
2202 CALL cp_cfm_get_info(matrix=cfm_mos, &
2203 nrow_global=n_mo, &
2204 nrow_local=nrow_local, &
2205 ncol_local=ncol_local, &
2206 row_indices=row_indices, &
2207 col_indices=col_indices)
2208
2209 n_ao = qs_env%bs_env%n_ao
2210
2211 ALLOCATE (atom_from_bf(n_ao))
2212 CALL get_atom_index_from_basis_function_index(qs_env, atom_from_bf, n_ao, "ORB")
2213
2214 proj_mo_on_kind(:, :) = 0.0_dp
2215
2216 CALL cp_cfm_create(cfm_s_i_kind, cfm_s%matrix_struct)
2217 CALL cp_cfm_create(cfm_work, cfm_s%matrix_struct)
2218 CALL cp_cfm_create(cfm_proj, cfm_s%matrix_struct)
2219 CALL cp_fm_create(fm_proj_re, cfm_s%matrix_struct)
2220 CALL cp_fm_create(fm_proj_im, cfm_s%matrix_struct)
2221
2222 DO i_kind = 1, nkind
2223
2224 CALL cp_cfm_to_cfm(cfm_s, cfm_s_i_kind)
2225
2226 ! set entries in overlap matrix to zero which do not belong to atoms of i_kind
2227 DO i_row = 1, nrow_local
2228 DO j_col = 1, ncol_local
2229
2230 i_global = row_indices(i_row)
2231
2232 IF (i_global .LE. n_ao) THEN
2233 i_atom = atom_from_bf(i_global)
2234 ELSE IF (i_global .LE. 2*n_ao) THEN
2235 i_atom = atom_from_bf(i_global - n_ao)
2236 ELSE
2237 cpabort("Wrong indices.")
2238 END IF
2239
2240 IF (i_kind .NE. kind_of(i_atom)) THEN
2241 cfm_s_i_kind%local_data(i_row, j_col) = z_zero
2242 END IF
2243
2244 END DO
2245 END DO
2246
2247 CALL parallel_gemm('N', 'N', n_mo, n_mo, n_mo, z_one, &
2248 cfm_s_i_kind, cfm_mos, z_zero, cfm_work)
2249 CALL parallel_gemm('C', 'N', n_mo, n_mo, n_mo, z_one, &
2250 cfm_mos, cfm_work, z_zero, cfm_proj)
2251
2252 CALL cp_cfm_to_fm(cfm_proj, fm_proj_re, fm_proj_im)
2253
2254 CALL cp_fm_get_diag(fm_proj_im, proj_mo_on_kind(:, i_kind))
2255 CALL cp_fm_get_diag(fm_proj_re, proj_mo_on_kind(:, i_kind))
2256
2257 END DO ! i_kind
2258
2259 CALL cp_cfm_release(cfm_s_i_kind)
2260 CALL cp_cfm_release(cfm_work)
2261 CALL cp_cfm_release(cfm_proj)
2262 CALL cp_fm_release(fm_proj_re)
2263 CALL cp_fm_release(fm_proj_im)
2264
2265 CALL timestop(handle)
2266
2267 END SUBROUTINE compute_proj_mo_on_kind
2268
2269! **************************************************************************************************
2270!> \brief ...
2271!> \param cfm_spinor_ikp ...
2272!> \param cfm_spinor_Gamma ...
2273!> \param fm_struct_non_spinor ...
2274!> \param ikp ...
2275!> \param qs_env ...
2276!> \param kpoints ...
2277!> \param basis_type ...
2278! **************************************************************************************************
2279 SUBROUTINE cfm_ikp_from_cfm_spinor_gamma(cfm_spinor_ikp, cfm_spinor_Gamma, fm_struct_non_spinor, &
2280 ikp, qs_env, kpoints, basis_type)
2281 TYPE(cp_cfm_type) :: cfm_spinor_ikp, cfm_spinor_gamma
2282 TYPE(cp_fm_struct_type), POINTER :: fm_struct_non_spinor
2283 INTEGER :: ikp
2284 TYPE(qs_environment_type), POINTER :: qs_env
2285 TYPE(kpoint_type), POINTER :: kpoints
2286 CHARACTER(LEN=*) :: basis_type
2287
2288 CHARACTER(LEN=*), PARAMETER :: routinen = 'cfm_ikp_from_cfm_spinor_Gamma'
2289
2290 INTEGER :: handle, i_block, i_offset, j_block, &
2291 j_offset, n_ao
2292 TYPE(cp_cfm_type) :: cfm_non_spinor_gamma, cfm_non_spinor_ikp
2293 TYPE(cp_fm_type) :: fm_non_spinor_gamma_im, &
2294 fm_non_spinor_gamma_re
2295
2296 CALL timeset(routinen, handle)
2297
2298 CALL cp_cfm_create(cfm_non_spinor_gamma, fm_struct_non_spinor)
2299 CALL cp_cfm_create(cfm_non_spinor_ikp, fm_struct_non_spinor)
2300 CALL cp_fm_create(fm_non_spinor_gamma_re, fm_struct_non_spinor)
2301 CALL cp_fm_create(fm_non_spinor_gamma_im, fm_struct_non_spinor)
2302
2303 CALL cp_cfm_get_info(cfm_non_spinor_gamma, nrow_global=n_ao)
2304
2305 CALL cp_cfm_set_all(cfm_spinor_ikp, z_zero)
2306
2307 DO i_block = 0, 1
2308 DO j_block = 0, 1
2309 i_offset = i_block*n_ao + 1
2310 j_offset = j_block*n_ao + 1
2311 CALL get_cfm_submat(cfm_non_spinor_gamma, cfm_spinor_gamma, i_offset, j_offset)
2312 CALL cp_cfm_to_fm(cfm_non_spinor_gamma, fm_non_spinor_gamma_re, fm_non_spinor_gamma_im)
2313
2314 ! transform real part of Gamma-point matrix to ikp
2315 CALL cfm_ikp_from_fm_gamma(cfm_non_spinor_ikp, fm_non_spinor_gamma_re, &
2316 ikp, qs_env, kpoints, basis_type)
2317 CALL add_cfm_submat(cfm_spinor_ikp, cfm_non_spinor_ikp, i_offset, j_offset)
2318
2319 ! transform imag part of Gamma-point matrix to ikp
2320 CALL cfm_ikp_from_fm_gamma(cfm_non_spinor_ikp, fm_non_spinor_gamma_im, &
2321 ikp, qs_env, kpoints, basis_type)
2322 CALL add_cfm_submat(cfm_spinor_ikp, cfm_non_spinor_ikp, i_offset, j_offset, gaussi)
2323
2324 END DO
2325 END DO
2326
2327 CALL cp_cfm_release(cfm_non_spinor_gamma)
2328 CALL cp_cfm_release(cfm_non_spinor_ikp)
2329 CALL cp_fm_release(fm_non_spinor_gamma_re)
2330 CALL cp_fm_release(fm_non_spinor_gamma_im)
2331
2332 CALL timestop(handle)
2333
2334 END SUBROUTINE cfm_ikp_from_cfm_spinor_gamma
2335
2336! **************************************************************************************************
2337!> \brief ...
2338!> \param cfm_ikp ...
2339!> \param fm_Gamma ...
2340!> \param ikp ...
2341!> \param qs_env ...
2342!> \param kpoints ...
2343!> \param basis_type ...
2344! **************************************************************************************************
2345 SUBROUTINE cfm_ikp_from_fm_gamma(cfm_ikp, fm_Gamma, ikp, qs_env, kpoints, basis_type)
2346 TYPE(cp_cfm_type) :: cfm_ikp
2347 TYPE(cp_fm_type) :: fm_gamma
2348 INTEGER :: ikp
2349 TYPE(qs_environment_type), POINTER :: qs_env
2350 TYPE(kpoint_type), POINTER :: kpoints
2351 CHARACTER(LEN=*) :: basis_type
2352
2353 CHARACTER(LEN=*), PARAMETER :: routinen = 'cfm_ikp_from_fm_Gamma'
2354
2355 INTEGER :: col_global, handle, i, i_atom, i_atom_old, i_cell, i_mic_cell, i_row, j, j_atom, &
2356 j_atom_old, j_cell, j_col, n_bf, ncol_local, nrow_local, num_cells, row_global
2357 INTEGER, ALLOCATABLE, DIMENSION(:) :: atom_from_bf
2358 INTEGER, DIMENSION(:), POINTER :: col_indices, row_indices
2359 INTEGER, DIMENSION(:, :), POINTER :: index_to_cell
2360 LOGICAL :: i_cell_is_the_minimum_image_cell
2361 REAL(kind=dp) :: abs_rab_cell_i, abs_rab_cell_j, arg
2362 REAL(kind=dp), DIMENSION(3) :: cell_vector, cell_vector_j, rab_cell_i, &
2363 rab_cell_j
2364 REAL(kind=dp), DIMENSION(3, 3) :: hmat
2365 TYPE(cell_type), POINTER :: cell
2366 TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
2367
2368 CALL timeset(routinen, handle)
2369
2370 IF (.NOT. ASSOCIATED(cfm_ikp%local_data)) THEN
2371 CALL cp_cfm_create(cfm_ikp, fm_gamma%matrix_struct)
2372 END IF
2373 CALL cp_cfm_set_all(cfm_ikp, z_zero)
2374
2375 CALL cp_fm_get_info(matrix=fm_gamma, &
2376 nrow_local=nrow_local, &
2377 ncol_local=ncol_local, &
2378 row_indices=row_indices, &
2379 col_indices=col_indices)
2380
2381 ! get number of basis functions (bf) for different basis sets
2382 IF (basis_type == "ORB") THEN
2383 n_bf = qs_env%bs_env%n_ao
2384 ELSE IF (basis_type == "RI_AUX") THEN
2385 n_bf = qs_env%bs_env%n_RI
2386 ELSE
2387 cpabort("Only ORB and RI_AUX basis implemented.")
2388 END IF
2389
2390 ALLOCATE (atom_from_bf(n_bf))
2391 CALL get_atom_index_from_basis_function_index(qs_env, atom_from_bf, n_bf, basis_type)
2392
2393 NULLIFY (cell, particle_set)
2394 CALL get_qs_env(qs_env, cell=cell, particle_set=particle_set)
2395 CALL get_cell(cell=cell, h=hmat)
2396
2397 index_to_cell => kpoints%index_to_cell
2398
2399 num_cells = SIZE(index_to_cell, 2)
2400 i_atom_old = 0
2401 j_atom_old = 0
2402
2403 DO i_row = 1, nrow_local
2404 DO j_col = 1, ncol_local
2405
2406 row_global = row_indices(i_row)
2407 col_global = col_indices(j_col)
2408
2409 i_atom = atom_from_bf(row_global)
2410 j_atom = atom_from_bf(col_global)
2411
2412 ! we only need to check for new MIC cell for new i_atom-j_atom pair
2413 IF (i_atom .NE. i_atom_old .OR. j_atom .NE. j_atom_old) THEN
2414 DO i_cell = 1, num_cells
2415
2416 ! only check nearest neigbors
2417 IF (any(abs(index_to_cell(1:3, i_cell)) > 1)) cycle
2418
2419 cell_vector(1:3) = matmul(hmat, real(index_to_cell(1:3, i_cell), dp))
2420
2421 rab_cell_i(1:3) = pbc(particle_set(i_atom)%r(1:3), cell) - &
2422 (pbc(particle_set(j_atom)%r(1:3), cell) + cell_vector(1:3))
2423 abs_rab_cell_i = sqrt(rab_cell_i(1)**2 + rab_cell_i(2)**2 + rab_cell_i(3)**2)
2424
2425 ! minimum image convention
2426 i_cell_is_the_minimum_image_cell = .true.
2427 DO j_cell = 1, num_cells
2428 cell_vector_j(1:3) = matmul(hmat, real(index_to_cell(1:3, j_cell), dp))
2429 rab_cell_j(1:3) = pbc(particle_set(i_atom)%r(1:3), cell) - &
2430 (pbc(particle_set(j_atom)%r(1:3), cell) + cell_vector_j(1:3))
2431 abs_rab_cell_j = sqrt(rab_cell_j(1)**2 + rab_cell_j(2)**2 + rab_cell_j(3)**2)
2432
2433 IF (abs_rab_cell_i > abs_rab_cell_j + 1.0e-6_dp) THEN
2434 i_cell_is_the_minimum_image_cell = .false.
2435 END IF
2436 END DO
2437
2438 IF (i_cell_is_the_minimum_image_cell) THEN
2439 i_mic_cell = i_cell
2440 END IF
2441
2442 END DO ! i_cell
2443 END IF
2444
2445 arg = real(index_to_cell(1, i_mic_cell), dp)*kpoints%xkp(1, ikp) + &
2446 REAL(index_to_cell(2, i_mic_cell), dp)*kpoints%xkp(2, ikp) + &
2447 REAL(index_to_cell(3, i_mic_cell), dp)*kpoints%xkp(3, ikp)
2448
2449 i = i_row
2450 j = j_col
2451
2452 cfm_ikp%local_data(i, j) = cos(twopi*arg)*fm_gamma%local_data(i, j)*z_one + &
2453 sin(twopi*arg)*fm_gamma%local_data(i, j)*gaussi
2454
2455 j_atom_old = j_atom
2456 i_atom_old = i_atom
2457
2458 END DO ! j_col
2459 END DO ! i_row
2460
2461 CALL timestop(handle)
2462
2463 END SUBROUTINE cfm_ikp_from_fm_gamma
2464
2465! **************************************************************************************************
2466!> \brief ...
2467!> \param bs_env ...
2468!> \param qs_env ...
2469!> \param fm_W_MIC_freq_j ...
2470!> \param cfm_W_ikp_freq_j ...
2471!> \param ikp ...
2472!> \param kpoints ...
2473!> \param basis_type ...
2474!> \param wkp_ext ...
2475! **************************************************************************************************
2476 SUBROUTINE mic_contribution_from_ikp(bs_env, qs_env, fm_W_MIC_freq_j, &
2477 cfm_W_ikp_freq_j, ikp, kpoints, basis_type, wkp_ext)
2478 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
2479 TYPE(qs_environment_type), POINTER :: qs_env
2480 TYPE(cp_fm_type) :: fm_w_mic_freq_j
2481 TYPE(cp_cfm_type) :: cfm_w_ikp_freq_j
2482 INTEGER :: ikp
2483 TYPE(kpoint_type), POINTER :: kpoints
2484 CHARACTER(LEN=*) :: basis_type
2485 REAL(kind=dp), OPTIONAL :: wkp_ext
2486
2487 CHARACTER(LEN=*), PARAMETER :: routinen = 'MIC_contribution_from_ikp'
2488
2489 INTEGER :: handle, i_bf, iatom, iatom_old, irow, &
2490 j_bf, jatom, jatom_old, jcol, n_bf, &
2491 ncol_local, nrow_local, num_cells
2492 INTEGER, ALLOCATABLE, DIMENSION(:) :: atom_from_bf_index
2493 INTEGER, DIMENSION(:), POINTER :: col_indices, row_indices
2494 INTEGER, DIMENSION(:, :), POINTER :: index_to_cell
2495 REAL(kind=dp) :: contribution, weight_im, weight_re, &
2496 wkp_of_ikp
2497 REAL(kind=dp), DIMENSION(3, 3) :: hmat
2498 REAL(kind=dp), DIMENSION(:), POINTER :: wkp
2499 REAL(kind=dp), DIMENSION(:, :), POINTER :: xkp
2500 TYPE(cell_type), POINTER :: cell
2501 TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
2502
2503 CALL timeset(routinen, handle)
2504
2505 ! get number of basis functions (bf) for different basis sets
2506 IF (basis_type == "ORB") THEN
2507 n_bf = qs_env%bs_env%n_ao
2508 ELSE IF (basis_type == "RI_AUX") THEN
2509 n_bf = qs_env%bs_env%n_RI
2510 ELSE
2511 cpabort("Only ORB and RI_AUX basis implemented.")
2512 END IF
2513
2514 ALLOCATE (atom_from_bf_index(n_bf))
2515 CALL get_atom_index_from_basis_function_index(qs_env, atom_from_bf_index, n_bf, basis_type)
2516
2517 NULLIFY (cell, particle_set)
2518 CALL get_qs_env(qs_env, cell=cell, particle_set=particle_set)
2519 CALL get_cell(cell=cell, h=hmat)
2520
2521 CALL cp_cfm_get_info(matrix=cfm_w_ikp_freq_j, &
2522 nrow_local=nrow_local, &
2523 ncol_local=ncol_local, &
2524 row_indices=row_indices, &
2525 col_indices=col_indices)
2526
2527 CALL get_kpoint_info(kpoints, xkp=xkp, wkp=wkp)
2528 index_to_cell => kpoints%index_to_cell
2529 num_cells = SIZE(index_to_cell, 2)
2530
2531 iatom_old = 0
2532 jatom_old = 0
2533
2534 DO irow = 1, nrow_local
2535 DO jcol = 1, ncol_local
2536
2537 i_bf = row_indices(irow)
2538 j_bf = col_indices(jcol)
2539
2540 iatom = atom_from_bf_index(i_bf)
2541 jatom = atom_from_bf_index(j_bf)
2542
2543 IF (PRESENT(wkp_ext)) THEN
2544 wkp_of_ikp = wkp_ext
2545 ELSE
2546 SELECT CASE (bs_env%l_RI(i_bf) + bs_env%l_RI(j_bf))
2547 CASE (0)
2548 ! both RI functions are s-functions, k-extrapolation for 2D and 3D
2549 wkp_of_ikp = wkp(ikp)
2550 CASE (1)
2551 ! one function is an s-function, the other a p-function, k-extrapolation for 3D
2552 wkp_of_ikp = bs_env%wkp_s_p(ikp)
2553 CASE DEFAULT
2554 ! for any other matrix element of W, there is no need for extrapolation
2555 wkp_of_ikp = bs_env%wkp_no_extra(ikp)
2556 END SELECT
2557 END IF
2558
2559 IF (iatom .NE. iatom_old .OR. jatom .NE. jatom_old) THEN
2560
2561 CALL compute_weight_re_im(weight_re, weight_im, &
2562 num_cells, iatom, jatom, xkp(1:3, ikp), wkp_of_ikp, &
2563 cell, index_to_cell, hmat, particle_set)
2564
2565 iatom_old = iatom
2566 jatom_old = jatom
2567
2568 END IF
2569
2570 contribution = weight_re*real(cfm_w_ikp_freq_j%local_data(irow, jcol)) + &
2571 weight_im*aimag(cfm_w_ikp_freq_j%local_data(irow, jcol))
2572
2573 fm_w_mic_freq_j%local_data(irow, jcol) = fm_w_mic_freq_j%local_data(irow, jcol) &
2574 + contribution
2575
2576 END DO
2577 END DO
2578
2579 CALL timestop(handle)
2580
2581 END SUBROUTINE mic_contribution_from_ikp
2582
2583! **************************************************************************************************
2584!> \brief ...
2585!> \param xkp ...
2586!> \param ikp_start ...
2587!> \param ikp_end ...
2588!> \param grid ...
2589! **************************************************************************************************
2590 SUBROUTINE compute_xkp(xkp, ikp_start, ikp_end, grid)
2591
2592 REAL(kind=dp), DIMENSION(:, :), POINTER :: xkp
2593 INTEGER :: ikp_start, ikp_end
2594 INTEGER, DIMENSION(3) :: grid
2595
2596 CHARACTER(LEN=*), PARAMETER :: routinen = 'compute_xkp'
2597
2598 INTEGER :: handle, i, ix, iy, iz
2599
2600 CALL timeset(routinen, handle)
2601
2602 i = ikp_start
2603 DO ix = 1, grid(1)
2604 DO iy = 1, grid(2)
2605 DO iz = 1, grid(3)
2606
2607 IF (i > ikp_end) cycle
2608
2609 xkp(1, i) = real(2*ix - grid(1) - 1, kind=dp)/(2._dp*real(grid(1), kind=dp))
2610 xkp(2, i) = real(2*iy - grid(2) - 1, kind=dp)/(2._dp*real(grid(2), kind=dp))
2611 xkp(3, i) = real(2*iz - grid(3) - 1, kind=dp)/(2._dp*real(grid(3), kind=dp))
2612 i = i + 1
2613
2614 END DO
2615 END DO
2616 END DO
2617
2618 CALL timestop(handle)
2619
2620 END SUBROUTINE compute_xkp
2621
2622! **************************************************************************************************
2623!> \brief ...
2624!> \param kpoints ...
2625!> \param qs_env ...
2626! **************************************************************************************************
2627 SUBROUTINE kpoint_init_cell_index_simple(kpoints, qs_env)
2628
2629 TYPE(kpoint_type), POINTER :: kpoints
2630 TYPE(qs_environment_type), POINTER :: qs_env
2631
2632 CHARACTER(LEN=*), PARAMETER :: routinen = 'kpoint_init_cell_index_simple'
2633
2634 INTEGER :: handle, nimages
2635 TYPE(dft_control_type), POINTER :: dft_control
2636 TYPE(mp_para_env_type), POINTER :: para_env
2637 TYPE(neighbor_list_set_p_type), DIMENSION(:), &
2638 POINTER :: sab_orb
2639
2640 CALL timeset(routinen, handle)
2641
2642 NULLIFY (dft_control, para_env, sab_orb)
2643 CALL get_qs_env(qs_env=qs_env, para_env=para_env, dft_control=dft_control, sab_orb=sab_orb)
2644 nimages = dft_control%nimages
2645 CALL kpoint_init_cell_index(kpoints, sab_orb, para_env, dft_control)
2646
2647 ! set back dft_control%nimages
2648 dft_control%nimages = nimages
2649
2650 CALL timestop(handle)
2651
2652 END SUBROUTINE kpoint_init_cell_index_simple
2653
2654! **************************************************************************************************
2655!> \brief ...
2656!> \param qs_env ...
2657!> \param bs_env ...
2658! **************************************************************************************************
2659 SUBROUTINE soc(qs_env, bs_env)
2660 TYPE(qs_environment_type), POINTER :: qs_env
2661 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
2662
2663 CHARACTER(LEN=*), PARAMETER :: routinen = 'soc'
2664
2665 INTEGER :: handle
2666
2667 CALL timeset(routinen, handle)
2668
2669 ! V^SOC_µν^(α),R = ħ/2 < ϕ_µ cell O | sum_ℓ ΔV_ℓ^SO(r,r') L^(α) | ϕ_ν cell R>, α = x,y,z
2670 ! see Hartwigsen, Goedecker, Hutter, Eq.(18), (19) (doi.org/10.1103/PhysRevB.58.3641)
2671 CALL v_soc_xyz_from_pseudopotential(qs_env, bs_env%mat_V_SOC_xyz)
2672
2673 ! Calculate H^SOC_µν,σσ'(k) = sum_α V^SOC_µν^(α)(k)*Pauli-matrix^(α)_σσ'
2674 ! see Hartwigsen, Goedecker, Hutter, Eq.(18) (doi.org/10.1103/PhysRevB.58.3641)
2675 SELECT CASE (bs_env%small_cell_full_kp_or_large_cell_Gamma)
2676 CASE (large_cell_gamma)
2677
2678 ! H^SOC_µν,σσ' = sum_α V^SOC_µν^(α)*Pauli-matrix^(α)_σσ'
2679 CALL h_ks_spinor_gamma(bs_env)
2680
2681 CASE (small_cell_full_kp)
2682
2683 ! V^SOC_µν^(α),R -> V^SOC_µν^(α)(k); then calculate spinor H^SOC_µν,σσ'(k) (see above)
2684 CALL h_ks_spinor_kp(qs_env, bs_env)
2685
2686 END SELECT
2687
2688 CALL timestop(handle)
2689
2690 END SUBROUTINE soc
2691
2692! **************************************************************************************************
2693!> \brief ...
2694!> \param bs_env ...
2695! **************************************************************************************************
2696 SUBROUTINE h_ks_spinor_gamma(bs_env)
2697
2698 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
2699
2700 CHARACTER(LEN=*), PARAMETER :: routinen = 'H_KS_spinor_Gamma'
2701
2702 INTEGER :: handle, nao, s
2703 TYPE(cp_fm_struct_type), POINTER :: str
2704
2705 CALL timeset(routinen, handle)
2706
2707 CALL cp_fm_get_info(bs_env%fm_ks_Gamma(1), nrow_global=nao)
2708
2709 ALLOCATE (bs_env%cfm_SOC_spinor_ao(1))
2710 CALL create_cfm_double(bs_env%cfm_SOC_spinor_ao(1), fm_orig=bs_env%fm_ks_Gamma(1))
2711 CALL cp_cfm_set_all(bs_env%cfm_SOC_spinor_ao(1), z_zero)
2712
2713 str => bs_env%fm_ks_Gamma(1)%matrix_struct
2714
2715 s = nao + 1
2716
2717 ! careful: inside add_dbcsr_submat, mat_V_SOC_xyz is multiplied by i because the real matrix
2718 ! mat_V_SOC_xyz is antisymmetric as V_SOC matrix is purely imaginary and Hermitian
2719 CALL add_dbcsr_submat(bs_env%cfm_SOC_spinor_ao(1), bs_env%mat_V_SOC_xyz(1, 1)%matrix, &
2720 str, s, 1, z_one, .true.)
2721 CALL add_dbcsr_submat(bs_env%cfm_SOC_spinor_ao(1), bs_env%mat_V_SOC_xyz(2, 1)%matrix, &
2722 str, s, 1, gaussi, .true.)
2723 CALL add_dbcsr_submat(bs_env%cfm_SOC_spinor_ao(1), bs_env%mat_V_SOC_xyz(3, 1)%matrix, &
2724 str, 1, 1, z_one, .false.)
2725 CALL add_dbcsr_submat(bs_env%cfm_SOC_spinor_ao(1), bs_env%mat_V_SOC_xyz(3, 1)%matrix, &
2726 str, s, s, -z_one, .false.)
2727
2728 CALL timestop(handle)
2729
2730 END SUBROUTINE h_ks_spinor_gamma
2731
2732! **************************************************************************************************
2733!> \brief ...
2734!> \param qs_env ...
2735!> \param bs_env ...
2736! **************************************************************************************************
2737 SUBROUTINE h_ks_spinor_kp(qs_env, bs_env)
2738 TYPE(qs_environment_type), POINTER :: qs_env
2739 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
2740
2741 CHARACTER(LEN=*), PARAMETER :: routinen = 'H_KS_spinor_kp'
2742
2743 INTEGER :: handle, i_dim, ikp, n_spin, &
2744 nkp_bs_and_dos, s
2745 INTEGER, DIMENSION(:, :, :), POINTER :: cell_to_index_scf
2746 REAL(kind=dp), DIMENSION(3) :: xkp
2747 TYPE(cp_cfm_type) :: cfm_v_soc_xyz_ikp
2748 TYPE(cp_fm_struct_type), POINTER :: str
2749 TYPE(kpoint_type), POINTER :: kpoints_scf
2750 TYPE(neighbor_list_set_p_type), DIMENSION(:), &
2751 POINTER :: sab_nl
2752
2753 CALL timeset(routinen, handle)
2754
2755 nkp_bs_and_dos = bs_env%nkp_bs_and_DOS
2756 n_spin = bs_env%n_spin
2757 s = bs_env%n_ao + 1
2758 str => bs_env%cfm_ks_kp(1, 1)%matrix_struct
2759
2760 CALL cp_cfm_create(cfm_v_soc_xyz_ikp, bs_env%cfm_work_mo%matrix_struct)
2761
2762 CALL alloc_cfm_double_array_1d(bs_env%cfm_SOC_spinor_ao, bs_env%cfm_ks_kp(1, 1), nkp_bs_and_dos)
2763
2764 CALL get_qs_env(qs_env, kpoints=kpoints_scf)
2765
2766 NULLIFY (sab_nl)
2767 CALL get_kpoint_info(kpoints_scf, sab_nl=sab_nl, cell_to_index=cell_to_index_scf)
2768
2769 DO i_dim = 1, 3
2770
2771 DO ikp = 1, nkp_bs_and_dos
2772
2773 xkp(1:3) = bs_env%kpoints_DOS%xkp(1:3, ikp)
2774
2775 CALL cp_cfm_set_all(cfm_v_soc_xyz_ikp, z_zero)
2776
2777 CALL rsmat_to_kp(bs_env%mat_V_SOC_xyz, i_dim, xkp, cell_to_index_scf, &
2778 sab_nl, bs_env, cfm_v_soc_xyz_ikp, imag_rs_mat=.true.)
2779
2780 ! multiply V_SOC with i because bs_env%mat_V_SOC_xyz stores imag. part (real part = 0)
2781 CALL cp_cfm_scale(gaussi, cfm_v_soc_xyz_ikp)
2782
2783 SELECT CASE (i_dim)
2784 CASE (1)
2785 ! add V^SOC_x * σ_x for σ_x = ( (0,1) (1,0) )
2786 CALL add_cfm_submat(bs_env%cfm_SOC_spinor_ao(ikp), cfm_v_soc_xyz_ikp, 1, s)
2787 CALL add_cfm_submat(bs_env%cfm_SOC_spinor_ao(ikp), cfm_v_soc_xyz_ikp, s, 1)
2788 CASE (2)
2789 ! add V^SOC_y * σ_y for σ_y = ( (0,-i) (i,0) )
2790 CALL cp_cfm_scale(gaussi, cfm_v_soc_xyz_ikp)
2791 CALL add_cfm_submat(bs_env%cfm_SOC_spinor_ao(ikp), cfm_v_soc_xyz_ikp, 1, s)
2792 CALL cp_cfm_scale(-z_one, cfm_v_soc_xyz_ikp)
2793 CALL add_cfm_submat(bs_env%cfm_SOC_spinor_ao(ikp), cfm_v_soc_xyz_ikp, s, 1)
2794 CASE (3)
2795 ! add V^SOC_z * σ_z for σ_z = ( (1,0) (0,1) )
2796 CALL add_cfm_submat(bs_env%cfm_SOC_spinor_ao(ikp), cfm_v_soc_xyz_ikp, 1, 1)
2797 CALL cp_cfm_scale(-z_one, cfm_v_soc_xyz_ikp)
2798 CALL add_cfm_submat(bs_env%cfm_SOC_spinor_ao(ikp), cfm_v_soc_xyz_ikp, s, s)
2799 END SELECT
2800
2801 END DO
2802
2803 END DO ! ikp
2804
2805 CALL cp_cfm_release(cfm_v_soc_xyz_ikp)
2806
2807 CALL timestop(handle)
2808
2809 END SUBROUTINE h_ks_spinor_kp
2810
2811! **************************************************************************************************
2812!> \brief ...
2813!> \param cfm_array ...
2814!> \param cfm_template ...
2815!> \param n ...
2816! **************************************************************************************************
2817 SUBROUTINE alloc_cfm_double_array_1d(cfm_array, cfm_template, n)
2818 TYPE(cp_cfm_type), ALLOCATABLE, DIMENSION(:) :: cfm_array
2819 TYPE(cp_cfm_type) :: cfm_template
2820 INTEGER :: n
2821
2822 CHARACTER(LEN=*), PARAMETER :: routinen = 'alloc_cfm_double_array_1d'
2823
2824 INTEGER :: handle, i
2825
2826 CALL timeset(routinen, handle)
2827
2828 ALLOCATE (cfm_array(n))
2829 DO i = 1, n
2830 CALL create_cfm_double(cfm_array(i), cfm_orig=cfm_template)
2831 CALL cp_cfm_set_all(cfm_array(i), z_zero)
2832 END DO
2833
2834 CALL timestop(handle)
2835
2836 END SUBROUTINE alloc_cfm_double_array_1d
2837
2838! **************************************************************************************************
2839!> \brief ...
2840!> \param bs_env ...
2841! **************************************************************************************************
2842 SUBROUTINE get_all_vbm_cbm_bandgaps(bs_env)
2843
2844 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
2845
2846 CHARACTER(LEN=*), PARAMETER :: routinen = 'get_all_VBM_CBM_bandgaps'
2847
2848 INTEGER :: handle
2849
2850 CALL timeset(routinen, handle)
2851
2852 CALL get_vbm_cbm_bandgaps(bs_env%band_edges_scf, bs_env%eigenval_scf, bs_env)
2853 CALL get_vbm_cbm_bandgaps(bs_env%band_edges_G0W0, bs_env%eigenval_G0W0, bs_env)
2854 CALL get_vbm_cbm_bandgaps(bs_env%band_edges_HF, bs_env%eigenval_HF, bs_env)
2855
2856 CALL timestop(handle)
2857
2858 END SUBROUTINE get_all_vbm_cbm_bandgaps
2859
2860! **************************************************************************************************
2861!> \brief ...
2862!> \param band_edges ...
2863!> \param ev ...
2864!> \param bs_env ...
2865! **************************************************************************************************
2866 SUBROUTINE get_vbm_cbm_bandgaps(band_edges, ev, bs_env)
2867 TYPE(band_edges_type) :: band_edges
2868 REAL(kind=dp), DIMENSION(:, :, :) :: ev
2869 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
2870
2871 CHARACTER(LEN=*), PARAMETER :: routinen = 'get_VBM_CBM_bandgaps'
2872
2873 INTEGER :: handle, homo, homo_1, homo_2, ikp, &
2874 ispin, lumo, lumo_1, lumo_2, n_mo
2875 REAL(kind=dp) :: e_dbg_at_ikp
2876
2877 CALL timeset(routinen, handle)
2878
2879 n_mo = bs_env%n_ao
2880
2881 band_edges%DBG = 1000.0_dp
2882
2883 SELECT CASE (bs_env%n_spin)
2884 CASE (1)
2885 homo = bs_env%n_occ(1)
2886 lumo = homo + 1
2887 band_edges%VBM = maxval(ev(1:homo, :, 1))
2888 band_edges%CBM = minval(ev(homo + 1:n_mo, :, 1))
2889 CASE (2)
2890 homo_1 = bs_env%n_occ(1)
2891 lumo_1 = homo_1 + 1
2892 homo_2 = bs_env%n_occ(2)
2893 lumo_2 = homo_2 + 1
2894 band_edges%VBM = max(maxval(ev(1:homo_1, :, 1)), maxval(ev(1:homo_2, :, 2)))
2895 band_edges%CBM = min(minval(ev(homo_1 + 1:n_mo, :, 1)), minval(ev(homo_2 + 1:n_mo, :, 2)))
2896 CASE DEFAULT
2897 cpabort("Error with number of spins.")
2898 END SELECT
2899
2900 band_edges%IDBG = band_edges%CBM - band_edges%VBM
2901
2902 DO ispin = 1, bs_env%n_spin
2903
2904 homo = bs_env%n_occ(ispin)
2905
2906 DO ikp = 1, bs_env%nkp_bs_and_DOS
2907
2908 e_dbg_at_ikp = -maxval(ev(1:homo, ikp, ispin)) + minval(ev(homo + 1:n_mo, ikp, ispin))
2909
2910 IF (e_dbg_at_ikp < band_edges%DBG) band_edges%DBG = e_dbg_at_ikp
2911
2912 END DO
2913
2914 END DO
2915
2916 CALL timestop(handle)
2917
2918 END SUBROUTINE get_vbm_cbm_bandgaps
2919
static GRID_HOST_DEVICE int modulo(int a, int m)
Equivalent of Fortran's MODULO, which always return a positive number. https://gcc....
static GRID_HOST_DEVICE int idx(const orbital a)
Return coset index of given orbital angular momentum.
Define the atomic kind types and their sub types.
subroutine, public get_atomic_kind_set(atomic_kind_set, atom_of_kind, kind_of, natom_of_kind, maxatom, natom, nshell, fist_potential_present, shell_present, shell_adiabatic, shell_check_distance, damping_present)
Get attributes of an atomic kind set.
subroutine, public get_atomic_kind(atomic_kind, fist_potential, element_symbol, name, mass, kind_number, natom, atom_list, rcov, rvdw, z, qeff, apol, cpol, mm_radius, shell, shell_active, damping)
Get attributes of an atomic kind.
Handles all functions related to the CELL.
Definition cell_types.F:15
subroutine, public get_cell(cell, alpha, beta, gamma, deth, orthorhombic, abc, periodic, h, h_inv, symmetry_id, tag)
Get informations about a simulation cell.
Definition cell_types.F:195
methods related to the blacs parallel environment
Basic linear algebra operations for complex full matrices.
various cholesky decomposition related routines
subroutine, public cp_cfm_cholesky_decompose(matrix, n, info_out)
Used to replace a symmetric positive definite matrix M with its Cholesky decomposition U: M = U^T * U...
used for collecting diagonalization schemes available for cp_cfm_type
Definition cp_cfm_diag.F:14
subroutine, public cp_cfm_geeig(amatrix, bmatrix, eigenvectors, eigenvalues, work)
General Eigenvalue Problem AX = BXE Single option version: Cholesky decomposition of B.
subroutine, public cp_cfm_heevd(matrix, eigenvectors, eigenvalues)
Perform a diagonalisation of a complex matrix.
Definition cp_cfm_diag.F:58
subroutine, public cp_cfm_geeig_canon(amatrix, bmatrix, eigenvectors, eigenvalues, work, epseig)
General Eigenvalue Problem AX = BXE Use canonical orthogonalization.
Represents a complex full matrix distributed on many processors.
subroutine, public cp_cfm_create(matrix, matrix_struct, name)
Creates a new full matrix with the given structure.
subroutine, public cp_cfm_release(matrix)
Releases a full matrix.
subroutine, public cp_fm_to_cfm(msourcer, msourcei, mtarget)
Construct a complex full matrix by taking its real and imaginary parts from two separate real-value f...
subroutine, public cp_cfm_get_info(matrix, name, nrow_global, ncol_global, nrow_block, ncol_block, nrow_local, ncol_local, row_indices, col_indices, local_data, context, matrix_struct, para_env)
Returns information about a full matrix.
subroutine, public cp_cfm_set_all(matrix, alpha, beta)
Set all elements of the full matrix to alpha. Besides, set all diagonal matrix elements to beta (if g...
subroutine, public cp_cfm_to_fm(msource, mtargetr, mtargeti)
Copy real and imaginary parts of a complex full matrix into separate real-value full matrices.
Defines control structures, which contain the parameters and the settings for the DFT-based calculati...
subroutine, public dbcsr_deallocate_matrix(matrix)
...
subroutine, public dbcsr_desymmetrize(matrix_a, matrix_b)
...
subroutine, public dbcsr_set(matrix, alpha)
...
DBCSR operations in CP2K.
subroutine, public copy_dbcsr_to_fm(matrix, fm)
Copy a DBCSR matrix to a BLACS matrix.
subroutine, public copy_fm_to_dbcsr(fm, matrix, keep_sparsity)
Copy a BLACS matrix to a dbcsr matrix.
Utility routines to open and close files. Tracking of preconnections.
Definition cp_files.F:16
subroutine, public open_file(file_name, file_status, file_form, file_action, file_position, file_pad, unit_number, debug, skip_get_unit_number, file_access)
Opens the requested file using a free unit number.
Definition cp_files.F:308
subroutine, public close_file(unit_number, file_status, keep_preconnection)
Close an open file given by its logical unit number. Optionally, keep the file and unit preconnected.
Definition cp_files.F:119
used for collecting some of the diagonalization schemes available for cp_fm_type. cp_fm_power also mo...
Definition cp_fm_diag.F:17
subroutine, public cp_fm_geeig_canon(amatrix, bmatrix, eigenvectors, eigenvalues, work, epseig)
General Eigenvalue Problem AX = BXE Use canonical diagonalization : U*s**(-1/2)
represent the structure of a full matrix
subroutine, public cp_fm_struct_create(fmstruct, para_env, context, nrow_global, ncol_global, nrow_block, ncol_block, descriptor, first_p_pos, local_leading_dimension, template_fmstruct, square_blocks, force_block)
allocates and initializes a full matrix structure
subroutine, public cp_fm_struct_release(fmstruct)
releases a full matrix structure
represent a full matrix distributed on many processors
Definition cp_fm_types.F:15
subroutine, public cp_fm_get_diag(matrix, diag)
returns the diagonal elements of a fm
subroutine, public cp_fm_get_info(matrix, name, nrow_global, ncol_global, nrow_block, ncol_block, nrow_local, ncol_local, row_indices, col_indices, local_data, context, nrow_locals, ncol_locals, matrix_struct, para_env)
returns all kind of information about the full matrix
subroutine, public cp_fm_set_all(matrix, alpha, beta)
set all elements of a matrix to the same value, and optionally the diagonal to a different one
subroutine, public cp_fm_create(matrix, matrix_struct, name, use_sp)
creates a new full matrix with the given structure
various routines to log and control the output. The idea is that decisions about where to log should ...
integer function, public cp_logger_get_default_io_unit(logger)
returns the unit nr for the ionode (-1 on all other processors) skips as well checks if the procs cal...
Utility routines to read data from files. Kept as close as possible to the old parser because.
elemental subroutine, public read_float_object(string, object, error_message)
Returns a floating point number read from a string including fraction like z1/z2.
collects all constants needed in input so that they can be used without circular dependencies
integer, parameter, public int_ldos_z
integer, parameter, public small_cell_full_kp
integer, parameter, public gaussian
integer, parameter, public large_cell_gamma
objects that represent the structure of input sections and the data contained in an input section
recursive type(section_vals_type) function, pointer, public section_vals_get_subs_vals(section_vals, subsection_name, i_rep_section, can_return_null)
returns the values of the requested subsection
subroutine, public section_vals_get(section_vals, ref_count, n_repetition, n_subs_vals_rep, section, explicit)
returns various attributes about the section_vals
subroutine, public section_vals_val_get(section_vals, keyword_name, i_rep_section, i_rep_val, n_rep_val, val, l_val, i_val, r_val, c_val, l_vals, i_vals, r_vals, c_vals, explicit)
returns the requested value
Defines the basic variable types.
Definition kinds.F:23
integer, parameter, public max_line_length
Definition kinds.F:59
integer, parameter, public dp
Definition kinds.F:34
integer, parameter, public default_string_length
Definition kinds.F:57
Routines needed for kpoint calculation.
subroutine, public rskp_transform(rmatrix, cmatrix, rsmat, ispin, xkp, cell_to_index, sab_nl, is_complex, rs_sign)
Transformation of real space matrices to a kpoint.
subroutine, public kpoint_init_cell_index(kpoint, sab_nl, para_env, dft_control)
Generates the mapping of cell indices and linear RS index CELL (0,0,0) is always mapped to index 1.
Types and basic routines needed for a kpoint calculation.
subroutine, public kpoint_create(kpoint)
Create a kpoint environment.
subroutine, public get_kpoint_info(kpoint, kp_scheme, nkp_grid, kp_shift, symmetry, verbose, full_grid, use_real_wfn, eps_geo, parallel_group_size, kp_range, nkp, xkp, wkp, para_env, blacs_env_all, para_env_kp, para_env_inter_kp, blacs_env, kp_env, kp_aux_env, mpools, iogrp, nkp_groups, kp_dist, cell_to_index, index_to_cell, sab_nl, sab_nl_nosym)
Retrieve information from a kpoint environment.
Machine interface based on Fortran 2003 and POSIX.
Definition machine.F:17
real(kind=dp) function, public m_walltime()
returns time from a real-time clock, protected against rolling early/easily
Definition machine.F:147
Definition of mathematical constants and functions.
complex(kind=dp), parameter, public z_one
complex(kind=dp), parameter, public gaussi
real(kind=dp), parameter, public twopi
complex(kind=dp), parameter, public z_zero
Interface to the message passing library MPI.
basic linear algebra operations for full matrixes
Define the data structure for the particle information.
Definition of physical constants:
Definition physcon.F:68
real(kind=dp), parameter, public evolt
Definition physcon.F:183
real(kind=dp), parameter, public angstrom
Definition physcon.F:144
subroutine, public dos_pdos_ldos(qs_env, bs_env)
...
subroutine, public rsmat_to_kp(mat_rs, ispin, xkp, cell_to_index_scf, sab_nl, bs_env, cfm_kp, imag_rs_mat)
...
subroutine, public kpoint_init_cell_index_simple(kpoints, qs_env)
...
subroutine, public cfm_ikp_from_fm_gamma(cfm_ikp, fm_gamma, ikp, qs_env, kpoints, basis_type)
...
subroutine, public get_all_vbm_cbm_bandgaps(bs_env)
...
subroutine, public soc(qs_env, bs_env)
...
subroutine, public mic_contribution_from_ikp(bs_env, qs_env, fm_w_mic_freq_j, cfm_w_ikp_freq_j, ikp, kpoints, basis_type, wkp_ext)
...
subroutine, public compute_xkp(xkp, ikp_start, ikp_end, grid)
...
subroutine, public create_and_init_bs_env(qs_env, bs_env, post_scf_bandstructure_section)
...
subroutine, public get_vbm_cbm_bandgaps(band_edges, ev, bs_env)
...
container for various plainwaves related things
subroutine, public pw_env_get(pw_env, pw_pools, cube_info, gridlevel_info, auxbas_pw_pool, auxbas_grid, auxbas_rs_desc, auxbas_rs_grid, rs_descs, rs_grids, xc_pw_pool, vdw_pw_pool, poisson_env, interp_section)
returns the various attributes of the pw env
Manages a pool of grids (to be used for example as tmp objects), but can also be used to instantiate ...
Calculate the plane wave density by collocating the primitive Gaussian functions (pgf).
subroutine, public calculate_rho_elec(matrix_p, matrix_p_kp, rho, rho_gspace, total_rho, ks_env, soft_valid, compute_tau, compute_grad, basis_type, der_type, idir, task_list_external, pw_env_external)
computes the density corresponding to a given density matrix on the grid
subroutine, public get_qs_env(qs_env, atomic_kind_set, qs_kind_set, cell, super_cell, cell_ref, use_ref_cell, kpoints, dft_control, mos, sab_orb, sab_all, qmmm, qmmm_periodic, sac_ae, sac_ppl, sac_lri, sap_ppnl, sab_vdw, sab_scp, sap_oce, sab_lrc, sab_se, sab_xtbe, sab_tbe, sab_core, sab_xb, sab_xtb_pp, sab_xtb_nonbond, sab_almo, sab_kp, sab_kp_nosym, particle_set, energy, force, matrix_h, matrix_h_im, matrix_ks, matrix_ks_im, matrix_vxc, run_rtp, rtp, matrix_h_kp, matrix_h_im_kp, matrix_ks_kp, matrix_ks_im_kp, matrix_vxc_kp, kinetic_kp, matrix_s_kp, matrix_w_kp, matrix_s_ri_aux_kp, matrix_s, matrix_s_ri_aux, matrix_w, matrix_p_mp2, matrix_p_mp2_admm, rho, rho_xc, pw_env, ewald_env, ewald_pw, active_space, mpools, input, para_env, blacs_env, scf_control, rel_control, kinetic, qs_charges, vppl, rho_core, rho_nlcc, rho_nlcc_g, ks_env, ks_qmmm_env, wf_history, scf_env, local_particles, local_molecules, distribution_2d, dbcsr_dist, molecule_kind_set, molecule_set, subsys, cp_subsys, oce, local_rho_set, rho_atom_set, task_list, task_list_soft, rho0_atom_set, rho0_mpole, rhoz_set, ecoul_1c, rho0_s_rs, rho0_s_gs, do_kpoints, has_unit_metric, requires_mo_derivs, mo_derivs, mo_loc_history, nkind, natom, nelectron_total, nelectron_spin, efield, neighbor_list_id, linres_control, xas_env, virial, cp_ddapc_env, cp_ddapc_ewald, outer_scf_history, outer_scf_ihistory, x_data, et_coupling, dftb_potential, results, se_taper, se_store_int_env, se_nddo_mpole, se_nonbond_env, admm_env, lri_env, lri_density, exstate_env, ec_env, harris_env, dispersion_env, gcp_env, vee, rho_external, external_vxc, mask, mp2_env, bs_env, kg_env, wanniercentres, atprop, ls_scf_env, do_transport, transport_env, v_hartree_rspace, s_mstruct_changed, rho_changed, potential_changed, forces_up_to_date, mscfg_env, almo_scf_env, gradient_history, variable_history, embed_pot, spin_embed_pot, polar_env, mos_last_converged, eeq, rhs)
Get the QUICKSTEP environment.
Definition and initialisation of the mo data type.
Definition qs_mo_types.F:22
subroutine, public get_mo_set(mo_set, maxocc, homo, lfomo, nao, nelectron, n_el_f, nmo, eigenvalues, occupation_numbers, mo_coeff, mo_coeff_b, uniform_occupation, kts, mu, flexible_electron_count)
Get the components of a MO set data structure.
Define the neighbor list data types and the corresponding functionality.
Utility routines for GW with imaginary time.
subroutine, public compute_weight_re_im(weight_re, weight_im, num_cells, iatom, jatom, xkp, wkp_w, cell, index_to_cell, hmat, particle_set)
...
subroutine, public get_atom_index_from_basis_function_index(qs_env, atom_from_basis_index, basis_size, basis_type, first_bf_from_atom)
...
parameters that control an scf iteration
subroutine, public v_soc_xyz_from_pseudopotential(qs_env, mat_v_soc_xyz)
V^SOC_µν^(α),R = ħ/2 < ϕ_µ cell O | sum_ℓ ΔV_ℓ^SO(r,r') L^(α) | ϕ_ν cell R>, α = x,...
subroutine, public remove_soc_outside_energy_window_mo(cfm_ks_spinor, e_win, eigenval, e_homo, e_lumo)
...
subroutine, public create_cfm_double(cfm_double, fm_orig, cfm_orig)
...
subroutine, public add_dbcsr_submat(cfm_mat_target, mat_source, fm_struct_source, nstart_row, nstart_col, factor, add_also_herm_conj)
...
subroutine, public add_cfm_submat(cfm_mat_target, cfm_mat_source, nstart_row, nstart_col, factor)
...
subroutine, public get_cfm_submat(cfm_mat_target, cfm_mat_source, nstart_row, nstart_col)
...
subroutine, public cfm_add_on_diag(cfm, alpha)
...
Provides all information about an atomic kind.
Type defining parameters related to the simulation cell.
Definition cell_types.F:55
represent a blacs multidimensional parallel environment (for the mpi corrispective see cp_paratypes/m...
Represent a complex full matrix.
keeps the information about the structure of a full matrix
represent a full matrix
Contains information about kpoints.
stores all the informations relevant to an mpi environment
contained for different pw related things
Manages a pool of grids (to be used for example as tmp objects), but can also be used to instantiate ...
calculation environment to calculate the ks matrix, holds all the needed vars. assumes that the core ...