(git:5e7fe52)
Loading...
Searching...
No Matches
qs_kpoint_operators.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 Assembly of complex k-point operators from real-space DBCSR matrices.
10!> The output is a complex full matrix on the distribution of the k-point group.
11!> The module splits this work into a start step and a finish step.
12!> One process can start the MPI transfers of many operators before it finishes
13!> any of them. The STANDARD k-point driver uses this order.
14!> The routines start, finish and get are collective over the
15!> environment-wide communicator. Every rank must call the same
16!> sequence of service calls.
17!> A context references its host kpoint environment without owning it,
18!> so it must not outlive that environment. The calls are not thread
19!> safe: the caller must serialize them, because their collective
20!> communication tolerates no concurrent service call. A separate
21!> context per thread only keeps the scratch from aliasing.
22! **************************************************************************************************
25 USE cp_cfm_types, ONLY: cp_cfm_to_fm,&
27 USE cp_dbcsr_api, ONLY: &
29 dbcsr_type, dbcsr_type_antisymmetric, dbcsr_type_no_symmetry, dbcsr_type_symmetric
38 USE cp_fm_types, ONLY: copy_info_type,&
46 USE kinds, ONLY: dp
50 USE kpoint_types, ONLY: kpoint_type
51 USE mathconstants, ONLY: gaussi,&
52 z_one,&
53 z_zero
55 USE qs_matrix_pools, ONLY: mpools_get,&
57 USE qs_mo_types, ONLY: get_mo_set,&
60#include "./base/base_uses.f90"
61
62 IMPLICIT NONE
63
64 PRIVATE
65
66 CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'qs_kpoint_operators'
67
71 PUBLIC :: kpoint_operator_get
72
73 INTEGER, PARAMETER, PUBLIC :: kpoint_slot_ks = 1, &
74 kpoint_slot_s = 2, &
76
77 !> Row of rsmat that carries the spin-free operator image. S and T carry
78 !> no spin copies: drivers launch one instance per spin of their loop and
79 !> read this same row in every instance.
80 INTEGER, PARAMETER, PUBLIC :: kpoint_spin_free = 1
81
82 !> Number of defined slots; grows only inside this module.
83 INTEGER, PARAMETER, PRIVATE :: kpoint_num_slots = kpoint_slot_t - kpoint_slot_ks + 1
84
85 !> Part indices of one transfer: its real and its imaginary half.
86 INTEGER, PARAMETER, PRIVATE :: kpoint_part_re = 1, &
87 kpoint_part_im = 2
88
89 !> Instance states of one (k point, spin, slot) transfer.
90 !> State transitions happen only inside the service routines.
91 INTEGER, PARAMETER, PRIVATE :: kpoint_slot_idle = 0, &
92 kpoint_slot_in_flight = 1
93
94! **************************************************************************************************
95!> \brief Caller-owned assembly context for one driver call.
96!> Created and released in the same driver routine and passed to helpers
97!> as an argument; never stored on the host kpoint_type.
98!> Components are private and touched only by this module.
99! **************************************************************************************************
101 PRIVATE
102 ! Instance spin space of the owning driver call: the bound of the spin
103 ! loop that start and finish key. Declared once at creation. It never
104 ! comes from the operators: the first matrix dimension of a spin-free
105 ! operator such as S counts derivatives, and the images live in the
106 ! second, so callers address operator rows through matrix_row instead.
107 INTEGER :: nspin = 0
108 ! Host references, read fresh at every use: sab_nl and cell_to_index
109 ! are reallocated at every energy evaluation.
110 TYPE(kpoint_type), POINTER :: kpoints => null()
111 TYPE(cp_fm_struct_type), POINTER :: ao_ao_fmstruct => null()
112 TYPE(qs_matrix_pools_type), POINTER :: group_mpools => null()
113 TYPE(cp_fm_pool_p_type), DIMENSION(:), POINTER :: group_fm_pools => null()
114 ! Identity of the neighbor lists the work trio was built from; every
115 ! buffer use asserts it.
116 TYPE(neighbor_list_set_p_type), DIMENSION(:), &
117 POINTER :: trio_sab => null()
118 ! Owned scratch, created on first use and released with the context.
119 TYPE(dbcsr_type), POINTER :: rmatrix => null()
120 TYPE(dbcsr_type), POINTER :: cmatrix => null()
121 TYPE(dbcsr_type), POINTER :: tmpmat => null()
122 TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:) :: fmwork
123 TYPE(cp_fm_type), ALLOCATABLE :: fmlocal
124 TYPE(cp_fm_type) :: fmdummy
125 ! Bookkeeping. info is keyed (local k point x group, spin, slot, part),
126 ! part kpoint_part_re holding the real half and kpoint_part_im holding
127 ! the imaginary half. Status is keyed (local k point, spin, slot)
128 ! because start and finish treat all groups of one instance
129 ! atomically. Allocated on first start.
130 TYPE(copy_info_type), ALLOCATABLE, DIMENSION(:, :, :, :) :: info
131 INTEGER, ALLOCATABLE, DIMENSION(:, :, :) :: status
133
134CONTAINS
135
136! **************************************************************************************************
137!> \brief Transform one real-space operator to one k point and densify the
138!> result: the real part into fm_re and the imaginary part into fm_im.
139!> Densify means: copy the blocks of a DBCSR matrix into a full matrix.
140!> Stateless: fills caller-provided scratch.
141!> \param rsmat real-space image matrices of the operator
142!> \param matrix_row row of rsmat to transform (kpoint_spin_free for
143!> spin-free matrices such as S)
144!> \param ik global k-point index
145!> \param xkp coordinates of this k point
146!> \param cell_to_index mapping of cell indices to real-space index
147!> \param sab_nl neighbor lists defining the real-space sparsity
148!> \param grid prepared reciprocal-grid cache of the caller. Required when use_grid is set
149!> \param use_grid extract from grid instead of a direct phase sum
150!> \param rmatrix symmetric DBCSR workspace holding the real part of the k-point matrix
151!> \param cmatrix antisymmetric DBCSR workspace holding the imaginary part of the k-point matrix
152!> \param tmpmat unsymmetric DBCSR workspace
153!> \param fm_re full-matrix workspace holding the real part
154!> \param fm_im full-matrix workspace holding the imaginary part
155! **************************************************************************************************
156 SUBROUTINE kpoint_operator_densify(rsmat, matrix_row, ik, xkp, cell_to_index, sab_nl, grid, use_grid, &
157 rmatrix, cmatrix, tmpmat, fm_re, fm_im)
158
159 TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: rsmat
160 INTEGER, INTENT(IN) :: matrix_row, ik
161 REAL(KIND=dp), DIMENSION(3), INTENT(IN) :: xkp
162 INTEGER, DIMENSION(:, :, :), POINTER :: cell_to_index
163 TYPE(neighbor_list_set_p_type), DIMENSION(:), &
164 POINTER :: sab_nl
165 TYPE(rskp_grid_type), INTENT(IN), OPTIONAL :: grid
166 LOGICAL, INTENT(IN) :: use_grid
167 TYPE(dbcsr_type) :: rmatrix, cmatrix, tmpmat
168 TYPE(cp_fm_type) :: fm_re, fm_im
169
170 CHARACTER(LEN=*), PARAMETER :: routineN = 'kpoint_operator_densify'
171
172 INTEGER :: handle
173
174 CALL timeset(routinen, handle)
175
176 IF (use_grid) THEN
177 cpassert(PRESENT(grid))
178 CALL rskp_transform_grid_extract(grid, ik, rmatrix, cmatrix)
179 ELSE
180 CALL dbcsr_set(rmatrix, 0.0_dp)
181 CALL dbcsr_set(cmatrix, 0.0_dp)
182 CALL rskp_transform(rmatrix=rmatrix, cmatrix=cmatrix, rsmat=rsmat, ispin=matrix_row, &
183 xkp=xkp, cell_to_index=cell_to_index, sab_nl=sab_nl)
184 END IF
185 CALL dbcsr_desymmetrize(rmatrix, tmpmat)
186 CALL copy_dbcsr_to_fm(tmpmat, fm_re)
187 CALL dbcsr_desymmetrize(cmatrix, tmpmat)
188 CALL copy_dbcsr_to_fm(tmpmat, fm_im)
189
190 CALL timestop(handle)
191
192 END SUBROUTINE kpoint_operator_densify
193
194! **************************************************************************************************
195!> \brief Transform one real-space operator row to one k point, densify the
196!> result, and start the transfer of both parts: into target_re and
197!> target_im on the group that owns this k point, into fmdummy on
198!> every other group so the collective calls stay balanced.
199!> Densify means: copy the blocks of a DBCSR matrix into a full matrix.
200!> Each transfer receives its data in a private buffer. For this reason,
201!> several launches can use the same target matrix.
202!> The caller owns the transfer states: finish or clean up every started
203!> copy through info_re and info_im.
204!> \param rsmat real-space image matrices of the operator
205!> \param matrix_row row of rsmat to transform (kpoint_spin_free for
206!> spin-free matrices such as S)
207!> \param ik global k-point index
208!> \param xkp coordinates of this k point
209!> \param cell_to_index mapping of cell indices to real-space index
210!> \param sab_nl neighbor lists defining the real-space sparsity
211!> \param grid prepared reciprocal-grid cache of the caller. Required when use_grid is set
212!> \param use_grid extract from grid instead of a direct phase sum
213!> \param rmatrix symmetric DBCSR workspace holding the real part of the k-point matrix
214!> \param cmatrix antisymmetric DBCSR workspace holding the imaginary part of the k-point matrix
215!> \param tmpmat unsymmetric DBCSR workspace
216!> \param fm_re full-matrix workspace of the global communicator holding the real part
217!> \param fm_im full-matrix workspace of the global communicator holding the imaginary part
218!> \param target_re transfer target of the real part on the group that owns this k point
219!> \param target_im transfer target of the imaginary part on the owning group
220!> \param fmdummy transfer target on the other groups. This keeps the collective
221!> calls balanced
222!> \param my_kpgrp true when the calling group owns this k point
223!> \param para_env communicator that spans the source and the target distributions
224!> \param info_re transfer state of the real part
225!> \param info_im transfer state of the imaginary part
226! **************************************************************************************************
227 SUBROUTINE kpoint_operator_launch(rsmat, matrix_row, ik, xkp, cell_to_index, sab_nl, &
228 grid, use_grid, rmatrix, cmatrix, tmpmat, fm_re, fm_im, &
229 target_re, target_im, fmdummy, my_kpgrp, para_env, &
230 info_re, info_im)
231
232 TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: rsmat
233 INTEGER, INTENT(IN) :: matrix_row, ik
234 REAL(KIND=dp), DIMENSION(3), INTENT(IN) :: xkp
235 INTEGER, DIMENSION(:, :, :), POINTER :: cell_to_index
236 TYPE(neighbor_list_set_p_type), DIMENSION(:), &
237 POINTER :: sab_nl
238 TYPE(rskp_grid_type), INTENT(IN), OPTIONAL :: grid
239 LOGICAL, INTENT(IN) :: use_grid
240 TYPE(dbcsr_type) :: rmatrix, cmatrix, tmpmat
241 TYPE(cp_fm_type) :: fm_re, fm_im, target_re, target_im, &
242 fmdummy
243 LOGICAL, INTENT(IN) :: my_kpgrp
244 TYPE(mp_para_env_type), POINTER :: para_env
245 TYPE(copy_info_type) :: info_re, info_im
246
247 CHARACTER(LEN=*), PARAMETER :: routineN = 'kpoint_operator_launch'
248
249 INTEGER :: handle
250
251 CALL timeset(routinen, handle)
252
253 CALL kpoint_operator_densify(rsmat, matrix_row, ik, xkp, cell_to_index, sab_nl, grid, use_grid, &
254 rmatrix, cmatrix, tmpmat, fm_re, fm_im)
255
256 IF (my_kpgrp) THEN
257 CALL cp_fm_start_copy_general(fm_re, target_re, para_env, info_re)
258 CALL cp_fm_start_copy_general(fm_im, target_im, para_env, info_im)
259 ELSE
260 CALL cp_fm_start_copy_general(fm_re, fmdummy, para_env, info_re)
261 CALL cp_fm_start_copy_general(fm_im, fmdummy, para_env, info_im)
262 END IF
263
264 CALL timestop(handle)
265
266 END SUBROUTINE kpoint_operator_launch
267
268! **************************************************************************************************
269!> \brief Finish one transfer that kpoint_operator_launch started and add the received
270!> matrix to a complex matrix.
271!> The finish of the real part overwrites cmat.
272!> The finish of the imaginary part adds to cmat.
273!> Finish the real part first. A real-part finish after an imaginary-part
274!> finish erases the imaginary contribution.
275!> The routine consumes fmlocal before it returns, so the next finish can
276!> reuse the same matrix.
277!> \param fmlocal transfer target filled by the finished copy
278!> \param info transfer state of one part
279!> \param cmat complex matrix accumulating the operator
280!> \param imaginary_part add fmlocal as the imaginary part instead of the real part
281! **************************************************************************************************
282 SUBROUTINE kpoint_operator_raw_finish_cfm(fmlocal, info, cmat, imaginary_part)
283
284 TYPE(cp_fm_type) :: fmlocal
285 TYPE(copy_info_type) :: info
286 TYPE(cp_cfm_type) :: cmat
287 LOGICAL, INTENT(IN) :: imaginary_part
288
289 CHARACTER(LEN=*), PARAMETER :: routineN = 'kpoint_operator_raw_finish_cfm'
290
291 INTEGER :: handle
292
293 CALL timeset(routinen, handle)
294
295 CALL cp_fm_finish_copy_general(fmlocal, info)
296 IF (imaginary_part) THEN
297 CALL cp_cfm_scale_and_add_fm(z_one, cmat, gaussi, fmlocal)
298 ELSE
299 CALL cp_cfm_scale_and_add_fm(z_zero, cmat, z_one, fmlocal)
300 END IF
301
302 CALL timestop(handle)
303
304 END SUBROUTINE kpoint_operator_raw_finish_cfm
305
306! **************************************************************************************************
307!> \brief Split a complex matrix into the real and imaginary MO sets and copy
308!> the eigenvalues to the imaginary set.
309!> \param cmat complex MO coefficients
310!> \param mo_re real part MO set
311!> \param mo_im imaginary part MO set
312!> \param eigenvalues eigenvalues of mo_re, copied to mo_im
313! **************************************************************************************************
314 SUBROUTINE kpoint_operator_cfm_to_mo(cmat, mo_re, mo_im, eigenvalues)
315
316 TYPE(cp_cfm_type) :: cmat
317 TYPE(mo_set_type) :: mo_re, mo_im
318 REAL(kind=dp), DIMENSION(:) :: eigenvalues
319
320 CHARACTER(LEN=*), PARAMETER :: routinen = 'kpoint_operator_cfm_to_mo'
321
322 INTEGER :: handle
323 TYPE(cp_fm_type), POINTER :: imos, rmos
324
325 CALL timeset(routinen, handle)
326
327 CALL get_mo_set(mo_re, mo_coeff=rmos)
328 CALL get_mo_set(mo_im, mo_coeff=imos)
329 mo_im%eigenvalues = eigenvalues
330 CALL cp_cfm_to_fm(cmat, rmos, imos)
331
332 CALL timestop(handle)
333
334 END SUBROUTINE kpoint_operator_cfm_to_mo
335
336! **************************************************************************************************
337!> \brief Create an empty operator context.
338!> The context owns no buffers after this call; they are created on first
339!> use and released with the context.
340!> \param ctx context to initialize
341!> \param kpoints host k-point environment, referenced, not copied
342!> \param ao_ao_fm any square full matrix on the environment-wide communicator;
343!> its matrix struct is the template for the context work buffers,
344!> which densify on the source side of transfers that cross into the
345!> k-point groups
346!> \param nspin instance spin space of the owning driver call: the bound of
347!> the spin loop its start and finish calls iterate. Fixed for the
348!> lifetime of the context
349! **************************************************************************************************
350 SUBROUTINE kpoint_operator_context_create(ctx, kpoints, ao_ao_fm, nspin)
351
352 TYPE(kpoint_operator_context_type), INTENT(OUT) :: ctx
353 TYPE(kpoint_type), POINTER :: kpoints
354 TYPE(cp_fm_type), INTENT(IN) :: ao_ao_fm
355 INTEGER, INTENT(IN) :: nspin
356
357 CHARACTER(LEN=*), PARAMETER :: routinen = 'kpoint_operator_context_create'
358
359 INTEGER :: handle
360
361 CALL timeset(routinen, handle)
362
363 cpassert(nspin >= 1)
364 ctx%nspin = nspin
365 cpassert(ASSOCIATED(kpoints))
366 ctx%kpoints => kpoints
367 CALL cp_fm_get_info(ao_ao_fm, matrix_struct=ctx%ao_ao_fmstruct)
368 cpassert(ASSOCIATED(ctx%ao_ao_fmstruct))
369 ! The template must live on the transfer world. A template from
370 ! another communicator fails during the transfers, far from this call.
371 cpassert(ASSOCIATED(ctx%ao_ao_fmstruct%para_env, kpoints%blacs_env_all%para_env))
372
373 CALL timestop(handle)
374
375 END SUBROUTINE kpoint_operator_context_create
376
377! **************************************************************************************************
378!> \brief Release the context together with every buffer it created.
379!> Call once, at the exit of the routine that created the context.
380!> Every started instance must be idle at this point. The call aborts
381!> when a transfer is still in flight, because nothing would ever wait
382!> for its MPI requests.
383!> \param ctx context to release
384! **************************************************************************************************
386
387 TYPE(kpoint_operator_context_type), INTENT(INOUT) :: ctx
388
389 CHARACTER(LEN=*), PARAMETER :: routinen = 'kpoint_operator_context_release'
390
391 INTEGER :: handle, iwork
392
393 CALL timeset(routinen, handle)
394
395 ! Every started instance must have been finished: an unfinished start
396 ! holds MPI requests that nothing would ever wait for.
397 IF (ALLOCATED(ctx%status)) THEN
398 cpassert(all(ctx%status == kpoint_slot_idle))
399 END IF
400
401 IF (ASSOCIATED(ctx%rmatrix)) CALL dbcsr_deallocate_matrix(ctx%rmatrix)
402 IF (ASSOCIATED(ctx%cmatrix)) CALL dbcsr_deallocate_matrix(ctx%cmatrix)
403 IF (ASSOCIATED(ctx%tmpmat)) CALL dbcsr_deallocate_matrix(ctx%tmpmat)
404 NULLIFY (ctx%rmatrix, ctx%cmatrix, ctx%tmpmat, ctx%trio_sab)
405 IF (ALLOCATED(ctx%fmwork)) THEN
406 DO iwork = 1, SIZE(ctx%fmwork)
407 CALL cp_fm_release(ctx%fmwork(iwork))
408 END DO
409 DEALLOCATE (ctx%fmwork)
410 END IF
411 IF (ALLOCATED(ctx%fmlocal)) THEN
412 IF (ASSOCIATED(ctx%group_fm_pools)) THEN
413 CALL fm_pool_give_back_fm(ctx%group_fm_pools(1)%pool, ctx%fmlocal)
414 ELSE
415 CALL cp_fm_release(ctx%fmlocal)
416 END IF
417 DEALLOCATE (ctx%fmlocal)
418 END IF
419 IF (ALLOCATED(ctx%info)) DEALLOCATE (ctx%info)
420 IF (ALLOCATED(ctx%status)) DEALLOCATE (ctx%status)
421 NULLIFY (ctx%kpoints, ctx%ao_ao_fmstruct, ctx%group_mpools, ctx%group_fm_pools)
422
423 CALL timestop(handle)
424
426
427! **************************************************************************************************
428!> \brief Create the context scratch that the first service call needs: the
429!> DBCSR work trio with blocks from the current neighbor lists, two
430!> densify buffers on the environment-wide struct, and the group
431!> transfer target from the group pools.
432!> The per-instance slot bookkeeping is not scratch: start creates it
433!> on its first call, because the synchronous get call never touches it.
434!> The buffers assume the context lifetime of one driver call: the
435!> host neighbor lists do not change within it, and every buffer use
436!> asserts this identity. Buffers from an earlier call stay in place.
437!> Called from the service routines only.
438!> \param ctx context that receives the buffers
439!> \param rsmat real-space image matrices of one operator. The call uses the
440!> first matrix as the DBCSR template of the work trio. It reads no
441!> matrix data.
442! **************************************************************************************************
443 SUBROUTINE kpoint_operator_ensure(ctx, rsmat)
444
445 TYPE(kpoint_operator_context_type), INTENT(INOUT) :: ctx
446 TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: rsmat
447
448 CHARACTER(LEN=*), PARAMETER :: routinen = 'kpoint_operator_ensure'
449
450 INTEGER :: handle
451
452 CALL timeset(routinen, handle)
453
454 ! The trio must still match the host neighbor lists: they are
455 ! reallocated at every energy evaluation, while the context spans one
456 ! driver call within it.
457 IF (ASSOCIATED(ctx%rmatrix)) THEN
458 cpassert(ASSOCIATED(ctx%trio_sab, ctx%kpoints%sab_nl))
459 END IF
460 IF (.NOT. ASSOCIATED(ctx%rmatrix)) THEN
461 ALLOCATE (ctx%rmatrix, ctx%cmatrix, ctx%tmpmat)
462 CALL dbcsr_create(ctx%rmatrix, template=rsmat(1, 1)%matrix, matrix_type=dbcsr_type_symmetric)
463 CALL dbcsr_create(ctx%cmatrix, template=rsmat(1, 1)%matrix, matrix_type=dbcsr_type_antisymmetric)
464 CALL dbcsr_create(ctx%tmpmat, template=rsmat(1, 1)%matrix, matrix_type=dbcsr_type_no_symmetry)
465 CALL cp_dbcsr_alloc_block_from_nbl(ctx%rmatrix, ctx%kpoints%sab_nl)
466 CALL cp_dbcsr_alloc_block_from_nbl(ctx%cmatrix, ctx%kpoints%sab_nl)
467 ctx%trio_sab => ctx%kpoints%sab_nl
468 END IF
469
470 IF (.NOT. ALLOCATED(ctx%fmwork)) THEN
471 ALLOCATE (ctx%fmwork(kpoint_part_im))
472 CALL cp_fm_create(ctx%fmwork(kpoint_part_re), ctx%ao_ao_fmstruct, &
473 name="KPOINT-OPERATOR-WORK-RE")
474 CALL cp_fm_create(ctx%fmwork(kpoint_part_im), ctx%ao_ao_fmstruct, &
475 name="KPOINT-OPERATOR-WORK-IM")
476 END IF
477
478 IF (.NOT. ALLOCATED(ctx%fmlocal)) THEN
479 ! The group pool owns the storage; the release returns the matrix
480 ! to the pool instead of destroying it.
481 ctx%group_mpools => ctx%kpoints%mpools
482 CALL mpools_get(ctx%group_mpools, ao_ao_fm_pools=ctx%group_fm_pools)
483 ALLOCATE (ctx%fmlocal)
484 CALL fm_pool_create_fm(ctx%group_fm_pools(1)%pool, ctx%fmlocal)
485 END IF
486
487 CALL timestop(handle)
488
489 END SUBROUTINE kpoint_operator_ensure
490
491! **************************************************************************************************
492!> \brief Start the assembly of one operator for one local k point and spin and
493!> launch its transfers to every k-point group. The caller index ikp is
494!> local; the walk over groups happens here, so no caller can express a
495!> group-local loop. Finish every started instance with
496!> kpoint_operator_finish. The first start also creates the slot
497!> bookkeeping of the context.
498!> Collective over the environment-wide communicator: every rank must
499!> call the same sequence of service calls.
500!> \param ctx context created by kpoint_operator_context_create
501!> \param ikp local k-point index within kp_range
502!> \param ispin instance spin: keys the bookkeeping
503!> \param rsmat real-space image matrices of the operator, read at start
504!> time only. The matching finish does not read them
505!> \param slot destination slot of the operator (one of kpoint_slot_ks/s/t);
506!> the slot must be idle
507!> \param grid prepared reciprocal-grid cache of the caller
508!> \param use_grid extract from grid instead of a direct phase sum
509!> \param matrix_row row of rsmat to transform. Spin-free operators such
510!> as S and T must pass kpoint_spin_free: their first matrix
511!> dimension counts derivatives, not spins. A spin index is out of
512!> bounds in plain SCF, but with derivatives stored it reads another
513!> valid row silently
514! **************************************************************************************************
515 SUBROUTINE kpoint_operator_start(ctx, ikp, ispin, rsmat, slot, grid, use_grid, matrix_row)
516
517 TYPE(kpoint_operator_context_type), INTENT(INOUT) :: ctx
518 INTEGER, INTENT(IN) :: ikp, ispin
519 TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: rsmat
520 INTEGER, INTENT(IN) :: slot
521 TYPE(rskp_grid_type), INTENT(IN), OPTIONAL :: grid
522 LOGICAL, INTENT(IN) :: use_grid
523 INTEGER, INTENT(IN) :: matrix_row
524
525 CHARACTER(LEN=*), PARAMETER :: routinen = 'kpoint_operator_start'
526
527 INTEGER :: handle, igroup, ik, indx, kplocal
528 INTEGER, DIMENSION(2) :: kp_range
529 INTEGER, DIMENSION(:, :), POINTER :: kp_dist
530 LOGICAL :: my_kpgrp
531 TYPE(mp_para_env_type), POINTER :: para_env
532
533 CALL timeset(routinen, handle)
534
535 cpassert(ASSOCIATED(ctx%kpoints))
536 cpassert(ASSOCIATED(ctx%kpoints%sab_nl))
537 ! The instance spin is bounded by the spin space declared at creation;
538 ! the matrix row by this operator's own rows. The two bounds differ for
539 ! spin-free operators such as S, whose first dimension counts
540 ! real-space blocks.
541 cpassert(ispin >= 1 .AND. ispin <= ctx%nspin)
542 cpassert(matrix_row >= 1 .AND. matrix_row <= SIZE(rsmat, 1))
543 kplocal = ctx%kpoints%kp_range(2) - ctx%kpoints%kp_range(1) + 1
544 cpassert(ikp >= 1 .AND. ikp <= kplocal)
545 cpassert(slot >= kpoint_slot_ks .AND. slot <= kpoint_slot_t)
546 IF (ALLOCATED(ctx%status)) THEN
547 cpassert(ctx%status(ikp, ispin, slot) == kpoint_slot_idle)
548 END IF
549
550 CALL kpoint_operator_ensure(ctx, rsmat)
551
552 ! The slot bookkeeping serves the asynchronous paths alone: the first
553 ! start creates it, and a get-only context never carries it. The spin
554 ! space of the sizing is the instance spin space declared at context
555 ! creation. The operator row count never enters it: spin-free
556 ! operators such as S carry their real-space blocks in the first
557 ! matrix dimension, and the row choice is made through matrix_row.
558 IF (.NOT. ALLOCATED(ctx%status)) THEN
559 ALLOCATE (ctx%status(kplocal, ctx%nspin, kpoint_num_slots))
560 ctx%status = kpoint_slot_idle
561 ! One copy_info per in-flight part: start takes it INTENT(OUT),
562 ! so two concurrent starts cannot share one instance.
563 ALLOCATE (ctx%info(kplocal*ctx%kpoints%nkp_groups, ctx%nspin, &
564 kpoint_num_slots, kpoint_part_im))
565 END IF
566
567 kp_range = ctx%kpoints%kp_range
568 kp_dist => ctx%kpoints%kp_dist
569 para_env => ctx%kpoints%blacs_env_all%para_env
570 DO igroup = 1, ctx%kpoints%nkp_groups
571 ik = kp_dist(1, igroup) + ikp - 1
572 my_kpgrp = (ik >= kp_range(1) .AND. ik <= kp_range(2))
573 indx = ikp + (igroup - 1)*kplocal
574 CALL kpoint_operator_launch(rsmat, matrix_row, ik, ctx%kpoints%xkp(1:3, ik), &
575 ctx%kpoints%cell_to_index, ctx%kpoints%sab_nl, grid, use_grid, &
576 ctx%rmatrix, ctx%cmatrix, ctx%tmpmat, &
577 ctx%fmwork(kpoint_part_re), ctx%fmwork(kpoint_part_im), &
578 target_re=ctx%fmlocal, target_im=ctx%fmlocal, fmdummy=ctx%fmdummy, &
579 my_kpgrp=my_kpgrp, para_env=para_env, &
580 info_re=ctx%info(indx, ispin, slot, kpoint_part_re), &
581 info_im=ctx%info(indx, ispin, slot, kpoint_part_im))
582 END DO
583 ctx%status(ikp, ispin, slot) = kpoint_slot_in_flight
584
585 CALL timestop(handle)
586
587 END SUBROUTINE kpoint_operator_start
588
589! **************************************************************************************************
590!> \brief Finish the transfers of one started instance: on the group that owns
591!> the k point, merge the received parts into cmat (real part first,
592!> overwrite then add); on every group, reclaim the send side.
593!> The slot returns to idle.
594!> Collective over the environment-wide communicator: every rank must
595!> call the same sequence of service calls.
596!> \param ctx context that started the instance
597!> \param ikp local k-point index of the start call
598!> \param ispin spin component of the start call
599!> \param slot slot of the start call; the slot must be in flight
600!> \param cmat caller-allocated complex matrix that receives the operator.
601!> It must share the distribution of the k-point group
602! **************************************************************************************************
603 SUBROUTINE kpoint_operator_finish(ctx, ikp, ispin, slot, cmat)
604
605 TYPE(kpoint_operator_context_type), INTENT(INOUT) :: ctx
606 INTEGER, INTENT(IN) :: ikp, ispin, slot
607 TYPE(cp_cfm_type) :: cmat
608
609 CHARACTER(LEN=*), PARAMETER :: routinen = 'kpoint_operator_finish'
610
611 INTEGER :: handle, igroup, ik, indx, kplocal
612 INTEGER, DIMENSION(2) :: kp_range
613 INTEGER, DIMENSION(:, :), POINTER :: kp_dist
614 LOGICAL :: my_kpgrp
615
616 CALL timeset(routinen, handle)
617
618 cpassert(ASSOCIATED(ctx%kpoints))
619 cpassert(ALLOCATED(ctx%status))
620 cpassert(ctx%status(ikp, ispin, slot) == kpoint_slot_in_flight)
621 ! The merge writes cmat in place. A foreign distribution would fail
622 ! inside the BLACS calls, far from this argument.
623 cpassert(cp_fm_struct_equivalent(cmat%matrix_struct, ctx%fmlocal%matrix_struct))
624
625 kplocal = ctx%kpoints%kp_range(2) - ctx%kpoints%kp_range(1) + 1
626 kp_range = ctx%kpoints%kp_range
627 kp_dist => ctx%kpoints%kp_dist
628 DO igroup = 1, ctx%kpoints%nkp_groups
629 ik = kp_dist(1, igroup) + ikp - 1
630 my_kpgrp = (ik >= kp_range(1) .AND. ik <= kp_range(2))
631 indx = ikp + (igroup - 1)*kplocal
632 IF (my_kpgrp) THEN
633 CALL kpoint_operator_raw_finish_cfm(ctx%fmlocal, ctx%info(indx, ispin, slot, kpoint_part_re), &
634 cmat, .false.)
635 CALL kpoint_operator_raw_finish_cfm(ctx%fmlocal, ctx%info(indx, ispin, slot, kpoint_part_im), &
636 cmat, .true.)
637 END IF
638 CALL cp_fm_cleanup_copy_general(ctx%info(indx, ispin, slot, kpoint_part_re))
639 CALL cp_fm_cleanup_copy_general(ctx%info(indx, ispin, slot, kpoint_part_im))
640 END DO
641 ctx%status(ikp, ispin, slot) = kpoint_slot_idle
642
643 CALL timestop(handle)
644
645 END SUBROUTINE kpoint_operator_finish
646
647! **************************************************************************************************
648!> \brief Assemble one operator for one local k point and spin in one call:
649!> run the single-group transfer of the service for every group and
650!> finish it immediately, through transfer states local to this call.
651!> The persistent slot machinery stays with start and finish.
652!> Exactly one output flavor must be present: cmat receives the complex
653!> operator (real part overwrites, imaginary part adds) through the
654!> context buffer; the fm pair receives the two parts separately,
655!> transferred directly into fm_re and fm_im on the owning group (any
656!> distribution: the general copy redistributes); or the dbcsr pair
657!> receives the two parts as block-cyclic matrices built by the service,
658!> replacing the caller-side copy_fm_to_dbcsr_bc detour. The dbcsr
659!> matrices must be freshly initialized (dbcsr_init_p) and the cmat
660!> flavor must share the distribution of the k-point group.
661!> Collective over the environment-wide communicator: every rank must
662!> call the same sequence of service calls.
663!> \param ctx context created by kpoint_operator_context_create
664!> \param ikp local k-point index within kp_range
665!> \param ispin instance spin: bounds-checked against the context spin space
666!> \param rsmat real-space image matrices of the operator
667!> \param cmat complex matrix output
668!> \param fm_re real-part matrix output
669!> \param fm_im imaginary-part matrix output
670!> \param mat_re real-part block-cyclic dbcsr output
671!> \param mat_im imaginary-part block-cyclic dbcsr output
672!> \param matrix_row row of rsmat to transform. Spin-free operators such
673!> as S and T must pass kpoint_spin_free: their first matrix
674!> dimension counts derivatives, not spins. A spin index is out of
675!> bounds in plain SCF, but with derivatives stored it reads another
676!> valid row silently
677! **************************************************************************************************
678 SUBROUTINE kpoint_operator_get(ctx, ikp, ispin, rsmat, cmat, fm_re, fm_im, &
679 mat_re, mat_im, matrix_row)
680
681 TYPE(kpoint_operator_context_type), INTENT(INOUT) :: ctx
682 INTEGER, INTENT(IN) :: ikp, ispin
683 TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: rsmat
684 TYPE(cp_cfm_type), OPTIONAL :: cmat
685 TYPE(cp_fm_type), OPTIONAL :: fm_re, fm_im
686 TYPE(dbcsr_type), INTENT(INOUT), OPTIONAL :: mat_re, mat_im
687 INTEGER, INTENT(IN) :: matrix_row
688
689 CHARACTER(LEN=*), PARAMETER :: routinen = 'kpoint_operator_get'
690
691 INTEGER :: handle, igroup, ik, kplocal
692 INTEGER, DIMENSION(2) :: kp_range
693 INTEGER, DIMENSION(:, :), POINTER :: kp_dist
694 LOGICAL :: my_kpgrp
695 TYPE(copy_info_type) :: info_im, info_re
696 TYPE(mp_para_env_type), POINTER :: para_env
697
698 CALL timeset(routinen, handle)
699
700 cpassert(count([PRESENT(cmat), PRESENT(fm_re), PRESENT(mat_re)]) == 1)
701 IF (PRESENT(fm_re) .OR. PRESENT(fm_im)) THEN
702 cpassert(PRESENT(fm_re) .AND. PRESENT(fm_im))
703 END IF
704 IF (PRESENT(mat_re) .OR. PRESENT(mat_im)) THEN
705 cpassert(PRESENT(mat_re) .AND. PRESENT(mat_im))
706 END IF
707
708 cpassert(ASSOCIATED(ctx%kpoints))
709 cpassert(ASSOCIATED(ctx%kpoints%sab_nl))
710 cpassert(ispin >= 1 .AND. ispin <= ctx%nspin)
711 cpassert(matrix_row >= 1 .AND. matrix_row <= SIZE(rsmat, 1))
712 CALL kpoint_operator_ensure(ctx, rsmat)
713 kplocal = ctx%kpoints%kp_range(2) - ctx%kpoints%kp_range(1) + 1
714 cpassert(ikp >= 1 .AND. ikp <= kplocal)
715 IF (PRESENT(cmat)) THEN
716 ! The merge writes cmat in place. A foreign distribution would fail
717 ! inside the BLACS calls, far from this argument.
718 cpassert(cp_fm_struct_equivalent(cmat%matrix_struct, ctx%fmlocal%matrix_struct))
719 END IF
720
721 kp_range = ctx%kpoints%kp_range
722 kp_dist => ctx%kpoints%kp_dist
723 para_env => ctx%kpoints%blacs_env_all%para_env
724 DO igroup = 1, ctx%kpoints%nkp_groups
725 ik = kp_dist(1, igroup) + ikp - 1
726 my_kpgrp = (ik >= kp_range(1) .AND. ik <= kp_range(2))
727 IF (PRESENT(cmat)) THEN
728 ! cmat flavor: both parts pass through the context buffer; the
729 ! real part overwrites cmat, the imaginary part adds to it
730 CALL kpoint_operator_launch(rsmat, matrix_row, ik, ctx%kpoints%xkp(1:3, ik), &
731 ctx%kpoints%cell_to_index, ctx%kpoints%sab_nl, &
732 use_grid=.false., rmatrix=ctx%rmatrix, cmatrix=ctx%cmatrix, &
733 tmpmat=ctx%tmpmat, fm_re=ctx%fmwork(kpoint_part_re), &
734 fm_im=ctx%fmwork(kpoint_part_im), target_re=ctx%fmlocal, &
735 target_im=ctx%fmlocal, fmdummy=ctx%fmdummy, my_kpgrp=my_kpgrp, &
736 para_env=para_env, info_re=info_re, info_im=info_im)
737 IF (my_kpgrp) THEN
738 CALL kpoint_operator_raw_finish_cfm(ctx%fmlocal, info_re, cmat, .false.)
739 CALL kpoint_operator_raw_finish_cfm(ctx%fmlocal, info_im, cmat, .true.)
740 END IF
741 ELSE IF (PRESENT(fm_re)) THEN
742 ! fm flavor: transfer each part straight into the caller matrices
743 CALL kpoint_operator_launch(rsmat, matrix_row, ik, ctx%kpoints%xkp(1:3, ik), &
744 ctx%kpoints%cell_to_index, ctx%kpoints%sab_nl, &
745 use_grid=.false., rmatrix=ctx%rmatrix, cmatrix=ctx%cmatrix, &
746 tmpmat=ctx%tmpmat, fm_re=ctx%fmwork(kpoint_part_re), &
747 fm_im=ctx%fmwork(kpoint_part_im), target_re=fm_re, &
748 target_im=fm_im, fmdummy=ctx%fmdummy, my_kpgrp=my_kpgrp, &
749 para_env=para_env, info_re=info_re, info_im=info_im)
750 IF (my_kpgrp) THEN
751 CALL cp_fm_finish_copy_general(fm_re, info_re)
752 CALL cp_fm_finish_copy_general(fm_im, info_im)
753 END IF
754 ELSE
755 ! dbcsr flavor: receive both parts through the context buffer,
756 ! then emit the block-cyclic pair
757 CALL kpoint_operator_launch(rsmat, matrix_row, ik, ctx%kpoints%xkp(1:3, ik), &
758 ctx%kpoints%cell_to_index, ctx%kpoints%sab_nl, &
759 use_grid=.false., rmatrix=ctx%rmatrix, cmatrix=ctx%cmatrix, &
760 tmpmat=ctx%tmpmat, fm_re=ctx%fmwork(kpoint_part_re), &
761 fm_im=ctx%fmwork(kpoint_part_im), target_re=ctx%fmlocal, &
762 target_im=ctx%fmlocal, fmdummy=ctx%fmdummy, my_kpgrp=my_kpgrp, &
763 para_env=para_env, info_re=info_re, info_im=info_im)
764 IF (my_kpgrp) THEN
765 CALL cp_fm_finish_copy_general(ctx%fmlocal, info_re)
766 CALL copy_fm_to_dbcsr_bc(ctx%fmlocal, mat_re)
767 CALL cp_fm_finish_copy_general(ctx%fmlocal, info_im)
768 CALL copy_fm_to_dbcsr_bc(ctx%fmlocal, mat_im)
769 END IF
770 END IF
771 CALL cp_fm_cleanup_copy_general(info_re)
772 CALL cp_fm_cleanup_copy_general(info_im)
773 END DO
774
775 CALL timestop(handle)
776
777 END SUBROUTINE kpoint_operator_get
778
779END MODULE qs_kpoint_operators
Basic linear algebra operations for complex full matrices.
subroutine, public cp_cfm_scale_and_add_fm(alpha, matrix_a, beta, matrix_b)
Scale and add two BLACS matrices (a = alpha*a + beta*b). where b is a real matrix (adapted from cp_cf...
Represents a complex full matrix distributed on many processors.
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.
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_bc(fm, bc_mat)
Copy a BLACS matrix to a dbcsr matrix with a special block-cyclic distribution, which requires no com...
pool for for elements that are retained and released
subroutine, public fm_pool_create_fm(pool, element, name)
returns an element, allocating it if none is in the pool
subroutine, public fm_pool_give_back_fm(pool, element)
returns the element to the pool
represent the structure of a full matrix
logical function, public cp_fm_struct_equivalent(fmstruct1, fmstruct2)
returns true if the two matrix structures are equivalent, false otherwise.
represent a full matrix distributed on many processors
Definition cp_fm_types.F:15
subroutine, public cp_fm_start_copy_general(source, destination, para_env, info)
Initiates the copy operation: get distribution data, post MPI isend and irecvs.
subroutine, public cp_fm_cleanup_copy_general(info)
Completes the copy operation: wait for comms clean up MPI state.
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_create(matrix, matrix_struct, name, nrow, ncol, set_zero)
creates a new full matrix with the given structure
subroutine, public cp_fm_finish_copy_general(destination, info)
Completes the copy operation: wait for comms, unpack, clean up MPI state.
Defines the basic variable types.
Definition kinds.F:23
integer, parameter, public dp
Definition kinds.F:34
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 rskp_transform_grid_extract(grid, ikp, rmatrix, cmatrix)
Extract one reciprocal-grid matrix from a prepared local DBCSR block cache.
Types and basic routines needed for a kpoint calculation.
Definition of mathematical constants and functions.
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.
Assembly of complex k-point operators from real-space DBCSR matrices. The output is a complex full ma...
subroutine, public kpoint_operator_context_create(ctx, kpoints, ao_ao_fm, nspin)
Create an empty operator context. The context owns no buffers after this call; they are created on fi...
subroutine, public kpoint_operator_cfm_to_mo(cmat, mo_re, mo_im, eigenvalues)
Split a complex matrix into the real and imaginary MO sets and copy the eigenvalues to the imaginary ...
subroutine kpoint_operator_densify(rsmat, matrix_row, ik, xkp, cell_to_index, sab_nl, grid, use_grid, rmatrix, cmatrix, tmpmat, fm_re, fm_im)
Transform one real-space operator to one k point and densify the result: the real part into fm_re and...
integer, parameter, public kpoint_spin_free
Row of rsmat that carries the spin-free operator image. S and T carry no spin copies: drivers launch ...
subroutine, public kpoint_operator_get(ctx, ikp, ispin, rsmat, cmat, fm_re, fm_im, mat_re, mat_im, matrix_row)
Assemble one operator for one local k point and spin in one call: run the single-group transfer of th...
integer, parameter, public kpoint_slot_s
integer, parameter, public kpoint_slot_t
integer, parameter, public kpoint_slot_ks
subroutine, public kpoint_operator_finish(ctx, ikp, ispin, slot, cmat)
Finish the transfers of one started instance: on the group that owns the k point, merge the received ...
subroutine, public kpoint_operator_start(ctx, ikp, ispin, rsmat, slot, grid, use_grid, matrix_row)
Start the assembly of one operator for one local k point and spin and launch its transfers to every k...
subroutine, public kpoint_operator_context_release(ctx)
Release the context together with every buffer it created. Call once, at the exit of the routine that...
wrapper for the pools of matrixes
subroutine, public mpools_get(mpools, ao_mo_fm_pools, ao_ao_fm_pools, mo_mo_fm_pools, ao_mosub_fm_pools, mosub_mosub_fm_pools, maxao_maxmo_fm_pool, maxao_maxao_fm_pool, maxmo_maxmo_fm_pool)
returns various attributes of the mpools (notably the pools contained in it)
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.
Represent a complex full matrix.
keeps the information about the structure of a full matrix
Stores the state of a copy between cp_fm_start_copy_general and cp_fm_finish_copy_general.
represent a full matrix
Contains information about kpoints.
stores all the informations relevant to an mpi environment
Caller-owned assembly context for one driver call. Created and released in the same driver routine an...
container for the pools of matrixes used by qs