elpa_api.F90 38.1 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
!
!    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.
!
48
49
!> \brief Fortran module which provides the definition of the ELPA API. Do not use directly! Use the module "elpa"

Andreas Marek's avatar
Andreas Marek committed
50
#include "config-f90.h"
51

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

57
#include "src/elpa_generated_public_fortran_interfaces.h"
58

59
60
61
62
  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

Andreas Marek's avatar
Andreas Marek committed
63
64
65
66
  integer, private, parameter :: earliest_autotune_version = EARLIEST_AUTOTUNE_VERSION !< Definition of the earliest API version
                                                                                       !< which supports autotuning
  integer, private            :: api_version_set
  logical, private            :: initDone = .false.
67
68
69
70
71
72

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

73
  !> \brief Abstract definition of the elpa_t type
74
75
76
  type, abstract :: elpa_t
    private

Andreas Marek's avatar
Andreas Marek committed
77

78
    !< these have to be public for proper bounds checking, sadly
79
80
81
82
83
84
85
86
    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
87
88
      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
89

90
      ! key/value store
91
      generic, public :: set => &                                   !< export a method to set integer/double key/values
92
93
          elpa_set_integer, &
          elpa_set_double
94
95
96
97

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

99
100
      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
101

102
      ! Timer
103
104
105
106
      procedure(elpa_get_time_i), deferred, public :: get_time        !< method to get the times from the timer object
      procedure(elpa_print_times_i), deferred, public :: print_times  !< method to print the timings tree
      procedure(elpa_timer_start_i), deferred, public :: timer_start  !< method to start a time measurement
      procedure(elpa_timer_stop_i), deferred, public :: timer_stop    !< method to stop a time measurement
107
108


109
      ! Actual math routines
Andreas Marek's avatar
Andreas Marek committed
110
111
112
      generic, public :: eigenvectors => &                          !< method eigenvectors for solving the full eigenvalue problem
          elpa_eigenvectors_d, &                                    !< the eigenvalues and (parts of) the eigenvectors are computed
          elpa_eigenvectors_f, &                                    !< for symmetric real valued / hermitian complex valued matrices
113
114
          elpa_eigenvectors_dc, &
          elpa_eigenvectors_fc
115

Andreas Marek's avatar
Andreas Marek committed
116
117
118
119
120
121
      generic, public :: eigenvalues => &                           !< method eigenvalues for solving the eigenvalue problem
          elpa_eigenvalues_d, &                                     !< only the eigenvalues are computed
          elpa_eigenvalues_f, &                                     !< for symmetric real valued / hermitian complex valued matrices
          elpa_eigenvalues_dc, &
          elpa_eigenvalues_fc

Pavel Kus's avatar
Pavel Kus committed
122
123
124
125
126
127
      generic, public :: generalized_eigenvectors => &              !< method eigenvectors for solving the full generalized eigenvalue problem
          elpa_generalized_eigenvectors_d, &                        !< the eigenvalues and (parts of) the eigenvectors are computed
          elpa_generalized_eigenvectors_f, &                        !< for symmetric real valued / hermitian complex valued matrices
          elpa_generalized_eigenvectors_dc, &
          elpa_generalized_eigenvectors_fc

128
129
130
131
132
133
      generic, public :: generalized_eigenvalues => &              !< method eigenvectors for solving the full generalized eigenvalue problem
          elpa_generalized_eigenvalues_d, &                        !< only the eigenvalues
          elpa_generalized_eigenvalues_f, &                        !< for symmetric real valued / hermitian complex valued matrices
          elpa_generalized_eigenvalues_dc, &
          elpa_generalized_eigenvalues_fc

134
      generic, public :: hermitian_multiply => &                    !< method for a "hermitian" multiplication of matrices a and b
135
          elpa_hermitian_multiply_d, &                              !< for real valued matrices:   a**T * b
136
          elpa_hermitian_multiply_dc, &                             !< for complex valued matrices a**H * b
137
138
          elpa_hermitian_multiply_f, &
          elpa_hermitian_multiply_fc
139

140
      generic, public :: cholesky => &                              !< method for the cholesky factorisation of matrix a
141
142
143
144
          elpa_cholesky_d, &
          elpa_cholesky_f, &
          elpa_cholesky_dc, &
          elpa_cholesky_fc
145

Andreas Marek's avatar
Andreas Marek committed
146
      generic, public :: invert_triangular => &                     !< method to invert a upper triangular matrix a
147
148
149
150
          elpa_invert_trm_d, &
          elpa_invert_trm_f, &
          elpa_invert_trm_dc, &
          elpa_invert_trm_fc
151

152
153
      generic, public :: solve_tridiagonal => &                      !< method to solve the eigenvalue problem for a tridiagonal
          elpa_solve_tridiagonal_d, &                                !< matrix
154
155
          elpa_solve_tridiagonal_f

156
157
158
      procedure(print_settings_i), deferred, public :: print_settings !< method to print all parameters
      procedure(store_settings_i), deferred, public :: store_settings !< method to save all parameters
      procedure(load_settings_i), deferred, public :: load_settings !< method to save all parameters
