elpa_api.F90 50.4 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
!
!    Copyright 2017, L. Hüdepohl and A. Marek, MPCDF
!
!    This file is part of ELPA.
!
!    The ELPA library was originally created by the ELPA consortium,
!    consisting of the following organizations:
!
!    - Max Planck Computing and Data Facility (MPCDF), formerly known as
!      Rechenzentrum Garching der Max-Planck-Gesellschaft (RZG),
!    - Bergische Universität Wuppertal, Lehrstuhl für angewandte
!      Informatik,
!    - Technische Universität München, Lehrstuhl für Informatik mit
!      Schwerpunkt Wissenschaftliches Rechnen ,
!    - Fritz-Haber-Institut, Berlin, Abt. Theorie,
!    - Max-Plack-Institut für Mathematik in den Naturwissenschaften,
!      Leipzig, Abt. Komplexe Strukutren in Biologie und Kognition,
!      and
!    - IBM Deutschland GmbH
!
!    This particular source code file contains additions, changes and
!    enhancements authored by Intel Corporation which is not part of
!    the ELPA consortium.
!
!    More information can be found here:
!    http://elpa.mpcdf.mpg.de/
!
!    ELPA is free software: you can redistribute it and/or modify
!    it under the terms of the version 3 of the license of the
!    GNU Lesser General Public License as published by the Free
!    Software Foundation.
!
!    ELPA is distributed in the hope that it will be useful,
!    but WITHOUT ANY WARRANTY; without even the implied warranty of
!    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
!    GNU Lesser General Public License for more details.
!
!    You should have received a copy of the GNU Lesser General Public License
!    along with ELPA.  If not, see <http://www.gnu.org/licenses/>
!
!    ELPA reflects a substantial effort on the part of the original
!    ELPA consortium, and we ask you to respect the spirit of the
!    license that we chose: i.e., please contribute any changes you
!    may have back to the original ELPA library distribution, and keep
!    any derivatives of ELPA under the same license that we chose for
!    the original distribution, the GNU Lesser General Public License.
!
#include "config-f90.h"
49
50
51
!> \brief Fortran module which provides the definition of the ELPA API. Do not use directly! Use the module "elpa"


52
53
54
55
56
module elpa_api
  use elpa_constants
  use, intrinsic :: iso_c_binding
  implicit none

57
58
59
60
  integer, private, parameter :: earliest_api_version = EARLIEST_API_VERSION !< Definition of the earliest API version supported
                                                                             !< with the current release
  integer, private, parameter :: current_api_version  = CURRENT_API_VERSION  !< Definition of the current API version

61
62
63
64
65
66
67
  logical, private :: initDone = .false.

  public :: elpa_t, &
      c_int, &
      c_double, c_double_complex, &
      c_float, c_float_complex

68
  !> \brief Abstract definition of the elpa_t type
69
70
71
  type, abstract :: elpa_t
    private

72
    !< these have to be public for proper bounds checking, sadly
73
74
75
76
77
78
79
80
    integer(kind=c_int), public, pointer :: na => NULL()
    integer(kind=c_int), public, pointer :: nev => NULL()
    integer(kind=c_int), public, pointer :: local_nrows => NULL()
    integer(kind=c_int), public, pointer :: local_ncols => NULL()
    integer(kind=c_int), public, pointer :: nblk => NULL()

    contains
      ! general
81
82
      procedure(elpa_setup_i),   deferred, public :: setup          !< method to setup an ELPA object
      procedure(elpa_destroy_i), deferred, public :: destroy        !< method to destroy an ELPA object
83

84
      ! key/value store
85
      generic, public :: set => &                                   !< export a method to set integer/double key/values
86
87
          elpa_set_integer, &
          elpa_set_double
88
89
90
91

      generic, public :: get => &                                   !< export a method to get integer/double key/values
          elpa_get_integer, &
          elpa_get_double
92

93
94
      procedure(elpa_is_set_i),  deferred, public :: is_set         !< method to check whether key/value is set
      procedure(elpa_can_set_i), deferred, public :: can_set        !< method to check whether key/value can be set
95

96
      ! Timer
97
98
99
      procedure(elpa_get_time_i), deferred, public :: get_time
      procedure(elpa_print_times_i), deferred, public :: print_times

100
      ! Actual math routines
101
102
103
104
105
      generic, public :: eigenvectors => &                          !< method solve for solving the full eigenvalue problem
          elpa_eigenvectors_d, &                                           !< for symmetric real valued / hermitian complex valued
          elpa_eigenvectors_f, &                                           !< matrices
          elpa_eigenvectors_dc, &
          elpa_eigenvectors_fc
106

107
      generic, public :: hermitian_multiply => &                    !< method for a "hermitian" multiplication of matrices a and b
108
          elpa_hermitian_multiply_d, &                              !< for real valued matrices:   a**T * b
109
          elpa_hermitian_multiply_dc, &                             !< for complex valued matrices a**H * b
110
111
          elpa_hermitian_multiply_f, &
          elpa_hermitian_multiply_fc
112

113
      generic, public :: cholesky => &                              !< method for the cholesky factorisation of matrix a
114
115
116
117
          elpa_cholesky_d, &
          elpa_cholesky_f, &
          elpa_cholesky_dc, &
          elpa_cholesky_fc
118

Andreas Marek's avatar
Andreas Marek committed
119
      generic, public :: invert_triangular => &                     !< method to invert a upper triangular matrix a
120
121
122
123
          elpa_invert_trm_d, &
          elpa_invert_trm_f, &
          elpa_invert_trm_dc, &
          elpa_invert_trm_fc
124

125
      generic, public :: solve_tridi => &                           !< method to solve the eigenvalue problem for a tridiagonal
126
          elpa_solve_tridi_d, &                                     !< matrix
127
          elpa_solve_tridi_f
128
129


130
      !> \brief private methods of elpa_t type. NOT accessible for the user
131
132
133
134
      ! privates
      procedure(elpa_set_integer_i), deferred, private :: elpa_set_integer
      procedure(elpa_set_double_i),  deferred, private :: elpa_set_double

