Line data Source code
1 : ! This file is part of ELPA.
2 : !
3 : ! The ELPA library was originally created by the ELPA consortium,
4 : ! consisting of the following organizations:
5 : !
6 : ! - Rechenzentrum Garching der Max-Planck-Gesellschaft (RZG),
7 : ! - Bergische Universität Wuppertal, Lehrstuhl für angewandte
8 : ! Informatik,
9 : ! - Technische Universität München, Lehrstuhl für Informatik mit
10 : ! Schwerpunkt Wissenschaftliches Rechnen ,
11 : ! - Fritz-Haber-Institut, Berlin, Abt. Theorie,
12 : ! - Max-Plack-Institut für Mathematik in den Naturwissenschaften,
13 : ! Leipzig, Abt. Komplexe Strukutren in Biologie und Kognition,
14 : ! and
15 : ! - IBM Deutschland GmbH
16 : !
17 : ! This particular source code file contains additions, changes and
18 : ! enhancements authored by Intel Corporation which is not part of
19 : ! the ELPA consortium.
20 : !
21 : ! More information can be found here:
22 : ! http://elpa.mpcdf.mpg.de/
23 : !
24 : ! ELPA is free software: you can redistribute it and/or modify
25 : ! it under the terms of the version 3 of the license of the
26 : ! GNU Lesser General Public License as published by the Free
27 : ! Software Foundation.
28 : !
29 : ! ELPA is distributed in the hope that it will be useful,
30 : ! but WITHOUT ANY WARRANTY; without even the implied warranty of
31 : ! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
32 : ! GNU Lesser General Public License for more details.
33 : !
34 : ! You should have received a copy of the GNU Lesser General Public License
35 : ! along with ELPA. If not, see <http://www.gnu.org/licenses/>
36 : !
37 : ! ELPA reflects a substantial effort on the part of the original
38 : ! ELPA consortium, and we ask you to respect the spirit of the
39 : ! license that we chose: i.e., please contribute any changes you
40 : ! may have back to the original ELPA library distribution, and keep
41 : ! any derivatives of ELPA under the same license that we chose for
42 : ! the original distribution, the GNU Lesser General Public License.
43 : !
44 : !
45 : ! ELPA1 -- Faster replacements for ScaLAPACK symmetric eigenvalue routines
46 : !
47 : ! Copyright of the original code rests with the authors inside the ELPA
48 : ! consortium. The copyright of any additional modifications shall rest
49 : ! with their original authors, but shall adhere to the licensing terms
50 : ! distributed along with the original code in the file "COPYING".
51 : !
52 : ! writen by A. Marek (MPCDF), andreas.marek@mpcdf.mpg.de
53 :
54 : #include "config-f90.h"
55 : !> \brief Fortran module which provides the routines to the ELPA solver (1 and 2 stage). This is the LEGACY interface. Do not use anymore!
56 : module elpa_driver
57 : use, intrinsic :: iso_c_binding, only : c_double, c_int, c_float, c_float_complex, c_double_complex
58 : use elpa1
59 : use elpa2
60 :
61 : implicit none
62 :
63 : public :: elpa_solve_evp_real_double, elpa_solve_evp_complex_double
64 : #ifdef WANT_SINGLE_PRECISION_REAL
65 : public :: elpa_solve_evp_real_single
66 : #endif
67 : #ifdef WANT_SINGLE_PRECISION_COMPLEX
68 : public :: elpa_solve_evp_complex_single
69 : #endif
70 :
71 :
72 : contains
73 : !-------------------------------------------------------------------------------
74 : !> \brief solve_evp_real_double: Fortran function to solve the real eigenvalue
75 : !> problem with either the ELPA 1stage or the ELPA 2stage solver
76 : !>
77 : !> Parameters
78 : !>
79 : !> \param na Order of matrix a
80 : !>
81 : !> \param nev Number of eigenvalues needed
82 : !>
83 : !> \param a(lda,matrixCols) Distributed matrix for which eigenvalues are to be computed.
84 : !> Distribution is like in Scalapack.
85 : !> The full matrix must be set (not only one half like in scalapack).
86 : !> Destroyed on exit (upper and lower half).
87 : !>
88 : !> \param lda Leading dimension of a
89 : !>
90 : !> \param ev(na) On output: eigenvalues of a, every processor gets the complete set
91 : !>
92 : !> \param q(ldq,matrixCols) On output: Eigenvectors of a
93 : !> Distribution is like in Scalapack.
94 : !> Must be always dimensioned to the full size (corresponding to (na,na))
95 : !> even if only a part of the eigenvalues is needed.
96 : !>
97 : !> \param ldq Leading dimension of q
98 : !>
99 : !> \param nblk blocksize of cyclic distribution, must be the same in both directions!
100 : !>
101 : !> \param matrixCols local columns of matrix a and q
102 : !>
103 : !> \param mpi_comm_rows MPI communicator for rows
104 : !> \param mpi_comm_cols MPI communicator for columns
105 : !> \param mpi_comm_all MPI communicator for the total processor set
106 : !>
107 : !> \param THIS_REAL_ELPA_KERNEL_API (optional) specify used ELPA 2stage
108 : !> kernel via API (only evalulated if 2 stage solver is used_
109 : !>
110 : !> \param use_qr (optional) use QR decomposition in the ELPA 2stage solver
111 : !> \param useGPU (optional) use GPU version of ELPA 1stage
112 : !>
113 : !> \param method choose whether to use ELPA 1stage or 2stage solver
114 : !> possible values: "1stage" => use ELPA 1stage solver
115 : !> "2stage" => use ELPA 2stage solver
116 : !> "auto" => (at the moment) use ELPA 2stage solver
117 : !>
118 : !> \result success logical, false if error occured
119 : !-------------------------------------------------------------------------------
120 3456 : function elpa_solve_evp_real_double(na, nev, a, lda, ev, q, ldq, nblk, &
121 : matrixCols, mpi_comm_rows, mpi_comm_cols, &
122 : mpi_comm_all, THIS_REAL_ELPA_KERNEL_API, &
123 : useQR, useGPU, method) result(success)
124 : use iso_c_binding
125 : use elpa_utilities
126 : implicit none
127 : integer(kind=c_int), intent(in) :: na, nev, lda, ldq, matrixCols, mpi_comm_rows, &
128 : mpi_comm_cols, mpi_comm_all
129 : integer(kind=c_int), intent(in) :: nblk
130 : real(kind=c_double), intent(inout) :: ev(na)
131 : #ifdef USE_ASSUMED_SIZE
132 : real(kind=c_double), intent(inout) :: a(lda,*), q(ldq,*)
133 : #else
134 : real(kind=c_double), intent(inout) :: a(lda,matrixCols), q(ldq,matrixCols)
135 : #endif
136 : logical, intent(in), optional :: useQR, useGPU
137 : integer(kind=c_int), intent(in), optional :: THIS_REAL_ELPA_KERNEL_API
138 : character(*), intent(in), optional :: method
139 :
140 : logical :: useELPA1
141 : logical :: success
142 :
143 1728 : useELPA1 = .false.
144 :
145 1728 : if (present(method)) then
146 1728 : if (trim(method) .eq. "1stage" .or. trim(method) .eq. "1STAGE") then
147 576 : useELPA1 = .true.
148 1152 : else if (trim(method) .eq. "2stage" .or. trim(method) .eq. "2STAGE") then
149 576 : useELPA1 = .false.
150 576 : else if (trim(method) .eq. "auto" .or. trim(method) .eq. "AUTO") then
151 576 : useELPA1 = .false.
152 : else
153 0 : write(error_unit,*) "Specified method not known! Using ELPA 2-stage"
154 0 : useELPA1 = .false.
155 : endif
156 : endif
157 :
158 1728 : if (useELPA1) then
159 : success = elpa_solve_evp_real_1stage_double(na, nev, a, lda, ev, q, ldq, nblk, &
160 : matrixCols, mpi_comm_rows, mpi_comm_cols, mpi_comm_all, &
161 576 : useGPU)
162 : else
163 : success = elpa_solve_evp_real_2stage_double(na, nev, a, lda, ev, q, ldq, nblk, &
164 : matrixCols, mpi_comm_rows, mpi_comm_cols, &
165 : mpi_comm_all, &
166 : THIS_REAL_ELPA_KERNEL_API, &
167 1152 : useQR, useGPU)
168 : endif
169 :
170 3456 : end function elpa_solve_evp_real_double
171 :
172 : #ifdef WANT_SINGLE_PRECISION_REAL
173 : !-------------------------------------------------------------------------------
174 : !> \brief solve_evp_real_single: Fortran function to solve the real eigenvalue
175 : !> problem with either the ELPA 1stage or the ELPA 2stage solver
176 : !>
177 : !> Parameters
178 : !>
179 : !> \param na Order of matrix a
180 : !>
181 : !> \param nev Number of eigenvalues needed
182 : !>
183 : !> \param a(lda,matrixCols) Distributed matrix for which eigenvalues are to be computed.
184 : !> Distribution is like in Scalapack.
185 : !> The full matrix must be set (not only one half like in scalapack).
186 : !> Destroyed on exit (upper and lower half).
187 : !>
188 : !> \param lda Leading dimension of a
189 : !>
190 : !> \param ev(na) On output: eigenvalues of a, every processor gets the complete set
191 : !>
192 : !> \param q(ldq,matrixCols) On output: Eigenvectors of a
193 : !> Distribution is like in Scalapack.
194 : !> Must be always dimensioned to the full size (corresponding to (na,na))
195 : !> even if only a part of the eigenvalues is needed.
196 : !>
197 : !> \param ldq Leading dimension of q
198 : !>
199 : !> \param nblk blocksize of cyclic distribution, must be the same in both directions!
200 : !>
201 : !> \param matrixCols local columns of matrix a and q
202 : !>
203 : !> \param mpi_comm_rows MPI communicator for rows
204 : !> \param mpi_comm_cols MPI communicator for columns
205 : !> \param mpi_comm_all MPI communicator for the total processor set
206 : !>
207 : !> \param THIS_REAL_ELPA_KERNEL_API (optional) specify used ELPA 2stage
208 : !> kernel via API (only evalulated if 2 stage solver is used_
209 : !>
210 : !> \param use_qr (optional) use QR decomposition in the ELPA 2stage solver
211 : !> \param useGPU (optional) use GPU version of ELPA 1stage
212 : !>
213 : !> \param method choose whether to use ELPA 1stage or 2stage solver
214 : !> possible values: "1stage" => use ELPA 1stage solver
215 : !> "2stage" => use ELPA 2stage solver
216 : !> "auto" => (at the moment) use ELPA 2stage solver
217 : !>
218 : !> \result success logical, false if error occured
219 : !-------------------------------------------------------------------------------
220 1728 : function elpa_solve_evp_real_single(na, nev, a, lda, ev, q, ldq, nblk, &
221 : matrixCols, mpi_comm_rows, mpi_comm_cols, &
222 : mpi_comm_all, THIS_REAL_ELPA_KERNEL_API, &
223 : useQR, useGPU, method) result(success)
224 : use iso_c_binding
225 : use elpa_utilities
226 : implicit none
227 : integer(kind=c_int), intent(in) :: na, nev, lda, ldq, matrixCols, mpi_comm_rows, &
228 : mpi_comm_cols, mpi_comm_all
229 : integer(kind=c_int), intent(in) :: nblk
230 : real(kind=c_float), intent(inout ) :: ev(na)
231 : #ifdef USE_ASSUMED_SIZE
232 : real(kind=c_float), intent(inout) :: a(lda,*), q(ldq,*)
233 : #else
234 : real(kind=c_float), intent(inout) :: a(lda,matrixCols), q(ldq,matrixCols)
235 : #endif
236 : logical, intent(in), optional :: useQR, useGPU
237 : integer(kind=c_int), intent(in), optional :: THIS_REAL_ELPA_KERNEL_API
238 : character(*), intent(in), optional :: method
239 :
240 : logical :: useELPA1
241 : logical :: success
242 :
243 864 : useELPA1 = .false.
244 :
245 864 : if (present(method)) then
246 864 : if (trim(method) .eq. "1stage" .or. trim(method) .eq. "1STAGE") then
247 288 : useELPA1 = .true.
248 576 : else if (trim(method) .eq. "2stage" .or. trim(method) .eq. "2STAGE") then
249 288 : useELPA1 = .false.
250 288 : else if (trim(method) .eq. "auto" .or. trim(method) .eq. "AUTO") then
251 288 : useELPA1 = .false.
252 : else
253 0 : write(error_unit,*) "Specified method not known! Using ELPA 2-stage"
254 0 : useELPA1 = .false.
255 : endif
256 : endif
257 :
258 864 : if (useELPA1) then
259 : success = elpa_solve_evp_real_1stage_single(na, nev, a, lda, ev, q, ldq, nblk, &
260 : matrixCols, mpi_comm_rows, mpi_comm_cols, mpi_comm_all, &
261 288 : useGPU)
262 : else
263 : success = elpa_solve_evp_real_2stage_single(na, nev, a, lda, ev, q, ldq, nblk, &
264 : matrixCols, mpi_comm_rows, mpi_comm_cols, &
265 : mpi_comm_all, &
266 : THIS_REAL_ELPA_KERNEL_API, &
267 576 : useQR, useGPU)
268 : endif
269 :
270 1728 : end function elpa_solve_evp_real_single
271 : #endif /* WANT_SINGLE_PRECISION_REAL */
272 :
273 : !-------------------------------------------------------------------------------
274 : !> \brief solve_evp_complex_double: Fortran function to solve the complex eigenvalue
275 : !> problem with either the ELPA 1stage or the ELPA 2stage solver
276 : !>
277 : !> Parameters
278 : !>
279 : !> \param na Order of matrix a
280 : !>
281 : !> \param nev Number of eigenvalues needed
282 : !>
283 : !> \param a(lda,matrixCols) Distributed matrix for which eigenvalues are to be computed.
284 : !> Distribution is like in Scalapack.
285 : !> The full matrix must be set (not only one half like in scalapack).
286 : !> Destroyed on exit (upper and lower half).
287 : !>
288 : !> \param lda Leading dimension of a
289 : !>
290 : !> \param ev(na) On output: eigenvalues of a, every processor gets the complete set
291 : !>
292 : !> \param q(ldq,matrixCols) On output: Eigenvectors of a
293 : !> Distribution is like in Scalapack.
294 : !> Must be always dimensioned to the full size (corresponding to (na,na))
295 : !> even if only a part of the eigenvalues is needed.
296 : !>
297 : !> \param ldq Leading dimension of q
298 : !>
299 : !> \param nblk blocksize of cyclic distribution, must be the same in both directions!
300 : !>
301 : !> \param matrixCols local columns of matrix a and q
302 : !>
303 : !> \param mpi_comm_rows MPI communicator for rows
304 : !> \param mpi_comm_cols MPI communicator for columns
305 : !> \param mpi_comm_all MPI communicator for the total processor set
306 : !>
307 : !> \param THIS_REAL_COMPLEX_KERNEL_API (optional) specify used ELPA 2stage
308 : !> kernel via API (only evalulated if 2 stage solver is used
309 : !> \param useGPU (optional) use GPU version of ELPA 1stage
310 : !>
311 : !> \param method choose whether to use ELPA 1stage or 2stage solver
312 : !> possible values: "1stage" => use ELPA 1stage solver
313 : !> "2stage" => use ELPA 2stage solver
314 : !> "auto" => (at the moment) use ELPA 2stage solver
315 : !>
316 : !> \result success logical, false if error occured
317 : !-------------------------------------------------------------------------------
318 3456 : function elpa_solve_evp_complex_double(na, nev, a, lda, ev, q, ldq, nblk, &
319 : matrixCols, mpi_comm_rows, mpi_comm_cols, &
320 : mpi_comm_all, THIS_COMPLEX_ELPA_KERNEL_API, &
321 : useGPU, method) result(success)
322 : use iso_c_binding
323 : use elpa_utilities
324 :
325 : implicit none
326 : integer(kind=c_int), intent(in) :: na, nev, lda, ldq, matrixCols, mpi_comm_rows, &
327 : mpi_comm_cols, mpi_comm_all
328 : integer(kind=c_int), intent(in) :: nblk
329 : real(kind=c_double), intent(inout) :: ev(na)
330 : #ifdef USE_ASSUMED_SIZE
331 : complex(kind=c_double_complex), intent(inout) :: a(lda,*), q(ldq,*)
332 : #else
333 : complex(kind=c_double_complex), intent(inout) :: a(lda,matrixCols), q(ldq,matrixCols)
334 : #endif
335 : integer(kind=c_int), intent(in), optional :: THIS_COMPLEX_ELPA_KERNEL_API
336 : logical, intent(in), optional :: useGPU
337 : character(*), intent(in), optional :: method
338 :
339 : logical :: useELPA1
340 : logical :: success
341 :
342 1728 : useELPA1 = .false.
343 :
344 1728 : if (present(method)) then
345 1728 : if (trim(method) .eq. "1stage" .or. trim(method) .eq. "1STAGE") then
346 576 : useELPA1 = .true.
347 1152 : else if (trim(method) .eq. "2stage" .or. trim(method) .eq. "2STAGE") then
348 576 : useELPA1 = .false.
349 576 : else if (trim(method) .eq. "auto" .or. trim(method) .eq. "AUTO") then
350 576 : useELPA1 = .false.
351 : else
352 0 : write(error_unit,*) "Specified method not known! Using ELPA 2-stage"
353 0 : useELPA1 = .false.
354 : endif
355 : endif
356 :
357 1728 : if (useELPA1) then
358 : success = elpa_solve_evp_complex_1stage_double(na, nev, a, lda, ev, q, ldq, nblk, &
359 : matrixCols, mpi_comm_rows, mpi_comm_cols, mpi_comm_all, &
360 576 : useGPU)
361 : else
362 : success = elpa_solve_evp_complex_2stage_double(na, nev, a, lda, ev, q, ldq, nblk, &
363 : matrixCols, mpi_comm_rows, mpi_comm_cols, &
364 : mpi_comm_all, &
365 1152 : THIS_COMPLEX_ELPA_KERNEL_API, useGPU)
366 : endif
367 :
368 3456 : end function elpa_solve_evp_complex_double
369 :
370 : #ifdef WANT_SINGLE_PRECISION_COMPLEX
371 : !-------------------------------------------------------------------------------
372 : !> \brief solve_evp_complex_single: Fortran function to solve the complex eigenvalue
373 : !> problem with either the ELPA 1stage or the ELPA 2stage solver
374 : !>
375 : !> Parameters
376 : !>
377 : !> \param na Order of matrix a
378 : !>
379 : !> \param nev Number of eigenvalues needed
380 : !>
381 : !> \param a(lda,matrixCols) Distributed matrix for which eigenvalues are to be computed.
382 : !> Distribution is like in Scalapack.
383 : !> The full matrix must be set (not only one half like in scalapack).
384 : !> Destroyed on exit (upper and lower half).
385 : !>
386 : !> \param lda Leading dimension of a
387 : !>
388 : !> \param ev(na) On output: eigenvalues of a, every processor gets the complete set
389 : !>
390 : !> \param q(ldq,matrixCols) On output: Eigenvectors of a
391 : !> Distribution is like in Scalapack.
392 : !> Must be always dimensioned to the full size (corresponding to (na,na))
393 : !> even if only a part of the eigenvalues is needed.
394 : !>
395 : !> \param ldq Leading dimension of q
396 : !>
397 : !> \param nblk blocksize of cyclic distribution, must be the same in both directions!
398 : !>
399 : !> \param matrixCols local columns of matrix a and q
400 : !>
401 : !> \param mpi_comm_rows MPI communicator for rows
402 : !> \param mpi_comm_cols MPI communicator for columns
403 : !> \param mpi_comm_all MPI communicator for the total processor set
404 : !>
405 : !> \param THIS_REAL_COMPLEX_KERNEL_API (optional) specify used ELPA 2stage
406 : !> kernel via API (only evalulated if 2 stage solver is used
407 : !> \param useGPU (optional) use GPU version of ELPA 1stage
408 : !>
409 : !> \param method choose whether to use ELPA 1stage or 2stage solver
410 : !> possible values: "1stage" => use ELPA 1stage solver
411 : !> "2stage" => use ELPA 2stage solver
412 : !> "auto" => (at the moment) use ELPA 2stage solver
413 : !>
414 : !> \result success logical, false if error occured
415 : !-------------------------------------------------------------------------------
416 1728 : function elpa_solve_evp_complex_single(na, nev, a, lda, ev, q, ldq, nblk, &
417 : matrixCols, mpi_comm_rows, mpi_comm_cols, &
418 : mpi_comm_all, THIS_COMPLEX_ELPA_KERNEL_API,&
419 : useGPU, method) result(success)
420 : use iso_c_binding
421 : use elpa_utilities
422 : implicit none
423 : integer(kind=c_int), intent(in) :: na, nev, lda, ldq, matrixCols, mpi_comm_rows, &
424 : mpi_comm_cols, mpi_comm_all
425 : integer(kind=c_int), intent(in) :: nblk
426 : real(kind=c_float), intent(inout) :: ev(na)
427 : #ifdef USE_ASSUMED_SIZE
428 : complex(kind=c_float_complex), intent(inout) :: a(lda,*), q(ldq,*)
429 : #else
430 : complex(kind=c_float_complex), intent(inout) :: a(lda,matrixCols), q(ldq,matrixCols)
431 : #endif
432 : integer(kind=c_int), intent(in), optional :: THIS_COMPLEX_ELPA_KERNEL_API
433 : logical, intent(in), optional :: useGPU
434 : character(*), intent(in), optional :: method
435 :
436 : logical :: useELPA1
437 : logical :: success
438 :
439 864 : useELPA1 = .false.
440 :
441 864 : if (present(method)) then
442 864 : if (trim(method) .eq. "1stage" .or. trim(method) .eq. "1STAGE") then
443 288 : useELPA1 = .true.
444 576 : else if (trim(method) .eq. "2stage" .or. trim(method) .eq. "2STAGE") then
445 288 : useELPA1 = .false.
446 288 : else if (trim(method) .eq. "auto" .or. trim(method) .eq. "AUTO") then
447 288 : useELPA1 = .false.
448 : else
449 0 : write(error_unit,*) "Specified method not known! Using ELPA 2-stage"
450 0 : useELPA1 = .false.
451 : endif
452 : endif
453 :
454 864 : if (useELPA1) then
455 : success = elpa_solve_evp_complex_1stage_single(na, nev, a, lda, ev, q, ldq, nblk, &
456 : matrixCols, mpi_comm_rows, mpi_comm_cols, mpi_comm_all, &
457 288 : useGPU)
458 : else
459 : success = elpa_solve_evp_complex_2stage_single(na, nev, a, lda, ev, q, ldq, nblk, &
460 : matrixCols, mpi_comm_rows, mpi_comm_cols, &
461 : mpi_comm_all, &
462 576 : THIS_COMPLEX_ELPA_KERNEL_API,useGPU)
463 : endif
464 :
465 1728 : end function elpa_solve_evp_complex_single
466 : #endif /* WANT_SINGLE_PRECISION_COMPLEX */
467 : end module elpa_driver
468 :
|