Andreas Marek's avatar
Andreas Marek committed
159
#ifdef ENABLE_AUTOTUNING
160
      ! Auto-tune
161
162
163
      procedure(elpa_autotune_setup_i), deferred, public :: autotune_setup       !< method to prepare the ELPA autotuning
      procedure(elpa_autotune_step_i), deferred, public :: autotune_step         !< method to do an autotuning step
      procedure(elpa_autotune_set_best_i), deferred, public :: autotune_set_best !< method to set the best options
164
165
166
      procedure(elpa_autotune_print_best_i), deferred, public :: autotune_print_best !< method to print the best options
      procedure(elpa_autotune_print_state_i), deferred, public :: autotune_print_state !< method to print the state
      procedure(elpa_autotune_save_state_i), deferred, public :: autotune_save_state !< method to save the state
167
      procedure(elpa_autotune_load_state_i), deferred, public :: autotune_load_state !< method to load the state
Andreas Marek's avatar
Andreas Marek committed
168
#endif
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186

      !> \brief These method have to be public, in order to be overrideable in the extension types
      procedure(elpa_set_integer_i), deferred, public :: elpa_set_integer
      procedure(elpa_set_double_i),  deferred, public :: elpa_set_double

      procedure(elpa_get_integer_i), deferred, public :: elpa_get_integer
      procedure(elpa_get_double_i),  deferred, public :: elpa_get_double

      procedure(elpa_eigenvectors_d_i),    deferred, public :: elpa_eigenvectors_d
      procedure(elpa_eigenvectors_f_i),    deferred, public :: elpa_eigenvectors_f
      procedure(elpa_eigenvectors_dc_i), deferred, public :: elpa_eigenvectors_dc
      procedure(elpa_eigenvectors_fc_i), deferred, public :: elpa_eigenvectors_fc

      procedure(elpa_eigenvalues_d_i),    deferred, public :: elpa_eigenvalues_d
      procedure(elpa_eigenvalues_f_i),    deferred, public :: elpa_eigenvalues_f
      procedure(elpa_eigenvalues_dc_i), deferred, public :: elpa_eigenvalues_dc
      procedure(elpa_eigenvalues_fc_i), deferred, public :: elpa_eigenvalues_fc

Pavel Kus's avatar
Pavel Kus committed
187
188
189
190
191
      procedure(elpa_generalized_eigenvectors_d_i),    deferred, public :: elpa_generalized_eigenvectors_d
      procedure(elpa_generalized_eigenvectors_f_i),    deferred, public :: elpa_generalized_eigenvectors_f
      procedure(elpa_generalized_eigenvectors_dc_i), deferred, public :: elpa_generalized_eigenvectors_dc
      procedure(elpa_generalized_eigenvectors_fc_i), deferred, public :: elpa_generalized_eigenvectors_fc

192
193
194
195
196
      procedure(elpa_generalized_eigenvalues_d_i),    deferred, public :: elpa_generalized_eigenvalues_d
      procedure(elpa_generalized_eigenvalues_f_i),    deferred, public :: elpa_generalized_eigenvalues_f
      procedure(elpa_generalized_eigenvalues_dc_i), deferred, public :: elpa_generalized_eigenvalues_dc
      procedure(elpa_generalized_eigenvalues_fc_i), deferred, public :: elpa_generalized_eigenvalues_fc

197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
      procedure(elpa_hermitian_multiply_d_i),  deferred, public :: elpa_hermitian_multiply_d
      procedure(elpa_hermitian_multiply_f_i),  deferred, public :: elpa_hermitian_multiply_f
      procedure(elpa_hermitian_multiply_dc_i), deferred, public :: elpa_hermitian_multiply_dc
      procedure(elpa_hermitian_multiply_fc_i), deferred, public :: elpa_hermitian_multiply_fc

      procedure(elpa_cholesky_d_i),    deferred, public :: elpa_cholesky_d
      procedure(elpa_cholesky_f_i),    deferred, public :: elpa_cholesky_f
      procedure(elpa_cholesky_dc_i), deferred, public :: elpa_cholesky_dc
      procedure(elpa_cholesky_fc_i), deferred, public :: elpa_cholesky_fc

      procedure(elpa_invert_trm_d_i),    deferred, public :: elpa_invert_trm_d
      procedure(elpa_invert_trm_f_i),    deferred, public :: elpa_invert_trm_f
      procedure(elpa_invert_trm_dc_i), deferred, public :: elpa_invert_trm_dc
      procedure(elpa_invert_trm_fc_i), deferred, public :: elpa_invert_trm_fc

      procedure(elpa_solve_tridiagonal_d_i), deferred, public :: elpa_solve_tridiagonal_d
      procedure(elpa_solve_tridiagonal_f_i), deferred, public :: elpa_solve_tridiagonal_f
214
215
  end type elpa_t

Andreas Marek's avatar
Andreas Marek committed
216
#ifdef ENABLE_AUTOTUNING
217
  !> \brief Abstract definition of the elpa_autotune type