135
136
137
      procedure(elpa_get_integer_i), deferred, private :: elpa_get_integer
      procedure(elpa_get_double_i),  deferred, private :: elpa_get_double

138
139
140
141
      procedure(elpa_eigenvectors_d_i),    deferred, private :: elpa_eigenvectors_d
      procedure(elpa_eigenvectors_f_i),    deferred, private :: elpa_eigenvectors_f
      procedure(elpa_eigenvectors_dc_i), deferred, private :: elpa_eigenvectors_dc
      procedure(elpa_eigenvectors_fc_i), deferred, private :: elpa_eigenvectors_fc
142

143
144
145
146
      procedure(elpa_hermitian_multiply_d_i),  deferred, private :: elpa_hermitian_multiply_d
      procedure(elpa_hermitian_multiply_f_i),  deferred, private :: elpa_hermitian_multiply_f
      procedure(elpa_hermitian_multiply_dc_i), deferred, private :: elpa_hermitian_multiply_dc
      procedure(elpa_hermitian_multiply_fc_i), deferred, private :: elpa_hermitian_multiply_fc
147

148
149
150
151
      procedure(elpa_cholesky_d_i),    deferred, private :: elpa_cholesky_d
      procedure(elpa_cholesky_f_i),    deferred, private :: elpa_cholesky_f
      procedure(elpa_cholesky_dc_i), deferred, private :: elpa_cholesky_dc
      procedure(elpa_cholesky_fc_i), deferred, private :: elpa_cholesky_fc
152

153
154
155
156
      procedure(elpa_invert_trm_d_i),    deferred, private :: elpa_invert_trm_d
      procedure(elpa_invert_trm_f_i),    deferred, private :: elpa_invert_trm_f
      procedure(elpa_invert_trm_dc_i), deferred, private :: elpa_invert_trm_dc
      procedure(elpa_invert_trm_fc_i), deferred, private :: elpa_invert_trm_fc
157

158
159
      procedure(elpa_solve_tridi_d_i), deferred, private :: elpa_solve_tridi_d
      procedure(elpa_solve_tridi_f_i), deferred, private :: elpa_solve_tridi_f
160
161
162
  end type elpa_t


163
164
165
166
167
  !> \brief definition of helper function to get C strlen
  !> Parameters
  !> \details
  !> \param   ptr         type(c_ptr) : pointer to string
  !> \result  size        integer(kind=c_size_t) : length of string
168
169
170
  interface
    pure function elpa_strlen_c(ptr) result(size) bind(c, name="strlen")
      use, intrinsic :: iso_c_binding
171
      implicit none
172
173
174
175
176
      type(c_ptr), intent(in), value :: ptr
      integer(kind=c_size_t) :: size
    end function
  end interface

177
178
179
180
181
  !> \brief abstract definition of setup method
  !> Parameters
  !> \details
  !> \param   self        class(elpa_t): the ELPA object
  !> \result  error       integer : error code, which can be queried with elpa_strerr()
182
  abstract interface
183
    function elpa_setup_i(self) result(error)
184
      import elpa_t
185
      implicit none
186
      class(elpa_t), intent(inout) :: self
187
      integer :: error
188
189
190
    end function
  end interface

191
192
193
194
195
196
197
  !> \brief abstract definition of set method for integer values
  !> Parameters
  !> \details
  !> \param   self        class(elpa_t): the ELPA object
  !> \param   name        string: the name of the key
  !> \param   value       integer : the value to set for the key
  !> \param   error       integer, optional : error code, which can be queried with elpa_strerr()
198
  abstract interface
199
    subroutine elpa_set_integer_i(self, name, value, error)
200
201
      use iso_c_binding
      import elpa_t
202
      implicit none
203
204
205
      class(elpa_t)                   :: self
      character(*), intent(in)        :: name
      integer(kind=c_int), intent(in) :: value
206
      integer, optional               :: error
207
208
209
    end subroutine
  end interface

210
211
212
213
214
  !> \brief abstract definition of get method for integer values
  !> Parameters
  !> \details
  !> \param   self        class(elpa_t): the ELPA object
  !> \param   name        string: the name of the key
215
  !> \param   value       integer : the value corresponding to the key
216
  !> \param   error       integer, optional : error code, which can be queried with elpa_strerr()
217
  abstract interface
218
    subroutine elpa_get_integer_i(self, name, value, error)
219
220
      use iso_c_binding
      import elpa_t
221
      implicit none
222
223
224
      class(elpa_t)                  :: self
      character(*), intent(in)       :: name
      integer(kind=c_int)            :: value
225
      integer, intent(out), optional :: error
226
    end subroutine
227
228
  end interface

229
230
231
232
233
234
235
  !> \brief abstract definition of is_set method for integer values
  !> Parameters
  !> \details
  !> \param   self        class(elpa_t): the ELPA object
  !> \param   name        string: the name of the key
  !> \result  state       integer : 1 is set, 0 if not, else a negativ error code
  !>                                                    which can be queried with elpa_strerr
236
  abstract interface
237
    function elpa_is_set_i(self, name) result(state)
238
      import elpa_t
239
      implicit none
240
241
      class(elpa_t)            :: self
      character(*), intent(in) :: name
242
      integer                  :: state
243
244
245
    end function
  end interface

246
247
248
249
250
251
252
253
  !> \brief abstract definition of can_set method for integer values
  !> Parameters
  !> \details
  !> \param   self        class(elpa_t): the ELPA object
  !> \param   name        string: the name of the key
  !> \param   value       integer: the valye to associate with the key
  !> \result  state       integer : 1 is set, 0 if not, else a negativ error code
  !>                                                    which can be queried with elpa_strerr
254
  abstract interface
255
    function elpa_can_set_i(self, name, value) result(state)
256
      import elpa_t, c_int
257
      implicit none
258
259
260
      class(elpa_t)                   :: self
      character(*), intent(in)        :: name
      integer(kind=c_int), intent(in) :: value
261
      integer                         :: state
262
    end function
263
264
  end interface

