(git:f2099e5)
Loading...
Searching...
No Matches
floquet_utils.F
Go to the documentation of this file.
1!--------------------------------------------------------------------------------------------------!
2! CP2K: A general program to perform molecular dynamics simulations !
3! Copyright 2000-2026 CP2K developers group <https://cp2k.org> !
4! !
5! SPDX-License-Identifier: GPL-2.0-or-later !
6!--------------------------------------------------------------------------------------------------!
7
8! **************************************************************************************************
9!> \brief Helper routines for the Floquet-Bloch band-structure calculation (floquet_main).
10!> \par History
11!> \author Shridhar Shanbhag (27.01.2026)
12! **************************************************************************************************
19 USE cp_files, ONLY: close_file,&
24 USE kinds, ONLY: default_string_length,&
25 dp,&
26 int_8
27 USE machine, ONLY: m_memory_details
28 USE mathconstants, ONLY: gaussi,&
29 pi,&
30 z_one,&
31 z_zero
35 USE physcon, ONLY: a_bohr,&
36 evolt,&
37 kelvin
42 USE util, ONLY: sort
43#include "./base/base_uses.f90"
44
45 IMPLICIT NONE
46
47 PRIVATE
48
49 CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'floquet_utils'
50
51 ! Number of full Floquet-Hamiltonian copies (each n_f_size^2 complex(dp), 16 bytes per
52 ! element) that the subgroup must be able to hold, distributed across its ranks.
53 ! We size for 8 to leave headroom.
54 INTEGER, PARAMETER, PRIVATE :: n_fm_work_copies = 8
55
56 ! Public subroutines
57 PUBLIC :: build_floquet_matrix, &
66
67CONTAINS
68
69! **************************************************************************************************
70!> \brief Off-diagonal coupling block of H_F(k) for one k-point and spin, from precomputed data.
71!> \param bs_env ...
72!> \param p_k_kp_spin ...
73!> \param off_diag_m ...
74! **************************************************************************************************
75 SUBROUTINE build_off_diagonal_matrix(bs_env, p_k_kp_spin, off_diag_m)
76 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
77 COMPLEX(KIND=dp), DIMENSION(:, :, :), INTENT(IN) :: p_k_kp_spin
78 COMPLEX(KIND=dp), DIMENSION(:, :), INTENT(OUT) :: off_diag_m
79
80 CHARACTER(LEN=*), PARAMETER :: routineN = 'build_off_diagonal_matrix'
81
82 COMPLEX(KIND=dp), DIMENSION(3) :: efactor
83 INTEGER :: handle, i, i_dir, j, n_mo
84 REAL(KIND=dp) :: amplitude, omega
85 REAL(KIND=dp), DIMENSION(3) :: e_vec, phi, polarisation
86
87 CALL timeset(routinen, handle)
88
89 ! Builds the matrix that occupies the off diagonal blocks in the Floquet Matrix H_F
90
91 n_mo = SIZE(p_k_kp_spin, 2)
92
93 polarisation(:) = bs_env%floquet_polarisation(:)
94 IF (sqrt(sum(polarisation**2)) < epsilon(0.0_dp)) THEN
95 cpabort("Invalid (too small) polarisation vector specified for POLARISATION")
96 END IF
97
98 amplitude = bs_env%floquet_amplitude
99 e_vec(:) = amplitude*polarisation
100 phi(:) = pi*bs_env%floquet_phi(:)
101 omega = bs_env%floquet_omega
102
103 ! E_factor(α) = (i E(α) exp(i·φ(α)))/(2ω), where α = x,y,z
104 DO i_dir = 1, 3
105 efactor(i_dir) = gaussi*e_vec(i_dir)*cmplx(cos(phi(i_dir)), sin(phi(i_dir)), kind=dp)/(2*omega)
106 END DO
107
108 ! off_diag_uv = Σ_α [p_uv^α(k) · E_factor(α)], where α = x,y,z
109 off_diag_m(:, :) = z_zero
110 DO i_dir = 1, 3
111 DO i = 1, n_mo
112 DO j = 1, n_mo
113 off_diag_m(i, j) = off_diag_m(i, j) + &
114 p_k_kp_spin(i_dir, i, j)*efactor(i_dir)
115 END DO
116 END DO
117 END DO
118
119 CALL timestop(handle)
120
121 END SUBROUTINE build_off_diagonal_matrix
122
123! **************************************************************************************************
124!> \brief Diagonal block of H_F(k) for Floquet sector f_index.
125!> \param bs_env ...
126!> \param e_k_kp_spin ...
127!> \param f_index Floquet sector index
128!> \param diag_e ...
129! **************************************************************************************************
130 SUBROUTINE build_diagonal_matrix(bs_env, e_k_kp_spin, f_index, diag_e)
131 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
132 REAL(KIND=dp), DIMENSION(:), INTENT(IN) :: e_k_kp_spin
133 INTEGER, INTENT(IN) :: f_index
134 COMPLEX(KIND=dp), DIMENSION(:, :), INTENT(OUT) :: diag_e
135
136 CHARACTER(LEN=*), PARAMETER :: routineN = 'build_diagonal_matrix'
137
138 INTEGER :: handle, i, n_mo
139 REAL(KIND=dp) :: omega
140
141 CALL timeset(routinen, handle)
142 ! Builds the diagonal block of the H_F for Floquet sector index f_index
143 ! Equilibrium band energies shifted by f_index·ħΩ, i.e., diag_e(n,n) = ε_{nk} + f_index·ħΩ.
144 n_mo = SIZE(e_k_kp_spin)
145 omega = bs_env%floquet_omega
146 diag_e(:, :) = z_zero
147 DO i = 1, n_mo
148 diag_e(i, i) = e_k_kp_spin(i) + f_index*omega
149 END DO
150
151 CALL timestop(handle)
152
153 END SUBROUTINE build_diagonal_matrix
154
155! **************************************************************************************************
156!> \brief Builds the Floquet-Bloch Hamiltonian H_F(k) for a single k-point and spin channel from
157!> the band data currently held in floquet_env.
158!> \param bs_env ...
159!> \param floquet_env ...
160!> \param floquet_matrix ...
161! **************************************************************************************************
162 SUBROUTINE build_floquet_matrix(bs_env, floquet_env, floquet_matrix)
163 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
164 TYPE(floquet_env_type), INTENT(IN) :: floquet_env
165 TYPE(cp_cfm_type), INTENT(IN) :: floquet_matrix
166
167 CHARACTER(LEN=*), PARAMETER :: routinen = 'build_floquet_matrix'
168
169 COMPLEX(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: conj_off_diag_m, diag_e, off_diag_m
170 INTEGER :: f_index, handle, i, i_f, max_f_index, &
171 n_fbands, n_mo
172
173 CALL timeset(routinen, handle)
174
175 n_mo = floquet_env%n_mo
176 max_f_index = floquet_env%max_f_index
177 n_fbands = 1 + 2*max_f_index
178
179 ! Creates the floquet matrix H_F by placing the diagonal and off diagonal blocks
180 ALLOCATE (diag_e(n_mo, n_mo), source=z_zero)
181 ALLOCATE (off_diag_m(n_mo, n_mo), source=z_zero)
182 ALLOCATE (conj_off_diag_m(n_mo, n_mo), source=z_zero)
183
184 CALL build_off_diagonal_matrix(bs_env, floquet_env%p_k_kp_spin, off_diag_m)
185 conj_off_diag_m(:, :) = conjg(transpose(off_diag_m(:, :)))
186
187 floquet_matrix%local_data(:, :) = z_zero
188 DO i = 1, n_fbands
189 i_f = 1 + (i - 1)*n_mo
190 f_index = i - max_f_index - 1
191 CALL build_diagonal_matrix(bs_env, floquet_env%e_k_kp_spin, f_index, diag_e)
192 CALL cp_cfm_set_submatrix(floquet_matrix, diag_e, i_f, i_f)
193 IF (i > 1) THEN
194 CALL cp_cfm_set_submatrix(floquet_matrix, off_diag_m, i_f, i_f - n_mo)
195 CALL cp_cfm_set_submatrix(floquet_matrix, conj_off_diag_m, i_f - n_mo, i_f)
196 END IF
197 END DO
198 DEALLOCATE (diag_e, off_diag_m, conj_off_diag_m)
199
200 CALL timestop(handle)
201 END SUBROUTINE build_floquet_matrix
202
203! **************************************************************************************************
204!> \brief Make this k-point/spin's band data available to every rank of the owning subgroup.
205!> \param para_env the global parallel environment
206!> \param para_env_sub the subgroup parallel environment
207!> \param ispin the spin channel
208!> \param ikp the DOS k-point index
209!> \param e_k band energies for all DOS k-points, distributed
210!> \param p_k momentum matrix elements, distributed
211!> \param floquet_env ...
212! **************************************************************************************************
213 SUBROUTINE distribute_floquet_kp_data(para_env, para_env_sub, ispin, ikp, e_k, p_k, &
214 floquet_env)
215 TYPE(mp_para_env_type), POINTER :: para_env, para_env_sub
216 INTEGER, INTENT(IN) :: ispin, ikp
217 REAL(kind=dp), DIMENSION(:, :, :), INTENT(IN) :: e_k
218 COMPLEX(KIND=dp), DIMENSION(:, :, :, :, :), &
219 INTENT(IN) :: p_k
220 TYPE(floquet_env_type), INTENT(INOUT) :: floquet_env
221
222 CHARACTER(LEN=*), PARAMETER :: routinen = 'distribute_floquet_kp_data'
223
224 INTEGER :: handle, loc_idx, local_src, nhi, nlo, &
225 owner
226
227 CALL timeset(routinen, handle)
228
229 ! Identify the owner's rank within the subgroup (all subgroup ranks agree on local_src).
230 owner = mod(ikp - 1, para_env%num_pe)
231
232 local_src = -1
233 IF (para_env%mepos == owner) local_src = para_env_sub%mepos
234 CALL para_env_sub%max(local_src)
235
236 ! The owner copies its single-spin slice of this k-point's distributed band data into the
237 ! broadcast buffers, then broadcasts them to the whole subgroup. Only the active band
238 ! window [n_lo, n_hi] (the MAX_NMO states closest to the VBM) is taken from the full-band
239 ! e_k/p_k arrays; the broadcast buffers are sized to this window (floquet_env%n_mo).
240 IF (para_env%mepos == owner) THEN
241 loc_idx = ceiling(real(ikp)/para_env%num_pe)
242 nlo = floquet_env%n_lo(ispin)
243 nhi = floquet_env%n_hi(ispin)
244 floquet_env%e_k_kp_spin(:) = e_k(ispin, loc_idx, nlo:nhi)
245 floquet_env%p_k_kp_spin(:, :, :) = p_k(ispin, loc_idx, :, nlo:nhi, nlo:nhi)
246 END IF
247 CALL para_env_sub%bcast(floquet_env%e_k_kp_spin, local_src)
248 CALL para_env_sub%bcast(floquet_env%p_k_kp_spin, local_src)
249
250 CALL timestop(handle)
251
252 END SUBROUTINE distribute_floquet_kp_data
253
254! **************************************************************************************************
255!> \brief Precompute, on the global communicator, the band quantities needed to assemble the
256!> Floquet-Bloch Hamiltonian for all DOS k-points (all spins), distributed across ranks.
257!> \param qs_env ...
258!> \param bs_env ...
259!> \param e_k ...
260!> \param p_k ...
261! **************************************************************************************************
262 SUBROUTINE compute_e_k_p_k(qs_env, bs_env, e_k, p_k)
263 TYPE(qs_environment_type), POINTER :: qs_env
264 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
265 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :, :), &
266 INTENT(OUT) :: e_k
267 COMPLEX(KIND=dp), ALLOCATABLE, &
268 DIMENSION(:, :, :, :, :), INTENT(OUT) :: p_k
269
270 CHARACTER(LEN=*), PARAMETER :: routinen = 'compute_e_k_p_k'
271
272 INTEGER :: handle, ikp, nkp_only_bs, nkp_start
273 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :) :: xkp_all
274
275 CALL timeset(routinen, handle)
276
277 ! The band-structure k-points are the last nkp_only_bs entries of kpoints_DOS%xkp, stored
278 ! after the nkp_only_DOS DOS-only k-points.
279 nkp_start = bs_env%nkp_only_DOS
280 nkp_only_bs = bs_env%nkp_only_bs
281
282 ! Collect the coordinates of all band-structure k-points (global index nkp_start + local).
283 ALLOCATE (xkp_all(3, nkp_only_bs))
284 DO ikp = 1, nkp_only_bs
285 xkp_all(:, ikp) = bs_env%kpoints_DOS%xkp(1:3, nkp_start + ikp)
286 END DO
287
288 ! Calculate and distribute the results across ranks
289 ! One k-point per rank, round-robin by global rank
290 ! So the results for ikp are stored in mepos==MOD(ikp-1,num_pe)
291 CALL qs_moment_kpoints_deep(qs_env, xkp_all, momentum=p_k, energy=e_k, do_parallel=.true.)
292
293 DEALLOCATE (xkp_all)
294
295 CALL timestop(handle)
296 END SUBROUTINE compute_e_k_p_k
297
298! **************************************************************************************************
299!> \brief Finds the number of MPI ranks that share a physical node, determined by splitting the
300!> given communicator into node-local communicators via MPI's shared-memory split type.
301!> \param para_env ...
302!> \return the number of ranks on the calling rank's node
303! **************************************************************************************************
304 FUNCTION find_ranks_per_node(para_env) RESULT(ranks_per_node)
305 TYPE(mp_para_env_type), POINTER :: para_env
306 INTEGER :: ranks_per_node
307
308 TYPE(mp_comm_type) :: node_comm
309
310 CALL node_comm%from_split_type(para_env, mp_comm_split_type_shared, key=para_env%mepos)
311 ranks_per_node = max(1, node_comm%num_pe)
312 CALL node_comm%free()
313
314 END FUNCTION find_ranks_per_node
315
316! **************************************************************************************************
317!> \brief Choose the optimal number of MPI ranks per subgroup for Floquet calculations.
318!> \param qs_env ...
319!> \param bs_env ...
320!> \return the chosen number of ranks per subgroup (1 .. num_pe)
321! **************************************************************************************************
322 FUNCTION floquet_determine_subgroup_size(qs_env, bs_env) RESULT(group_size)
323 TYPE(qs_environment_type), POINTER :: qs_env
324 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
325 INTEGER :: group_size
326
327 CHARACTER(LEN=*), PARAMETER :: routinen = 'floquet_determine_subgroup_size'
328
329 INTEGER :: g_load, g_mem, handle, n_f_size, &
330 nkp_only_bs, ranks_per_node, unit_nr
331 INTEGER(KIND=int_8) :: buffers, cached, memfree, memlikelyfree, &
332 memtotal, needed_bytes, slab, &
333 sreclaimable, usable_per_rank
334 REAL(kind=dp) :: mem_fill_fraction
335 TYPE(mp_para_env_type), POINTER :: para_env
336
337 CALL timeset(routinen, handle)
338
339 CALL get_qs_env(qs_env, para_env=para_env)
340
341 unit_nr = bs_env%unit_nr
342 ! Size for the active band window (the MAX_NMO band count, or the full count when MAX_NMO <= 0)
343 n_f_size = floquet_active_band_count(bs_env)*(1 + 2*bs_env%max_floquet_index)
344 nkp_only_bs = bs_env%nkp_only_bs
345 mem_fill_fraction = bs_env%floquet_mem_fill_fraction
346
347 ! We choose the subgroup size to be the larger of two floors:
348 ! 1. Memory floor G_mem: the subgroup must jointly hold the Floquet working set,
349 ! G_mem = ceil(needed_bytes/usable per-rank memory), where the usable memory is
350 ! the mem_fill_fraction of the per-rank FREE memory.
351 ! 2. K-point floor G_load = floor(num_pe / nkp_only_bs): the LARGEST G that still
352 ! yields at least nkp_only_bs subgroups (floor(num_pe/G) >= nkp_only_bs). When ranks
353 ! outnumber k-points this hands every k-point its own (larger, hence faster)
354 ! subgroup instead of leaving spare ranks idle.
355
356 ! usable_per_rank = a fraction of the per-rank FREE memory, not including SCF and other data
357 CALL m_memory_details(memtotal, memfree, buffers, cached, slab, sreclaimable, memlikelyfree)
358 ranks_per_node = find_ranks_per_node(para_env)
359 usable_per_rank = int(mem_fill_fraction*real(memfree, dp), int_8)/int(ranks_per_node, int_8)
360
361 ! Total memory the subgroup must hold: n_fm_work_copies copies of the Floquet
362 ! Hamiltonian, each n_f_size^2 complex(dp) numbers at 16 bytes each.
363 needed_bytes = 16_int_8*int(n_fm_work_copies, int_8)*int(n_f_size, int_8)**2
364
365 IF (usable_per_rank <= 0_int_8) THEN
366 ! Memory info unavailable (e.g. no /proc found) use one subgroup spanning all ranks
367 g_mem = para_env%num_pe
368 ELSE
369 ! Memory floor: smallest G with needed_bytes/G <= usable_per_rank
370 g_mem = int(min((needed_bytes + usable_per_rank - 1_int_8)/usable_per_rank, &
371 int(para_env%num_pe, int_8)))
372 END IF
373
374 IF (g_mem > para_env%num_pe) cpwarn("Total Memory Likely Insufficient, process may be killed")
375
376 ! K-point floor: floor(num_pe / nkp_only_bs) = largest G that gives at least nkp_only_bs subgroups
377 g_load = para_env%num_pe/max(nkp_only_bs, 1)
378
379 group_size = max(g_mem, g_load)
380 group_size = min(group_size, para_env%num_pe)
381 group_size = max(group_size, 1)
382 CALL para_env%max(group_size)
383
384 IF (unit_nr > 0) THEN
385 WRITE (unit_nr, '(T2,A)') ""
386 WRITE (unit_nr, '(T2,A,T66,I15)') "FLOQUET MEMORY | Detected MPI ranks per node:", ranks_per_node
387 WRITE (unit_nr, '(T2,A,T66,I12,A)') "FLOQUET MEMORY | Free memory per rank:", &
388 (memlikelyfree/int(ranks_per_node, int_8))/1048576_int_8, " MB"
389 WRITE (unit_nr, '(T2,A,T66,I12,A)') "FLOQUET MEMORY | Usable per rank (reserve applied):", &
390 usable_per_rank/1048576_int_8, " MB"
391 WRITE (unit_nr, '(T2,A,T66,I15)') "FLOQUET MEMORY | Floquet copies needed:", n_fm_work_copies
392 WRITE (unit_nr, '(T2,A,T66,I12,A)') "FLOQUET MEMORY | Total Floquet working set:", &
393 needed_bytes/1048576_int_8, " MB"
394 WRITE (unit_nr, '(T2,A,T66,I12,A)') "FLOQUET MEMORY | Floquet working set per rank:", &
395 (needed_bytes/int(max(group_size, 1), int_8))/1048576_int_8, " MB"
396 WRITE (unit_nr, '(T2,A,T66,I15)') "FLOQUET MEMORY | Memory floor (ranks/subgroup):", g_mem
397 WRITE (unit_nr, '(T2,A,T66,I15)') "FLOQUET MEMORY | K-point floor (ranks/subgroup):", g_load
398 WRITE (unit_nr, '(T2,A,T66,I15)') "FLOQUET MEMORY | Chosen MPI ranks per subgroup:", group_size
399 END IF
400
401 CALL timestop(handle)
402 END FUNCTION floquet_determine_subgroup_size
403
404! **************************************************************************************************
405!> \brief Split the para_env into subgroups so that the Floquet Hamiltonian is distributed across
406!> the ranks of each subgroup. Also creates the subgroup BLACS context.
407!> \param qs_env ...
408!> \param bs_env ...
409!> \param para_env_sub the created subgroup parallel environment
410!> \param blacs_env_sub the created subgroup BLACS context
411!> \param group_distribution subgroup index of every global rank, 0:num_pe-1
412!> \param ngroups the number of subgroups created
413! **************************************************************************************************
414 SUBROUTINE make_floquet_subgroups(qs_env, bs_env, para_env_sub, blacs_env_sub, &
415 group_distribution, ngroups)
416 TYPE(qs_environment_type), POINTER :: qs_env
417 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
418 TYPE(mp_para_env_type), POINTER :: para_env_sub
419 TYPE(cp_blacs_env_type), POINTER :: blacs_env_sub
420 INTEGER, ALLOCATABLE, DIMENSION(:), INTENT(OUT) :: group_distribution
421 INTEGER, INTENT(OUT) :: ngroups
422
423 CHARACTER(LEN=*), PARAMETER :: routinen = 'make_floquet_subgroups'
424
425 INTEGER :: group_size, handle, n_spin, nkp_only_bs, &
426 stride_kp, unit_nr
427 TYPE(mp_para_env_type), POINTER :: para_env
428
429 CALL timeset(routinen, handle)
430
431 CALL get_qs_env(qs_env, para_env=para_env)
432 unit_nr = bs_env%unit_nr
433 nkp_only_bs = bs_env%nkp_only_bs
434 n_spin = bs_env%n_spin
435
436 ! We split the global communicator into subgroups with the Floquet Hamiltonian distributed
437 ! across the processes in each subgroup and the k-points distributed across subgroups.
438 group_size = floquet_determine_subgroup_size(qs_env, bs_env)
439
440 IF (nkp_only_bs < para_env%num_pe) THEN
441 stride_kp = para_env%num_pe/group_size
442 ELSE
443 stride_kp = 1
444 END IF
445 ALLOCATE (group_distribution(0:para_env%num_pe - 1))
446 ALLOCATE (para_env_sub)
447 CALL para_env_sub%from_split(comm=para_env, ngroups=ngroups, &
448 group_distribution=group_distribution, &
449 subgroup_min_size=group_size, stride=stride_kp)
450 IF (unit_nr > 0) THEN
451 WRITE (unit_nr, '(T2,A,T66,I15)') "FLOQUET MEMORY | Subgroup rank stride:", stride_kp
452 WRITE (unit_nr, '(T2,A,T66,I15)') "FLOQUET MEMORY | Number of subgroups:", ngroups
453 WRITE (unit_nr, '(/,T2,A,I5,A,I1,A)') "FLOQUET CALCULATIONS PROGRESS OUT OF", nkp_only_bs, &
454 " K-POINTS AND ", n_spin, " SPINS"
455 END IF
456
457 NULLIFY (blacs_env_sub)
458 CALL cp_blacs_env_create(blacs_env_sub, para_env_sub)
459
460 CALL timestop(handle)
461
462 END SUBROUTINE make_floquet_subgroups
463
464! **************************************************************************************************
465!> \brief Central and boundary-sector weights of every Floquet eigenvector, stored into
466!> floquet_env%w0 and floquet_env%wE.
467!> \param floquet_env ...
468!> \param floquet_eigenvectors Floquet eigenvectors
469! **************************************************************************************************
470 SUBROUTINE floquet_sector_weights(floquet_env, floquet_eigenvectors)
471 TYPE(floquet_env_type), INTENT(INOUT) :: floquet_env
472 TYPE(cp_cfm_type), INTENT(IN) :: floquet_eigenvectors
473
474 CHARACTER(LEN=*), PARAMETER :: routinen = 'floquet_sector_weights'
475
476 COMPLEX(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: v_block
477 INTEGER :: handle, max_f_index, n_f_size, n_mo
478
479 CALL timeset(routinen, handle)
480
481 n_mo = floquet_env%n_mo
482 max_f_index = floquet_env%max_f_index
483 n_f_size = floquet_env%n_f_size
484
485 ALLOCATE (v_block(n_mo, n_f_size))
486
487 ! Evaluate w0_α = Σ_{n=1..n_mo} |<n,m=0|α>|^2 (central sector)
488 CALL cp_cfm_get_submatrix(floquet_eigenvectors, v_block, 1 + n_mo*max_f_index, 1)
489 floquet_env%w0(:) = sum(abs(v_block)**2, dim=1)
490
491 ! Evaluate wE_α = Σ_{n=1..n_mo} (|<n,m=-M|α>|^2 + |<n,m=+M|α>|^2) (outermost rungs)
492 floquet_env%wE(:) = 0.0_dp
493 IF (max_f_index >= 1) THEN
494 CALL cp_cfm_get_submatrix(floquet_eigenvectors, v_block, 1, 1)
495 floquet_env%wE(:) = sum(abs(v_block)**2, dim=1)
496
497 CALL cp_cfm_get_submatrix(floquet_eigenvectors, v_block, 1 + n_mo*2*max_f_index, 1)
498 floquet_env%wE(:) = floquet_env%wE(:) + sum(abs(v_block)**2, dim=1)
499 END IF
500
501 DEALLOCATE (v_block)
502
503 ! The orthonormal rows of a unitary matrix are such that Σ_α w0_α = n_mo.
504 cpassert(abs(sum(floquet_env%w0) - real(n_mo, dp)) < 1.0e-6_dp*real(n_mo, dp))
505
506 CALL timestop(handle)
507
508 END SUBROUTINE floquet_sector_weights
509
510! **************************************************************************************************
511!> \brief Checks that MAX_FLOQUET_INDEX is large enough and the Floquet Hamiltonian was
512!> truncated far enough away from the central sector to leave it unperturbed.
513!> \param bs_env ...
514!> \param floquet_env holds the central- (w0) and outermost-sector (wE) weights
515! **************************************************************************************************
516 SUBROUTINE check_floquet_convergence(bs_env, floquet_env)
517 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
518 TYPE(floquet_env_type), INTENT(IN) :: floquet_env
519
520 CHARACTER(LEN=*), PARAMETER :: routinen = 'check_floquet_convergence'
521
522 CHARACTER(LEN=default_string_length) :: msg
523 INTEGER :: handle
524 REAL(kind=dp) :: leak
525
526 ! The truncation is converged if m=0 states have small weight on outermost rungs m = ±M
527 CALL timeset(routinen, handle)
528
529 ! MAX_FLOQUET_INDEX = 0 means no sidebands at all
530 IF (bs_env%max_floquet_index < 1) THEN
531 CALL timestop(handle)
532 RETURN
533 END IF
534
535 ! No cleanly m=0-dominated state exists: the drive has hybridised every band with
536 ! its sidebands, strong field but not a truncation failure.
537 IF (.NOT. any(floquet_env%w0 > 0.5_dp)) THEN
538 cpwarn("Floquet: no m=0-dominated state; cannot assess MAX_FLOQUET_INDEX convergence.")
539 CALL timestop(handle)
540 RETURN
541 END IF
542
543 leak = maxval(floquet_env%wE, mask=(floquet_env%w0 > 0.5_dp))
544
545 IF (bs_env%eps_floquet > 0.0_dp .AND. leak > bs_env%eps_floquet) THEN
546 WRITE (msg, '(A,ES10.2E2,A,ES10.2E2)') &
547 "MAX_FLOQUET_INDEX is too small. Leak: ", leak, "exceeds EPS_FLOQUET: ", bs_env%eps_floquet
548 cpabort(trim(msg))
549 END IF
550
551 CALL timestop(handle)
552
553 END SUBROUTINE check_floquet_convergence
554
555! **************************************************************************************************
556!> \brief Energy origin for the Floquet calculations, chosen to be the valence band maximum.
557!> \param bs_env ...
558!> \return the valence band maximum
559! **************************************************************************************************
560 FUNCTION floquet_reference_energy(bs_env) RESULT(mu)
561 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
562 REAL(kind=dp) :: mu
563
564 IF (bs_env%do_gw .OR. &
565 bs_env%gw_implementation == tensor_small_cell_full_kp) THEN
566 mu = bs_env%band_edges_scf%VBM
567 ELSE IF (bs_env%n_spin == 1) THEN
568 mu = bs_env%eigenval_scf_Gamma(bs_env%n_occ(1), 1)
569 ELSE
570 mu = max(bs_env%eigenval_scf_Gamma(bs_env%n_occ(1), 1), &
571 bs_env%eigenval_scf_Gamma(bs_env%n_occ(2), 2))
572 END IF
573
574 END FUNCTION floquet_reference_energy
575
576! **************************************************************************************************
577!> \brief Calculate all Floquet observables for one k-point and spin: the DOS (a_k), the m=0 bands,
578!> the quasi-energies, and store in floquet_env.
579!> \param bs_env ...
580!> \param para_env_sub ...
581!> \param ispin ...
582!> \param ikp ...
583!> \param floquet_env holds eigenvalues, w0 (input) and a_k, m0_energies, m0_weights,
584!> quasi_energies (output)
585! **************************************************************************************************
586 SUBROUTINE calculate_floquet_observables(bs_env, para_env_sub, ispin, ikp, floquet_env)
587 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
588 TYPE(mp_para_env_type), POINTER :: para_env_sub
589 INTEGER, INTENT(IN) :: ispin, ikp
590 TYPE(floquet_env_type), INTENT(INOUT) :: floquet_env
591
592 CHARACTER(LEN=*), PARAMETER :: routinen = 'calculate_floquet_observables'
593
594 INTEGER :: handle, i, i_e, j, n_e, n_f_size, n_mo
595 INTEGER, ALLOCATABLE, DIMENSION(:) :: work
596 REAL(kind=dp) :: broad, cum, e_min, energy, energy_step, &
597 mu, omega, target_level
598
599 CALL timeset(routinen, handle)
600
601 n_f_size = floquet_env%n_f_size
602 n_mo = floquet_env%n_mo
603 n_e = floquet_env%n_E
604
605 mu = floquet_reference_energy(bs_env)
606 omega = bs_env%floquet_omega
607 broad = bs_env%broadening_floquet
608 energy_step = bs_env%energy_step_floquet
609 e_min = mu - bs_env%energy_window_floquet
610
611 ! (1) Spectral function / DOS, A(k,E) = -(1/π) Im Tr_KS G^R_00(k,E),
612 ! where G^R_00(k,E) = (E + iη - H_F)^(-1) is the retarded Green's function
613 ! With H_F = Σ_α λ_α |α><α|, we simplify
614 ! A(k,E) = -(1/π) Σ_α w0_α Im[1/(E + iη - λ_α)], η = broadening/2.
615 ! This avoids the per-energy dense inversion of the full H_F.
616
617 DO i_e = 1, n_e
618 energy = e_min + i_e*energy_step
619 floquet_env%a_k(i_e) = -sum(floquet_env%w0(:)* &
620 aimag(z_one/(energy + gaussi*broad/2.0_dp - &
621 floquet_env%eigenvalues(:))))/pi
622 END DO
623
624 ! (2) m=0 band structure by weighted count
625 cum = 0.0_dp
626 j = 0
627 DO i = 1, n_mo
628 target_level = real(i, dp) - 0.5_dp
629 DO WHILE (cum < target_level .AND. j < n_f_size)
630 j = j + 1
631 cum = cum + floquet_env%w0(j)
632 END DO
633 floquet_env%m0_energies(i) = floquet_env%eigenvalues(j) - mu
634 floquet_env%m0_weights(i) = floquet_env%w0(j)
635 END DO
636
637 ! (3) Fold the m=0 bands (already relative to the VBM) into the first Floquet Brillouin zone.
638 floquet_env%quasi_energies(:) = floquet_env%m0_energies &
639 - omega*real(ceiling(floquet_env%m0_energies/omega - 0.5_dp), dp)
640
641 ! Sort the quasi-energies
642 ALLOCATE (work(n_mo))
643 CALL sort(floquet_env%quasi_energies, n_mo, work)
644 DEALLOCATE (work)
645
646 ! Store this result on the subgroup source only, so the global sum below picks up
647 ! each work item only once
648 IF (para_env_sub%is_source()) THEN
649 floquet_env%all_quasi_energies(:, ispin, ikp) = floquet_env%quasi_energies(:)
650 floquet_env%all_a_k(:, ispin, ikp) = floquet_env%a_k(:)
651 floquet_env%all_m0_energies(:, ispin, ikp) = floquet_env%m0_energies(:)
652 floquet_env%all_m0_weights(:, ispin, ikp) = floquet_env%m0_weights(:)
653 END IF
654
655 CALL timestop(handle)
656
657 END SUBROUTINE calculate_floquet_observables
658
659! **************************************************************************************************
660!> \brief Print the Floquet header with the input parameters and a short description of the output.
661!> \param bs_env ...
662! **************************************************************************************************
663 SUBROUTINE write_floquet_header(bs_env)
664 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
665
666 CHARACTER(LEN=*), PARAMETER :: routinen = 'write_floquet_header'
667
668 INTEGER :: handle, n_active, n_f_size, unit_nr
669
670 CALL timeset(routinen, handle)
671
672 unit_nr = bs_env%unit_nr
673 ! Active band window (the MAX_NMO states closest to the VBM, or all bands when MAX_NMO <= 0)
674 n_active = floquet_active_band_count(bs_env)
675 n_f_size = n_active*(1 + 2*bs_env%max_floquet_index)
676
677 IF (unit_nr > 0) THEN
678
679 WRITE (unit_nr, '(T2,A)') ' '
680 WRITE (unit_nr, '(T2,A)') repeat('-', 79)
681 WRITE (unit_nr, '(T2,A,A78)') '-', '-'
682 WRITE (unit_nr, '(T2,A,A51,A27)') '-', 'FLOQUET BANDSTRUCTURE CALCULATION', '-'
683 WRITE (unit_nr, '(T2,A,A78)') '-', '-'
684 WRITE (unit_nr, '(T2,A)') repeat('-', 79)
685 WRITE (unit_nr, '(T2,A)') ' '
686
687 WRITE (unit_nr, '(T2,A,T37,A,T67,ES12.2E2)') "FLOQUET PARAMETERS", "Amplitude [V/m]:", &
688 bs_env%floquet_amplitude*evolt/a_bohr
689 WRITE (unit_nr, '(T37,A,T67,F12.4)') "Frequency [eV]:", bs_env%floquet_omega*evolt
690 WRITE (unit_nr, '(T37,A)') repeat("-", 44)
691 WRITE (unit_nr, '(T37,A,T55,3F8.4)') "Polarisation:", bs_env%floquet_polarisation(1:3)
692 WRITE (unit_nr, '(T37,A,T55,3F8.4)') "Phase offsets:", pi*bs_env%floquet_phi(1:3)
693 WRITE (unit_nr, '(T37,A)') repeat("-", 44)
694 WRITE (unit_nr, '(T37,A,T67,I12)') "Max Floquet index:", bs_env%max_floquet_index
695 WRITE (unit_nr, '(T37,A,T67,I12)') "Max KS states (MAX_NMO, 0=all):", bs_env%max_nmo_floquet
696 WRITE (unit_nr, '(T37,A,T67,I12)') "Active bands used (of total):", n_active
697 WRITE (unit_nr, '(T37,A,T67,I12)') "Total number of bands:", bs_env%n_ao
698 WRITE (unit_nr, '(T37,A,T67,I12)') "Floquet Hamiltonian Size:", n_f_size
699 WRITE (unit_nr, '(T37,A)') repeat("-", 44)
700 WRITE (unit_nr, '(T37,A,T67,F12.4)') &
701 "Energy window [eV]:", bs_env%energy_window_floquet*evolt
702 WRITE (unit_nr, '(T37,A,T67,F12.4)') "Energy step [eV]:", bs_env%energy_step_floquet*evolt
703 WRITE (unit_nr, '(T37,A,T67,F12.4)') "Broadening [eV]:", bs_env%broadening_floquet*evolt
704 WRITE (unit_nr, '(T37,A)') repeat("-", 44)
705 WRITE (unit_nr, '(A)') ""
706
707 WRITE (unit_nr, '(T2,A)') &
708 "We construct the Floquet-Bloch Hamiltonian and diagonalise it. Projecting the"
709 WRITE (unit_nr, '(T2,A)') &
710 "eigenvectors onto the Floquet sectors gives the weights w = Σ_n |<n,m|α>|²,"
711 WRITE (unit_nr, '(T2,A)') &
712 "from which all of the following are obtained."
713 WRITE (unit_nr, '(A)') ""
714 WRITE (unit_nr, '(T2,A)') &
715 "The m=0 bands are the eigenvectors with the largest central-sector weight; they"
716 WRITE (unit_nr, '(T2,A)') &
717 "reduce to the equilibrium bands at zero field and are stored, with their"
718 WRITE (unit_nr, '(T2,A)') &
719 " weights, in FLOQUET_BANDSTRUCTURE.bs"
720 WRITE (unit_nr, '(A)') ""
721 WRITE (unit_nr, '(T2,A)') &
722 "Folding those bands into the first Floquet Brillouin zone, relative to the VBM,"
723 WRITE (unit_nr, '(T2,A)') &
724 "gives the quasi-energies stored in QUASI_ENERGIES.bs"
725 WRITE (unit_nr, '(A)') ""
726 WRITE (unit_nr, '(T2,A)') &
727 "The k-resolved density of states is obtained by computing the trace of"
728 WRITE (unit_nr, '(T2,A)') &
729 "the retarded Green's function and stored in FLOQUET_DOS.out"
730 WRITE (unit_nr, '(T2,A)') &
731 "DOS(ω,k) = -1/π*Im[Tr_KS(G^R(ω,k))]"
732 WRITE (unit_nr, '(A)') ""
733 END IF
734
735 CALL timestop(handle)
736
737 END SUBROUTINE write_floquet_header
738
739! **************************************************************************************************
740!> \brief Sum the accumulated results across MPI ranks and write the m=0 band structure,
741!> the quasi-energies and the Floquet DOS to their files.
742!> \param bs_env ...
743!> \param floquet_env ...
744! **************************************************************************************************
745 SUBROUTINE write_floquet_results(bs_env, floquet_env)
746 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
747 TYPE(floquet_env_type), INTENT(INOUT) :: floquet_env
748
749 CHARACTER(LEN=*), PARAMETER :: routinen = 'write_floquet_results'
750
751 CHARACTER(LEN=default_string_length) :: fname
752 INTEGER :: bunit, handle, i, i_e, ikp_for_file, &
753 ispin, n_e, n_mo, n_spin, nkp_only_bs, &
754 nkp_start, qunit, wunit
755 REAL(kind=dp) :: e_min, energy, energy_step, f_occ, kt, &
756 mu, x
757 REAL(kind=dp), DIMENSION(3) :: xkp
758
759 CALL timeset(routinen, handle)
760
761 ! Collect all results on the global communicator and write them
762 CALL bs_env%para_env%sum(floquet_env%all_quasi_energies)
763 CALL bs_env%para_env%sum(floquet_env%all_a_k)
764 CALL bs_env%para_env%sum(floquet_env%all_m0_energies)
765 CALL bs_env%para_env%sum(floquet_env%all_m0_weights)
766
767 IF (bs_env%para_env%is_source()) THEN
768
769 n_mo = floquet_env%n_mo
770 n_spin = floquet_env%n_spin
771 nkp_only_bs = floquet_env%nkp_only_bs
772 n_e = floquet_env%n_E
773 nkp_start = bs_env%nkp_only_DOS
774
775 ! All three share one energy origin, the VBM.
776 mu = floquet_reference_energy(bs_env)
777 energy_step = bs_env%energy_step_floquet
778 e_min = mu - bs_env%energy_window_floquet
779
780 ! k_B T in Hartree (only used when TEMPERATURE > 0); E[K] = E[Hartree]*kelvin.
781 kt = bs_env%floquet_temperature/kelvin
782
783 ! Each file is opened once (REPLACE) and written for every band-structure k-point and spin.
784
785 ! The m=0 band structure
786 WRITE (fname, "(2A)") trim(bs_env%floquet_bs_file), ".bs"
787 CALL open_file(trim(fname), unit_number=bunit, file_status="REPLACE", file_action="WRITE")
788 WRITE (bunit, "(A)") "# Floquet m=0 (central-sector) band structure"
789 WRITE (bunit, "(A)") "# (in units of eV, relative to the VBM, not folded)"
790 WRITE (bunit, "(A)") "# w = sum_n |<n,m=0|alpha>|^2 in [0,1]: w~1 clean m=0 replica,"
791 WRITE (bunit, "(A)") "# w~0.5 hybridised with a sideband (drive near resonance)"
792 WRITE (bunit, "(A)") "# The band column is the absolute Kohn-Sham band index; only the"
793 WRITE (bunit, "(A)") "# MAX_NMO band window closest to the VBM is reported (all bands if 0)."
794
795 ! Quasi-energies
796 WRITE (fname, "(2A)") trim(bs_env%floquet_qe_file), ".bs"
797 CALL open_file(trim(fname), unit_number=qunit, file_status="REPLACE", file_action="WRITE")
798 WRITE (qunit, "(A)") "# Quasi-energies obtained by diagonalising the Floquet Hamiltonian"
799 WRITE (qunit, "(A)") "# (in units of eV, the m=0 bands relative to the VBM, folded to"
800 WRITE (qunit, "(A)") "# the first Floquet Brillouin zone -hbar*Omega/2 < e <= hbar*Omega/2)"
801
802 ! DOS
803 WRITE (fname, "(2A)") trim(bs_env%floquet_dos_file), ".out"
804 CALL open_file(trim(fname), unit_number=wunit, file_status="REPLACE", file_action="WRITE")
805 WRITE (wunit, "(A)") "# Floquet Density of States: D(ω,k) = -1/π*Im[Tr_KS(G^R(ω,k))]"
806
807 DO ikp_for_file = 1, nkp_only_bs
808 xkp(1:3) = bs_env%kpoints_DOS%xkp(1:3, nkp_start + ikp_for_file)
809 DO ispin = 1, n_spin
810
811 ! <floquet_bs_file>.bs the m=0 band structure (absolute energies) and its weights
812 WRITE (bunit, "(A,I0,T10,A,I0,A,T24,3(1X,F14.8))") &
813 "# Spin ", ispin, " Point ", ikp_for_file, ": ", xkp(1:3)
814 WRITE (bunit, "(A)") "# KS band Energy [eV] m=0 weight"
815 DO i = 1, n_mo
816 WRITE (bunit, "(I8,F21.8,F17.5)") floquet_env%n_lo(ispin) - 1 + i, &
817 floquet_env%all_m0_energies(i, ispin, ikp_for_file)*evolt, &
818 floquet_env%all_m0_weights(i, ispin, ikp_for_file)
819 END DO
820
821 ! <floquet_qe_file>.bs Quasi-energies (folded to -ħΩ/2 < ε ≤ ħΩ/2)
822 WRITE (qunit, "(A,I0,T10,A,I0,A,T24,3(1X,F14.8))") &
823 "# Spin ", ispin, " Point ", ikp_for_file, ": ", xkp(1:3)
824 WRITE (qunit, "(A)") "# Floquet band Quasi-energy [eV]"
825 DO i = 1, n_mo
826 WRITE (qunit, "(I8,F21.8)") i, &
827 floquet_env%all_quasi_energies(i, ispin, ikp_for_file)*evolt
828 END DO
829
830 ! <floquet_dos_file>.out the k-resolved DOS A(k,ω), and (if TEMPERATURE > 0) the
831 ! occupied spectral weight f(E)*A(k,ω), f the Fermi-Dirac occupation at the VBM.
832 WRITE (wunit, "(A,I0,T10,A,I0,A,T24,3(1X,F14.8))") &
833 "# Spin ", ispin, " Point ", ikp_for_file, ": ", xkp(1:3)
834 IF (bs_env%floquet_temperature > 0.0_dp) THEN
835 WRITE (wunit, "(A)") "#Energy-VBM (eV) A(ω,k) = DOS (1/eV) f*A = occupied DOS (1/eV)"
836 DO i_e = 1, n_e
837 energy = e_min + i_e*energy_step
838 x = (energy - mu)/kt ! (E - VBM)/k_B T, dimensionless
839 IF (x > 40.0_dp) THEN ! guard EXP overflow at low T
840 f_occ = 0.0_dp
841 ELSE IF (x < -40.0_dp) THEN
842 f_occ = 1.0_dp
843 ELSE
844 f_occ = 1.0_dp/(exp(x) + 1.0_dp)
845 END IF
846 WRITE (wunit, "(2X,3G13.4)") (energy - mu)*evolt, &
847 floquet_env%all_a_k(i_e, ispin, ikp_for_file)/evolt, &
848 f_occ*floquet_env%all_a_k(i_e, ispin, ikp_for_file)/evolt
849 END DO
850 ELSE
851 WRITE (wunit, "(A)") "#Energy-VBM (eV) A(ω,k) = DOS (1/eV)"
852 DO i_e = 1, n_e
853 energy = e_min + i_e*energy_step
854 WRITE (wunit, "(2X,2G13.4)") (energy - mu)*evolt, &
855 floquet_env%all_a_k(i_e, ispin, ikp_for_file)/evolt
856 END DO
857 END IF
858
859 END DO
860 END DO
861
862 CALL close_file(bunit)
863 CALL close_file(qunit)
864 CALL close_file(wunit)
865 END IF
866
867 CALL timestop(handle)
868
869 END SUBROUTINE write_floquet_results
870
871END MODULE floquet_utils
methods related to the blacs parallel environment
subroutine, public cp_blacs_env_create(blacs_env, para_env, blacs_grid_layout, blacs_repeatable, row_major, grid_2d)
allocates and initializes a type that represent a blacs context
Represents a complex full matrix distributed on many processors.
subroutine, public cp_cfm_get_submatrix(fm, target_m, start_row, start_col, n_rows, n_cols, transpose)
Extract a sub-matrix from the full matrix: op(target_m)(1:n_rows,1:n_cols) = fm(start_row:start_row+n...
subroutine, public cp_cfm_set_submatrix(matrix, new_values, start_row, start_col, n_rows, n_cols, alpha, beta, transpose)
Set a sub-matrix of the full matrix: matrix(start_row:start_row+n_rows,start_col:start_col+n_cols) = ...
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:323
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:123
Environment type holding the work and accumulation arrays of the Floquet-Bloch band-structure calcula...
integer function, public floquet_active_band_count(bs_env)
Number of active bands used by the Floquet calculation: the MAX_NMO band window closest to the VBM,...
Helper routines for the Floquet-Bloch band-structure calculation (floquet_main).
subroutine, public check_floquet_convergence(bs_env, floquet_env)
Checks that MAX_FLOQUET_INDEX is large enough and the Floquet Hamiltonian was truncated far enough aw...
subroutine, public make_floquet_subgroups(qs_env, bs_env, para_env_sub, blacs_env_sub, group_distribution, ngroups)
Split the para_env into subgroups so that the Floquet Hamiltonian is distributed across the ranks of ...
subroutine, public write_floquet_header(bs_env)
Print the Floquet header with the input parameters and a short description of the output.
subroutine, public write_floquet_results(bs_env, floquet_env)
Sum the accumulated results across MPI ranks and write the m=0 band structure, the quasi-energies and...
subroutine, public build_floquet_matrix(bs_env, floquet_env, floquet_matrix)
Builds the Floquet-Bloch Hamiltonian H_F(k) for a single k-point and spin channel from the band data ...
subroutine, public distribute_floquet_kp_data(para_env, para_env_sub, ispin, ikp, e_k, p_k, floquet_env)
Make this k-point/spin's band data available to every rank of the owning subgroup.
subroutine, public compute_e_k_p_k(qs_env, bs_env, e_k, p_k)
Precompute, on the global communicator, the band quantities needed to assemble the Floquet-Bloch Hami...
subroutine, public calculate_floquet_observables(bs_env, para_env_sub, ispin, ikp, floquet_env)
Calculate all Floquet observables for one k-point and spin: the DOS (a_k), the m=0 bands,...
subroutine, public floquet_sector_weights(floquet_env, floquet_eigenvectors)
Central and boundary-sector weights of every Floquet eigenvector, stored into floquet_envw0 and floqu...
collects all constants needed in input so that they can be used without circular dependencies
integer, parameter, public tensor_small_cell_full_kp
Defines the basic variable types.
Definition kinds.F:23
integer, parameter, public int_8
Definition kinds.F:54
integer, parameter, public dp
Definition kinds.F:34
integer, parameter, public default_string_length
Definition kinds.F:57
Machine interface based on Fortran 2003 and POSIX.
Definition machine.F:17
subroutine, public m_memory_details(memtotal, memfree, buffers, cached, slab, sreclaimable, memlikelyfree)
get more detailed memory info, all units are bytes. the only 'useful' option is MemLikelyFree which i...
Definition machine.F:510
Definition of mathematical constants and functions.
real(kind=dp), parameter, public pi
complex(kind=dp), parameter, public z_one
complex(kind=dp), parameter, public gaussi
complex(kind=dp), parameter, public z_zero
Interface to the message passing library MPI.
type(mp_split_type), parameter, public mp_comm_split_type_shared
Definition of physical constants:
Definition physcon.F:68
real(kind=dp), parameter, public a_bohr
Definition physcon.F:136
real(kind=dp), parameter, public kelvin
Definition physcon.F:165
real(kind=dp), parameter, public evolt
Definition physcon.F:183
subroutine, public get_qs_env(qs_env, atomic_kind_set, qs_kind_set, cell, super_cell, cell_ref, use_ref_cell, kpoints, dft_control, mos, sab_orb, sab_all, qmmm, qmmm_periodic, mimic, sac_ae, sac_ppl, sac_lri, sap_ppnl, sab_vdw, sab_scp, sap_oce, sab_lrc, sab_se, sab_xtbe, sab_tbe, sab_core, sab_xb, sab_xtb_pp, sab_xtb_nonbond, sab_almo, sab_kp, sab_kp_nosym, sab_cneo, particle_set, energy, force, matrix_h, matrix_h_im, matrix_ks, matrix_ks_im, matrix_vxc, run_rtp, rtp, matrix_h_kp, matrix_h_im_kp, matrix_ks_kp, matrix_ks_im_kp, matrix_vxc_kp, kinetic_kp, matrix_s_kp, matrix_w_kp, matrix_s_ri_aux_kp, matrix_s, matrix_s_ri_aux, matrix_w, matrix_p_mp2, matrix_p_mp2_admm, matrix_vhxc, rho, rho_xc, pw_env, ewald_env, ewald_pw, active_space, mpools, input, para_env, blacs_env, scf_control, rel_control, kinetic, qs_charges, vppl, xcint_weights, rho_core, rho_nlcc, rho_nlcc_g, ks_env, ks_qmmm_env, wf_history, scf_env, local_particles, local_molecules, distribution_2d, dbcsr_dist, molecule_kind_set, molecule_set, subsys, cp_subsys, oce, local_rho_set, rho_atom_set, task_list, task_list_soft, rho0_atom_set, rho0_mpole, rhoz_set, rhoz_cneo_set, ecoul_1c, rho0_s_rs, rho0_s_gs, rhoz_cneo_s_rs, rhoz_cneo_s_gs, do_kpoints, has_unit_metric, requires_mo_derivs, mo_derivs, mo_loc_history, nkind, natom, nelectron_total, nelectron_spin, efield, neighbor_list_id, linres_control, xas_env, virial, cp_ddapc_env, cp_ddapc_ewald, outer_scf_history, outer_scf_ihistory, x_data, et_coupling, dftb_potential, results, se_taper, se_store_int_env, se_nddo_mpole, se_nonbond_env, admm_env, lri_env, lri_density, exstate_env, ec_env, harris_env, dispersion_env, gcp_env, vee, rho_external, external_vxc, mask, mp2_env, bs_env, kg_env, wanniercentres, atprop, ls_scf_env, do_transport, transport_env, v_hartree_rspace, s_mstruct_changed, rho_changed, potential_changed, forces_up_to_date, mscfg_env, almo_scf_env, gradient_history, variable_history, embed_pot, spin_embed_pot, polar_env, mos_last_converged, eeq, rhs, do_rixs, tb_tblite)
Get the QUICKSTEP environment.
Calculates the moment integrals <a|r^m|b> and <a|r x d/dr|b>.
Definition qs_moments.F:14
subroutine, public qs_moment_kpoints_deep(qs_env, xkp, dipole, rcc, berry_c, momentum, energy, do_parallel)
Calculates the dipole moments, berry curvature, momentum and band energy for periodic systems for kpo...
All kind of helpful little routines.
Definition util.F:14
represent a blacs multidimensional parallel environment (for the mpi corrispective see cp_paratypes/m...
Represent a complex full matrix.
Work and accumulation arrays for one Floquet-Bloch band-structure run, plus the derived sizes....
stores all the informations relevant to an mpi environment