218
219
220
221
222
223
  type, abstract :: elpa_autotune_t
    private
    contains
      procedure(elpa_autotune_destroy_i), deferred, public :: destroy
      procedure(elpa_autotune_print_i), deferred, public :: print
  end type
Andreas Marek's avatar
Andreas Marek committed
224
#endif
225

226
227
228
229
230
  !> \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
231
232
233
  interface
    pure function elpa_strlen_c(ptr) result(size) bind(c, name="strlen")
      use, intrinsic :: iso_c_binding
234
      implicit none
235
236
237
238
239
      type(c_ptr), intent(in), value :: ptr
      integer(kind=c_size_t) :: size
    end function
  end interface

240

241
  !> \brief abstract definition of the ELPA setup method
242
243
244
245
  !> Parameters
  !> \details
  !> \param   self        class(elpa_t): the ELPA object
  !> \result  error       integer : error code, which can be queried with elpa_strerr()
246
  abstract interface
247
    function elpa_setup_i(self) result(error)
248
      import elpa_t
249
      implicit none
250
251
      class(elpa_t), intent(inout)   :: self
      integer                        :: error
252
253
254
    end function
  end interface

255
  !> \brief abstract definition of the print_settings method
Pavel Kus's avatar
Pavel Kus committed
256
257
  !> Parameters
  !> \details
Pavel Kus's avatar
Pavel Kus committed
258
  !> \param   self        class(elpa_t): the ELPA object
259
  !> \param   error       integer, optional
Pavel Kus's avatar
Pavel Kus committed
260
261
  !> Prints all the elpa parameters
  abstract interface
262
    subroutine print_settings_i(self, error)
Pavel Kus's avatar
Pavel Kus committed
263
264
      import elpa_t
      implicit none
265
      class(elpa_t), intent(inout)   :: self
Andreas Marek's avatar
Andreas Marek committed
266
#ifdef USE_FORTRAN2008
267
      integer, optional, intent(out) :: error
Andreas Marek's avatar
Andreas Marek committed
268
269
270
#else
      integer, intent(out)           :: error
#endif
Pavel Kus's avatar
Pavel Kus committed
271
272
273
    end subroutine
  end interface

274
  !> \brief abstract definition of the store_settings method
Pavel Kus's avatar
Pavel Kus committed
275
276
  !> Parameters
  !> \details
Pavel Kus's avatar
Pavel Kus committed
277
  !> \param   self        class(elpa_t): the ELPA object
Pavel Kus's avatar
Pavel Kus committed
278
  !> \param   file_name   string, the name of the file where to save the parameters
279
  !> \param   error       integer, optional
Pavel Kus's avatar
Pavel Kus committed
280
281
  !> Saves all the elpa parameters
  abstract interface
282
    subroutine store_settings_i(self, file_name, error)
Pavel Kus's avatar
Pavel Kus committed
283
284
      import elpa_t
      implicit none
285
286
      class(elpa_t), intent(inout)  :: self
      character(*), intent(in)      :: file_name
Andreas Marek's avatar
Andreas Marek committed
287
#ifdef USE_FORTRAN2008
288
      integer, optional, intent(out):: error
Andreas Marek's avatar
Andreas Marek committed
289
290
291
#else
      integer, intent(out)          :: error
#endif
Pavel Kus's avatar
Pavel Kus committed
292
293
294
    end subroutine
  end interface

295
  !> \brief abstract definition of the load_settings method
Pavel Kus's avatar
Pavel Kus committed
296
297
298
299
  !> Parameters
  !> \details
  !> \param   self        class(elpa_t): the ELPA object
  !> \param   file_name   string, the name of the file from which to load the parameters
300
  !> \param   error       integer, optional
Pavel Kus's avatar
Pavel Kus committed
301
302
  !> Loads all the elpa parameters
  abstract interface
303
    subroutine load_settings_i(self, file_name, error)
Pavel Kus's avatar
Pavel Kus committed
304
305
      import elpa_t
      implicit none
306
307
      class(elpa_t), intent(inout)   :: self
      character(*), intent(in)       :: file_name
Andreas Marek's avatar
Andreas Marek committed
308
#ifdef USE_FORTRAN2008
309
      integer, optional, intent(out) :: error
Andreas Marek's avatar
Andreas Marek committed
310
311
312
#else
      integer, intent(out)           :: error
#endif
Pavel Kus's avatar
Pavel Kus committed
313
314
315
    end subroutine
  end interface

Andreas Marek's avatar
Andreas Marek committed
316
#ifdef ENABLE_AUTOTUNING
317
318
319
320
321
322
323
  !> \brief abstract definition of the autotune setup method
  !> Parameters
  !> \details
  !> \param   self        class(elpa_t): the ELPA object, which should be tuned
  !> \param   level       integer: the level of "thoroughness" of the tuning steps
  !> \param   domain      integer: domain (real/complex) which should be tuned
  !> \result  tune_state  class(elpa_autotune_t): the autotuning object
324
  abstract interface
325
    function elpa_autotune_setup_i(self, level, domain, error) result(tune_state)