265
266
267
268
269
270
271
  !> \brief abstract definition of set method for double values
  !> Parameters
  !> \details
  !> \param   self        class(elpa_t): the ELPA object
  !> \param   name        string: the name of the key
  !? \param   value       double: the value to associate with the key
  !> \param   error       integer. optional : error code, which can be queried with elpa_strerr
272
  abstract interface
273
    subroutine elpa_set_double_i(self, name, value, error)
274
275
      use iso_c_binding
      import elpa_t
276
      implicit none
277
278
279
      class(elpa_t)                   :: self
      character(*), intent(in)        :: name
      real(kind=c_double), intent(in) :: value
280
      integer, optional               :: error
281
282
283
    end subroutine
  end interface

284
285
286
287
288
  !> \brief abstract definition of get method for double values
  !> Parameters
  !> \details
  !> \param   self        class(elpa_t): the ELPA object
  !> \param   name        string: the name of the key
289
  !> \param   value       double: the value associated with the key
290
  !> \param   error       integer. optional : error code, which can be queried with elpa_strerr
291
  abstract interface
292
    subroutine elpa_get_double_i(self, name, value, error)
293
294
      use iso_c_binding
      import elpa_t
295
      implicit none
296
297
298
      class(elpa_t)                  :: self
      character(*), intent(in)       :: name
      real(kind=c_double)            :: value
299
      integer, intent(out), optional :: error
300
    end subroutine
301
302
  end interface

303
304
305
306
307
308
  !> \brief abstract definition of associate method for integer pointers
  !> Parameters
  !> \details
  !> \param   self        class(elpa_t): the ELPA object
  !> \param   name        string: the name of the key
  !> \result  value       integer pointer: the value associated with the key
309
310
311
312
  abstract interface
    function elpa_associate_int_i(self, name) result(value)
      use iso_c_binding
      import elpa_t
313
      implicit none
314
315
316
317
318
319
      class(elpa_t)                  :: self
      character(*), intent(in)       :: name
      integer(kind=c_int), pointer   :: value
    end function
  end interface

320
321
322

  ! Timer routines

323
324
325
326
327
328
  !> \brief abstract definition of get_time method to querry the timer
  !> Parameters
  !> \details
  !> \param   self        class(elpa_t): the ELPA object
  !> \param   name1..6    string: the name of the timer entry, supports up to 6 levels
  !> \result  s           double: the time for the entry name1..6
329
330
331
  abstract interface
    function elpa_get_time_i(self, name1, name2, name3, name4, name5, name6) result(s)
      import elpa_t, c_double
332
      implicit none
333
334
335
336
337
338
339
      class(elpa_t), intent(in) :: self
      ! this is clunky, but what can you do..
      character(len=*), intent(in), optional :: name1, name2, name3, name4, name5, name6
      real(kind=c_double) :: s
    end function
  end interface

340
341
342
343
  !> \brief abstract definition of print method for timer
  !> Parameters
  !> \details
  !> \param   self        class(elpa_t): the ELPA object
344
345
346
  abstract interface
    subroutine elpa_print_times_i(self)
      import elpa_t
347
      implicit none
348
349
350
351
352
      class(elpa_t), intent(in) :: self
    end subroutine
  end interface


353
  ! Actual math routines
354

355
  !> \brief abstract definition of interface to solve double real eigenvalue problem
356
357
358
359
360
361
362
363
  !>
  !>  The dimensions of the matrix a (locally ditributed and global), the block-cyclic distribution
  !>  blocksize, the number of eigenvectors
  !>  to be computed and the MPI communicators are already known to the object and MUST be set BEFORE
  !>  with the class method "setup"
  !>
  !>  It is possible to change the behaviour of the method by setting tunable parameters with the
  !>  class method "set"
364
365
366
367
368
369
  !> Parameters
  !> \details
  !> \param   self        class(elpa_t), the ELPA object
  !> \param   a           double real matrix a: defines the problem to solve
  !> \param   ev          double real: on output stores the eigenvalues
  !> \param   q           double real matrix q: on output stores the eigenvalues
370
  !> \result  error       integer, optional : error code, which can be queried with elpa_strerr
371
  abstract interface
372
    subroutine elpa_eigenvectors_d_i(self, a, ev, q, error)
373
374
      use iso_c_binding
      import elpa_t
375
      implicit none
376
377
378
379
380
381
382
383
      class(elpa_t)       :: self
#ifdef USE_ASSUMED_SIZE
      real(kind=c_double) :: a(self%local_nrows, *), q(self%local_nrows, *)
#else
      real(kind=c_double) :: a(self%local_nrows, self%local_ncols), q(self%local_nrows, self%local_ncols)
#endif
      real(kind=c_double) :: ev(self%na)

384
      integer, optional   :: error
385
386
387
    end subroutine
  end interface

388
  !> \brief abstract definition of interface to solve single real eigenvalue problem
389
390
391
392
393
394
395
396
  !>
  !>  The dimensions of the matrix a (locally ditributed and global), the block-cyclic distribution
  !>  blocksize, the number of eigenvectors
  !>  to be computed and the MPI communicators are already known to the object and MUST be set BEFORE
  !>  with the class method "setup"
  !>
  !>  It is possible to change the behaviour of the method by setting tunable parameters with the
  !>  class method "set"
397
398
399
400
401
402
  !> Parameters
  !> \details
  !> \param   self        class(elpa_t), the ELPA object
  !> \param   a           single real matrix a: defines the problem to solve
  !> \param   ev          single real: on output stores the eigenvalues
  !> \param   q           single real matrix q: on output stores the eigenvalues
403
  !> \result  error       integer, optional : error code, which can be queried with elpa_strerr
404
  abstract interface
405
    subroutine elpa_eigenvectors_f_i(self, a, ev, q, error)
406
407
      use iso_c_binding
      import elpa_t
408
      implicit none
409
410
411
412
413
414
415
416
      class(elpa_t)       :: self
#ifdef USE_ASSUMED_SIZE
      real(kind=c_float)  :: a(self%local_nrows, *), q(self%local_nrows, *)
