(git:fc9bb57)
Loading...
Searching...
No Matches
cp_cfm_elpa.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 Wrapper for ELPA (complex matrices, i.e. cp_cfm_type)
10! **************************************************************************************************
17 USE cp_cfm_types, ONLY: cp_cfm_create, &
24 USE cp_fm_elpa, ONLY: elpa_one_stage, &
35 USE machine, ONLY: m_cpuid_static, &
41 USE message_passing, ONLY: mp_comm_self, &
44 USE omp_lib, ONLY: omp_get_max_threads
47#if defined(__HAS_IEEE_EXCEPTIONS)
48 USE ieee_exceptions, ONLY: ieee_get_halting_mode, &
49 ieee_set_halting_mode, &
50 ieee_all
51#endif
52#include "../base/base_uses.f90"
53
54#if defined(__ELPA)
55 USE elpa_constants, ONLY: elpa_solver_1stage, elpa_solver_2stage, elpa_ok, &
56 elpa_2stage_complex_invalid, &
57 elpa_2stage_complex_default, &
58 elpa_2stage_complex_generic, &
59 elpa_2stage_complex_generic_simple, &
60 elpa_2stage_complex_bgp, &
61 elpa_2stage_complex_bgq, &
62 elpa_2stage_complex_sse_block1, &
63 elpa_2stage_complex_sse_block2, &
64 elpa_2stage_complex_avx_block1, &
65 elpa_2stage_complex_avx_block2, &
66 elpa_2stage_complex_avx2_block1, &
67 elpa_2stage_complex_avx2_block2, &
68 elpa_2stage_complex_avx512_block1, &
69 elpa_2stage_complex_avx512_block2, &
70 elpa_2stage_complex_nvidia_gpu, &
71 elpa_2stage_complex_amd_gpu, &
72 elpa_2stage_complex_intel_gpu_sycl
73
74 USE elpa, ONLY: elpa_t, &
75 elpa_allocate, elpa_deallocate
76#endif
77
78 IMPLICIT NONE
79
80 PRIVATE
81
82 CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'cp_cfm_elpa'
83
84#if defined(__ELPA)
85 INTEGER, DIMENSION(16), PARAMETER :: elpa_c_kernel_ids = [ &
86 elpa_2stage_complex_invalid, & ! auto
87 elpa_2stage_complex_generic, &
88 elpa_2stage_complex_generic_simple, &
89 elpa_2stage_complex_bgp, &
90 elpa_2stage_complex_bgq, &
91 elpa_2stage_complex_sse_block1, &
92 elpa_2stage_complex_sse_block2, &
93 elpa_2stage_complex_avx_block1, &
94 elpa_2stage_complex_avx_block2, &
95 elpa_2stage_complex_avx2_block1, &
96 elpa_2stage_complex_avx2_block2, &
97 elpa_2stage_complex_avx512_block1, &
98 elpa_2stage_complex_avx512_block2, &
99 elpa_2stage_complex_nvidia_gpu, &
100 elpa_2stage_complex_amd_gpu, &
101 elpa_2stage_complex_intel_gpu_sycl]
102
103 CHARACTER(len=14), DIMENSION(SIZE(elpa_c_kernel_ids)), PARAMETER :: &
104 elpa_c_kernel_names = [character(len=14) :: &
105 "AUTO", &
106 "GENERIC", &
107 "GENERIC_SIMPLE", &
108 "BGP", &
109 "BGQ", &
110 "SSE_BLOCK1", &
111 "SSE_BLOCK2", &
112 "AVX_BLOCK1", &
113 "AVX_BLOCK2", &
114 "AVX2_BLOCK1", &
115 "AVX2_BLOCK2", &
116 "AVX512_BLOCK1", &
117 "AVX512_BLOCK2", &
118 "NVIDIA_GPU", &
119 "AMD_GPU", &
120 "INTEL_GPU"]
121
122 CHARACTER(len=44), DIMENSION(SIZE(elpa_c_kernel_ids)), PARAMETER :: &
123 elpa_c_kernel_descriptions = [character(len=44) :: &
124 "Automatically selected kernel", &
125 "Generic kernel", &
126 "Simplified generic kernel", &
127 "Kernel optimized for IBM BGP", &
128 "Kernel optimized for IBM BGQ", &
129 "Kernel optimized for x86_64/SSE (block=1)", &
130 "Kernel optimized for x86_64/SSE (block=2)", &
131 "Kernel optimized for Intel AVX (block=1)", &
132 "Kernel optimized for Intel AVX (block=2)", &
133 "Kernel optimized for Intel AVX2 (block=1)", &
134 "Kernel optimized for Intel AVX2 (block=2)", &
135 "Kernel optimized for Intel AVX-512 (block=1)", &
136 "Kernel optimized for Intel AVX-512 (block=2)", &
137 "Kernel targeting Nvidia GPUs", &
138 "Kernel targeting AMD GPUs", &
139 "Kernel targeting Intel GPUs"]
140#else
141 INTEGER, DIMENSION(1), PARAMETER :: elpa_c_kernel_ids = [-1]
142 CHARACTER(len=14), DIMENSION(1), PARAMETER :: elpa_c_kernel_names = ["AUTO"]
143 CHARACTER(len=44), DIMENSION(1), PARAMETER :: elpa_c_kernel_descriptions = ["Automatically selected kernel"]
144#endif
145
146#if defined(__ELPA)
147 INTEGER, SAVE :: elpa_c_kernel = elpa_c_kernel_ids(1) ! auto
148#endif
149
150 ! Runtime correctness check state
151 LOGICAL, SAVE, PRIVATE :: elpa_c_correctness_checked = .false.
152 LOGICAL, SAVE, PRIVATE :: elpa_c_broken = .false.
153
154 PUBLIC :: cp_cfm_diag_elpa, &
158 elpa_c_kernel_ids, &
159 elpa_c_kernel_names, &
160 elpa_c_kernel_descriptions
161
162CONTAINS
163
164#if defined(__ELPA)
165! **************************************************************************************************
166!> \brief Return a printable name for an ELPA complex kernel.
167!> \param kernel ELPA complex kernel id
168!> \return ...
169! **************************************************************************************************
170 FUNCTION get_elpa_c_kernel_name(kernel) RESULT(kernel_name)
171 INTEGER, INTENT(IN) :: kernel
172 CHARACTER(len=default_string_length) :: kernel_name
173
174 INTEGER :: i
175
176 kernel_name = "id: "//trim(adjustl(cp_to_string(kernel)))
177 DO i = 1, SIZE(elpa_c_kernel_ids)
178 IF (elpa_c_kernel_ids(i) == kernel) THEN
179 kernel_name = elpa_c_kernel_names(i)
180 EXIT
181 END IF
182 END DO
183 END FUNCTION get_elpa_c_kernel_name
184#endif
185
186! **************************************************************************************************
187!> \brief Sets the active ELPA kernel for complex matrices.
188!> \param requested_kernel one of the elpa_c_kernel_ids
189! **************************************************************************************************
190 SUBROUTINE set_elpa_c_kernel(requested_kernel)
191 INTEGER, INTENT(IN) :: requested_kernel
192
193#if defined(__ELPA)
194 INTEGER :: cpuid
195
196 elpa_c_kernel = requested_kernel
197
198 ! Resolve AUTO kernel.
199 IF (elpa_c_kernel == elpa_2stage_complex_invalid) THEN
200 cpuid = m_cpuid_static()
201 SELECT CASE (cpuid)
203 elpa_c_kernel = elpa_2stage_complex_generic
204 CASE (machine_x86_sse4)
205 elpa_c_kernel = elpa_2stage_complex_sse_block2
206 CASE (machine_x86_avx)
207 elpa_c_kernel = elpa_2stage_complex_avx_block2
208 CASE (machine_x86_avx2)
209 elpa_c_kernel = elpa_2stage_complex_avx2_block2
210 CASE (machine_x86_avx512)
211 elpa_c_kernel = elpa_2stage_complex_avx512_block2
212 END SELECT
213
214 ! Prefer GPU kernel if available.
215#if !defined(__NO_OFFLOAD_ELPA)
216#if defined(__OFFLOAD_CUDA)
217 elpa_c_kernel = elpa_2stage_complex_nvidia_gpu
218#endif
219#if defined(__OFFLOAD_HIP)
220 elpa_c_kernel = elpa_2stage_complex_amd_gpu
221#endif
222#if defined(__OFFLOAD_OPENCL)
223 elpa_c_kernel = elpa_2stage_complex_intel_gpu_sycl
224#endif
225#endif
226 ! If we could not find a suitable kernel then use ELPA_2STAGE_COMPLEX_DEFAULT.
227 IF (elpa_c_kernel == elpa_2stage_complex_invalid) THEN
228 elpa_c_kernel = elpa_2stage_complex_default
229 END IF
230 END IF
231#else
232 mark_used(requested_kernel)
233#endif
234 END SUBROUTINE set_elpa_c_kernel
235
236#if defined(__ELPA)
237! **************************************************************************************************
238!> \brief Returns .TRUE. if the complex kernel is an SSE/AVX/AVX2/AVX512 BLOCK2 variant
239!> (these may be affected by the GCC 15.2 regression, marekandreas/elpa#77).
240!> \param kernel ...
241!> \return ...
242! **************************************************************************************************
243 FUNCTION is_block2_c_kernel(kernel) RESULT(is_block2)
244 INTEGER, INTENT(IN) :: kernel
245 LOGICAL :: is_block2
246
247 is_block2 = (kernel == elpa_2stage_complex_sse_block2) .OR. &
248 (kernel == elpa_2stage_complex_avx_block2) .OR. &
249 (kernel == elpa_2stage_complex_avx2_block2) .OR. &
250 (kernel == elpa_2stage_complex_avx512_block2)
251 END FUNCTION is_block2_c_kernel
252#endif
253
254! **************************************************************************************************
255!> \brief One-time runtime correctness check for ELPA complex BLOCK2 kernels.
256!> A small deterministic eigenproblem is solved on a single process with the
257!> same production routine used for the actual diagonalizations, and the
258!> eigenpair residual as well as the eigenvector orthogonality are verified.
259!> This guards against mis-compiled kernels (GCC 15.2 regression, marekandreas/elpa#77).
260!> If the check fails, a module flag is set such that cp_cfm_heevd falls back to ScaLAPACK.
261!> \param para_env communicator of the run, used to agree on the check result
262! **************************************************************************************************
264 TYPE(mp_para_env_type), INTENT(IN) :: para_env
265
266#if defined(__ELPA)
267 CHARACTER(LEN=*), PARAMETER :: routinen = 'check_elpa_c_kernel_correctness'
268 CHARACTER(LEN=4*default_string_length) :: message
269 INTEGER :: handle, i, is_broken, j
270 ! Geometry aligned with the standalone reproducer of marekandreas/elpa#77.
271 INTEGER, PARAMETER :: na_test = 20, nev_test = 18, nblk_test = 8
272 REAL(kind=dp) :: eps_ortho, eps_residual, rnd_im, rnd_re, test
273 REAL(kind=dp), PARAMETER :: th = 1.0e-8_dp
274 REAL(kind=dp), DIMENSION(:), ALLOCATABLE :: eigenvalues
275 TYPE(cp_blacs_env_type), POINTER :: context
276 TYPE(cp_cfm_type) :: eigenvectors, matrix, matrix_ref
277 TYPE(cp_fm_redistribute_info) :: rdinfo
278 TYPE(cp_fm_struct_type), POINTER :: fmstruct
279 TYPE(mp_para_env_type) :: para_env_self
280 TYPE(rng_stream_type) :: rng_stream
281
282 IF (elpa_c_correctness_checked) RETURN ! one-shot per process
283
284 IF (.NOT. is_block2_c_kernel(elpa_c_kernel)) RETURN ! only BLOCK2 kernels are affected
285 IF (elpa_one_stage) RETURN ! the 1-stage solver does not use kernels
286 elpa_c_correctness_checked = .true.
287
288 CALL timeset(routinen, handle)
289
290 ! Solve a small deterministic Hermitian eigenproblem redundantly on every process,
291 ! reusing the production ELPA path (kernel setup, fallbacks and solver call).
292 para_env_self = mp_comm_self
293 CALL cp_blacs_env_create(context, para_env_self)
294 CALL cp_fm_struct_create(fmstruct, para_env=para_env_self, context=context, &
295 nrow_global=na_test, ncol_global=na_test, &
296 nrow_block=nblk_test, ncol_block=nblk_test)
297 CALL cp_cfm_create(matrix, fmstruct, name="elpa_check_mat")
298 CALL cp_cfm_create(matrix_ref, fmstruct, name="elpa_check_ref")
299 CALL cp_cfm_create(eigenvectors, fmstruct, name="elpa_check_vec")
300
301 ! Fill with a dense random Hermitian matrix; the RNG stream starts from the
302 ! library default seed, hence the matrix is identical on all processes.
303 rng_stream = rng_stream_type(name="elpa_kernel_correctness", distribution_type=uniform)
304 DO j = 1, na_test
305 DO i = 1, j - 1
306 rnd_re = 2.0_dp*rng_stream%next() - 1.0_dp
307 rnd_im = 2.0_dp*rng_stream%next() - 1.0_dp
308 matrix%local_data(i, j) = cmplx(rnd_re, rnd_im, kind=dp)
309 matrix%local_data(j, i) = conjg(matrix%local_data(i, j))
310 END DO
311 rnd_re = 2.0_dp*rng_stream%next() - 1.0_dp
312 matrix%local_data(j, j) = cmplx(rnd_re, 0.0_dp, kind=dp)
313 END DO
314 CALL cp_cfm_to_cfm(matrix, matrix_ref) ! the solver destroys its input matrix
315
316 ALLOCATE (eigenvalues(nev_test))
317 CALL cp_cfm_diag_elpa_base(matrix, eigenvectors, eigenvalues, rdinfo)
318
319 ! Check the orthogonality of the eigenvectors, |Z^H*Z - I|
320 CALL cp_cfm_gemm("C", "N", nev_test, nev_test, na_test, (1.0_dp, 0.0_dp), &
321 eigenvectors, eigenvectors, (0.0_dp, 0.0_dp), matrix)
322 eps_ortho = 0.0_dp
323 outer_ortho: DO i = 1, nev_test
324 DO j = 1, nev_test
325 test = abs(matrix%local_data(i, j))
326 IF (i == j) test = abs(matrix%local_data(i, j) - (1.0_dp, 0.0_dp))
327 IF (test > eps_ortho) eps_ortho = test
328 IF (eps_ortho > th) EXIT outer_ortho
329 END DO
330 END DO outer_ortho
331
332 ! Check the eigenpair residuals, |A*Z - Z*diag(eigenvalues)|
333 CALL cp_cfm_gemm("N", "N", na_test, nev_test, na_test, (1.0_dp, 0.0_dp), &
334 matrix_ref, eigenvectors, (0.0_dp, 0.0_dp), matrix)
335 eps_residual = 0.0_dp
336 outer_res: DO i = 1, na_test
337 DO j = 1, nev_test
338 test = abs(matrix%local_data(i, j) - eigenvectors%local_data(i, j)*eigenvalues(j))
339 IF (test > eps_residual) eps_residual = test
340 IF (eps_residual > th) EXIT outer_res
341 END DO
342 END DO outer_res
343
344 ! Mis-compiled kernels produce grossly wrong results (deviations ~1e-1), not subtle rounding.
345 elpa_c_broken = (eps_ortho > th) .OR. (eps_residual > th)
346
347 ! Agree on the result to guarantee a consistent fallback on all processes.
348 is_broken = 0
349 IF (elpa_c_broken) is_broken = 1
350 CALL para_env%max(is_broken)
351 elpa_c_broken = is_broken == 1
352 IF (elpa_c_broken) THEN
353 message = "The ELPA complex kernel "//trim(get_elpa_c_kernel_name(elpa_c_kernel))// &
354 " failed a runtime correctness check (orthogonality: "//trim(cp_to_string(eps_ortho))// &
355 ", residual: "//trim(cp_to_string(eps_residual))//") and may return incorrect"// &
356 " eigenvectors. Complex matrices fall back to ScaLAPACK. Consider the GENERIC"// &
357 " kernel or rebuilding ELPA with -fno-tree-slp-vectorize."
358 CALL cp_warn(__location__, trim(message))
359 END IF
360
361 DEALLOCATE (eigenvalues)
362 CALL cp_cfm_release(eigenvectors)
363 CALL cp_cfm_release(matrix_ref)
364 CALL cp_cfm_release(matrix)
365 CALL cp_fm_struct_release(fmstruct)
366 CALL cp_blacs_env_release(context)
367
368 CALL timestop(handle)
369#else
370 mark_used(para_env)
371#endif
373
374! **************************************************************************************************
375!> \brief Returns .TRUE. if the runtime check detected broken BLOCK2 kernels.
376!> \return ...
377! **************************************************************************************************
378 FUNCTION is_elpa_c_broken() RESULT(broken)
379 LOGICAL :: broken
380
381 broken = elpa_c_broken
382 END FUNCTION is_elpa_c_broken
383
384! **************************************************************************************************
385!> \brief Driver routine to diagonalize a CFM matrix with the ELPA library.
386!> \param matrix the matrix that is diagonalized
387!> \param eigenvectors eigenvectors of the input matrix
388!> \param eigenvalues eigenvalues of the input matrix
389! **************************************************************************************************
390 SUBROUTINE cp_cfm_diag_elpa(matrix, eigenvectors, eigenvalues)
391 TYPE(cp_cfm_type), INTENT(IN) :: matrix, eigenvectors
392 REAL(kind=dp), DIMENSION(:), INTENT(OUT) :: eigenvalues
393
394#if defined(__ELPA)
395 CHARACTER(len=*), PARAMETER :: routinen = 'cp_cfm_diag_elpa'
396
397 INTEGER :: handle
398 TYPE(cp_cfm_type) :: eigenvectors_new, matrix_new
399 TYPE(cp_fm_redistribute_info) :: rdinfo
400
401 CALL timeset(routinen, handle)
402
403 ! Determine if the input matrix needs to be redistributed before diagonalization.
404 ! Heuristics are used to determine the optimal number of CPUs for diagonalization.
405 ! The redistributed matrix is stored in matrix_new, which is just a pointer
406 ! to the original matrix if no redistribution is required.
407 ! With ELPA, we have to make sure that all processor columns have nonzero width
408 CALL cp_cfm_redistribute_start(matrix, eigenvectors, matrix_new, eigenvectors_new, &
409 caller_is_elpa=.true., redist_info=rdinfo)
410
411 ! Call ELPA on CPUs that hold the new matrix
412 IF (ASSOCIATED(matrix_new%matrix_struct)) THEN
413 CALL cp_cfm_diag_elpa_base(matrix_new, eigenvectors_new, eigenvalues, rdinfo)
414 END IF
415
416 ! Redistribute results and clean up
417 CALL cp_cfm_redistribute_end(matrix, eigenvectors, eigenvalues, matrix_new, eigenvectors_new)
418
419 CALL timestop(handle)
420#else
421 eigenvalues = 0
422 mark_used(matrix)
423 mark_used(eigenvectors)
424
425 cpabort("CP2K compiled without the ELPA library.")
426#endif
427 END SUBROUTINE cp_cfm_diag_elpa
428
429#if defined(__ELPA)
430! **************************************************************************************************
431!> \brief Actual routine that calls ELPA to diagonalize a CFM matrix.
432!> \param matrix the matrix that is diagonalized
433!> \param eigenvectors eigenvectors of the input matrix
434!> \param eigenvalues eigenvalues of the input matrix
435!> \param rdinfo ...
436! **************************************************************************************************
437 SUBROUTINE cp_cfm_diag_elpa_base(matrix, eigenvectors, eigenvalues, rdinfo)
438
439 TYPE(cp_cfm_type), INTENT(IN) :: matrix, eigenvectors
440 REAL(kind=dp), DIMENSION(:), INTENT(OUT) :: eigenvalues
441 TYPE(cp_fm_redistribute_info), INTENT(IN) :: rdinfo
442
443 CHARACTER(len=*), PARAMETER :: routinen = 'cp_cfm_diag_elpa_base'
444
445 INTEGER :: handle
446
447 CLASS(elpa_t), POINTER :: elpa_obj
448 CHARACTER(len=default_string_length) :: kernel_name
449 CHARACTER(len=2*default_string_length) :: message
450 TYPE(mp_comm_type) :: group
451 INTEGER :: fallback_kernel, &
452 mypcol, myprow, n, &
453 n_rows, n_cols, &
454 nblk, neig, io_unit, &
455 success
456 REAL(kind=dp), DIMENSION(:), ALLOCATABLE :: eval
457 TYPE(cp_blacs_env_type), POINTER :: context
458 TYPE(cp_logger_type), POINTER :: logger
459 INTEGER, DIMENSION(:), POINTER :: ncol_locals
460#if defined(__HAS_IEEE_EXCEPTIONS)
461 LOGICAL, DIMENSION(5) :: halt
462#endif
463
464 CALL timeset(routinen, handle)
465 NULLIFY (logger)
466 NULLIFY (ncol_locals)
467
468 logger => cp_get_default_logger()
469 io_unit = cp_logger_get_default_io_unit(logger)
470
471 n = matrix%matrix_struct%nrow_global
472 context => matrix%matrix_struct%context
473 group = matrix%matrix_struct%para_env
474
475 myprow = context%mepos(1)
476 mypcol = context%mepos(2)
477
478 ! elpa needs the full matrix
479 CALL cp_cfm_uplo_to_full(matrix, eigenvectors)
480
481 CALL cp_fm_struct_get(matrix%matrix_struct, &
482 local_leading_dimension=n_rows, &
483 ncol_local=n_cols, &
484 nrow_block=nblk, &
485 ncol_locals=ncol_locals)
486
487 ! ELPA will fail in 'solve_tridi', with no useful error message, fail earlier
488 IF (io_unit > 0 .AND. any(ncol_locals == 0)) THEN
489 CALL rdinfo%write(io_unit)
490 cpabort("ELPA [pre-fail]: Problem contains processor column with zero width.")
491 END IF
492
493 neig = SIZE(eigenvalues, 1)
494 ! ELPA's QR decomposition is only available for real matrices
495
496 IF (io_unit > 0 .AND. elpa_print) THEN
497 WRITE (unit=io_unit, fmt="(/,T2,A)") &
498 "ELPA| Matrix diagonalization information"
499
500 kernel_name = get_elpa_c_kernel_name(elpa_c_kernel)
501
502 WRITE (unit=io_unit, fmt="(T2,A,T71,I10)") &
503 "ELPA| Matrix order (NA) ", n, &
504 "ELPA| Matrix block size (NBLK) ", nblk, &
505 "ELPA| Number of eigenvectors (NEV) ", neig, &
506 "ELPA| Local rows (LOCAL_NROWS) ", n_rows, &
507 "ELPA| Local columns (LOCAL_NCOLS) ", n_cols
508 WRITE (unit=io_unit, fmt="(T2,A,T61,A20)") &
509 "ELPA| Kernel ", adjustr(trim(kernel_name))
510 END IF
511
512 ! the full eigenvalues vector is needed
513 ALLOCATE (eval(n))
514
515 elpa_obj => elpa_allocate()
516
517 CALL elpa_obj%set("na", n, success)
518 cpassert(success == elpa_ok)
519
520 CALL elpa_obj%set("nev", neig, success)
521 cpassert(success == elpa_ok)
522
523 CALL elpa_obj%set("local_nrows", n_rows, success)
524 cpassert(success == elpa_ok)
525
526 CALL elpa_obj%set("local_ncols", n_cols, success)
527 cpassert(success == elpa_ok)
528
529 CALL elpa_obj%set("nblk", nblk, success)
530 cpassert(success == elpa_ok)
531
532 CALL elpa_obj%set("mpi_comm_parent", group%get_handle(), success)
533 cpassert(success == elpa_ok)
534
535 CALL elpa_obj%set("process_row", myprow, success)
536 cpassert(success == elpa_ok)
537
538 CALL elpa_obj%set("process_col", mypcol, success)
539 cpassert(success == elpa_ok)
540
541 success = elpa_obj%setup()
542 cpassert(success == elpa_ok)
543
544 CALL elpa_obj%set("solver", &
545 merge(elpa_solver_1stage, elpa_solver_2stage, elpa_one_stage), &
546 success)
547 IF (success /= elpa_ok) THEN
548 cpabort("Setting solver for ELPA failed")
549 END IF
550
551 ! enabling the GPU must happen before setting the kernel
552 SELECT CASE (elpa_c_kernel)
553 CASE (elpa_2stage_complex_nvidia_gpu)
554 CALL elpa_obj%set("nvidia-gpu", 1, success)
555 cpassert(success == elpa_ok)
556 CASE (elpa_2stage_complex_amd_gpu)
557 CALL elpa_obj%set("amd-gpu", 1, success)
558 cpassert(success == elpa_ok)
559 CASE (elpa_2stage_complex_intel_gpu_sycl)
560 CALL elpa_obj%set("intel-gpu", 1, success)
561 cpassert(success == elpa_ok)
562 END SELECT
563
564 IF (.NOT. elpa_one_stage) THEN
565 ! Keep ELPA's configured default in case the requested kernel is unavailable.
566 CALL elpa_obj%get("complex_kernel", fallback_kernel, success)
567 cpassert(success == elpa_ok)
568
569 CALL elpa_obj%set("complex_kernel", elpa_c_kernel, success)
570 IF (success /= elpa_ok) THEN
571 message = "Requested ELPA complex kernel "//trim(get_elpa_c_kernel_name(elpa_c_kernel))// &
572 " is unavailable; falling back to "//trim(get_elpa_c_kernel_name(fallback_kernel))
573 CALL cp_warn(__location__, trim(message))
574 CALL elpa_obj%set("complex_kernel", fallback_kernel, success)
575 cpassert(success == elpa_ok)
576 ! Avoid retrying the unavailable kernel for every subsequent diagonalization.
577 elpa_c_kernel = fallback_kernel
578 END IF
579 END IF
580
581 ! Set number of threads only when ELPA was built with OpenMP support.
582 IF (elpa_obj%can_set("omp_threads", omp_get_max_threads()) == elpa_ok) THEN
583 CALL elpa_obj%set("omp_threads", omp_get_max_threads(), success)
584 cpassert(success == elpa_ok)
585 END IF
586
587 ! ELPA solver: calculate the Eigenvalues/vectors
588#if defined(__HAS_IEEE_EXCEPTIONS)
589 CALL ieee_get_halting_mode(ieee_all, halt)
590 CALL ieee_set_halting_mode(ieee_all, .false.)
591#endif
592 CALL elpa_obj%eigenvectors(matrix%local_data, eval, eigenvectors%local_data, success)
593#if defined(__HAS_IEEE_EXCEPTIONS)
594 CALL ieee_set_halting_mode(ieee_all, halt)
595#endif
596
597 IF (success /= elpa_ok) THEN
598 cpabort("ELPA failed to diagonalize a matrix")
599 END IF
600
601 CALL elpa_deallocate(elpa_obj, success)
602 cpassert(success == elpa_ok)
603
604 eigenvalues(1:neig) = eval(1:neig)
605 DEALLOCATE (eval)
606
607 CALL timestop(handle)
608
609 END SUBROUTINE cp_cfm_diag_elpa_base
610#endif
611
612END MODULE cp_cfm_elpa
Target architecture or instruction set extension according to compiler target flags.
Definition machine.F:90
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
Basic linear algebra operations for complex full matrices.
subroutine, public cp_cfm_gemm(transa, transb, m, n, k, alpha, matrix_a, matrix_b, beta, matrix_c, a_first_col, a_first_row, b_first_col, b_first_row, c_first_col, c_first_row)
Performs one of the matrix-matrix operations: matrix_c = alpha * op1( matrix_a ) * op2( matrix_b ) + ...
subroutine, public cp_cfm_uplo_to_full(matrix, workspace, uplo)
...
Wrapper for ELPA (complex matrices, i.e. cp_cfm_type)
Definition cp_cfm_elpa.F:11
subroutine, public cp_cfm_diag_elpa(matrix, eigenvectors, eigenvalues)
Driver routine to diagonalize a CFM matrix with the ELPA library.
subroutine, public check_elpa_c_kernel_correctness(para_env)
One-time runtime correctness check for ELPA complex BLOCK2 kernels. A small deterministic eigenproble...
subroutine, public set_elpa_c_kernel(requested_kernel)
Sets the active ELPA kernel for complex matrices.
logical function, public is_elpa_c_broken()
Returns .TRUE. if the runtime check detected broken BLOCK2 kernels.
Represents a complex full matrix distributed on many processors.
subroutine, public cp_cfm_release(matrix)
Releases a full matrix.
subroutine, public cp_cfm_create(matrix, matrix_struct, name, nrow, ncol, set_zero)
Creates a new full matrix with the given structure.
Auxiliary tools to redistribute cp_fm_type and cp_cfm_type matrices before and after diagonalization....
subroutine, public cp_cfm_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_cfm_redistribute_end(matrix, eigenvectors, eig, matrix_new, eigenvectors_new)
Redistributes eigenvectors and eigenvalues back to the original communicator group.
Wrapper for ELPA.
Definition cp_fm_elpa.F:12
logical, save, public elpa_print
Definition cp_fm_elpa.F:161
logical, save, public elpa_one_stage
Definition cp_fm_elpa.F:168
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_get(fmstruct, para_env, context, descriptor, ncol_block, nrow_block, nrow_global, ncol_global, first_p_pos, row_indices, col_indices, nrow_local, ncol_local, nrow_locals, ncol_locals, local_leading_dimension)
returns the values of various attributes of the matrix structure
subroutine, public cp_fm_struct_release(fmstruct)
releases a full matrix 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
integer, parameter, public default_string_length
Definition kinds.F:57
Machine interface based on Fortran 2003 and POSIX.
Definition machine.F:17
integer, parameter, public machine_x86_avx
Definition machine.F:57
integer, parameter, public machine_x86_sse4
Definition machine.F:57
integer, parameter, public machine_cpu_generic
Definition machine.F:57
integer, parameter, public machine_x86_avx2
Definition machine.F:57
integer, parameter, public machine_x86_avx512
Definition machine.F:57
Interface to the message passing library MPI.
type(mp_comm_type), parameter, public mp_comm_self
Parallel (pseudo)random number generator (RNG) for multiple streams and substreams of random numbers.
integer, parameter, public uniform
represent a blacs multidimensional parallel environment (for the mpi corrispective see cp_paratypes/m...
Represent a complex full matrix.
keeps the information about the structure of a full matrix
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