326
327
328
      import elpa_t, elpa_autotune_t
      implicit none
      class(elpa_t), intent(inout), target :: self
329
330
331
332
333
334
335
      integer, intent(in)                  :: level, domain
      class(elpa_autotune_t), pointer      :: tune_state
#ifdef USE_FORTRAN2008
      integer , optional                   :: error
#else
      integer                              :: error
#endif
336
337
338
339
    end function
  end interface


340
341
342
343
344
345
  !> \brief abstract definition of the autotune step method
  !> Parameters
  !> \details
  !> \param   self        class(elpa_t): the ELPA object, which should be tuned
  !> \param   tune_state  class(elpa_autotune_t): the autotuning object
  !> \param   unfinished  logical: state whether tuning is unfinished or not
346
  !> \param   error       integer, optional
347
  abstract interface
348
    function elpa_autotune_step_i(self, tune_state, error) result(unfinished)
349
350
      import elpa_t, elpa_autotune_t
      implicit none
351
      class(elpa_t), intent(inout)                  :: self
352
      class(elpa_autotune_t), intent(inout), target :: tune_state
353
      logical                                       :: unfinished
Andreas Marek's avatar
Andreas Marek committed
354
#ifdef USE_FORTRAN2008
355
      integer, optional, intent(out)                :: error
Andreas Marek's avatar
Andreas Marek committed
356
357
358
#else
      integer, intent(out)                          :: error
#endif
359
360
361
    end function
  end interface

362
363
364
365
366
367
  
  !> \brief abstract definition of the autotune set_best method
  !> Parameters
  !> \details
  !> \param   self        class(elpa_t): the ELPA object, which should be tuned
  !> \param   tune_state  class(elpa_autotune_t): the autotuning object
368
  !> \param   error       integer, optional
369
  !> Sets the best combination of ELPA options
370
  abstract interface
371
    subroutine elpa_autotune_set_best_i(self, tune_state, error)
372
373
      import elpa_t, elpa_autotune_t
      implicit none
374
      class(elpa_t), intent(inout)               :: self
375
      class(elpa_autotune_t), intent(in), target :: tune_state
Andreas Marek's avatar
Andreas Marek committed
376
#ifdef USE_FORTRAN2008
377
      integer, optional, intent(out)             :: error
Andreas Marek's avatar
Andreas Marek committed
378
379
380
381
#else
      integer, intent(out)                       :: error

#endif
382
383
    end subroutine
  end interface
384
385
386
387
388
389
390

  
  !> \brief abstract definition of the autotune print best method
  !> Parameters
  !> \details
  !> \param   self        class(elpa_t): the ELPA object, which should be tuned
  !> \param   tune_state  class(elpa_autotune_t): the autotuning object
391
  !> \param   error       integer, optional
392
393
  !> Prints the best combination of ELPA options
  abstract interface
394
    subroutine elpa_autotune_print_best_i(self, tune_state, error)
395
396
      import elpa_t, elpa_autotune_t
      implicit none
397
      class(elpa_t), intent(inout)               :: self
398
      class(elpa_autotune_t), intent(in), target :: tune_state
Andreas Marek's avatar
Andreas Marek committed
399
#ifdef USE_FORTRAN2008
400
      integer, optional, intent(out)             :: error
Andreas Marek's avatar
Andreas Marek committed
401
402
403
404
#else
      integer, intent(out)                       :: error

#endif
405
406
    end subroutine
  end interface
Pavel Kus's avatar
Pavel Kus committed
407
408
409
410
411
412

  !> \brief abstract definition of the autotune print state method
  !> Parameters
  !> \details
  !> \param   self        class(elpa_t): the ELPA object, which should be tuned
  !> \param   tune_state  class(elpa_autotune_t): the autotuning object
413
  !> \param   error       integer, optional
414
  !> Prints the autotuning state
Pavel Kus's avatar
Pavel Kus committed
415
  abstract interface
416
    subroutine elpa_autotune_print_state_i(self, tune_state, error)
Pavel Kus's avatar
Pavel Kus committed
417
418
      import elpa_t, elpa_autotune_t
      implicit none
419
      class(elpa_t), intent(inout)               :: self
Pavel Kus's avatar
Pavel Kus committed
420
      class(elpa_autotune_t), intent(in), target :: tune_state
Andreas Marek's avatar
Andreas Marek committed
421
#ifdef USE_FORTRAN2008
422
      integer, optional, intent(out)             :: error
Andreas Marek's avatar
Andreas Marek committed
423
424
425
#else
      integer,  intent(out)                      :: error
#endif
Pavel Kus's avatar
Pavel Kus committed
426
427
    end subroutine
  end interface
428
429
430
431
432
433
434

  !> \brief abstract definition of the autotune save state method
  !> Parameters
  !> \details
  !> \param   self        class(elpa_t): the ELPA object, which should be tuned
  !> \param   tune_state  class(elpa_autotune_t): the autotuning object
  !> \param   file_name   string, the name of the file where to save the state
435
  !> \param   error       integer, optional
436
  !> Saves the autotuning state
437
  abstract interface