#else
      real(kind=c_float)  :: a(self%local_nrows, self%local_ncols), q(self%local_nrows, self%local_ncols)
#endif
      real(kind=c_float)  :: ev(self%na)

417
      integer, optional   :: error
418
419
420
    end subroutine
  end interface

421
  !> \brief abstract definition of interface to solve double complex eigenvalue problem
422
423
424
425
426
427
428
429
  !>
  !>  The dimensions of the matrix a (locally ditributed and global), the block-cyclic distribution
  !>  blocksize, the number of eigenvectors
  !>  to be computed and the MPI communicators are already known to the object and MUST be set BEFORE
  !>  with the class method "setup"
  !>
  !>  It is possible to change the behaviour of the method by setting tunable parameters with the
  !>  class method "set"
430
431
432
433
434
435
  !> Parameters
  !> \details
  !> \param   self        class(elpa_t), the ELPA object
  !> \param   a           double complex matrix a: defines the problem to solve
  !> \param   ev          double real: on output stores the eigenvalues
  !> \param   q           double complex matrix q: on output stores the eigenvalues
436
  !> \result  error       integer, optional : error code, which can be queried with elpa_strerr
437
  abstract interface
438
    subroutine elpa_eigenvectors_dc_i(self, a, ev, q, error)
439
440
      use iso_c_binding
      import elpa_t
441
      implicit none
442
443
444
445
446
447
448
449
450
      class(elpa_t)                  :: self

#ifdef USE_ASSUMED_SIZE
      complex(kind=c_double_complex) :: a(self%local_nrows, *), q(self%local_nrows, *)
#else
      complex(kind=c_double_complex) :: a(self%local_nrows, self%local_ncols), q(self%local_nrows, self%local_ncols)
#endif
      real(kind=c_double)            :: ev(self%na)

451
      integer, optional              :: error
452
453
454
    end subroutine
  end interface

455
  !> \brief abstract definition of interface to solve single complex eigenvalue problem
456
457
458
459
460
461
462
463
  !>
  !>  The dimensions of the matrix a (locally ditributed and global), the block-cyclic distribution
  !>  blocksize, the number of eigenvectors
  !>  to be computed and the MPI communicators are already known to the object and MUST be set BEFORE
  !>  with the class method "setup"
  !>
  !>  It is possible to change the behaviour of the method by setting tunable parameters with the
  !>  class method "set"
464
465
466
467
468
469
  !> Parameters
  !> \details
  !> \param   self        class(elpa_t), the ELPA object
  !> \param   a           single complex matrix a: defines the problem to solve
  !> \param   ev          single real: on output stores the eigenvalues
  !> \param   q           single complex matrix q: on output stores the eigenvalues
470
  !> \result  error       integer, optional : error code, which can be queried with elpa_strerr
471
  abstract interface
472
    subroutine elpa_eigenvectors_fc_i(self, a, ev, q, error)
473
474
      use iso_c_binding
      import elpa_t
475
      implicit none
476
477
478
479
480
481
482
483
      class(elpa_t)                 :: self
#ifdef USE_ASSUMED_SIZE
      complex(kind=c_float_complex) :: a(self%local_nrows, *), q(self%local_nrows, *)
#else
      complex(kind=c_float_complex) :: a(self%local_nrows, self%local_ncols), q(self%local_nrows, self%local_ncols)
#endif
      real(kind=c_float)            :: ev(self%na)

484
      integer, optional             :: error
485
486
487
    end subroutine
  end interface

Andreas Marek's avatar
Andreas Marek committed
488
  !> \brief abstract definition of interface to compute C : = A**T * B for double real matrices
489
490
491
  !>         where   A is a square matrix (self%a,self%na) which is optionally upper or lower triangular
  !>                 B is a (self%na,ncb) matrix
  !>                 C is a (self%na,ncb) matrix where optionally only the upper or lower
Andreas Marek's avatar
Andreas Marek committed
492
493
494
495
  !>                   triangle may be computed
  !>
  !> the MPI commicators are already known to the type. Thus the class method "setup" must be called
  !> BEFORE this method is used
496
  !> \details
Andreas Marek's avatar
Andreas Marek committed
497
  !>
498
  !> \param   self                class(elpa_t), the ELPA object
Andreas Marek's avatar
Andreas Marek committed
499
500
501
502
503
504
505
506
507
508
509
510
511
512
  !> \param  uplo_a               'U' if A is upper triangular
  !>                              'L' if A is lower triangular
  !>                              anything else if A is a full matrix
  !>                              Please note: This pertains to the original A (as set in the calling program)
  !>                                           whereas the transpose of A is used for calculations
  !>                              If uplo_a is 'U' or 'L', the other triangle is not used at all,
  !>                              i.e. it may contain arbitrary numbers
  !> \param uplo_c                'U' if only the upper diagonal part of C is needed
  !>                              'L' if only the upper diagonal part of C is needed
  !>                              anything else if the full matrix C is needed
  !>                              Please note: Even when uplo_c is 'U' or 'L', the other triangle may be
  !>                                            written to a certain extent, i.e. one shouldn't rely on the content there!
  !> \param ncb                   Number of columns  of global matrices B and C
  !> \param a                     matrix a
513
514
  !> \param self%local_nrows      number of rows of local (sub) matrix a, set with method set("local_nrows,value")
  !> \param self%local_ncols      number of columns of local (sub) matrix a, set with method set("local_ncols,value")
Andreas Marek's avatar
Andreas Marek committed
515
516
517
518
519
520
521
522
  !> \param b                     matrix b
  !> \param nrows_b               number of rows of local (sub) matrix b
  !> \param ncols_b               number of columns of local (sub) matrix b
  !> \param nblk                  blocksize of cyclic distribution, must be the same in both directions!
  !> \param c                     matrix c
  !> \param nrows_c               number of rows of local (sub) matrix c
  !> \param ncols_c               number of columns of local (sub) matrix c
  !> \param error                 optional argument, error code which can be queried with elpa_strerr
