(git:42db5d2)
Loading...
Searching...
No Matches
cp_fm_diag_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 Auxiliary tools to redistribute cp_fm_type matrices before and after diagonalization.
10!> Heuristics are used to determine the optimal number of CPUs for diagonalization and the
11!> input matrices are redistributed if necessary
12!> \par History
13!> - [01.2018] moved redistribution related code from cp_fm_syevd here
14!> \author Nico Holmberg [01.2018]
15! **************************************************************************************************
23 USE cp_fm_types, ONLY: cp_fm_create,&
30 USE kinds, ONLY: dp
31 USE mathlib, ONLY: gcd
33#include "../base/base_uses.f90"
34
35 IMPLICIT NONE
36
37 PRIVATE
38
39 CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'cp_fm_diag_utils'
40
41 ! Information on redistribution
43 INTEGER :: matrix_order = -1
44 INTEGER :: num_pe_old = -1 ! number of processes before a potential redistribute
45 INTEGER :: num_pe_new = -1 ! number of processes after a potential redistribute
46 INTEGER :: num_pe_opt = -1 ! optimal number of processes for the given matrix
47 INTEGER :: num_pe_max_nz_col = -1 ! the maximal number of processes s.t. no column has zero width, may be < 0 if ignored
48 LOGICAL :: redistribute = .false. ! whether or not the matrix was actually redistributed
49 CONTAINS
50 PROCEDURE, pass(self) :: write => cp_fm_redistribute_info_write
52
53 ! Container for redistribution settings and temporary work structs
54 TYPE cp_fm_redistribute_type
55 ! Settings
56 INTEGER :: a = -1, x = -1
57 LOGICAL :: should_print = .false.
58 LOGICAL :: elpa_force_redistribute = .false.
59 ! Temporaries
60 INTEGER, DIMENSION(:), POINTER :: group_distribution => null(), &
61 group_partition => null()
62 TYPE(cp_blacs_env_type), POINTER :: blacs_env_new => null()
63 TYPE(mp_para_env_type), POINTER :: para_env_new => null()
64 END TYPE cp_fm_redistribute_type
65
66 ! Permanent instance of the redistribute type
67 TYPE(cp_fm_redistribute_type), PRIVATE, &
68 SAVE :: work_redistribute
69
70 ! Public subroutines
71
72 PUBLIC :: cp_fm_redistribute_start, &
75
76CONTAINS
77
78! **************************************************************************************************
79!> \brief Write the redistribute info nicely formatted to the given I/O unit
80!> \param self reference to the cp_fm_redistribute_info instance
81!> \param io_unit I/O unit to use for writing
82! **************************************************************************************************
83 SUBROUTINE cp_fm_redistribute_info_write(self, io_unit)
84 CLASS(cp_fm_redistribute_info), INTENT(IN) :: self
85 INTEGER, INTENT(IN) :: io_unit
86
87 WRITE (unit=io_unit, fmt="(A)") ""
88 WRITE (unit=io_unit, fmt="(T2,A,T71,I10)") &
89 "CP_FM_DIAG| Number of processes over which the matrix is distributed ", self%num_pe_old, &
90 "CP_FM_DIAG| Matrix order ", self%matrix_order
91 WRITE (unit=io_unit, fmt="(T2,A,T71,I10)") &
92 "CP_FM_DIAG| Optimal number of CPUs ", self%num_pe_opt
93 IF (self%num_pe_max_nz_col < 0) THEN
94 WRITE (unit=io_unit, fmt="(T2,A,T71,A10)") &
95 "CP_FM_DIAG| Maximum number of CPUs (with non-zero columns) ", "<N/A>"
96 ELSE
97 WRITE (unit=io_unit, fmt="(T2,A,T71,I10)") &
98 "CP_FM_DIAG| Maximum number of CPUs (with non-zero columns): ", self%num_pe_max_nz_col
99 END IF
100 IF (self%redistribute) THEN
101 WRITE (unit=io_unit, fmt="(T2,A,T71,I10)") &
102 "CP_FM_DIAG| Number of processes for the redistribution ", self%num_pe_new
103 ELSE
104 WRITE (unit=io_unit, fmt="(T2,A)") &
105 "CP_FM_DIAG| The matrix will NOT be redistributed"
106 END IF
107 WRITE (unit=io_unit, fmt="(A)") ""
108
109 END SUBROUTINE cp_fm_redistribute_info_write
110
111! **************************************************************************************************
112!> \brief Releases the temporary storage needed when redistributing arrays
113!> \param has_redistributed flag that determines if the processors holds a part of the
114!> redistributed array
115!> \author Nico Holmberg [01.2018]
116! **************************************************************************************************
117 SUBROUTINE cp_fm_redistribute_work_finalize(has_redistributed)
118 LOGICAL, INTENT(IN) :: has_redistributed
119
120 IF (ASSOCIATED(work_redistribute%group_distribution)) THEN
121 IF (has_redistributed) THEN
122 CALL cp_blacs_env_release(work_redistribute%blacs_env_new)
123 END IF
124 CALL work_redistribute%para_env_new%free()
125 DEALLOCATE (work_redistribute%para_env_new)
126 DEALLOCATE (work_redistribute%group_distribution)
127 DEALLOCATE (work_redistribute%group_partition)
128 END IF
129 ! Return work to its initial state
130 work_redistribute = cp_fm_redistribute_type()
131
132 END SUBROUTINE cp_fm_redistribute_work_finalize
133
134! **************************************************************************************************
135!> \brief Initializes the parameters that determine how to calculate the optimal number of CPUs
136!> for diagonalizing a matrix. The parameters are read from the GLOBAL input section.
137!> \param a integer parameter used to define the rule for determining the optimal
138!> number of CPUs for diagonalization
139!> \param x integer parameter used to define the rule for determining the optimal
140!> number of CPUs for diagonalization
141!> \param should_print flag that determines if information about the redistribution process
142!> should be printed
143!> \param elpa_force_redistribute flag that if redistribution should always be performed when
144!> the ELPA diagonalization library is in use
145!> \author Nico Holmberg [01.2018]
146! **************************************************************************************************
147 SUBROUTINE cp_fm_redistribute_init(a, x, should_print, elpa_force_redistribute)
148 INTEGER, INTENT(IN) :: a, x
149 LOGICAL, INTENT(IN) :: should_print, elpa_force_redistribute
150
151 work_redistribute%a = a
152 work_redistribute%x = x
153 work_redistribute%should_print = should_print
154 work_redistribute%elpa_force_redistribute = elpa_force_redistribute
155 ! Init work
156 work_redistribute = cp_fm_redistribute_type()
157
158 END SUBROUTINE cp_fm_redistribute_init
159
160! **************************************************************************************************
161!> \brief Calculates the optimal number of CPUs for diagonalizing a matrix.
162!> \param size the size of the diagonalized matrix
163!> \return the optimal number of CPUs
164!> \author Nico Holmberg [01.2018]
165! **************************************************************************************************
166 PURE FUNCTION cp_fm_diag_get_optimal_ncpu(size) RESULT(ncpu)
167 INTEGER, INTENT(IN) :: size
168 INTEGER :: ncpu
169
170 ncpu = ((size + work_redistribute%a*work_redistribute%x - 1)/ &
171 (work_redistribute%a*work_redistribute%x))*work_redistribute%a
172
173 END FUNCTION cp_fm_diag_get_optimal_ncpu
174
175#if defined(__parallel)
176! **************************************************************************************************
177!> \brief Determines the largest number of CPUs a matrix can be distributed on without any of the
178!> processors getting a zero-width column (currently only needed for ELPA).
179!> \param matrix the matrix that will be diagonalized
180!> \return the maximum number of CPUs for ELPA
181!> \author Nico Holmberg [01.2018]
182! **************************************************************************************************
183 FUNCTION cp_fm_max_ncpu_non_zero_column(matrix) RESULT(ncpu)
184 TYPE(cp_fm_type), INTENT(IN) :: matrix
185 INTEGER :: ncpu
186
187 INTEGER :: gcd_max, ipe, jpe, ncol_block, &
188 ncol_global, npcol, nrow_block, &
189 nrow_global, num_pe_old, nzero
190 INTEGER, DIMENSION(:), POINTER :: ncol_locals
191 INTEGER, EXTERNAL :: numroc
192
193 NULLIFY (ncol_locals)
194 ! First check if there are any zero width columns in current layout
195 CALL cp_fm_get_info(matrix, ncol_locals=ncol_locals, &
196 nrow_global=nrow_global, ncol_global=ncol_global, &
197 nrow_block=nrow_block, ncol_block=ncol_block)
198 nzero = count(ncol_locals == 0)
199 num_pe_old = matrix%matrix_struct%para_env%num_pe
200 ncpu = num_pe_old - nzero
201
202 ! Avoid layouts with odd number of CPUs (blacs grid layout will be square)
203 IF (ncpu > 2) THEN
204 ncpu = ncpu - modulo(ncpu, 2)
205 END IF
206
207 ! if there are no zero-width columns and the number of processors was even, leave it at that
208 IF (ncpu == num_pe_old) THEN
209 RETURN
210 END IF
211
212 ! Iteratively search for the maximum number of CPUs for ELPA
213 ! On each step, we test whether the blacs grid created with ncpu processes
214 ! contains any columns with zero width
215 DO WHILE (ncpu > 1)
216 ! Determine layout of new blacs grid with ncpu CPUs
217 ! (snippet copied from cp_blacs_env.F:cp_blacs_env_create)
218 gcd_max = -1
219 DO ipe = 1, ceiling(sqrt(real(ncpu, dp)))
220 jpe = ncpu/ipe
221 IF (ipe*jpe /= ncpu) THEN
222 cycle
223 END IF
224 IF (gcd(ipe, jpe) >= gcd_max) THEN
225 npcol = jpe
226 gcd_max = gcd(ipe, jpe)
227 END IF
228 END DO
229
230 ! Count the number of processors without any columns
231 ! (snippet copied from cp_fm_struct.F:cp_fm_struct_create)
232 nzero = 0
233 DO ipe = 0, npcol - 1
234 IF (numroc(ncol_global, ncol_block, ipe, 0, npcol) == 0) THEN
235 nzero = nzero + 1
236 END IF
237 END DO
238
239 IF (nzero == 0) THEN
240 EXIT
241 END IF
242
243 ncpu = ncpu - nzero
244
245 IF (ncpu > 2) THEN
246 ncpu = ncpu - modulo(ncpu, 2)
247 END IF
248 END DO
249
250 END FUNCTION cp_fm_max_ncpu_non_zero_column
251#endif
252
253! **************************************************************************************************
254!> \brief Determines the optimal number of CPUs for matrix diagonalization and redistributes
255!> the input matrices if necessary
256!> \param matrix the input cp_fm_type matrix to be diagonalized
257!> \param eigenvectors the cp_fm_type matrix that will hold the eigenvectors of the input matrix
258!> \param matrix_new the redistributed input matrix which will subsequently be diagonalized,
259!> or a pointer to the original matrix if no redistribution is required
260!> \param eigenvectors_new the redistributed eigenvectors matrix, or a pointer to the original
261!> matrix if no redistribution is required
262!> \param caller_is_elpa flag that determines if ELPA is used for diagonalization
263!> \param redist_info get info about the redistribution
264!> \par History
265!> - [01.2018] created by moving redistribution related code from cp_fm_syevd here
266!> \author Nico Holmberg [01.2018]
267! **************************************************************************************************
268 SUBROUTINE cp_fm_redistribute_start(matrix, eigenvectors, matrix_new, eigenvectors_new, &
269 caller_is_elpa, redist_info)
270
271 TYPE(cp_fm_type), INTENT(IN) :: matrix, eigenvectors
272 TYPE(cp_fm_type), INTENT(OUT) :: matrix_new, eigenvectors_new
273 LOGICAL, OPTIONAL, INTENT(IN) :: caller_is_elpa
274
275 CHARACTER(len=*), PARAMETER :: routinen = 'cp_fm_redistribute_start'
276
277 INTEGER :: handle
278 LOGICAL :: is_elpa
279 TYPE(cp_fm_redistribute_info), OPTIONAL, INTENT(OUT) :: redist_info
280
281#if defined(__parallel)
282 REAL(kind=dp) :: fake_local_data(1, 1)
283 INTEGER :: fake_descriptor(9), mepos_old, &
284 io_unit, ngroups, ncol_block, blksize, nrow_block
285 TYPE(cp_fm_struct_type), POINTER :: fm_struct_new
286 TYPE(mp_para_env_type), POINTER :: para_env
287 TYPE(cp_logger_type), POINTER :: logger
288 TYPE(cp_fm_redistribute_info) :: rdinfo
289#endif
290
291 CALL timeset(routinen, handle)
292 is_elpa = .false.
293 IF (PRESENT(caller_is_elpa)) THEN
294#if defined(__ELPA)
295 is_elpa = caller_is_elpa
296#else
297 cpabort("CP2K compiled without the ELPA library.")
298#endif
299 END IF
300
301#if defined(__parallel)
302
303 logger => cp_get_default_logger()
304 io_unit = cp_logger_get_default_io_unit(logger)
305
306 ! first figure out the optimal number of cpus
307 ! this is pure heuristics, the defaults are based on rosa timings
308 ! that demonstrate that timings go up sharply if too many tasks are used
309 ! we take a multiple of 4, and approximately n/60
310 para_env => matrix%matrix_struct%para_env
311 mepos_old = para_env%mepos
312 ncol_block = -1 ! normally we also want to adjust the block size according to the optimal # of CPUs
313 nrow_block = -1
314 blksize = -1
315
316 rdinfo%matrix_order = matrix%matrix_struct%nrow_global
317 rdinfo%num_pe_old = para_env%num_pe
318 rdinfo%num_pe_opt = cp_fm_diag_get_optimal_ncpu(rdinfo%matrix_order)
319 rdinfo%num_pe_new = rdinfo%num_pe_opt
320 rdinfo%num_pe_max_nz_col = -1
321 rdinfo%redistribute = .false.
322
323 IF (is_elpa) THEN
324 ! with ELPA we don't have to redistribute if not necessary (scales, unlike ScaLAPACK)
325 rdinfo%num_pe_new = rdinfo%num_pe_old
326
327 ! BUT: Diagonalization with ELPA fails when a processor column has zero width
328 ! Determine the maximum number of CPUs the matrix can be distributed without zero-width columns
329 ! for the current block size.
330 rdinfo%num_pe_max_nz_col = cp_fm_max_ncpu_non_zero_column(matrix)
331
332 ! if the user wants to redistribute to the ScaLAPACK optimal number of CPUs anyway, let him if it's safe.
333 IF (work_redistribute%elpa_force_redistribute .AND. rdinfo%num_pe_opt < rdinfo%num_pe_max_nz_col) THEN
334 ! Use heuristics to determine the need for redistribution (when num_pe_opt is smaller than the safe maximum)
335 ! in this case we can also take the block size used for ScaLAPACK
336 rdinfo%num_pe_new = rdinfo%num_pe_opt
337 ELSE IF (rdinfo%num_pe_old > rdinfo%num_pe_max_nz_col) THEN
338 ! Otherwise, only redistribute if we have to
339 rdinfo%num_pe_new = rdinfo%num_pe_max_nz_col
340 ! do NOT let cp_fm_struct_create automatically adjust the block size because the
341 ! calculated number of processors such that no block has 0 columns wouldn't match (see #578):
342 ! if the automatically chosen block size is larger than the present one we would still end
343 ! up with empty processors
344 END IF
345
346 CALL cp_fm_get_info(matrix, ncol_block=ncol_block, nrow_block=nrow_block)
347
348 ! On GPUs, ELPA requires the block size to be a power of 2
349 blksize = 1
350 DO WHILE (2*blksize <= min(nrow_block, ncol_block))
351 blksize = blksize*2
352 END DO
353 nrow_block = blksize
354 ncol_block = blksize
355 END IF
356
357 ! finally, only redistribute if we're going to use less CPUs than before or changed the block size
358 rdinfo%redistribute = (rdinfo%num_pe_old > rdinfo%num_pe_new) .OR. (blksize >= 0 .AND. &
359 ((blksize /= matrix%matrix_struct%ncol_block) .OR. (blksize /= matrix%matrix_struct%nrow_block)))
360
361 IF (work_redistribute%should_print .AND. io_unit > 0) THEN
362 IF (is_elpa) THEN
363 IF (work_redistribute%elpa_force_redistribute) THEN
364 WRITE (unit=io_unit, fmt="(T2,A,T78,A3)") &
365 "CP_FM_DIAG| Force redistribute (ELPA):", "YES"
366 ELSE
367 WRITE (unit=io_unit, fmt="(T2,A,T79,A2)") &
368 "CP_FM_DIAG| Force redistribute (ELPA):", "NO"
369 END IF
370 END IF
371 CALL rdinfo%write(io_unit)
372 END IF
373 CALL para_env%sync()
374
375 ! if the optimal is smaller than num_pe, we will redistribute the input matrix
376 IF (rdinfo%redistribute) THEN
377 ! split comm, the first num_pe_new tasks will do the work
378 ALLOCATE (work_redistribute%group_distribution(0:rdinfo%num_pe_old - 1))
379 ALLOCATE (work_redistribute%group_partition(0:1))
380 work_redistribute%group_partition = [rdinfo%num_pe_new, rdinfo%num_pe_old - rdinfo%num_pe_new]
381 ALLOCATE (work_redistribute%para_env_new)
382 CALL work_redistribute%para_env_new%from_split( &
383 comm=para_env, ngroups=ngroups, group_distribution=work_redistribute%group_distribution, &
384 n_subgroups=2, group_partition=work_redistribute%group_partition)
385
386 IF (work_redistribute%group_distribution(mepos_old) == 0) THEN
387
388 ! create blacs, should inherit the preferences for the layout and so on, from the higher level
389 NULLIFY (work_redistribute%blacs_env_new)
390 CALL cp_blacs_env_create(blacs_env=work_redistribute%blacs_env_new, para_env=work_redistribute%para_env_new)
391
392 ! create new matrix
393 NULLIFY (fm_struct_new)
394 IF (nrow_block == -1 .OR. ncol_block == -1) THEN
395 CALL cp_fm_struct_create(fmstruct=fm_struct_new, &
396 para_env=work_redistribute%para_env_new, &
397 context=work_redistribute%blacs_env_new, &
398 nrow_global=rdinfo%matrix_order, ncol_global=rdinfo%matrix_order, &
399 ncol_block=ncol_block, nrow_block=nrow_block)
400 ELSE
401 CALL cp_fm_struct_create(fmstruct=fm_struct_new, &
402 para_env=work_redistribute%para_env_new, &
403 context=work_redistribute%blacs_env_new, &
404 nrow_global=rdinfo%matrix_order, ncol_global=rdinfo%matrix_order, &
405 ncol_block=ncol_block, nrow_block=nrow_block, force_block=.true.)
406 END IF
407 CALL cp_fm_create(matrix_new, matrix_struct=fm_struct_new, name="yevd_new_mat")
408 CALL cp_fm_create(eigenvectors_new, matrix_struct=fm_struct_new, name="yevd_new_vec")
409 CALL cp_fm_struct_release(fm_struct_new)
410
411 ! redistribute old
412 CALL pdgemr2d(rdinfo%matrix_order, rdinfo%matrix_order, matrix%local_data(1, 1), 1, 1, &
413 matrix%matrix_struct%descriptor, &
414 matrix_new%local_data(1, 1), 1, 1, matrix_new%matrix_struct%descriptor, &
415 matrix%matrix_struct%context)
416 ELSE
417 ! these tasks must help redistribute (they own part of the data),
418 ! but need fake 'new' data, and their descriptor must indicate this with -1
419 ! see also scalapack comments on pdgemr2d
420 fake_descriptor = -1
421 CALL pdgemr2d(rdinfo%matrix_order, rdinfo%matrix_order, matrix%local_data(1, 1), 1, 1, &
422 matrix%matrix_struct%descriptor, &
423 fake_local_data(1, 1), 1, 1, fake_descriptor, &
424 matrix%matrix_struct%context)
425 END IF
426 ELSE
427 ! No need to redistribute, just return pointers to the original arrays
428 matrix_new = matrix
429 eigenvectors_new = eigenvectors
430 END IF
431
432 IF (PRESENT(redist_info)) THEN
433 redist_info = rdinfo
434 END IF
435#else
436
437 mark_used(matrix)
438 mark_used(eigenvectors)
439 mark_used(matrix_new)
440 mark_used(eigenvectors_new)
441 mark_used(redist_info)
442 cpabort("Routine called in non-parallel case.")
443#endif
444
445 CALL timestop(handle)
446
447 END SUBROUTINE cp_fm_redistribute_start
448
449! **************************************************************************************************
450!> \brief Redistributes eigenvectors and eigenvalues back to the original communicator group
451!> \param matrix the input cp_fm_type matrix to be diagonalized
452!> \param eigenvectors the cp_fm_type matrix that will hold the eigenvectors of the input matrix
453!> \param eig global array holding the eigenvalues of the input matrixmatrix
454!> \param matrix_new the redistributed input matrix which will subsequently be diagonalized,
455!> or a pointer to the original matrix if no redistribution is required
456!> \param eigenvectors_new the redistributed eigenvectors matrix, or a pointer to the original
457!> matrix if no redistribution is required
458!> \par History
459!> - [01.2018] created by moving redistribution related code from cp_fm_syevd here
460!> \author Nico Holmberg [01.2018]
461! **************************************************************************************************
462 SUBROUTINE cp_fm_redistribute_end(matrix, eigenvectors, eig, matrix_new, eigenvectors_new)
463
464 TYPE(cp_fm_type), INTENT(IN) :: matrix, eigenvectors
465 REAL(kind=dp), DIMENSION(:), INTENT(INOUT) :: eig
466 TYPE(cp_fm_type), INTENT(INOUT) :: matrix_new, eigenvectors_new
467
468 CHARACTER(len=*), PARAMETER :: routinen = 'cp_fm_redistribute_end'
469
470 INTEGER :: handle
471#if defined(__parallel)
472 REAL(kind=dp) :: fake_local_data(1, 1)
473 INTEGER :: fake_descriptor(9), mepos_old, n
474 TYPE(mp_para_env_type), POINTER :: para_env
475#endif
476
477 CALL timeset(routinen, handle)
478
479#if defined(__parallel)
480
481 ! Check if matrix was redistributed
482 IF (ASSOCIATED(work_redistribute%group_distribution)) THEN
483 n = matrix%matrix_struct%nrow_global
484 para_env => matrix%matrix_struct%para_env
485 mepos_old = para_env%mepos
486
487 IF (work_redistribute%group_distribution(mepos_old) == 0) THEN
488 ! redistribute results on CPUs that hold the redistributed matrix
489 CALL pdgemr2d(n, n, eigenvectors_new%local_data(1, 1), 1, 1, eigenvectors_new%matrix_struct%descriptor, &
490 eigenvectors%local_data(1, 1), 1, 1, eigenvectors%matrix_struct%descriptor, &
491 eigenvectors%matrix_struct%context)
492 CALL cp_fm_release(matrix_new)
493 CALL cp_fm_release(eigenvectors_new)
494 ELSE
495 ! these tasks must help redistribute (they own part of the data),
496 ! but need fake 'new' data, and their descriptor must indicate this with -1
497 ! see also scalapack comments on pdgemr2d
498 fake_descriptor = -1
499 CALL pdgemr2d(n, n, fake_local_data(1, 1), 1, 1, fake_descriptor, &
500 eigenvectors%local_data(1, 1), 1, 1, eigenvectors%matrix_struct%descriptor, &
501 eigenvectors%matrix_struct%context)
502 END IF
503 ! free work
504 CALL cp_fm_redistribute_work_finalize(work_redistribute%group_distribution(mepos_old) == 0)
505
506 ! finally, also the eigenvalues need to end up on the non-group member tasks
507 CALL para_env%bcast(eig, 0)
508 END IF
509
510#else
511
512 mark_used(matrix)
513 mark_used(eigenvectors)
514 mark_used(eig)
515 mark_used(matrix_new)
516 mark_used(eigenvectors_new)
517 cpabort("Routine called in non-parallel case.")
518#endif
519
520 CALL timestop(handle)
521
522 END SUBROUTINE cp_fm_redistribute_end
523
524END MODULE cp_fm_diag_utils
static GRID_HOST_DEVICE int modulo(int a, int m)
Equivalent of Fortran's MODULO, which always return a positive number. https://gcc....
methods related to the blacs parallel environment
subroutine, public cp_blacs_env_release(blacs_env)
releases the given blacs_env
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
Auxiliary tools to redistribute cp_fm_type matrices before and after diagonalization....
subroutine, public cp_fm_redistribute_end(matrix, eigenvectors, eig, matrix_new, eigenvectors_new)
Redistributes eigenvectors and eigenvalues back to the original communicator group.
subroutine, public cp_fm_redistribute_start(matrix, eigenvectors, matrix_new, eigenvectors_new, caller_is_elpa, redist_info)
Determines the optimal number of CPUs for matrix diagonalization and redistributes the input matrices...
subroutine, public cp_fm_redistribute_init(a, x, should_print, elpa_force_redistribute)
Initializes the parameters that determine how to calculate the optimal number of CPUs for diagonalizi...
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_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
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...
type(cp_logger_type) function, pointer, public cp_get_default_logger()
returns the default logger
Defines the basic variable types.
Definition kinds.F:23
integer, parameter, public dp
Definition kinds.F:34
Collection of simple mathematical functions and subroutines.
Definition mathlib.F:15
elemental integer function, public gcd(a, b)
computes the greatest common divisor of two number
Definition mathlib.F:1289
Interface to the message passing library MPI.
represent a blacs multidimensional parallel environment (for the mpi corrispective see cp_paratypes/m...
keeps the information about the structure of a full matrix
represent a full matrix
type of a logger, at the moment it contains just a print level starting at which level it should be l...
stores all the informations relevant to an mpi environment