438
    subroutine elpa_autotune_save_state_i(self, tune_state, file_name, error)
439
440
      import elpa_t, elpa_autotune_t
      implicit none
441
      class(elpa_t), intent(inout)               :: self
442
      class(elpa_autotune_t), intent(in), target :: tune_state
443
      character(*), intent(in)                   :: file_name
Andreas Marek's avatar
Andreas Marek committed
444
#ifdef USE_FORTRAN2008
445
      integer, optional, intent(out)             :: error
Andreas Marek's avatar
Andreas Marek committed
446
447
448
#else
      integer, intent(out)                       :: error
#endif
449
450
    end subroutine
  end interface
451
452
453
454
455
456
457

  !> \brief abstract definition of the autotune load state method
  !> Parameters
  !> \details
  !> \param   self        class(elpa_t): the ELPA object, which is being tuned
  !> \param   tune_state  class(elpa_autotune_t): the autotuning object
  !> \param   file_name   string, the name of the file from which to load the autotuning state
458
  !> \param   error       integer, optional
459
460
  !> Loads all the elpa parameters
  abstract interface
461
    subroutine elpa_autotune_load_state_i(self, tune_state, file_name, error)
462
463
      import elpa_t, elpa_autotune_t
      implicit none
464
      class(elpa_t), intent(inout)               :: self
465
      class(elpa_autotune_t), intent(in), target :: tune_state
466
      character(*), intent(in)                   :: file_name
Andreas Marek's avatar
Andreas Marek committed
467
#ifdef USE_FORTRAN2008
468
      integer, optional, intent(out)             :: error
Andreas Marek's avatar
Andreas Marek committed
469
470
471
#else
      integer, intent(out)                       :: error
#endif
472
473
    end subroutine
  end interface
Andreas Marek's avatar
Andreas Marek committed
474
#endif
475

476
477
478
479
480
481
482
  !> \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()
483
  abstract interface
484
    subroutine elpa_set_integer_i(self, name, value, error)
485
486
      use iso_c_binding
      import elpa_t
487
      implicit none
488
489
490
      class(elpa_t)                   :: self
      character(*), intent(in)        :: name
      integer(kind=c_int), intent(in) :: value
Andreas Marek's avatar
Andreas Marek committed
491
#ifdef USE_FORTRAN2008
492
      integer, optional               :: error
Andreas Marek's avatar
Andreas Marek committed
493
494
495
#else
      integer                         :: error
#endif
496
497
498
    end subroutine
  end interface

499

500
501
502
503
504
  !> \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
505
  !> \param   value       integer : the value corresponding to the key
506
  !> \param   error       integer, optional : error code, which can be queried with elpa_strerr()
507
  abstract interface
508
    subroutine elpa_get_integer_i(self, name, value, error)
509
510
      use iso_c_binding
      import elpa_t
511
      implicit none
512
513
514
      class(elpa_t)                  :: self
      character(*), intent(in)       :: name
      integer(kind=c_int)            :: value
Andreas Marek's avatar
Andreas Marek committed
515
#ifdef USE_FORTRAN2008
516
      integer, intent(out), optional :: error
Andreas Marek's avatar
Andreas Marek committed
517
518
519
#else
      integer, intent(out)           :: error
#endif
520
    end subroutine
521
522
  end interface

523

524
525
526
527
528
529
530
  !> \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
531
  abstract interface
532
    function elpa_is_set_i(self, name) result(state)
533
      import elpa_t
534
      implicit none
535
536
      class(elpa_t)            :: self
      character(*), intent(in) :: name
537
      integer                  :: state
538
539
540
    end function
  end interface

541

542
543
544
545
546
547
548
549
  !> \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
550
  abstract interface
551
    function elpa_can_set_i(self, name, value) result(state)
552
      import elpa_t, c_int
553
      implicit none
554
555
556
      class(elpa_t)                   :: self
      character(*), intent(in)        :: name
      integer(kind=c_int), intent(in) :: value
557
      integer                         :: state
558
    end function
559
560
  end interface

561

562
563
564
565
566
567
568
  !> \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
569
  abstract interface
570
    subroutine elpa_set_double_i(self, name, value, error)
571
572
      use iso_c_binding
      import elpa_t
573
      implicit none
574
575
576
      class(elpa_t)                   :: self
      character(*), intent(in)        :: name
      real(kind=c_double), intent(in) :: value
Andreas Marek's avatar
Andreas Marek committed
577
#ifdef USE_FORTRAN2008
578
      integer, optional               :: error
Andreas Marek's avatar
Andreas Marek committed
579
580
581
#else
      integer                         :: error
#endif
582
583
584
    end subroutine
  end interface

585

586
587
588
589
590
  !> \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
591
  !> \param   value       double: the value associated with the key
592
  !> \param   error       integer, optional : error code, which can be queried with elpa_strerr
593
  abstract interface
594
    subroutine elpa_get_double_i(self, name, value, error)
595
596
      use iso_c_binding
      import elpa_t
597
      implicit none
598
599
600
      class(elpa_t)                  :: self
      character(*), intent(in)       :: name
      real(kind=c_double)            :: value