523
  abstract interface
524
    subroutine elpa_hermitian_multiply_d_i (self,uplo_a, uplo_c, ncb, a, b, nrows_b, ncols_b, &
Andreas Marek's avatar
Andreas Marek committed
525
                                          c, nrows_c, ncols_c, error)
526
527
      use iso_c_binding
      import elpa_t
528
      implicit none
529
530
      class(elpa_t)                   :: self
      character*1                     :: uplo_a, uplo_c
531
      integer(kind=c_int), intent(in) :: nrows_b, ncols_b, nrows_c, ncols_c, ncb
532
#ifdef USE_ASSUMED_SIZE
533
      real(kind=c_double)             :: a(self%local_nrows,*), b(nrows_b,*), c(nrows_c,*)
534
#else
535
      real(kind=c_double)             :: a(self%local_nrows,self%local_ncols), b(nrows_b,ncols_b), c(nrows_c,ncols_c)
536
#endif
537
      integer, optional               :: error
538
539
540
    end subroutine
  end interface

541
  !> \brief abstract definition of interface to compute C : = A**T * B
542
543
544
  !>         where   A is a square matrix (self%na,self%na) which is optionally upper or lower triangular
  !>                 B is a (self%na,ncb) matrix
  !>                 C is a (self%na,ncb) matrix where optionally only the upper or lower
Andreas Marek's avatar
Andreas Marek committed
545
546
547
548
  !>                   triangle may be computed
  !>
  !> the MPI commicators are already known to the type. Thus the class method "setup" must be called
  !> BEFORE this method is used
549
  !> \details
Andreas Marek's avatar
Andreas Marek committed
550
  !>
551
  !> \param   self                class(elpa_t), the ELPA object
Andreas Marek's avatar
Andreas Marek committed
552
553
554
555
556
557
558
559
560
561
562
563
564
565
  !> \param  uplo_a               'U' if A is upper triangular
  !>                              'L' if A is lower triangular
  !>                              anything else if A is a full matrix
  !>                              Please note: This pertains to the original A (as set in the calling program)
  !>                                           whereas the transpose of A is used for calculations
  !>                              If uplo_a is 'U' or 'L', the other triangle is not used at all,
  !>                              i.e. it may contain arbitrary numbers
  !> \param uplo_c                'U' if only the upper diagonal part of C is needed
  !>                              'L' if only the upper diagonal part of C is needed
  !>                              anything else if the full matrix C is needed
  !>                              Please note: Even when uplo_c is 'U' or 'L', the other triangle may be
  !>                                            written to a certain extent, i.e. one shouldn't rely on the content there!
  !> \param ncb                   Number of columns  of global matrices B and C
  !> \param a                     matrix a
566
567
  !> \param self%local_nrows      number of rows of local (sub) matrix a, set with method set("local_nrows",value)
  !> \param self%local_ncols      number of columns of local (sub) matrix a, set with method set("local_nrows",value)
Andreas Marek's avatar
Andreas Marek committed
568
569
570
571
572
573
574
575
  !> \param b                     matrix b
  !> \param nrows_b               number of rows of local (sub) matrix b
  !> \param ncols_b               number of columns of local (sub) matrix b
  !> \param nblk                  blocksize of cyclic distribution, must be the same in both directions!
  !> \param c                     matrix c
  !> \param nrows_c               number of rows of local (sub) matrix c
  !> \param ncols_c               number of columns of local (sub) matrix c
  !> \param error                 optional argument, error code which can be queried with elpa_strerr
576
  abstract interface
577
    subroutine elpa_hermitian_multiply_f_i (self,uplo_a, uplo_c, ncb, a, b, nrows_b, ncols_b, &
Andreas Marek's avatar
Andreas Marek committed
578
                                          c, nrows_c, ncols_c, error)
579
580
      use iso_c_binding
      import elpa_t
581
      implicit none
582
583
      class(elpa_t)                   :: self
      character*1                     :: uplo_a, uplo_c
584
      integer(kind=c_int), intent(in) :: nrows_b, ncols_b, nrows_c, ncols_c, ncb
585
#ifdef USE_ASSUMED_SIZE
586
      real(kind=c_float)              :: a(self%local_nrows,*), b(nrows_b,*), c(nrows_c,*)
587
#else
588
      real(kind=c_float)              :: a(self%local_nrows,self%local_ncols), b(nrows_b,ncols_b), c(nrows_c,ncols_c)
589
#endif
590
      integer, optional               :: error
591
592
593
    end subroutine
  end interface

594
  !> \brief abstract definition of interface to compute C : = A**H * B
595
596
597
  !>         where   A is a square matrix (self%na,self%a) which is optionally upper or lower triangular
  !>                 B is a (self%na,ncb) matrix
  !>                 C is a (self%na,ncb) matrix where optionally only the upper or lower
Andreas Marek's avatar
Andreas Marek committed
598
599
600
601
  !>                   triangle may be computed
  !>
  !> the MPI commicators are already known to the type. Thus the class method "setup" must be called
  !> BEFORE this method is used
602
  !> \details
Andreas Marek's avatar
Andreas Marek committed
603
  !>
604
  !> \param   self                class(elpa_t), the ELPA object
Andreas Marek's avatar
Andreas Marek committed
605
606
607
608
609
610
611
612
613
614
615
616
617
618
  !> \param  uplo_a               'U' if A is upper triangular
  !>                              'L' if A is lower triangular
  !>                              anything else if A is a full matrix
  !>                              Please note: This pertains to the original A (as set in the calling program)
  !>                                           whereas the transpose of A is used for calculations
  !>                              If uplo_a is 'U' or 'L', the other triangle is not used at all,
  !>                              i.e. it may contain arbitrary numbers
  !> \param uplo_c                'U' if only the upper diagonal part of C is needed
  !>                              'L' if only the upper diagonal part of C is needed
  !>                              anything else if the full matrix C is needed
  !>                              Please note: Even when uplo_c is 'U' or 'L', the other triangle may be
  !>                                            written to a certain extent, i.e. one shouldn't rely on the content there!
  !> \param ncb                   Number of columns  of global matrices B and C
  !> \param a                     matrix a
