(git:81d9eb2)
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)), source=0)
1396
1397 ! transform interval [i_x_start, i_x_end] to [1, bin_mesh(1)] (and same for y)
1398 DO i_y = i_y_start, i_y_end
1399 DO i_x = i_x_start, i_x_end
1400 i_x_bin = bin_mesh(1)*(i_x - i_x_start_glob)/(i_x_end_glob - i_x_start_glob + 1) + 1
1401 i_y_bin = bin_mesh(2)*(i_y - i_y_start_glob)/(i_y_end_glob - i_y_start_glob + 1) + 1
1402 ldos_2d_bins(i_x_bin, i_y_bin, :) = ldos_2d_bins(i_x_bin, i_y_bin, :) + &
1403 ldos_2d(i_x, i_y, :)
1404 n_sum_for_bins(i_x_bin, i_y_bin) = n_sum_for_bins(i_x_bin, i_y_bin) + 1
1405 END DO
1406 END DO
1407
1408 CALL bs_env%para_env%sum(ldos_2d_bins)
1409 CALL bs_env%para_env%sum(n_sum_for_bins)
1410
1411 ! divide by number of terms in the sum so we have the average LDOS(x,y,E)
1412 DO i_y_bin = 1, bin_mesh(2)
1413 DO i_x_bin = 1, bin_mesh(1)
1414 ldos_2d_bins(i_x_bin, i_y_bin, :) = ldos_2d_bins(i_x_bin, i_y_bin, :)/ &
1415 REAL(n_sum_for_bins(i_x_bin, i_y_bin), kind=dp)
1416 END DO
1417 END DO
1418
1419 ELSE
1420
1421 ldos_2d_bins(:, :, :) = ldos_2d(:, :, :)
1422
1423 END IF
1424
1425 IF (bin_mesh(1)*bin_mesh(2) < bs_env%n_bins_max_for_printing) THEN
1426 CALL print_ldos_2d_bins(ldos_2d_bins, bs_env, e_min, scf_gw_soc)
1427 ELSE
1428 cpwarn("The number of bins for the LDOS is too large. Decrease BIN_MESH.")
1429 END IF
1430
1431 CALL timestop(handle)
1432
1433 END SUBROUTINE print_ldos_main
1434
1435! **************************************************************************************************
1436!> \brief ...
1437!> \param LDOS_2d_bins ...
1438!> \param bs_env ...
1439!> \param E_min ...
1440!> \param scf_gw_soc ...
1441! **************************************************************************************************
1442 SUBROUTINE print_ldos_2d_bins(LDOS_2d_bins, bs_env, E_min, scf_gw_soc)
1443 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :, :) :: ldos_2d_bins
1444 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
1445 REAL(kind=dp) :: e_min
1446 CHARACTER(LEN=*) :: scf_gw_soc
1447
1448 CHARACTER(LEN=*), PARAMETER :: routinen = 'print_LDOS_2d_bins'
1449
1450 CHARACTER(LEN=18) :: print_format
1451 CHARACTER(LEN=4) :: print_format_1, print_format_2
1452 CHARACTER(len=default_string_length) :: fname
1453 INTEGER :: handle, i_e, i_x, i_x_end, i_x_start, &
1454 i_y, i_y_end, i_y_start, iunit, n_e, &
1455 n_x, n_y
1456 REAL(kind=dp) :: energy
1457 REAL(kind=dp), DIMENSION(3) :: coord, idx
1458
1459 CALL timeset(routinen, handle)
1460
1461 i_x_start = lbound(ldos_2d_bins, 1)
1462 i_x_end = ubound(ldos_2d_bins, 1)
1463 i_y_start = lbound(ldos_2d_bins, 2)
1464 i_y_end = ubound(ldos_2d_bins, 2)
1465 n_e = SIZE(ldos_2d_bins, 3)
1466
1467 n_x = i_x_end - i_x_start + 1
1468 n_y = i_y_end - i_y_start + 1
1469
1470 IF (bs_env%para_env%is_source()) THEN
1471
1472 DO i_y = i_y_start, i_y_end
1473 DO i_x = i_x_start, i_x_end
1474
1475 idx(1) = (real(i_x, kind=dp) - 0.5_dp)/real(n_x, kind=dp)
1476 idx(2) = (real(i_y, kind=dp) - 0.5_dp)/real(n_y, kind=dp)
1477 idx(3) = 0.0_dp
1478 coord(1:3) = matmul(bs_env%hmat, idx)
1479
1480 CALL get_print_format(coord(1), print_format_1)
1481 CALL get_print_format(coord(2), print_format_2)
1482
1483 print_format = "(3A,"//print_format_1//",A,"//print_format_2//",A)"
1484
1485 WRITE (fname, print_format) "LDOS_", scf_gw_soc, &
1486 "_at_x_", coord(1)*angstrom, '_A_and_y_', coord(2)*angstrom, '_A'
1487
1488 CALL open_file(trim(fname), unit_number=iunit, file_status="REPLACE", &
1489 file_action="WRITE")
1490
1491 WRITE (iunit, "(2A)") Å" Energy E (eV) average LDOS(x,y,E) (1/(eV*^2), ", &
1492 "integrated over z, averaged inside bin)"
1493
1494 DO i_e = 1, n_e
1495 energy = e_min + i_e*bs_env%energy_step_DOS
1496 WRITE (iunit, "(2F17.3)") energy*evolt, &
1497 ldos_2d_bins(i_x, i_y, i_e)* &
1498 bs_env%unit_ldos_int_z_inv_Ang2_eV
1499 END DO
1500
1501 CALL close_file(iunit)
1502
1503 END DO
1504 END DO
1505
1506 END IF
1507
1508 CALL timestop(handle)
1509
1510 END SUBROUTINE print_ldos_2d_bins
1511
1512! **************************************************************************************************
1513!> \brief ...
1514!> \param coord ...
1515!> \param print_format ...
1516! **************************************************************************************************
1517 SUBROUTINE get_print_format(coord, print_format)
1518 REAL(kind=dp) :: coord
1519 CHARACTER(LEN=4) :: print_format
1520
1521 CHARACTER(LEN=*), PARAMETER :: routinen = 'get_print_format'
1522
1523 INTEGER :: handle
1524
1525 CALL timeset(routinen, handle)
1526
1527 IF (coord < -10000/angstrom) THEN
1528 print_format = "F9.2"
1529 ELSE IF (coord < -1000/angstrom) THEN
1530 print_format = "F8.2"
1531 ELSE IF (coord < -100/angstrom) THEN
1532 print_format = "F7.2"
1533 ELSE IF (coord < -10/angstrom) THEN
1534 print_format = "F6.2"
1535 ELSE IF (coord < -1/angstrom) THEN
1536 print_format = "F5.2"
1537 ELSE IF (coord < 10/angstrom) THEN
1538 print_format = "F4.2"
1539 ELSE IF (coord < 100/angstrom) THEN
1540 print_format = "F5.2"
1541 ELSE IF (coord < 1000/angstrom) THEN
1542 print_format = "F6.2"
1543 ELSE IF (coord < 10000/angstrom) THEN
1544 print_format = "F7.2"
1545 ELSE
1546 print_format = "F8.2"
1547 END IF
1548
1549 CALL timestop(handle)
1550
1551 END SUBROUTINE get_print_format
1552
1553! **************************************************************************************************
1554!> \brief ...
1555!> \param bs_env ...
1556!> \param qs_env ...
1557!> \param ikp ...
1558!> \param eigenval_no_SOC ...
1559!> \param band_edges_no_SOC ...
1560!> \param E_min ...
1561!> \param cfm_mos_ikp ...
1562!> \param DOS ...
1563!> \param PDOS ...
1564!> \param band_edges ...
1565!> \param eigenval_spinor ...
1566!> \param cfm_spinor_wf_ikp ...
1567! **************************************************************************************************
1568 SUBROUTINE soc_ev(bs_env, qs_env, ikp, eigenval_no_SOC, band_edges_no_SOC, E_min, cfm_mos_ikp, &
1569 DOS, PDOS, band_edges, eigenval_spinor, cfm_spinor_wf_ikp)
1570
1571 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
1572 TYPE(qs_environment_type), POINTER :: qs_env
1573 INTEGER :: ikp
1574 REAL(kind=dp), DIMENSION(:, :, :) :: eigenval_no_soc
1575 TYPE(band_edges_type) :: band_edges_no_soc
1576 REAL(kind=dp) :: e_min
1577 TYPE(cp_cfm_type), DIMENSION(2) :: cfm_mos_ikp
1578 REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: dos
1579 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :) :: pdos
1580 TYPE(band_edges_type) :: band_edges
1581 REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: eigenval_spinor
1582 TYPE(cp_cfm_type) :: cfm_spinor_wf_ikp
1583
1584 CHARACTER(LEN=*), PARAMETER :: routinen = 'SOC_ev'
1585
1586 INTEGER :: handle, homo_spinor, n_ao, n_e, nkind
1587 REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: eigenval_spinor_no_soc
1588 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :) :: proj_mo_on_kind_spinor
1589 TYPE(cp_cfm_type) :: cfm_eigenvec_ikp_spinor, &
1590 cfm_ks_ikp_spinor, cfm_mos_ikp_spinor, &
1591 cfm_soc_ikp_spinor, cfm_work_ikp_spinor
1592
1593 CALL timeset(routinen, handle)
1594
1595 n_ao = bs_env%n_ao
1596 homo_spinor = bs_env%n_occ(1) + bs_env%n_occ(bs_env%n_spin)
1597 n_e = SIZE(dos)
1598 nkind = SIZE(pdos, 2)
1599
1600 CALL cp_cfm_create(cfm_ks_ikp_spinor, bs_env%cfm_SOC_spinor_ao(1)%matrix_struct)
1601 CALL cp_cfm_create(cfm_soc_ikp_spinor, bs_env%cfm_SOC_spinor_ao(1)%matrix_struct)
1602 CALL cp_cfm_create(cfm_mos_ikp_spinor, bs_env%cfm_SOC_spinor_ao(1)%matrix_struct)
1603 CALL cp_cfm_create(cfm_work_ikp_spinor, bs_env%cfm_SOC_spinor_ao(1)%matrix_struct)
1604 CALL cp_cfm_create(cfm_eigenvec_ikp_spinor, bs_env%cfm_SOC_spinor_ao(1)%matrix_struct)
1605
1606 ALLOCATE (eigenval_spinor_no_soc(2*n_ao))
1607 ALLOCATE (proj_mo_on_kind_spinor(2*n_ao, nkind))
1608 ! PDOS not yet implemented -> projection is just zero -> PDOS is zero
1609 proj_mo_on_kind_spinor(:, :) = 0.0_dp
1610
1611 ! 1. get V^SOC_µν,σσ'(k_i)
1612 SELECT CASE (bs_env%small_cell_full_kp_or_large_cell_Gamma)
1613 CASE (large_cell_gamma)
1614
1615 ! 1. get V^SOC_µν,σσ'(k_i) from V^SOC_µν,σσ'(k=0)
1616 CALL cfm_ikp_from_cfm_spinor_gamma(cfm_soc_ikp_spinor, &
1617 bs_env%cfm_SOC_spinor_ao(1), &
1618 bs_env%fm_s_Gamma%matrix_struct, &
1619 ikp, qs_env, bs_env%kpoints_DOS, "ORB")
1620
1621 CASE (small_cell_full_kp)
1622
1623 ! 1. V^SOC_µν,σσ'(k_i) already there
1624 CALL cp_cfm_to_cfm(bs_env%cfm_SOC_spinor_ao(ikp), cfm_soc_ikp_spinor)
1625
1626 END SELECT
1627
1628 ! 2. V^SOC_nn',σσ'(k_i) = sum_µν C^*_µn,σ(k_i) V^SOC_µν,σσ'(k_i) C_νn'(k_i),
1629 ! C_µn,σ(k_i): MO coefficiencts from diagonalizing KS-matrix h^KS_nn',σσ'(k_i)
1630
1631 ! 2.1 build matrix C_µn,σ(k_i)
1632 CALL cp_cfm_set_all(cfm_mos_ikp_spinor, z_zero)
1633 CALL add_cfm_submat(cfm_mos_ikp_spinor, cfm_mos_ikp(1), 1, 1)
1634 CALL add_cfm_submat(cfm_mos_ikp_spinor, cfm_mos_ikp(bs_env%n_spin), n_ao + 1, n_ao + 1)
1635
1636 ! 2.2 work_nν,σσ' = sum_µ C^*_µn,σ(k_i) V^SOC_µν,σσ'(k_i)
1637 CALL parallel_gemm('C', 'N', 2*n_ao, 2*n_ao, 2*n_ao, z_one, &
1638 cfm_mos_ikp_spinor, cfm_soc_ikp_spinor, &
1639 z_zero, cfm_work_ikp_spinor)
1640
1641 ! 2.3 V^SOC_nn',σσ'(k_i) = sum_ν work_nν,σσ' C_νn'(k_i)
1642 CALL parallel_gemm('N', 'N', 2*n_ao, 2*n_ao, 2*n_ao, z_one, &
1643 cfm_work_ikp_spinor, cfm_mos_ikp_spinor, &
1644 z_zero, cfm_ks_ikp_spinor)
1645
1646 ! 3. remove SOC outside of energy window (otherwise, numerical problems arise
1647 ! because energetically low semicore states and energetically very high
1648 ! unbound states couple to the states around the Fermi level)
1649 eigenval_spinor_no_soc(1:n_ao) = eigenval_no_soc(1:n_ao, ikp, 1)
1650 eigenval_spinor_no_soc(n_ao + 1:) = eigenval_no_soc(1:n_ao, ikp, bs_env%n_spin)
1651 IF (bs_env%energy_window_soc > 0.0_dp) THEN
1652 CALL remove_soc_outside_energy_window_mo(cfm_ks_ikp_spinor, &
1653 bs_env%energy_window_soc, &
1654 eigenval_spinor_no_soc, &
1655 band_edges_no_soc%VBM, &
1656 band_edges_no_soc%CBM)
1657 END IF
1658
1659 ! 4. h^G0W0+SOC_nn',σσ'(k_i) = ε_nσ^G0W0(k_i) δ_nn' δ_σσ' + V^SOC_nn',σσ'(k_i)
1660 CALL cfm_add_on_diag(cfm_ks_ikp_spinor, eigenval_spinor_no_soc)
1661
1662 ! 5. diagonalize h^G0W0+SOC_nn',σσ'(k_i) to get eigenvalues
1663 CALL cp_cfm_heevd(cfm_ks_ikp_spinor, cfm_eigenvec_ikp_spinor, eigenval_spinor)
1664
1665 ! 6. DOS from spinors, no PDOS
1666 CALL add_to_dos_pdos(dos, pdos, eigenval_spinor, &
1667 ikp, bs_env, n_e, e_min, proj_mo_on_kind_spinor)
1668
1669 ! 7. valence band max. (VBM), conduction band min. (CBM) and direct bandgap (DBG)
1670 band_edges%VBM = max(band_edges%VBM, eigenval_spinor(homo_spinor))
1671 band_edges%CBM = min(band_edges%CBM, eigenval_spinor(homo_spinor + 1))
1672 band_edges%DBG = min(band_edges%DBG, eigenval_spinor(homo_spinor + 1) &
1673 - eigenval_spinor(homo_spinor))
1674
1675 ! 8. spinor wavefunctions:
1676 CALL parallel_gemm('N', 'N', 2*n_ao, 2*n_ao, 2*n_ao, z_one, &
1677 cfm_mos_ikp_spinor, cfm_eigenvec_ikp_spinor, &
1678 z_zero, cfm_spinor_wf_ikp)
1679
1680 CALL cp_cfm_release(cfm_ks_ikp_spinor)
1681 CALL cp_cfm_release(cfm_soc_ikp_spinor)
1682 CALL cp_cfm_release(cfm_work_ikp_spinor)
1683 CALL cp_cfm_release(cfm_eigenvec_ikp_spinor)
1684 CALL cp_cfm_release(cfm_mos_ikp_spinor)
1685
1686 CALL timestop(handle)
1687
1688 END SUBROUTINE soc_ev
1689
1690! **************************************************************************************************
1691!> \brief ...
1692!> \param DOS ...
1693!> \param PDOS ...
1694!> \param eigenval ...
1695!> \param ikp ...
1696!> \param bs_env ...
1697!> \param n_E ...
1698!> \param E_min ...
1699!> \param proj_mo_on_kind ...
1700! **************************************************************************************************
1701 SUBROUTINE add_to_dos_pdos(DOS, PDOS, eigenval, ikp, bs_env, n_E, E_min, proj_mo_on_kind)
1702
1703 REAL(kind=dp), DIMENSION(:) :: dos
1704 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :) :: pdos
1705 REAL(kind=dp), DIMENSION(:) :: eigenval
1706 INTEGER :: ikp
1707 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
1708 INTEGER :: n_e
1709 REAL(kind=dp) :: e_min
1710 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :) :: proj_mo_on_kind
1711
1712 CHARACTER(LEN=*), PARAMETER :: routinen = 'add_to_DOS_PDOS'
1713
1714 INTEGER :: handle, i_e, i_kind, i_mo, n_mo, nkind
1715 REAL(kind=dp) :: broadening, energy, energy_step_dos, wkp
1716
1717 CALL timeset(routinen, handle)
1718
1719 energy_step_dos = bs_env%energy_step_DOS
1720 broadening = bs_env%broadening_DOS
1721
1722 n_mo = SIZE(eigenval)
1723 nkind = SIZE(proj_mo_on_kind, 2)
1724
1725 ! normalize to closed-shell / open-shell
1726 wkp = bs_env%kpoints_DOS%wkp(ikp)*bs_env%spin_degeneracy
1727 DO i_e = 1, n_e
1728 energy = e_min + i_e*energy_step_dos
1729 DO i_mo = 1, n_mo
1730 ! DOS
1731 dos(i_e) = dos(i_e) + wkp*gaussian(energy - eigenval(i_mo), broadening)
1732
1733 ! PDOS
1734 DO i_kind = 1, nkind
1735 IF (proj_mo_on_kind(i_mo, i_kind) > 0.0_dp) THEN
1736 pdos(i_e, i_kind) = pdos(i_e, i_kind) + &
1737 proj_mo_on_kind(i_mo, i_kind)*wkp* &
1738 gaussian(energy - eigenval(i_mo), broadening)
1739 END IF
1740 END DO
1741 END DO
1742 END DO
1743
1744 CALL timestop(handle)
1745
1746 END SUBROUTINE add_to_dos_pdos
1747
1748! **************************************************************************************************
1749!> \brief ...
1750!> \param LDOS_2d ...
1751!> \param qs_env ...
1752!> \param ikp ...
1753!> \param bs_env ...
1754!> \param cfm_mos_ikp ...
1755!> \param eigenval ...
1756!> \param band_edges ...
1757!> \param do_spinor ...
1758!> \param cfm_non_spinor ...
1759! **************************************************************************************************
1760 SUBROUTINE add_to_ldos_2d(LDOS_2d, qs_env, ikp, bs_env, cfm_mos_ikp, eigenval, &
1761 band_edges, do_spinor, cfm_non_spinor)
1762 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :, :) :: ldos_2d
1763 TYPE(qs_environment_type), POINTER :: qs_env
1764 INTEGER :: ikp
1765 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
1766 TYPE(cp_cfm_type) :: cfm_mos_ikp
1767 REAL(kind=dp), DIMENSION(:) :: eigenval
1768 TYPE(band_edges_type) :: band_edges
1769 LOGICAL, OPTIONAL :: do_spinor
1770 TYPE(cp_cfm_type), OPTIONAL :: cfm_non_spinor
1771
1772 CHARACTER(LEN=*), PARAMETER :: routinen = 'add_to_LDOS_2d'
1773
1774 INTEGER :: handle, i_e, i_x_end, i_x_start, i_y_end, i_y_start, i_z, i_z_end, i_z_start, &
1775 j_col, j_mo, n_e, n_mo, n_z, ncol_local, nimages, z_end_global, z_start_global
1776 INTEGER, DIMENSION(:), POINTER :: col_indices
1777 LOGICAL :: is_any_weight_non_zero, my_do_spinor
1778 REAL(kind=dp) :: broadening, e_max, e_min, &
1779 e_total_window, energy, energy_step, &
1780 energy_window, spin_degeneracy, weight
1781 TYPE(cp_cfm_type) :: cfm_weighted_dm_ikp, cfm_work
1782 TYPE(cp_fm_type) :: fm_non_spinor, fm_weighted_dm_mic
1783 TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: weighted_dm_mic
1784 TYPE(dft_control_type), POINTER :: dft_control
1785 TYPE(pw_c1d_gs_type) :: rho_g
1786 TYPE(pw_env_type), POINTER :: pw_env
1787 TYPE(pw_pool_type), POINTER :: auxbas_pw_pool
1788 TYPE(pw_r3d_rs_type) :: ldos_3d
1789 TYPE(qs_ks_env_type), POINTER :: ks_env
1790
1791 CALL timeset(routinen, handle)
1792
1793 my_do_spinor = .false.
1794 IF (PRESENT(do_spinor)) my_do_spinor = do_spinor
1795
1796 CALL get_qs_env(qs_env, ks_env=ks_env, pw_env=pw_env, dft_control=dft_control)
1797
1798 ! previously, dft_control%nimages set to # neighbor cells, revert for Γ-only KS matrix
1799 nimages = dft_control%nimages
1800 dft_control%nimages = bs_env%nimages_scf
1801
1802 energy_window = bs_env%energy_window_DOS
1803 energy_step = bs_env%energy_step_DOS
1804 broadening = bs_env%broadening_DOS
1805
1806 e_min = band_edges%VBM - 0.5_dp*energy_window
1807 e_max = band_edges%CBM + 0.5_dp*energy_window
1808 e_total_window = e_max - e_min
1809
1810 n_e = int(e_total_window/energy_step)
1811
1812 CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool)
1813
1814 CALL auxbas_pw_pool%create_pw(ldos_3d)
1815 CALL auxbas_pw_pool%create_pw(rho_g)
1816
1817 i_x_start = lbound(ldos_3d%array, 1)
1818 i_x_end = ubound(ldos_3d%array, 1)
1819 i_y_start = lbound(ldos_3d%array, 2)
1820 i_y_end = ubound(ldos_3d%array, 2)
1821 i_z_start = lbound(ldos_3d%array, 3)
1822 i_z_end = ubound(ldos_3d%array, 3)
1823
1824 z_start_global = i_z_start
1825 z_end_global = i_z_end
1826
1827 CALL bs_env%para_env%min(z_start_global)
1828 CALL bs_env%para_env%max(z_end_global)
1829 n_z = z_end_global - z_start_global + 1
1830
1831 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)) &
1832 cpabort(°"Please choose a cell that has 90 angles to the z-direction.")
1833 ! for integration, we need the dz and the conversion from H -> eV and a_Bohr -> Å
1834 bs_env%unit_ldos_int_z_inv_Ang2_eV = bs_env%hmat(3, 3)/real(n_z, kind=dp)/evolt/angstrom**2
1835
1836 IF (ikp == 1) THEN
1837 ALLOCATE (ldos_2d(i_x_start:i_x_end, i_y_start:i_y_end, n_e))
1838 ldos_2d(:, :, :) = 0.0_dp
1839 END IF
1840
1841 CALL cp_cfm_create(cfm_work, cfm_mos_ikp%matrix_struct)
1842 CALL cp_cfm_create(cfm_weighted_dm_ikp, cfm_mos_ikp%matrix_struct)
1843 CALL cp_fm_create(fm_weighted_dm_mic, cfm_mos_ikp%matrix_struct)
1844 IF (my_do_spinor) THEN
1845 CALL cp_fm_create(fm_non_spinor, cfm_non_spinor%matrix_struct)
1846 END IF
1847
1848 CALL cp_cfm_get_info(matrix=cfm_mos_ikp, &
1849 ncol_global=n_mo, &
1850 ncol_local=ncol_local, &
1851 col_indices=col_indices)
1852
1853 NULLIFY (weighted_dm_mic)
1854 CALL dbcsr_allocate_matrix_set(weighted_dm_mic, 1)
1855 ALLOCATE (weighted_dm_mic(1)%matrix)
1856 CALL dbcsr_create(weighted_dm_mic(1)%matrix, template=bs_env%mat_ao_ao%matrix, &
1857 matrix_type=dbcsr_type_symmetric)
1858
1859 DO i_e = 1, n_e
1860
1861 energy = e_min + i_e*energy_step
1862
1863 is_any_weight_non_zero = .false.
1864
1865 DO j_col = 1, ncol_local
1866
1867 j_mo = col_indices(j_col)
1868
1869 IF (my_do_spinor) THEN
1870 spin_degeneracy = 1.0_dp
1871 ELSE
1872 spin_degeneracy = bs_env%spin_degeneracy
1873 END IF
1874
1875 weight = gaussian(energy - eigenval(j_mo), broadening)*spin_degeneracy
1876
1877 cfm_work%local_data(:, j_col) = cfm_mos_ikp%local_data(:, j_col)*weight
1878
1879 IF (weight > 1.0e-5_dp) is_any_weight_non_zero = .true.
1880
1881 END DO
1882
1883 CALL bs_env%para_env%sync()
1884 CALL bs_env%para_env%sum(is_any_weight_non_zero)
1885 CALL bs_env%para_env%sync()
1886
1887 ! cycle if there are no states at the energy i_E
1888 IF (is_any_weight_non_zero) THEN
1889
1890 CALL parallel_gemm('N', 'C', n_mo, n_mo, n_mo, z_one, &
1891 cfm_mos_ikp, cfm_work, z_zero, cfm_weighted_dm_ikp)
1892
1893 IF (my_do_spinor) THEN
1894
1895 ! contribution from up,up to fm_non_spinor
1896 CALL get_cfm_submat(cfm_non_spinor, cfm_weighted_dm_ikp, 1, 1)
1897 CALL cp_fm_set_all(fm_non_spinor, 0.0_dp)
1898 CALL mic_contribution_from_ikp(bs_env, qs_env, fm_non_spinor, &
1899 cfm_non_spinor, ikp, bs_env%kpoints_DOS, &
1900 "ORB", bs_env%kpoints_DOS%wkp(ikp))
1901
1902 ! add contribution from down,down to fm_non_spinor
1903 CALL get_cfm_submat(cfm_non_spinor, cfm_weighted_dm_ikp, n_mo/2, n_mo/2)
1904 CALL mic_contribution_from_ikp(bs_env, qs_env, fm_non_spinor, &
1905 cfm_non_spinor, ikp, bs_env%kpoints_DOS, &
1906 "ORB", bs_env%kpoints_DOS%wkp(ikp))
1907 CALL copy_fm_to_dbcsr(fm_non_spinor, weighted_dm_mic(1)%matrix, &
1908 keep_sparsity=.false.)
1909 ELSE
1910 CALL cp_fm_set_all(fm_weighted_dm_mic, 0.0_dp)
1911 CALL mic_contribution_from_ikp(bs_env, qs_env, fm_weighted_dm_mic, &
1912 cfm_weighted_dm_ikp, ikp, bs_env%kpoints_DOS, &
1913 "ORB", bs_env%kpoints_DOS%wkp(ikp))
1914 CALL copy_fm_to_dbcsr(fm_weighted_dm_mic, weighted_dm_mic(1)%matrix, &
1915 keep_sparsity=.false.)
1916 END IF
1917
1918 ldos_3d%array(:, :, :) = 0.0_dp
1919
1920 CALL calculate_rho_elec(matrix_p_kp=weighted_dm_mic, &
1921 rho=ldos_3d, &
1922 rho_gspace=rho_g, &
1923 ks_env=ks_env)
1924
1925 DO i_z = i_z_start, i_z_end
1926 ldos_2d(:, :, i_e) = ldos_2d(:, :, i_e) + ldos_3d%array(:, :, i_z)
1927 END DO
1928
1929 END IF
1930
1931 END DO
1932
1933 ! set back nimages
1934 dft_control%nimages = nimages
1935
1936 CALL auxbas_pw_pool%give_back_pw(ldos_3d)
1937 CALL auxbas_pw_pool%give_back_pw(rho_g)
1938
1939 CALL cp_cfm_release(cfm_work)
1940 CALL cp_cfm_release(cfm_weighted_dm_ikp)
1941
1942 CALL cp_fm_release(fm_weighted_dm_mic)
1943
1944 CALL dbcsr_deallocate_matrix_set(weighted_dm_mic)
1945
1946 IF (my_do_spinor) THEN
1947 CALL cp_fm_release(fm_non_spinor)
1948 END IF
1949
1950 CALL timestop(handle)
1951
1952 END SUBROUTINE add_to_ldos_2d
1953
1954! **************************************************************************************************
1955!> \brief ...
1956!> \param eigenval_spinor ...
1957!> \param ikp_for_file ...
1958!> \param ikp ...
1959!> \param bs_env ...
1960!> \param eigenval_spinor_G0W0 ...
1961! **************************************************************************************************
1962 SUBROUTINE write_soc_eigenvalues(eigenval_spinor, ikp_for_file, ikp, bs_env, eigenval_spinor_G0W0)
1963
1964 REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: eigenval_spinor
1965 INTEGER :: ikp_for_file, ikp
1966 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
1967 REAL(kind=dp), ALLOCATABLE, DIMENSION(:), OPTIONAL :: eigenval_spinor_g0w0
1968
1969 CHARACTER(LEN=*), PARAMETER :: routinen = 'write_SOC_eigenvalues'
1970
1971 CHARACTER(len=3) :: occ_vir
1972 CHARACTER(LEN=default_string_length) :: fname
1973 INTEGER :: handle, i_mo, iunit, n_occ_spinor
1974
1975 CALL timeset(routinen, handle)
1976
1977 fname = "bandstructure_SCF_and_G0W0_plus_SOC"
1978
1979 IF (bs_env%para_env%is_source()) THEN
1980
1981 IF (ikp_for_file == 1) THEN
1982 CALL open_file(trim(fname), unit_number=iunit, file_status="REPLACE", &
1983 file_action="WRITE")
1984 ELSE
1985 CALL open_file(trim(fname), unit_number=iunit, file_status="OLD", &
1986 file_action="WRITE", file_position="APPEND")
1987 END IF
1988
1989 WRITE (iunit, "(A)") " "
1990 WRITE (iunit, "(A10,I7,A25,3F10.4)") "kpoint: ", ikp_for_file, "coordinate: ", &
1991 bs_env%kpoints_DOS%xkp(:, ikp)
1992 WRITE (iunit, "(A)") " "
1993
1994 IF (PRESENT(eigenval_spinor_g0w0)) THEN
1995 ! SCF+SOC and G0W0+SOC eigenvalues
1996 WRITE (iunit, "(A5,A12,2A22)") "n", "k", ϵ"_nk^DFT+SOC (eV)", ϵ"_nk^G0W0+SOC (eV)"
1997 ELSE
1998 ! SCF+SOC eigenvalues only
1999 WRITE (iunit, "(A5,A12,A22)") "n", "k", ϵ"_nk^DFT+SOC (eV)"
2000 END IF
2001
2002 n_occ_spinor = bs_env%n_occ(1) + bs_env%n_occ(bs_env%n_spin)
2003
2004 DO i_mo = 1, SIZE(eigenval_spinor)
2005 IF (i_mo .LE. n_occ_spinor) occ_vir = 'occ'
2006 IF (i_mo > n_occ_spinor) occ_vir = 'vir'
2007 IF (PRESENT(eigenval_spinor_g0w0)) THEN
2008 ! SCF+SOC and G0W0+SOC eigenvalues
2009 WRITE (iunit, "(I5,3A,I5,4F16.3,2F17.3)") i_mo, ' (', occ_vir, ') ', &
2010 ikp_for_file, eigenval_spinor(i_mo)*evolt, eigenval_spinor_g0w0(i_mo)*evolt
2011 ELSE
2012 ! SCF+SOC eigenvalues only
2013 WRITE (iunit, "(I5,3A,I5,4F16.3,F17.3)") i_mo, ' (', occ_vir, ') ', &
2014 ikp_for_file, eigenval_spinor(i_mo)*evolt
2015 END IF
2016 END DO
2017
2018 CALL close_file(iunit)
2019
2020 END IF
2021
2022 CALL timestop(handle)
2023
2024 END SUBROUTINE write_soc_eigenvalues
2025
2026! **************************************************************************************************
2027!> \brief ...
2028!> \param int_number ...
2029!> \return ...
2030! **************************************************************************************************
2031 PURE FUNCTION count_digits(int_number)
2032
2033 INTEGER, INTENT(IN) :: int_number
2034 INTEGER :: count_digits
2035
2036 INTEGER :: digitcount, tempint
2037
2038 digitcount = 0
2039
2040 tempint = int_number
2041
2042 DO WHILE (tempint /= 0)
2043 tempint = tempint/10
2044 digitcount = digitcount + 1
2045 END DO
2046
2047 count_digits = digitcount
2048
2049 END FUNCTION count_digits
2050
2051! **************************************************************************************************
2052!> \brief ...
2053!> \param band_edges ...
2054!> \param scf_gw_soc ...
2055!> \param bs_env ...
2056! **************************************************************************************************
2057 SUBROUTINE write_band_edges(band_edges, scf_gw_soc, bs_env)
2058
2059 TYPE(band_edges_type) :: band_edges
2060 CHARACTER(LEN=*) :: scf_gw_soc
2061 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
2062
2063 CHARACTER(LEN=*), PARAMETER :: routinen = 'write_band_edges'
2064
2065 CHARACTER(LEN=17) :: print_format
2066 INTEGER :: handle, u
2067
2068 CALL timeset(routinen, handle)
2069
2070 ! print format
2071 print_format = "(T2,2A,T61,F20.3)"
2072
2073 u = bs_env%unit_nr
2074 IF (u > 0) THEN
2075 WRITE (u, '(T2,A)') ''
2076 WRITE (u, print_format) scf_gw_soc, ' valence band maximum (eV):', band_edges%VBM*evolt
2077 WRITE (u, print_format) scf_gw_soc, ' conduction band minimum (eV):', band_edges%CBM*evolt
2078 WRITE (u, print_format) scf_gw_soc, ' indirect band gap (eV):', band_edges%IDBG*evolt
2079 WRITE (u, print_format) scf_gw_soc, ' direct band gap (eV):', band_edges%DBG*evolt
2080 END IF
2081
2082 CALL timestop(handle)
2083
2084 END SUBROUTINE write_band_edges
2085
2086! **************************************************************************************************
2087!> \brief ...
2088!> \param DOS ...
2089!> \param PDOS ...
2090!> \param bs_env ...
2091!> \param qs_env ...
2092!> \param scf_gw_soc ...
2093!> \param E_min ...
2094!> \param E_VBM ...
2095! **************************************************************************************************
2096 SUBROUTINE write_dos_pdos(DOS, PDOS, bs_env, qs_env, scf_gw_soc, E_min, E_VBM)
2097 REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: dos
2098 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :) :: pdos
2099 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
2100 TYPE(qs_environment_type), POINTER :: qs_env
2101 CHARACTER(LEN=*) :: scf_gw_soc
2102 REAL(kind=dp) :: e_min, e_vbm
2103
2104 CHARACTER(LEN=*), PARAMETER :: routinen = 'write_dos_pdos'
2105
2106 CHARACTER(LEN=3), DIMENSION(100) :: elements
2107 CHARACTER(LEN=default_string_length) :: atom_name, fname, output_string
2108 INTEGER :: handle, i_e, i_kind, iatom, iunit, n_a, &
2109 n_e, nkind
2110 REAL(kind=dp) :: energy
2111 TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
2112
2113 CALL timeset(routinen, handle)
2114
2115 WRITE (fname, "(3A)") "DOS_PDOS_", scf_gw_soc, ".out"
2116
2117 n_e = SIZE(pdos, 1)
2118 nkind = SIZE(pdos, 2)
2119 CALL get_qs_env(qs_env, particle_set=particle_set)
2120
2121 IF (bs_env%para_env%is_source()) THEN
2122
2123 CALL open_file(trim(fname), unit_number=iunit, file_status="REPLACE", file_action="WRITE")
2124
2125 n_a = 2 + nkind
2126
2127 DO iatom = 1, bs_env%n_atom
2128 CALL get_atomic_kind(atomic_kind=particle_set(iatom)%atomic_kind, &
2129 kind_number=i_kind, name=atom_name)
2130 elements(i_kind) = atom_name(1:3)
2131 END DO
2132
2133 WRITE (output_string, "(A,I1,A)") "(", n_a, "A)"
2134
2135 WRITE (iunit, trim(output_string)) "Energy-E_F (eV) DOS (1/eV) PDOS (1/eV) ", &
2136 " of atom type ", elements(1:nkind)
2137
2138 WRITE (output_string, "(A,I1,A)") "(", n_a, "F13.5)"
2139
2140 DO i_e = 1, n_e
2141 ! energy is relative to valence band maximum => - E_VBM
2142 energy = e_min + i_e*bs_env%energy_step_DOS - e_vbm
2143 WRITE (iunit, trim(output_string)) energy*evolt, dos(i_e)/evolt, pdos(i_e, :)/evolt
2144 END DO
2145
2146 CALL close_file(iunit)
2147
2148 END IF
2149
2150 CALL timestop(handle)
2151
2152 END SUBROUTINE write_dos_pdos
2153
2154! **************************************************************************************************
2155!> \brief ...
2156!> \param energy ...
2157!> \param broadening ...
2158!> \return ...
2159! **************************************************************************************************
2160 PURE FUNCTION gaussian(energy, broadening)
2161
2162 REAL(kind=dp), INTENT(IN) :: energy, broadening
2163 REAL(kind=dp) :: gaussian
2164
2165 IF (abs(energy) < 5*broadening) THEN
2166 gaussian = 1.0_dp/broadening/sqrt(twopi)*exp(-0.5_dp*energy**2/broadening**2)
2167 ELSE
2168 gaussian = 0.0_dp
2169 END IF
2170
2171 END FUNCTION
2172
2173! **************************************************************************************************
2174!> \brief ...
2175!> \param proj_mo_on_kind ...
2176!> \param qs_env ...
2177!> \param cfm_mos ...
2178!> \param cfm_s ...
2179! **************************************************************************************************
2180 SUBROUTINE compute_proj_mo_on_kind(proj_mo_on_kind, qs_env, cfm_mos, cfm_s)
2181 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :) :: proj_mo_on_kind
2182 TYPE(qs_environment_type), POINTER :: qs_env
2183 TYPE(cp_cfm_type) :: cfm_mos, cfm_s
2184
2185 CHARACTER(LEN=*), PARAMETER :: routinen = 'compute_proj_mo_on_kind'
2186
2187 INTEGER :: handle, i_atom, i_global, i_kind, i_row, &
2188 j_col, n_ao, n_mo, ncol_local, nkind, &
2189 nrow_local
2190 INTEGER, ALLOCATABLE, DIMENSION(:) :: atom_from_bf, kind_of
2191 INTEGER, DIMENSION(:), POINTER :: col_indices, row_indices
2192 TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set
2193 TYPE(cp_cfm_type) :: cfm_proj, cfm_s_i_kind, cfm_work
2194 TYPE(cp_fm_type) :: fm_proj_im, fm_proj_re
2195
2196 CALL timeset(routinen, handle)
2197
2198 CALL get_qs_env(qs_env, atomic_kind_set=atomic_kind_set, nkind=nkind)
2199 CALL get_atomic_kind_set(atomic_kind_set, kind_of=kind_of)
2200
2201 CALL cp_cfm_get_info(matrix=cfm_mos, &
2202 nrow_global=n_mo, &
2203 nrow_local=nrow_local, &
2204 ncol_local=ncol_local, &
2205 row_indices=row_indices, &
2206 col_indices=col_indices)
2207
2208 n_ao = qs_env%bs_env%n_ao
2209
2210 ALLOCATE (atom_from_bf(n_ao))
2211 CALL get_atom_index_from_basis_function_index(qs_env, atom_from_bf, n_ao, "ORB")
2212
2213 proj_mo_on_kind(:, :) = 0.0_dp
2214
2215 CALL cp_cfm_create(cfm_s_i_kind, cfm_s%matrix_struct)
2216 CALL cp_cfm_create(cfm_work, cfm_s%matrix_struct)
2217 CALL cp_cfm_create(cfm_proj, cfm_s%matrix_struct)
2218 CALL cp_fm_create(fm_proj_re, cfm_s%matrix_struct)
2219 CALL cp_fm_create(fm_proj_im, cfm_s%matrix_struct)
2220
2221 DO i_kind = 1, nkind
2222
2223 CALL cp_cfm_to_cfm(cfm_s, cfm_s_i_kind)
2224
2225 ! set entries in overlap matrix to zero which do not belong to atoms of i_kind
2226 DO j_col = 1, ncol_local
2227 DO i_row = 1, nrow_local
2228
2229 i_global = row_indices(i_row)
2230
2231 IF (i_global .LE. n_ao) THEN
2232 i_atom = atom_from_bf(i_global)
2233 ELSE IF (i_global .LE. 2*n_ao) THEN
2234 i_atom = atom_from_bf(i_global - n_ao)
2235 ELSE
2236 cpabort("Wrong indices.")
2237 END IF
2238
2239 IF (i_kind .NE. kind_of(i_atom)) THEN
2240 cfm_s_i_kind%local_data(i_row, j_col) = z_zero
2241 END IF
2242
2243 END DO
2244 END DO
2245
2246 CALL parallel_gemm('N', 'N', n_mo, n_mo, n_mo, z_one, &
2247 cfm_s_i_kind, cfm_mos, z_zero, cfm_work)
2248 CALL parallel_gemm('C', 'N', n_mo, n_mo, n_mo, z_one, &
2249 cfm_mos, cfm_work, z_zero, cfm_proj)
2250
2251 CALL cp_cfm_to_fm(cfm_proj, fm_proj_re, fm_proj_im)
2252
2253 CALL cp_fm_get_diag(fm_proj_im, proj_mo_on_kind(:, i_kind))
2254 CALL cp_fm_get_diag(fm_proj_re, proj_mo_on_kind(:, i_kind))
2255
2256 END DO ! i_kind
2257
2258 CALL cp_cfm_release(cfm_s_i_kind)
2259 CALL cp_cfm_release(cfm_work)
2260 CALL cp_cfm_release(cfm_proj)
2261 CALL cp_fm_release(fm_proj_re)
2262 CALL cp_fm_release(fm_proj_im)
2263
2264 CALL timestop(handle)
2265
2266 END SUBROUTINE compute_proj_mo_on_kind
2267
2268! **************************************************************************************************
2269!> \brief ...
2270!> \param cfm_spinor_ikp ...
2271!> \param cfm_spinor_Gamma ...
2272!> \param fm_struct_non_spinor ...
2273!> \param ikp ...
2274!> \param qs_env ...
2275!> \param kpoints ...
2276!> \param basis_type ...
2277! **************************************************************************************************
2278 SUBROUTINE cfm_ikp_from_cfm_spinor_gamma(cfm_spinor_ikp, cfm_spinor_Gamma, fm_struct_non_spinor, &
2279 ikp, qs_env, kpoints, basis_type)
2280 TYPE(cp_cfm_type) :: cfm_spinor_ikp, cfm_spinor_gamma
2281 TYPE(cp_fm_struct_type), POINTER :: fm_struct_non_spinor
2282 INTEGER :: ikp
2283 TYPE(qs_environment_type), POINTER :: qs_env
2284 TYPE(kpoint_type), POINTER :: kpoints
2285 CHARACTER(LEN=*) :: basis_type
2286
2287 CHARACTER(LEN=*), PARAMETER :: routinen = 'cfm_ikp_from_cfm_spinor_Gamma'
2288
2289 INTEGER :: handle, i_block, i_offset, j_block, &
2290 j_offset, n_ao
2291 TYPE(cp_cfm_type) :: cfm_non_spinor_gamma, cfm_non_spinor_ikp
2292 TYPE(cp_fm_type) :: fm_non_spinor_gamma_im, &
2293 fm_non_spinor_gamma_re
2294
2295 CALL timeset(routinen, handle)
2296
2297 CALL cp_cfm_create(cfm_non_spinor_gamma, fm_struct_non_spinor)
2298 CALL cp_cfm_create(cfm_non_spinor_ikp, fm_struct_non_spinor)
2299 CALL cp_fm_create(fm_non_spinor_gamma_re, fm_struct_non_spinor)
2300 CALL cp_fm_create(fm_non_spinor_gamma_im, fm_struct_non_spinor)
2301
2302 CALL cp_cfm_get_info(cfm_non_spinor_gamma, nrow_global=n_ao)
2303
2304 CALL cp_cfm_set_all(cfm_spinor_ikp, z_zero)
2305
2306 DO i_block = 0, 1
2307 DO j_block = 0, 1
2308 i_offset = i_block*n_ao + 1
2309 j_offset = j_block*n_ao + 1
2310 CALL get_cfm_submat(cfm_non_spinor_gamma, cfm_spinor_gamma, i_offset, j_offset)
2311 CALL cp_cfm_to_fm(cfm_non_spinor_gamma, fm_non_spinor_gamma_re, fm_non_spinor_gamma_im)
2312
2313 ! transform real part of Gamma-point matrix to ikp
2314 CALL cfm_ikp_from_fm_gamma(cfm_non_spinor_ikp, fm_non_spinor_gamma_re, &
2315 ikp, qs_env, kpoints, basis_type)
2316 CALL add_cfm_submat(cfm_spinor_ikp, cfm_non_spinor_ikp, i_offset, j_offset)
2317
2318 ! transform imag part of Gamma-point matrix to ikp
2319 CALL cfm_ikp_from_fm_gamma(cfm_non_spinor_ikp, fm_non_spinor_gamma_im, &
2320 ikp, qs_env, kpoints, basis_type)
2321 CALL add_cfm_submat(cfm_spinor_ikp, cfm_non_spinor_ikp, i_offset, j_offset, gaussi)
2322
2323 END DO
2324 END DO
2325
2326 CALL cp_cfm_release(cfm_non_spinor_gamma)
2327 CALL cp_cfm_release(cfm_non_spinor_ikp)
2328 CALL cp_fm_release(fm_non_spinor_gamma_re)
2329 CALL cp_fm_release(fm_non_spinor_gamma_im)
2330
2331 CALL timestop(handle)
2332
2333 END SUBROUTINE cfm_ikp_from_cfm_spinor_gamma
2334
2335! **************************************************************************************************
2336!> \brief ...
2337!> \param cfm_ikp ...
2338!> \param fm_Gamma ...
2339!> \param ikp ...
2340!> \param qs_env ...
2341!> \param kpoints ...
2342!> \param basis_type ...
2343! **************************************************************************************************
2344 SUBROUTINE cfm_ikp_from_fm_gamma(cfm_ikp, fm_Gamma, ikp, qs_env, kpoints, basis_type)
2345 TYPE(cp_cfm_type) :: cfm_ikp
2346 TYPE(cp_fm_type) :: fm_gamma
2347 INTEGER :: ikp
2348 TYPE(qs_environment_type), POINTER :: qs_env
2349 TYPE(kpoint_type), POINTER :: kpoints
2350 CHARACTER(LEN=*) :: basis_type
2351
2352 CHARACTER(LEN=*), PARAMETER :: routinen = 'cfm_ikp_from_fm_Gamma'
2353
2354 INTEGER :: col_global, handle, i_atom, i_atom_old, i_cell, i_mic_cell, i_row, j_atom, &
2355 j_atom_old, j_cell, j_col, n_bf, ncol_local, nrow_local, num_cells, row_global
2356 INTEGER, ALLOCATABLE, DIMENSION(:) :: atom_from_bf
2357 INTEGER, DIMENSION(:), POINTER :: col_indices, row_indices
2358 INTEGER, DIMENSION(:, :), POINTER :: index_to_cell
2359 LOGICAL :: i_cell_is_the_minimum_image_cell
2360 REAL(kind=dp) :: abs_rab_cell_i, abs_rab_cell_j, arg
2361 REAL(kind=dp), DIMENSION(3) :: cell_vector, cell_vector_j, rab_cell_i, &
2362 rab_cell_j
2363 REAL(kind=dp), DIMENSION(3, 3) :: hmat
2364 TYPE(cell_type), POINTER :: cell
2365 TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
2366
2367 CALL timeset(routinen, handle)
2368
2369 IF (.NOT. ASSOCIATED(cfm_ikp%local_data)) THEN
2370 CALL cp_cfm_create(cfm_ikp, fm_gamma%matrix_struct)
2371 END IF
2372 CALL cp_cfm_set_all(cfm_ikp, z_zero)
2373
2374 CALL cp_fm_get_info(matrix=fm_gamma, &
2375 nrow_local=nrow_local, &
2376 ncol_local=ncol_local, &
2377 row_indices=row_indices, &
2378 col_indices=col_indices)
2379
2380 ! get number of basis functions (bf) for different basis sets
2381 IF (basis_type == "ORB") THEN
2382 n_bf = qs_env%bs_env%n_ao
2383 ELSE IF (basis_type == "RI_AUX") THEN
2384 n_bf = qs_env%bs_env%n_RI
2385 ELSE
2386 cpabort("Only ORB and RI_AUX basis implemented.")
2387 END IF
2388
2389 ALLOCATE (atom_from_bf(n_bf))
2390 CALL get_atom_index_from_basis_function_index(qs_env, atom_from_bf, n_bf, basis_type)
2391
2392 NULLIFY (cell, particle_set)
2393 CALL get_qs_env(qs_env, cell=cell, particle_set=particle_set)
2394 CALL get_cell(cell=cell, h=hmat)
2395
2396 index_to_cell => kpoints%index_to_cell
2397
2398 num_cells = SIZE(index_to_cell, 2)
2399 i_atom_old = 0
2400 j_atom_old = 0
2401
2402 DO j_col = 1, ncol_local
2403 DO i_row = 1, nrow_local
2404
2405 row_global = row_indices(i_row)
2406 col_global = col_indices(j_col)
2407
2408 i_atom = atom_from_bf(row_global)
2409 j_atom = atom_from_bf(col_global)
2410
2411 ! we only need to check for new MIC cell for new i_atom-j_atom pair
2412 IF (i_atom .NE. i_atom_old .OR. j_atom .NE. j_atom_old) THEN
2413 DO i_cell = 1, num_cells
2414
2415 ! only check nearest neigbors
2416 IF (any(abs(index_to_cell(1:3, i_cell)) > 1)) cycle
2417
2418 cell_vector(1:3) = matmul(hmat, real(index_to_cell(1:3, i_cell), dp))
2419
2420 rab_cell_i(1:3) = pbc(particle_set(i_atom)%r(1:3), cell) - &
2421 (pbc(particle_set(j_atom)%r(1:3), cell) + cell_vector(1:3))
2422 abs_rab_cell_i = sqrt(rab_cell_i(1)**2 + rab_cell_i(2)**2 + rab_cell_i(3)**2)
2423
2424 ! minimum image convention
2425 i_cell_is_the_minimum_image_cell = .true.
2426 DO j_cell = 1, num_cells
2427 cell_vector_j(1:3) = matmul(hmat, real(index_to_cell(1:3, j_cell), dp))
2428 rab_cell_j(1:3) = pbc(particle_set(i_atom)%r(1:3), cell) - &
2429 (pbc(particle_set(j_atom)%r(1:3), cell) + cell_vector_j(1:3))
2430 abs_rab_cell_j = sqrt(rab_cell_j(1)**2 + rab_cell_j(2)**2 + rab_cell_j(3)**2)
2431
2432 IF (abs_rab_cell_i > abs_rab_cell_j + 1.0e-6_dp) THEN
2433 i_cell_is_the_minimum_image_cell = .false.
2434 END IF
2435 END DO
2436
2437 IF (i_cell_is_the_minimum_image_cell) THEN
2438 i_mic_cell = i_cell
2439 END IF
2440
2441 END DO ! i_cell
2442 END IF
2443
2444 arg = real(index_to_cell(1, i_mic_cell), dp)*kpoints%xkp(1, ikp) + &
2445 REAL(index_to_cell(2, i_mic_cell), dp)*kpoints%xkp(2, ikp) + &
2446 REAL(index_to_cell(3, i_mic_cell), dp)*kpoints%xkp(3, ikp)
2447
2448 cfm_ikp%local_data(i_row, j_col) = cos(twopi*arg)*fm_gamma%local_data(i_row, j_col)*z_one + &
2449 sin(twopi*arg)*fm_gamma%local_data(i_row, j_col)*gaussi
2450
2451 j_atom_old = j_atom
2452 i_atom_old = i_atom
2453
2454 END DO ! j_col
2455 END DO ! i_row
2456
2457 CALL timestop(handle)
2458
2459 END SUBROUTINE cfm_ikp_from_fm_gamma
2460
2461! **************************************************************************************************
2462!> \brief ...
2463!> \param bs_env ...
2464!> \param qs_env ...
2465!> \param fm_W_MIC_freq_j ...
2466!> \param cfm_W_ikp_freq_j ...
2467!> \param ikp ...
2468!> \param kpoints ...
2469!> \param basis_type ...
2470!> \param wkp_ext ...
2471! **************************************************************************************************
2472 SUBROUTINE mic_contribution_from_ikp(bs_env, qs_env, fm_W_MIC_freq_j, &
2473 cfm_W_ikp_freq_j, ikp, kpoints, basis_type, wkp_ext)
2474 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
2475 TYPE(qs_environment_type), POINTER :: qs_env
2476 TYPE(cp_fm_type) :: fm_w_mic_freq_j
2477 TYPE(cp_cfm_type) :: cfm_w_ikp_freq_j
2478 INTEGER, INTENT(IN) :: ikp
2479 TYPE(kpoint_type), POINTER :: kpoints
2480 CHARACTER(LEN=*) :: basis_type
2481 REAL(kind=dp), OPTIONAL :: wkp_ext
2482
2483 CHARACTER(LEN=*), PARAMETER :: routinen = 'MIC_contribution_from_ikp'
2484
2485 INTEGER :: handle, i_bf, iatom, iatom_old, irow, &
2486 j_bf, jatom, jatom_old, jcol, n_bf, &
2487 ncol_local, nrow_local, num_cells
2488 INTEGER, ALLOCATABLE, DIMENSION(:) :: atom_from_bf_index
2489 INTEGER, DIMENSION(:), POINTER :: col_indices, row_indices
2490 INTEGER, DIMENSION(:, :), POINTER :: index_to_cell
2491 REAL(kind=dp) :: contribution, weight_im, weight_re, &
2492 wkp_of_ikp
2493 REAL(kind=dp), DIMENSION(3, 3) :: hmat
2494 REAL(kind=dp), DIMENSION(:), POINTER :: wkp
2495 REAL(kind=dp), DIMENSION(:, :), POINTER :: xkp
2496 TYPE(cell_type), POINTER :: cell
2497 TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
2498
2499 CALL timeset(routinen, handle)
2500
2501 ! get number of basis functions (bf) for different basis sets
2502 IF (basis_type == "ORB") THEN
2503 n_bf = qs_env%bs_env%n_ao
2504 ELSE IF (basis_type == "RI_AUX") THEN
2505 n_bf = qs_env%bs_env%n_RI
2506 ELSE
2507 cpabort("Only ORB and RI_AUX basis implemented.")
2508 END IF
2509
2510 ALLOCATE (atom_from_bf_index(n_bf))
2511 CALL get_atom_index_from_basis_function_index(qs_env, atom_from_bf_index, n_bf, basis_type)
2512
2513 NULLIFY (cell, particle_set)
2514 CALL get_qs_env(qs_env, cell=cell, particle_set=particle_set)
2515 CALL get_cell(cell=cell, h=hmat)
2516
2517 CALL cp_cfm_get_info(matrix=cfm_w_ikp_freq_j, &
2518 nrow_local=nrow_local, &
2519 ncol_local=ncol_local, &
2520 row_indices=row_indices, &
2521 col_indices=col_indices)
2522
2523 CALL get_kpoint_info(kpoints, xkp=xkp, wkp=wkp)
2524 index_to_cell => kpoints%index_to_cell
2525 num_cells = SIZE(index_to_cell, 2)
2526
2527 iatom_old = 0
2528 jatom_old = 0
2529
2530 DO jcol = 1, ncol_local
2531 DO irow = 1, nrow_local
2532
2533 i_bf = row_indices(irow)
2534 j_bf = col_indices(jcol)
2535
2536 iatom = atom_from_bf_index(i_bf)
2537 jatom = atom_from_bf_index(j_bf)
2538
2539 IF (PRESENT(wkp_ext)) THEN
2540 wkp_of_ikp = wkp_ext
2541 ELSE
2542 SELECT CASE (bs_env%l_RI(i_bf) + bs_env%l_RI(j_bf))
2543 CASE (0)
2544 ! both RI functions are s-functions, k-extrapolation for 2D and 3D
2545 wkp_of_ikp = wkp(ikp)
2546 CASE (1)
2547 ! one function is an s-function, the other a p-function, k-extrapolation for 3D
2548 wkp_of_ikp = bs_env%wkp_s_p(ikp)
2549 CASE DEFAULT
2550 ! for any other matrix element of W, there is no need for extrapolation
2551 wkp_of_ikp = bs_env%wkp_no_extra(ikp)
2552 END SELECT
2553 END IF
2554
2555 IF (iatom .NE. iatom_old .OR. jatom .NE. jatom_old) THEN
2556
2557 CALL compute_weight_re_im(weight_re, weight_im, &
2558 num_cells, iatom, jatom, xkp(1:3, ikp), wkp_of_ikp, &
2559 cell, index_to_cell, hmat, particle_set)
2560
2561 iatom_old = iatom
2562 jatom_old = jatom
2563
2564 END IF
2565
2566 contribution = weight_re*real(cfm_w_ikp_freq_j%local_data(irow, jcol)) + &
2567 weight_im*aimag(cfm_w_ikp_freq_j%local_data(irow, jcol))
2568
2569 fm_w_mic_freq_j%local_data(irow, jcol) = fm_w_mic_freq_j%local_data(irow, jcol) &
2570 + contribution
2571
2572 END DO
2573 END DO
2574
2575 CALL timestop(handle)
2576
2577 END SUBROUTINE mic_contribution_from_ikp
2578
2579! **************************************************************************************************
2580!> \brief ...
2581!> \param xkp ...
2582!> \param ikp_start ...
2583!> \param ikp_end ...
2584!> \param grid ...
2585! **************************************************************************************************
2586 SUBROUTINE compute_xkp(xkp, ikp_start, ikp_end, grid)
2587
2588 REAL(kind=dp), DIMENSION(:, :), POINTER :: xkp
2589 INTEGER :: ikp_start, ikp_end
2590 INTEGER, DIMENSION(3) :: grid
2591
2592 CHARACTER(LEN=*), PARAMETER :: routinen = 'compute_xkp'
2593
2594 INTEGER :: handle, i, ix, iy, iz
2595
2596 CALL timeset(routinen, handle)
2597
2598 i = ikp_start
2599 DO ix = 1, grid(1)
2600 DO iy = 1, grid(2)
2601 DO iz = 1, grid(3)
2602
2603 IF (i > ikp_end) cycle
2604
2605 xkp(1, i) = real(2*ix - grid(1) - 1, kind=dp)/(2._dp*real(grid(1), kind=dp))
2606 xkp(2, i) = real(2*iy - grid(2) - 1, kind=dp)/(2._dp*real(grid(2), kind=dp))
2607 xkp(3, i) = real(2*iz - grid(3) - 1, kind=dp)/(2._dp*real(grid(3), kind=dp))
2608 i = i + 1
2609
2610 END DO
2611 END DO
2612 END DO
2613
2614 CALL timestop(handle)
2615
2616 END SUBROUTINE compute_xkp
2617
2618! **************************************************************************************************
2619!> \brief ...
2620!> \param kpoints ...
2621!> \param qs_env ...
2622! **************************************************************************************************
2623 SUBROUTINE kpoint_init_cell_index_simple(kpoints, qs_env)
2624
2625 TYPE(kpoint_type), POINTER :: kpoints
2626 TYPE(qs_environment_type), POINTER :: qs_env
2627
2628 CHARACTER(LEN=*), PARAMETER :: routinen = 'kpoint_init_cell_index_simple'
2629
2630 INTEGER :: handle, nimages
2631 TYPE(dft_control_type), POINTER :: dft_control
2632 TYPE(mp_para_env_type), POINTER :: para_env
2633 TYPE(neighbor_list_set_p_type), DIMENSION(:), &
2634 POINTER :: sab_orb
2635
2636 CALL timeset(routinen, handle)
2637
2638 NULLIFY (dft_control, para_env, sab_orb)
2639 CALL get_qs_env(qs_env=qs_env, para_env=para_env, dft_control=dft_control, sab_orb=sab_orb)
2640 nimages = dft_control%nimages
2641 CALL kpoint_init_cell_index(kpoints, sab_orb, para_env, dft_control)
2642
2643 ! set back dft_control%nimages
2644 dft_control%nimages = nimages
2645
2646 CALL timestop(handle)
2647
2648 END SUBROUTINE kpoint_init_cell_index_simple
2649
2650! **************************************************************************************************
2651!> \brief ...
2652!> \param qs_env ...
2653!> \param bs_env ...
2654! **************************************************************************************************
2655 SUBROUTINE soc(qs_env, bs_env)
2656 TYPE(qs_environment_type), POINTER :: qs_env
2657 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
2658
2659 CHARACTER(LEN=*), PARAMETER :: routinen = 'soc'
2660
2661 INTEGER :: handle
2662
2663 CALL timeset(routinen, handle)
2664
2665 ! V^SOC_µν^(α),R = ħ/2 < ϕ_µ cell O | sum_ℓ ΔV_ℓ^SO(r,r') L^(α) | ϕ_ν cell R>, α = x,y,z
2666 ! see Hartwigsen, Goedecker, Hutter, Eq.(18), (19) (doi.org/10.1103/PhysRevB.58.3641)
2667 CALL v_soc_xyz_from_pseudopotential(qs_env, bs_env%mat_V_SOC_xyz)
2668
2669 ! Calculate H^SOC_µν,σσ'(k) = sum_α V^SOC_µν^(α)(k)*Pauli-matrix^(α)_σσ'
2670 ! see Hartwigsen, Goedecker, Hutter, Eq.(18) (doi.org/10.1103/PhysRevB.58.3641)
2671 SELECT CASE (bs_env%small_cell_full_kp_or_large_cell_Gamma)
2672 CASE (large_cell_gamma)
2673
2674 ! H^SOC_µν,σσ' = sum_α V^SOC_µν^(α)*Pauli-matrix^(α)_σσ'
2675 CALL h_ks_spinor_gamma(bs_env)
2676
2677 CASE (small_cell_full_kp)
2678
2679 ! V^SOC_µν^(α),R -> V^SOC_µν^(α)(k); then calculate spinor H^SOC_µν,σσ'(k) (see above)
2680 CALL h_ks_spinor_kp(qs_env, bs_env)
2681
2682 END SELECT
2683
2684 CALL timestop(handle)
2685
2686 END SUBROUTINE soc
2687
2688! **************************************************************************************************
2689!> \brief ...
2690!> \param bs_env ...
2691! **************************************************************************************************
2692 SUBROUTINE h_ks_spinor_gamma(bs_env)
2693
2694 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
2695
2696 CHARACTER(LEN=*), PARAMETER :: routinen = 'H_KS_spinor_Gamma'
2697
2698 INTEGER :: handle, nao, s
2699 TYPE(cp_fm_struct_type), POINTER :: str
2700
2701 CALL timeset(routinen, handle)
2702
2703 CALL cp_fm_get_info(bs_env%fm_ks_Gamma(1), nrow_global=nao)
2704
2705 ALLOCATE (bs_env%cfm_SOC_spinor_ao(1))
2706 CALL create_cfm_double(bs_env%cfm_SOC_spinor_ao(1), fm_orig=bs_env%fm_ks_Gamma(1))
2707 CALL cp_cfm_set_all(bs_env%cfm_SOC_spinor_ao(1), z_zero)
2708
2709 str => bs_env%fm_ks_Gamma(1)%matrix_struct
2710
2711 s = nao + 1
2712
2713 ! careful: inside add_dbcsr_submat, mat_V_SOC_xyz is multiplied by i because the real matrix
2714 ! mat_V_SOC_xyz is antisymmetric as V_SOC matrix is purely imaginary and Hermitian
2715 CALL add_dbcsr_submat(bs_env%cfm_SOC_spinor_ao(1), bs_env%mat_V_SOC_xyz(1, 1)%matrix, &
2716 str, s, 1, z_one, .true.)
2717 CALL add_dbcsr_submat(bs_env%cfm_SOC_spinor_ao(1), bs_env%mat_V_SOC_xyz(2, 1)%matrix, &
2718 str, s, 1, gaussi, .true.)
2719 CALL add_dbcsr_submat(bs_env%cfm_SOC_spinor_ao(1), bs_env%mat_V_SOC_xyz(3, 1)%matrix, &
2720 str, 1, 1, z_one, .false.)
2721 CALL add_dbcsr_submat(bs_env%cfm_SOC_spinor_ao(1), bs_env%mat_V_SOC_xyz(3, 1)%matrix, &
2722 str, s, s, -z_one, .false.)
2723
2724 CALL timestop(handle)
2725
2726 END SUBROUTINE h_ks_spinor_gamma
2727
2728! **************************************************************************************************
2729!> \brief ...
2730!> \param qs_env ...
2731!> \param bs_env ...
2732! **************************************************************************************************
2733 SUBROUTINE h_ks_spinor_kp(qs_env, bs_env)
2734 TYPE(qs_environment_type), POINTER :: qs_env
2735 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
2736
2737 CHARACTER(LEN=*), PARAMETER :: routinen = 'H_KS_spinor_kp'
2738
2739 INTEGER :: handle, i_dim, ikp, n_spin, &
2740 nkp_bs_and_dos, s
2741 INTEGER, DIMENSION(:, :, :), POINTER :: cell_to_index_scf
2742 REAL(kind=dp), DIMENSION(3) :: xkp
2743 TYPE(cp_cfm_type) :: cfm_v_soc_xyz_ikp
2744 TYPE(cp_fm_struct_type), POINTER :: str
2745 TYPE(kpoint_type), POINTER :: kpoints_scf
2746 TYPE(neighbor_list_set_p_type), DIMENSION(:), &
2747 POINTER :: sab_nl
2748
2749 CALL timeset(routinen, handle)
2750
2751 nkp_bs_and_dos = bs_env%nkp_bs_and_DOS
2752 n_spin = bs_env%n_spin
2753 s = bs_env%n_ao + 1
2754 str => bs_env%cfm_ks_kp(1, 1)%matrix_struct
2755
2756 CALL cp_cfm_create(cfm_v_soc_xyz_ikp, bs_env%cfm_work_mo%matrix_struct)
2757
2758 CALL alloc_cfm_double_array_1d(bs_env%cfm_SOC_spinor_ao, bs_env%cfm_ks_kp(1, 1), nkp_bs_and_dos)
2759
2760 CALL get_qs_env(qs_env, kpoints=kpoints_scf)
2761
2762 NULLIFY (sab_nl)
2763 CALL get_kpoint_info(kpoints_scf, sab_nl=sab_nl, cell_to_index=cell_to_index_scf)
2764
2765 DO i_dim = 1, 3
2766
2767 DO ikp = 1, nkp_bs_and_dos
2768
2769 xkp(1:3) = bs_env%kpoints_DOS%xkp(1:3, ikp)
2770
2771 CALL cp_cfm_set_all(cfm_v_soc_xyz_ikp, z_zero)
2772
2773 CALL rsmat_to_kp(bs_env%mat_V_SOC_xyz, i_dim, xkp, cell_to_index_scf, &
2774 sab_nl, bs_env, cfm_v_soc_xyz_ikp, imag_rs_mat=.true.)
2775
2776 ! multiply V_SOC with i because bs_env%mat_V_SOC_xyz stores imag. part (real part = 0)
2777 CALL cp_cfm_scale(gaussi, cfm_v_soc_xyz_ikp)
2778
2779 SELECT CASE (i_dim)
2780 CASE (1)
2781 ! add V^SOC_x * σ_x for σ_x = ( (0,1) (1,0) )
2782 CALL add_cfm_submat(bs_env%cfm_SOC_spinor_ao(ikp), cfm_v_soc_xyz_ikp, 1, s)
2783 CALL add_cfm_submat(bs_env%cfm_SOC_spinor_ao(ikp), cfm_v_soc_xyz_ikp, s, 1)
2784 CASE (2)
2785 ! add V^SOC_y * σ_y for σ_y = ( (0,-i) (i,0) )
2786 CALL cp_cfm_scale(gaussi, cfm_v_soc_xyz_ikp)
2787 CALL add_cfm_submat(bs_env%cfm_SOC_spinor_ao(ikp), cfm_v_soc_xyz_ikp, 1, s)
2788 CALL cp_cfm_scale(-z_one, cfm_v_soc_xyz_ikp)
2789 CALL add_cfm_submat(bs_env%cfm_SOC_spinor_ao(ikp), cfm_v_soc_xyz_ikp, s, 1)
2790 CASE (3)
2791 ! add V^SOC_z * σ_z for σ_z = ( (1,0) (0,1) )
2792 CALL add_cfm_submat(bs_env%cfm_SOC_spinor_ao(ikp), cfm_v_soc_xyz_ikp, 1, 1)
2793 CALL cp_cfm_scale(-z_one, cfm_v_soc_xyz_ikp)
2794 CALL add_cfm_submat(bs_env%cfm_SOC_spinor_ao(ikp), cfm_v_soc_xyz_ikp, s, s)
2795 END SELECT
2796
2797 END DO
2798
2799 END DO ! ikp
2800
2801 CALL cp_cfm_release(cfm_v_soc_xyz_ikp)
2802
2803 CALL timestop(handle)
2804
2805 END SUBROUTINE h_ks_spinor_kp
2806
2807! **************************************************************************************************
2808!> \brief ...
2809!> \param cfm_array ...
2810!> \param cfm_template ...
2811!> \param n ...
2812! **************************************************************************************************
2813 SUBROUTINE alloc_cfm_double_array_1d(cfm_array, cfm_template, n)
2814 TYPE(cp_cfm_type), ALLOCATABLE, DIMENSION(:) :: cfm_array
2815 TYPE(cp_cfm_type) :: cfm_template
2816 INTEGER :: n
2817
2818 CHARACTER(LEN=*), PARAMETER :: routinen = 'alloc_cfm_double_array_1d'
2819
2820 INTEGER :: handle, i
2821
2822 CALL timeset(routinen, handle)
2823
2824 ALLOCATE (cfm_array(n))
2825 DO i = 1, n
2826 CALL create_cfm_double(cfm_array(i), cfm_orig=cfm_template)
2827 CALL cp_cfm_set_all(cfm_array(i), z_zero)
2828 END DO
2829
2830 CALL timestop(handle)
2831
2832 END SUBROUTINE alloc_cfm_double_array_1d
2833
2834! **************************************************************************************************
2835!> \brief ...
2836!> \param bs_env ...
2837! **************************************************************************************************
2838 SUBROUTINE get_all_vbm_cbm_bandgaps(bs_env)
2839
2840 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
2841
2842 CHARACTER(LEN=*), PARAMETER :: routinen = 'get_all_VBM_CBM_bandgaps'
2843
2844 INTEGER :: handle
2845
2846 CALL timeset(routinen, handle)
2847
2848 CALL get_vbm_cbm_bandgaps(bs_env%band_edges_scf, bs_env%eigenval_scf, bs_env)
2849 CALL get_vbm_cbm_bandgaps(bs_env%band_edges_G0W0, bs_env%eigenval_G0W0, bs_env)
2850 CALL get_vbm_cbm_bandgaps(bs_env%band_edges_HF, bs_env%eigenval_HF, bs_env)
2851
2852 CALL timestop(handle)
2853
2854 END SUBROUTINE get_all_vbm_cbm_bandgaps
2855
2856! **************************************************************************************************
2857!> \brief ...
2858!> \param band_edges ...
2859!> \param ev ...
2860!> \param bs_env ...
2861! **************************************************************************************************
2862 SUBROUTINE get_vbm_cbm_bandgaps(band_edges, ev, bs_env)
2863 TYPE(band_edges_type) :: band_edges
2864 REAL(kind=dp), DIMENSION(:, :, :) :: ev
2865 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
2866
2867 CHARACTER(LEN=*), PARAMETER :: routinen = 'get_VBM_CBM_bandgaps'
2868
2869 INTEGER :: handle, homo, homo_1, homo_2, ikp, &
2870 ispin, lumo, lumo_1, lumo_2, n_mo
2871 REAL(kind=dp) :: e_dbg_at_ikp
2872
2873 CALL timeset(routinen, handle)
2874
2875 n_mo = bs_env%n_ao
2876
2877 band_edges%DBG = 1000.0_dp
2878
2879 SELECT CASE (bs_env%n_spin)
2880 CASE (1)
2881 homo = bs_env%n_occ(1)
2882 lumo = homo + 1
2883 band_edges%VBM = maxval(ev(1:homo, :, 1))
2884 band_edges%CBM = minval(ev(homo + 1:n_mo, :, 1))
2885 CASE (2)
2886 homo_1 = bs_env%n_occ(1)
2887 lumo_1 = homo_1 + 1
2888 homo_2 = bs_env%n_occ(2)
2889 lumo_2 = homo_2 + 1
2890 band_edges%VBM = max(maxval(ev(1:homo_1, :, 1)), maxval(ev(1:homo_2, :, 2)))
2891 band_edges%CBM = min(minval(ev(homo_1 + 1:n_mo, :, 1)), minval(ev(homo_2 + 1:n_mo, :, 2)))
2892 CASE DEFAULT
2893 cpabort("Error with number of spins.")
2894 END SELECT
2895
2896 band_edges%IDBG = band_edges%CBM - band_edges%VBM
2897
2898 DO ispin = 1, bs_env%n_spin
2899
2900 homo = bs_env%n_occ(ispin)
2901
2902 DO ikp = 1, bs_env%nkp_bs_and_DOS
2903
2904 e_dbg_at_ikp = -maxval(ev(1:homo, ikp, ispin)) + minval(ev(homo + 1:n_mo, ikp, ispin))
2905
2906 IF (e_dbg_at_ikp < band_edges%DBG) band_edges%DBG = e_dbg_at_ikp
2907
2908 END DO
2909
2910 END DO
2911
2912 CALL timestop(handle)
2913
2914 END SUBROUTINE get_vbm_cbm_bandgaps
2915
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:60
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:311
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:122
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:150
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, sab_cneo, particle_set, energy, force, matrix_h, matrix_h_im, matrix_ks, matrix_ks_im, matrix_vxc, run_rtp, rtp, matrix_h_kp, matrix_h_im_kp, matrix_ks_kp, matrix_ks_im_kp, matrix_vxc_kp, kinetic_kp, matrix_s_kp, matrix_w_kp, matrix_s_ri_aux_kp, matrix_s, matrix_s_ri_aux, matrix_w, matrix_p_mp2, matrix_p_mp2_admm, 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, rhoz_cneo_set, ecoul_1c, rho0_s_rs, rho0_s_gs, rhoz_cneo_s_rs, rhoz_cneo_s_gs, do_kpoints, has_unit_metric, requires_mo_derivs, mo_derivs, mo_loc_history, nkind, natom, nelectron_total, nelectron_spin, efield, neighbor_list_id, linres_control, xas_env, virial, cp_ddapc_env, cp_ddapc_ewald, outer_scf_history, outer_scf_ihistory, x_data, et_coupling, dftb_potential, results, se_taper, se_store_int_env, se_nddo_mpole, se_nonbond_env, admm_env, lri_env, lri_density, exstate_env, ec_env, harris_env, dispersion_env, gcp_env, vee, rho_external, external_vxc, mask, mp2_env, bs_env, kg_env, wanniercentres, atprop, ls_scf_env, do_transport, transport_env, v_hartree_rspace, s_mstruct_changed, rho_changed, potential_changed, forces_up_to_date, mscfg_env, almo_scf_env, gradient_history, variable_history, embed_pot, spin_embed_pot, polar_env, mos_last_converged, eeq, rhs, do_rixs, tb_tblite)
Get the QUICKSTEP environment.
Definition and initialisation of the mo data type.
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 ...