Andreas Marek's avatar
Andreas Marek committed
601
#ifdef USE_FORTRAN2008
602
      integer, intent(out), optional :: error
Andreas Marek's avatar
Andreas Marek committed
603
604
605
#else
      integer, intent(out)           :: error
#endif
606
    end subroutine
607
608
  end interface

609

610
611
612
613
614
  !> \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
615
  !> \result  value       integer, pointer: the value associated with the key
616
617
618
619
  abstract interface
    function elpa_associate_int_i(self, name) result(value)
      use iso_c_binding
      import elpa_t
620
      implicit none
621
622
623
624
625
626
      class(elpa_t)                  :: self
      character(*), intent(in)       :: name
      integer(kind=c_int), pointer   :: value
    end function
  end interface

627
628
629

  ! Timer routines

630
631
632
633
634
635
  !> \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
636
637
638
  abstract interface
    function elpa_get_time_i(self, name1, name2, name3, name4, name5, name6) result(s)
      import elpa_t, c_double
639
      implicit none
640
641
642
643
644
645
646
      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

647

648
649
650
651
  !> \brief abstract definition of print method for timer
  !> Parameters
  !> \details
  !> \param   self        class(elpa_t): the ELPA object
652
  abstract interface
653
    subroutine elpa_print_times_i(self, name1, name2, name3, name4)
654
      import elpa_t
655
      implicit none
656
      class(elpa_t), intent(in) :: self
657
658
659
660
      character(len=*), intent(in), optional :: name1, name2, name3, name4
    end subroutine
  end interface

661

662
663
664
665
666
  !> \brief abstract definition of the start method for timer
  !> Parameters
  !> \details
  !> \param   self        class(elpa_t): the ELPA object
  !> \param   name        character(len=*) the name of the entry int the timer tree
667
668
669
670
671
672
673
674
675
  abstract interface
    subroutine elpa_timer_start_i(self, name)
      import elpa_t
      implicit none
      class(elpa_t), intent(inout) :: self
      character(len=*), intent(in) :: name
    end subroutine
  end interface

676

677
678
679
680
681
  !> \brief abstract definition of the stop method for timer
  !> Parameters
  !> \details
  !> \param   self        class(elpa_t): the ELPA object
  !> \param   name        character(len=*) the name of the entry int the timer tree
682
683
684
685
686
687
  abstract interface
    subroutine elpa_timer_stop_i(self, name)
      import elpa_t
      implicit none
      class(elpa_t), intent(inout) :: self
      character(len=*), intent(in) :: name
688
689
690
    end subroutine
  end interface

691
  ! Actual math routines
692

Andreas Marek's avatar
Andreas Marek committed
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
#define REALCASE 1
#define DOUBLE_PRECISION 1
#include "general/precision_macros.h"
#include "elpa_api_math_template.F90"
#undef REALCASE
#undef DOUBLE_PRECISION

#define REALCASE 1
#define SINGLE_PRECISION 1
#include "general/precision_macros.h"
#include "elpa_api_math_template.F90"
#undef REALCASE
#undef SINGLE_PRECISION

#define COMPLEXCASE 1
#define DOUBLE_PRECISION 1
#include "general/precision_macros.h"
#include "elpa_api_math_template.F90"
#undef DOUBLE_PRECISION
#undef COMPLEXCASE

#define COMPLEXCASE 1
#define SINGLE_PRECISION
#include "general/precision_macros.h"
#include "elpa_api_math_template.F90"
#undef COMPLEXCASE
#undef SINGLE_PRECISION

! end of math routines
722

723
  !> \brief abstract definition of interface to destroy an ELPA object
724
725
  !> Parameters
  !> \param   self        class(elpa_t), the ELPA object
726
  !> \param   error       integer, optional, the error code
727
  abstract interface
728
    subroutine elpa_destroy_i(self, error)
729
      import elpa_t
730
      implicit none
731
732
733
734
735
736
      class(elpa_t)                  :: self
#ifdef USE_FORTRAN2008
      integer, optional, intent(out) :: error
#else
      integer, intent(out)           :: error
#endif
737
738
739
    end subroutine
  end interface

Andreas Marek's avatar
Andreas Marek committed
740
#ifdef ENABLE_AUTOTUNING
741
742
743
  !> \brief abstract definition of interface to print the autotuning state
  !> Parameters
  !> \param   self        class(elpa_autotune_t): the ELPA autotune object
744
  abstract interface
Andreas Marek's avatar
Andreas Marek committed
745
    subroutine elpa_autotune_print_i(self, error)
746
747
748
      import elpa_autotune_t
      implicit none
      class(elpa_autotune_t), intent(in) :: self
Andreas Marek's avatar
Andreas Marek committed
749
#ifdef USE_FORTRAN2008
750
      integer, intent(out), optional     :: error
Andreas Marek's avatar
Andreas Marek committed
751
#else
752
      integer, intent(out)               :: error
Andreas Marek's avatar
Andreas Marek committed
753
754
#endif

755
756
757
    end subroutine
  end interface