619
620
  !> \param self%local_nrows      number of rows of local (sub) matrix a, set with the method set("local_nrows",value)
  !> \param self%local_ncols      number of columns of local (sub) matrix a, set with the method set("local_ncols",value)
Andreas Marek's avatar
Andreas Marek committed
621
622
623
624
625
626
627
628
  !> \param b                     matrix b
  !> \param nrows_b               number of rows of local (sub) matrix b
  !> \param ncols_b               number of columns of local (sub) matrix b
  !> \param nblk                  blocksize of cyclic distribution, must be the same in both directions!
  !> \param c                     matrix c
  !> \param nrows_c               number of rows of local (sub) matrix c
  !> \param ncols_c               number of columns of local (sub) matrix c
  !> \param error                 optional argument, error code which can be queried with elpa_strerr
629
  abstract interface
630
    subroutine elpa_hermitian_multiply_dc_i (self,uplo_a, uplo_c, ncb, a, b, nrows_b, ncols_b, &
Andreas Marek's avatar
Andreas Marek committed
631
                                          c, nrows_c, ncols_c, error)
632
633
      use iso_c_binding
      import elpa_t
634
      implicit none
635
636
      class(elpa_t)                   :: self
      character*1                     :: uplo_a, uplo_c
637
      integer(kind=c_int), intent(in) :: nrows_b, ncols_b, nrows_c, ncols_c, ncb
638
#ifdef USE_ASSUMED_SIZE
639
      complex(kind=c_double_complex)  :: a(self%local_nrows,*), b(nrows_b,*), c(nrows_c,*)
640
#else
641
      complex(kind=c_double_complex)  :: a(self%local_nrows,self%local_ncols), b(nrows_b,ncols_b), c(nrows_c,ncols_c)
642
#endif
643
      integer, optional               :: error
644
645
646
    end subroutine
  end interface

647
  !> \brief abstract definition of interface to compute C : = A**H * B
648
649
650
  !>         where   A is a square matrix (self%na,self%na) which is optionally upper or lower triangular
  !>                 B is a (self%na,ncb) matrix
  !>                 C is a (self%na,ncb) matrix where optionally only the upper or lower
Andreas Marek's avatar
Andreas Marek committed
651
652
653
654
  !>                   triangle may be computed
  !>
  !> the MPI commicators are already known to the type. Thus the class method "setup" must be called
  !> BEFORE this method is used
655
  !> \details
Andreas Marek's avatar
Andreas Marek committed
656
  !>
657
  !> \param   self                class(elpa_t), the ELPA object
Andreas Marek's avatar
Andreas Marek committed
658
659
660
661
662
663
664
665
666
667
668
669
670
671
  !> \param  uplo_a               'U' if A is upper triangular
  !>                              'L' if A is lower triangular
  !>                              anything else if A is a full matrix
  !>                              Please note: This pertains to the original A (as set in the calling program)
  !>                                           whereas the transpose of A is used for calculations
  !>                              If uplo_a is 'U' or 'L', the other triangle is not used at all,
  !>                              i.e. it may contain arbitrary numbers
  !> \param uplo_c                'U' if only the upper diagonal part of C is needed
  !>                              'L' if only the upper diagonal part of C is needed
  !>                              anything else if the full matrix C is needed
  !>                              Please note: Even when uplo_c is 'U' or 'L', the other triangle may be
  !>                                            written to a certain extent, i.e. one shouldn't rely on the content there!
  !> \param ncb                   Number of columns  of global matrices B and C
  !> \param a                     matrix a
672
673
  !> \param self%local_nrows      number of rows of local (sub) matrix a, set with class method set("local_nrows",value)
  !> \param self%local_ncols      number of columns of local (sub) matrix a, set with class method set("local_ncols",value)
Andreas Marek's avatar
Andreas Marek committed
674
675
676
677
678
679
680
681
  !> \param b                     matrix b
  !> \param nrows_b               number of rows of local (sub) matrix b
  !> \param ncols_b               number of columns of local (sub) matrix b
  !> \param nblk                  blocksize of cyclic distribution, must be the same in both directions!
  !> \param c                     matrix c
  !> \param nrows_c               number of rows of local (sub) matrix c
  !> \param ncols_c               number of columns of local (sub) matrix c
  !> \param error                 optional argument, error code which can be queried with elpa_strerr
682
  abstract interface
683
    subroutine elpa_hermitian_multiply_fc_i (self, uplo_a, uplo_c, ncb, a, b, nrows_b, ncols_b, &
Andreas Marek's avatar
Andreas Marek committed
684
                                          c, nrows_c, ncols_c, error)
685
686
      use iso_c_binding
      import elpa_t
687
      implicit none
688
689
      class(elpa_t)                   :: self
      character*1                     :: uplo_a, uplo_c
690
      integer(kind=c_int), intent(in) :: nrows_b, ncols_b, nrows_c, ncols_c, ncb
691
#ifdef USE_ASSUMED_SIZE
692
      complex(kind=c_float_complex)   :: a(self%local_nrows,*), b(nrows_b,*), c(nrows_c,*)
693
#else
694
      complex(kind=c_float_complex)   :: a(self%local_nrows,self%local_ncols), b(nrows_b,ncols_b), c(nrows_c,ncols_c)
695
#endif
696
      integer, optional               :: error
697
698
699
    end subroutine
  end interface

700
  !> \brief abstract definition of interface to do a cholesky decomposition of a double real matrix
701
702
703
704
  !>
  !>  The dimensions of the matrix a (locally ditributed and global), the block-cylic-distribution
  !>  block size, and the MPI communicators are already known to the object and MUST be set BEFORE
  !>  with the class method "setup"
705
  !>
706
707
708
  !> Parameters
  !> \param   self        class(elpa_t), the ELPA object
  !> \param   a           double real matrix: the matrix to be decomposed
709
  !> \param   error       integer, optional : error code, which can be queried with elpa_strerr
710
  abstract interface