758
759
760
761
 
  !> \brief abstract definition of interface to destroy the autotuning state
  !> Parameters
  !> \param   self        class(elpa_autotune_t): the ELPA autotune object
762
  abstract interface
763
    subroutine elpa_autotune_destroy_i(self, error)
764
765
766
      import elpa_autotune_t
      implicit none
      class(elpa_autotune_t), intent(inout) :: self
767
768
769
770
771
#ifdef USE_FORTRAN2008
      integer, optional, intent(out)        :: error
#else
      integer, intent(out)                  :: error
#endif
772
773
    end subroutine
  end interface
Andreas Marek's avatar
Andreas Marek committed
774
#endif
775

776
777
  contains

778

Andreas Marek's avatar
Andreas Marek committed
779
    !> \brief function to intialize the ELPA library
780
    !> Parameters
781
782
    !> \param   api_version integer: api_version that ELPA should use
    !> \result  error       integer: error code, which can be queried with elpa_strerr
783
784
785
    !
    !c> int elpa_init(int api_version);
    function elpa_init(api_version) result(error) bind(C, name="elpa_init")
786
      use elpa_utilities, only : error_unit
Andreas Marek's avatar
Andreas Marek committed
787
788
789
      use iso_c_binding
      integer(kind=c_int), intent(in), value :: api_version
      integer(kind=c_int)                    :: error
790
791
792

      if (earliest_api_version <= api_version .and. api_version <= current_api_version) then
        initDone = .true.
Andreas Marek's avatar
Andreas Marek committed
793
        api_version_set = api_version
794
795
796
        error = ELPA_OK
      else
        write(error_unit, "(a,i0,a)") "ELPA: Error API version ", api_version," is not supported by this library"
Andreas Marek's avatar
Andreas Marek committed
797
        error = ELPA_ERROR_API_VERSION
798
799
800
      endif
    end function

801

802
803
    !> \brief function to check whether the ELPA library has been correctly initialised
    !> Parameters
804
    !> \result  state      integer: state is either ELPA_OK or ELPA_ERROR, which can be queried with elpa_strerr
805
    function elpa_initialized() result(state)
806
807
808
809
      integer :: state
      if (initDone) then
        state = ELPA_OK
      else
810
        state = ELPA_ERROR_CRITICAL
811
      endif
812
813
    end function

Andreas Marek's avatar
Andreas Marek committed
814
815
816
817
818
819
    function elpa_get_api_version() result(api_version)
       integer :: api_version

       api_version = api_version_set
    end function

Andreas Marek's avatar
Andreas Marek committed
820
821
822
823
824
#ifdef OPTIONAL_C_ERROR_ARGUMENT
    !c_o> #ifdef OPTIONAL_C_ERROR_ARGUMENT
    !c_o> #define elpa_uninit(...) CONC(elpa_uninit, NARGS(__VA_ARGS__))(__VA_ARGS__)
    !c_o> #endif
#endif
825
    !> \brief subroutine to uninit the ELPA library. Does nothing at the moment. Might do sth. later
826
    !
Andreas Marek's avatar
Andreas Marek committed
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
#ifdef OPTIONAL_C_ERROR_ARGUMENT
    !c_o> #ifdef OPTIONAL_C_ERROR_ARGUMENT
    !c_o> void elpa_uninit1(int *error);
    !c_o> void elpa_uninit0();
    !c_o> #endif
    subroutine elpa_uninit_c1(error) bind(C, name="elpa_uninit1")
      integer(kind=c_int)        :: error
      call elpa_uninit(error)
    end subroutine

    subroutine elpa_uninit_c0() bind(C, name="elpa_uninit0")
      call elpa_uninit()
    end subroutine
#else
    !c_no> #ifndef OPTIONAL_C_ERROR_ARGUMENT
    !c_no> void elpa_uninit(int *error);
    !c_no> #endif
    subroutine elpa_uninit_c(error) bind(C, name="elpa_uninit")
      integer(kind=c_int)        :: error
      call elpa_uninit(error)
    end subroutine
#endif

    subroutine elpa_uninit(error)
851
#ifdef USE_FORTRAN2008
Andreas Marek's avatar
Andreas Marek committed
852
      integer, optional, intent(out) :: error
853
#else
Andreas Marek's avatar
Andreas Marek committed
854
855
856
857
858
859
860
      integer, intent(out)           :: error
#endif
#ifdef USE_FORTRAN2008
      if (present(error)) then
        error = ELPA_OK
        return
      endif
861
#endif
862
    end subroutine
863
    !> \brief helper function for error strings
864
    !> Parameters
865
866
    !> \param   elpa_error  integer: error code to querry
    !> \result  string      string:  error string
867
868
869
870
871
872
    function elpa_strerr(elpa_error) result(string)
      integer, intent(in) :: elpa_error
      character(kind=C_CHAR, len=elpa_strlen_c(elpa_strerr_c(elpa_error))), pointer :: string
      call c_f_pointer(elpa_strerr_c(elpa_error), string)
    end function

873

874
    !> \brief helper function for c strings