711
    subroutine elpa_cholesky_d_i (self, a, error)
712
713
      use iso_c_binding
      import elpa_t
714
      implicit none
715
716
717
718
719
720
      class(elpa_t)                   :: self
#ifdef USE_ASSUMED_SIZE
      real(kind=c_double)             :: a(self%local_nrows,*)
#else
      real(kind=c_double)             :: a(self%local_nrows,self%local_ncols)
#endif
721
      integer, optional               :: error
722
723
724
    end subroutine
  end interface

725
  !> \brief abstract definition of interface to do a cholesky decomposition of a single real matrix
726
727
728
729
730
  !>
  !>  The dimensions of the matrix a (locally ditributed and global), the block-cylic-distribution
  !>  block size, and the MPI communicators are already known to the object and MUST be set BEFORE
  !>  with the class method "setup"
  !> 
731
732
733
  !> Parameters
  !> \param   self        class(elpa_t), the ELPA object
  !> \param   a           single real matrix: the matrix to be decomposed
734
  !> \param   error       integer, optional : error code, which can be queried with elpa_strerr
735
  abstract interface
736
    subroutine elpa_cholesky_f_i(self, a, error)
737
738
      use iso_c_binding
      import elpa_t
739
      implicit none
740
741
742
743
744
745
      class(elpa_t)                   :: self
#ifdef USE_ASSUMED_SIZE
      real(kind=c_float)              :: a(self%local_nrows,*)
#else
      real(kind=c_float)              :: a(self%local_nrows,self%local_ncols)
#endif
746
      integer, optional               :: error
747
748
749
    end subroutine
  end interface

750
  !> \brief abstract definition of interface to do a cholesky decomposition of a double complex matrix
751
752
753
754
755
  !>
  !>  The dimensions of the matrix a (locally ditributed and global), the block-cylic-distribution
  !>  block size, and the MPI communicators are already known to the object and MUST be set BEFORE
  !>  with the class method "setup"
  !> 
756
757
758
  !> Parameters
  !> \param   self        class(elpa_t), the ELPA object
  !> \param   a           double complex matrix: the matrix to be decomposed
759
  !> \param   error       integer, optional : error code, which can be queried with elpa_strerr
760
  abstract interface
761
    subroutine elpa_cholesky_dc_i (self, a, error)
762
763
      use iso_c_binding
      import elpa_t
764
      implicit none
765
766
767
768
769
770
      class(elpa_t)                   :: self
#ifdef USE_ASSUMED_SIZE
      complex(kind=c_double_complex)  :: a(self%local_nrows,*)
#else
      complex(kind=c_double_complex)  :: a(self%local_nrows,self%local_ncols)
#endif
771
      integer, optional               :: error
772
773
774
    end subroutine
  end interface

775
  !> \brief abstract definition of interface to do a cholesky decomposition of a single complex matrix
776
777
778
779
780
  !>
  !>  The dimensions of the matrix a (locally ditributed and global), the block-cylic-distribution
  !>  block size, and the MPI communicators are already known to the object and MUST be set BEFORE
  !>  with the class method "setup"
  !> 
781
782
783
  !> Parameters
  !> \param   self        class(elpa_t), the ELPA object
  !> \param   a           single complex matrix: the matrix to be decomposed
784
  !> \param   error       integer, optional : error code, which can be queried with elpa_strerr
785
  abstract interface
786
    subroutine elpa_cholesky_fc_i (self, a, error)
787
788
      use iso_c_binding
      import elpa_t
789
      implicit none
790
791
792
793
794
795
      class(elpa_t)                   :: self
#ifdef USE_ASSUMED_SIZE
      complex(kind=c_float_complex)   :: a(self%local_nrows,*)
#else
      complex(kind=c_float_complex)   :: a(self%local_nrows,self%local_ncols)
#endif
796
      integer, optional               :: error
797
798
799
    end subroutine
  end interface

800
  !> \brief abstract definition of interface to invert a triangular double real matrix
801
802
803
804
805
  !>
  !>  The dimensions of the matrix a (locally ditributed and global), the block-cylic-distribution
  !>  block size, and the MPI communicators are already known to the object and MUST be set BEFORE
  !>  with the class method "setup"
  !>
806
807
808
  !> Parameters
  !> \param   self        class(elpa_t), the ELPA object
  !> \param   a           double real matrix: the matrix to be inverted
809
  !> \param   error       integer, optional : error code, which can be queried with elpa_strerr
810
  abstract interface
811
    subroutine elpa_invert_trm_d_i (self, a, error)
812
813
      use iso_c_binding
      import elpa_t
814
      implicit none
815
816
817
818
819
820
      class(elpa_t)                   :: self
#ifdef USE_ASSUMED_SIZE
      real(kind=c_double)             :: a(self%local_nrows,*)
#else
      real(kind=c_double)             :: a(self%local_nrows,self%local_ncols)
#endif
821
      integer, optional               :: error
822
823
824
    end subroutine
  end interface

825
  !> \brief abstract definition of interface to invert a triangular single real matrix
826
  !> Parameters
827
828
829
830
831
  !>
  !>  The dimensions of the matrix a (locally ditributed and global), the block-cylic-distribution
  !>  block size, and the MPI communicators are already known to the object and MUST be set BEFORE
  !>  with the class method "setup"
  !>
832
833
  !> \param   self        class(elpa_t), the ELPA object
  !> \param   a           single real matrix: the matrix to be inverted
834
  !> \param   error       integer, optional : error code, which can be queried with elpa_strerr
835
  abstract interface
836
    subroutine elpa_invert_trm_f_i (self, a, error)
837
838
      use iso_c_binding
      import elpa_t
839
      implicit none
840
841
842
843
844
845
      class(elpa_t)                   :: self
#ifdef USE_ASSUMED_SIZE
      real(kind=c_float)              :: a(self%local_nrows,*)
#else
      real(kind=c_float)              :: a(self%local_nrows,self%local_ncols)
#endif
846
      integer, optional               :: error
847
848
849
    end subroutine
  end interface