875
876
877
    !> Parameters
    !> \param   ptr         type(c_ptr)
    !> \result  string      string
878
879
880
881
882
883
884
    function elpa_c_string(ptr) result(string)
      use, intrinsic :: iso_c_binding
      type(c_ptr), intent(in) :: ptr
      character(kind=c_char, len=elpa_strlen_c(ptr)), pointer :: string
      call c_f_pointer(ptr, string)
    end function

885

886
    !> \brief function to convert an integer in its string representation
887
    !> Parameters
888
889
890
891
    !> \param   name        string: the key
    !> \param   value       integer: the value correponding to the key
    !> \param   error       integer, optional: error code, which can be queried with elpa_strerr()
    !> \result  string      string: the string representation
892
893
894
895
896
897
    function elpa_int_value_to_string(name, value, error) result(string)
      use elpa_utilities, only : error_unit
      implicit none
      character(kind=c_char, len=*), intent(in) :: name
      integer(kind=c_int), intent(in) :: value
      integer(kind=c_int), intent(out), optional :: error
898
899
900
901
902

#ifdef PGI_VARIABLE_STRING_BUG
      character(kind=c_char, len=elpa_int_value_to_strlen_c(name // C_NULL_CHAR, value)), pointer :: string_ptr
      character(kind=c_char, len=elpa_int_value_to_strlen_c(name // C_NULL_CHAR, value)) :: string
#else
903
      character(kind=c_char, len=elpa_int_value_to_strlen_c(name // C_NULL_CHAR, value)), pointer :: string
904
905
#endif

906
907
908
      integer(kind=c_int) :: actual_error
      type(c_ptr) :: ptr

909
      actual_error = elpa_int_value_to_string_c(name // C_NULL_CHAR, value, ptr)
910
      if (c_associated(ptr)) then
911
912
913
914
#ifdef PGI_VARIABLE_STRING_BUG
        call c_f_pointer(ptr, string_ptr)
        string = string_ptr
#else
915
        call c_f_pointer(ptr, string)
916
#endif
917
      else
918
919
920
#ifdef PGI_VARIABLE_STRING_BUG
        nullify(string_ptr)
#else
921
        nullify(string)
922
#endif
923
924
925
926
927
928
929
930
931
932
      endif

      if (present(error)) then
        error = actual_error
      else if (actual_error /= ELPA_OK) then
        write(error_unit,'(a,i0,a)') "ELPA: Error converting value '", value, "' to a string for option '" // &
                name // "' and you did not check for errors: " // elpa_strerr(actual_error)
      endif
    end function

933

934
    !> \brief function to convert a string in its integer representation:
935
    !> Parameters
936
937
938
939
    !> \param   name        string: the key
    !> \param   string      string: the string whose integer representation should be associated with the key
    !> \param   error       integer, optional: error code, which can be queried with elpa_strerr()
    !> \result  value       integer: the integer representation of the string
940
941
942
943
    function elpa_int_string_to_value(name, string, error) result(value)
      use elpa_generated_fortran_interfaces
      use elpa_utilities, only : error_unit
      implicit none
Andreas Marek's avatar
Andreas Marek committed
944
      character(kind=c_char, len=*), intent(in)         :: name
945
      character(kind=c_char, len=*), intent(in), target :: string
Andreas Marek's avatar
Andreas Marek committed
946
947
      integer(kind=c_int), intent(out), optional        :: error
      integer(kind=c_int)                               :: actual_error
948

Andreas Marek's avatar
Andreas Marek committed
949
      integer(kind=c_int)                               :: value
950

951
      actual_error = elpa_int_string_to_value_c(name // C_NULL_CHAR, string // C_NULL_CHAR, value)
952
953
954
955
956
957
958
959
960

      if (present(error)) then
        error = actual_error
      else if (actual_error /= ELPA_OK) then
        write(error_unit,'(a)') "ELPA: Error converting string '" // string // "' to value for option '" // &
                name // "' and you did not check for errors: " // elpa_strerr(actual_error)
      endif
    end function

961

962
    !> \brief function to get the number of possible choices for an option
963
    !> Parameters
964
965
    !> \param   option_name string:   the option
    !> \result  number      integer:  the total number of possible values to be chosen
966
967
968
969
970
971
972
    function elpa_option_cardinality(option_name) result(number)
      use elpa_generated_fortran_interfaces
      character(kind=c_char, len=*), intent(in) :: option_name
      integer                                   :: number
      number = elpa_option_cardinality_c(option_name // C_NULL_CHAR)
    end function

973

974
    !> \brief function to enumerate an option
975
    !> Parameters
976
    !> \param   option_name string: the option
977
978
    !> \param   i           integer
    !> \result  option      integer
979
980
981
982
983
984
985
986
    function elpa_option_enumerate(option_name, i) result(option)
      use elpa_generated_fortran_interfaces
      character(kind=c_char, len=*), intent(in) :: option_name
      integer, intent(in)                       :: i
      integer                                   :: option
      option = elpa_option_enumerate_c(option_name // C_NULL_CHAR, i)
    end function

987
end module