850
  !> \brief abstract definition of interface to invert a triangular double complex matrix
851
852
853
854
855
  !>
  !>  The dimensions of the matrix a (locally ditributed and global), the block-cylic-distribution
  !>  block size, and the MPI communicators are already known to the object and MUST be set BEFORE
  !>  with the class method "setup"
  !>
856
857
858
  !> Parameters
  !> \param   self        class(elpa_t), the ELPA object
  !> \param   a           double complex matrix: the matrix to be inverted
859
  !> \param   error       integer, optional : error code, which can be queried with elpa_strerr
860
  abstract interface
861
    subroutine elpa_invert_trm_dc_i (self, a, error)
862
863
      use iso_c_binding
      import elpa_t
864
      implicit none
865
866
867
868
869
870
      class(elpa_t)                   :: self
#ifdef USE_ASSUMED_SIZE
      complex(kind=c_double_complex)  :: a(self%local_nrows,*)
#else
      complex(kind=c_double_complex)  :: a(self%local_nrows,self%local_ncols)
#endif
871
      integer, optional               :: error
872
873
874
    end subroutine
  end interface

875
  !> \brief abstract definition of interface to invert a triangular single complex matrix
876
877
878
879
880
  !>
  !>  The dimensions of the matrix a (locally ditributed and global), the block-cylic-distribution
  !>  block size, and the MPI communicators are already known to the object and MUST be set BEFORE
  !>  with the class method "setup"
  !>
881
882
883
  !> Parameters
  !> \param   self        class(elpa_t), the ELPA object
  !> \param   a           single complex matrix: the matrix to be inverted
884
  !> \param   error       integer, optional : error code, which can be queried with elpa_strerr
885
  abstract interface
886
    subroutine elpa_invert_trm_fc_i (self, a, error)
887
888
      use iso_c_binding
      import elpa_t
889
      implicit none
890
891
892
893
894
895
      class(elpa_t)                   :: self
#ifdef USE_ASSUMED_SIZE
      complex(kind=c_float_complex)   :: a(self%local_nrows,*)
#else
      complex(kind=c_float_complex)   :: a(self%local_nrows,self%local_ncols)
#endif
896
      integer, optional               :: error
897
898
899
    end subroutine
  end interface

900
  !> \brief abstract definition of interface to solve the eigenvalue problem for a double-precision real valued tridiangular matrix
901
902
903
904
905
  !>
  !>  The dimensions of the matrix a (locally ditributed and global), the block-cylic-distribution
  !>  block size, and the MPI communicators are already known to the object and MUST be set BEFORE
  !>  with the class method "setup"
  !>
906
907
  !> Parameters
  !> \param   self        class(elpa_t), the ELPA object
908
909
  !> \param   d           double real 1d array: the diagonal elements of a matrix defined in setup, on output the eigenvalues
  !>                      in ascending order
910
911
  !> \param   e           double real 1d array: the subdiagonal elements of a matrix defined in setup
  !> \param   q           double real matrix: on output contains the eigenvectors
912
  !> \param   error       integer, optional : error code, which can be queried with elpa_strerr
913
  abstract interface
914
    subroutine elpa_solve_tridi_d_i (self, d, e, q, error)
915
916
      use iso_c_binding
      import elpa_t
917
      implicit none
918
919
920
921
922
923
924
      class(elpa_t)                   :: self
      real(kind=c_double)             :: d(self%na), e(self%na)
#ifdef USE_ASSUMED_SIZE
      real(kind=c_double)             :: q(self%local_nrows,*)
#else
      real(kind=c_double)             :: q(self%local_nrows,self%local_ncols)
#endif
925
      integer, optional               :: error
926
927
928
    end subroutine
  end interface

929
  !> \brief abstract definition of interface to solve the eigenvalue problem for a single-precision real valued tridiangular matrix
930
931
932
933
934
  !>
  !>  The dimensions of the matrix a (locally ditributed and global), the block-cylic-distribution
  !>  block size, and the MPI communicators are already known to the object and MUST be set BEFORE
  !>  with the class method "setup"
  !>
935
936
  !> Parameters
  !> \param   self        class(elpa_t), the ELPA object
937
938
  !> \param   d           single real 1d array: the diagonal elements of a matrix defined in setup, on output the eigenvalues
  !>                      in ascending order
939
940
  !> \param   e           single real 1d array: the subdiagonal elements of a matrix defined in setup
  !> \param   q           single real matrix: on output contains the eigenvectors
941
  !> \param   error       integer, optional : error code, which can be queried with elpa_strerr
942
  abstract interface
943
    subroutine elpa_solve_tridi_f_i (self, d, e, q, error)
944
945
      use iso_c_binding
      import elpa_t
946
      implicit none
947
948
949
950
951
952
953
      class(elpa_t)                   :: self
      real(kind=c_float)              :: d(self%na), e(self%na)
#ifdef USE_ASSUMED_SIZE
      real(kind=c_float)              :: q(self%local_nrows,*)
#else
      real(kind=c_float)              :: q(self%local_nrows,self%local_ncols)
#endif
954
      integer, optional               :: error
955
956
957
    end subroutine
  end interface

958
  !> \brief abstract definition of interface to destroy an ELPA object
959
960
  !> Parameters
  !> \param   self        class(elpa_t), the ELPA object
961
962
963
  abstract interface
    subroutine elpa_destroy_i(self)
      import elpa_t
964
      implicit none
965
966
967
968
969
970
      class(elpa_t) :: self
    end subroutine
  end interface

  contains

971
972
    !> \brief function to intialise the ELPA library
    !> Parameters
973
974
    !> \param   api_version integer: api_version that ELPA should use
    !> \result  error       integer: error code, which can be queried with elpa_strerr
975
976
977
    !
    !c> int elpa_init(int api_version);
    function elpa_init(api_version) result(error) bind(C, name="elpa_init")
978
      use elpa_utilities, only : error_unit
Andreas Marek's avatar
Andreas Marek committed
979
980
981
      use iso_c_binding
      integer(kind=c_int), intent(in), value :: api_version