elpa_api.F90 37.7 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

Pavel Kus's avatar
Pavel Kus committed
102 103 104 105
      ! call before setup if created from the legacy api
      ! remove this function completely after the legacy api is dropped
      procedure(elpa_creating_from_legacy_api_i), deferred, public :: creating_from_legacy_api

106
      ! Timer
107 108 109 110
      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
111 112


113
      ! Actual math routines
Andreas Marek's avatar
Andreas Marek committed
114 115 116
      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
117 118
          elpa_eigenvectors_dc, &
          elpa_eigenvectors_fc
119

Andreas Marek's avatar
Andreas Marek committed
120 121 122 123 124 125
      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
126 127 128 129 130 131
      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

132 133 134 135 136 137
      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

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

144
      generic, public :: cholesky => &                              !< method for the cholesky factorisation of matrix a
145 146 147 148
          elpa_cholesky_d, &
          elpa_cholesky_f, &
          elpa_cholesky_dc, &
          elpa_cholesky_fc
149

Andreas Marek's avatar
Andreas Marek committed
150
      generic, public :: invert_triangular => &                     !< method to invert a upper triangular matrix a
151 152 153 154
          elpa_invert_trm_d, &
          elpa_invert_trm_f, &
          elpa_invert_trm_dc, &
          elpa_invert_trm_fc
155

156 157
      generic, public :: solve_tridiagonal => &                      !< method to solve the eigenvalue problem for a tridiagonal
          elpa_solve_tridiagonal_d, &                                !< matrix
158 159
          elpa_solve_tridiagonal_f

160 161 162
      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
163
#ifdef ENABLE_AUTOTUNING
164
      ! Auto-tune
165 166 167
      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
168 169 170
      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
171
      procedure(elpa_autotune_load_state_i), deferred, public :: autotune_load_state !< method to load the state
Andreas Marek's avatar
Andreas Marek committed
172
#endif
173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190

      !> \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
191 192 193 194 195
      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

196 197 198 199 200
      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

201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217
      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
218 219
  end type elpa_t

Andreas Marek's avatar
Andreas Marek committed
220
#ifdef ENABLE_AUTOTUNING
221
  !> \brief Abstract definition of the elpa_autotune type
222 223 224 225 226 227
  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
228
#endif
229

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

244

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

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

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

299
  !> \brief abstract definition of the load_settings method
Pavel Kus's avatar
Pavel Kus committed
300 301 302 303
  !> 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
304
  !> \param   error       integer, optional
Pavel Kus's avatar
Pavel Kus committed
305 306
  !> Loads all the elpa parameters
  abstract interface
307
    subroutine load_settings_i(self, file_name, error)
Pavel Kus's avatar
Pavel Kus committed
308 309
      import elpa_t
      implicit none
310 311
      class(elpa_t), intent(inout)   :: self
      character(*), intent(in)       :: file_name
Andreas Marek's avatar
Andreas Marek committed
312
#ifdef USE_FORTRAN2008
313
      integer, optional, intent(out) :: error
Andreas Marek's avatar
Andreas Marek committed
314 315 316
#else
      integer, intent(out)           :: error
#endif
Pavel Kus's avatar
Pavel Kus committed
317 318 319
    end subroutine
  end interface

Andreas Marek's avatar
Andreas Marek committed
320
#ifdef ENABLE_AUTOTUNING
321 322 323 324 325 326 327
  !> \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
328
  abstract interface
329
    function elpa_autotune_setup_i(self, level, domain, error) result(tune_state)
330 331 332
      import elpa_t, elpa_autotune_t
      implicit none
      class(elpa_t), intent(inout), target :: self
333 334 335 336 337 338 339
      integer, intent(in)                  :: level, domain
      class(elpa_autotune_t), pointer      :: tune_state
#ifdef USE_FORTRAN2008
      integer , optional                   :: error
#else
      integer                              :: error
#endif
340 341 342 343
    end function
  end interface


344 345 346 347 348 349
  !> \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
350
  !> \param   error       integer, optional
351
  abstract interface
352
    function elpa_autotune_step_i(self, tune_state, error) result(unfinished)
353 354
      import elpa_t, elpa_autotune_t
      implicit none
355
      class(elpa_t), intent(inout)                  :: self
356
      class(elpa_autotune_t), intent(inout), target :: tune_state
357
      logical                                       :: unfinished
Andreas Marek's avatar
Andreas Marek committed
358
#ifdef USE_FORTRAN2008
359
      integer, optional, intent(out)                :: error
Andreas Marek's avatar
Andreas Marek committed
360 361 362
#else
      integer, intent(out)                          :: error
#endif
363 364 365
    end function
  end interface

366 367 368 369 370 371
  
  !> \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
372
  !> \param   error       integer, optional
373
  !> Sets the best combination of ELPA options
374
  abstract interface
375
    subroutine elpa_autotune_set_best_i(self, tune_state, error)
376 377
      import elpa_t, elpa_autotune_t
      implicit none
378
      class(elpa_t), intent(inout)               :: self
379
      class(elpa_autotune_t), intent(in), target :: tune_state
Andreas Marek's avatar
Andreas Marek committed
380
#ifdef USE_FORTRAN2008
381
      integer, optional, intent(out)             :: error
Andreas Marek's avatar
Andreas Marek committed
382 383 384 385
#else
      integer, intent(out)                       :: error

#endif
386 387
    end subroutine
  end interface
388 389 390 391 392 393 394

  
  !> \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
395
  !> \param   error       integer, optional
396 397
  !> Prints the best combination of ELPA options
  abstract interface
398
    subroutine elpa_autotune_print_best_i(self, tune_state, error)
399 400
      import elpa_t, elpa_autotune_t
      implicit none
401
      class(elpa_t), intent(inout)               :: self
402
      class(elpa_autotune_t), intent(in), target :: tune_state
Andreas Marek's avatar
Andreas Marek committed
403
#ifdef USE_FORTRAN2008
404
      integer, optional, intent(out)             :: error
Andreas Marek's avatar
Andreas Marek committed
405 406 407 408
#else
      integer, intent(out)                       :: error

#endif
409 410
    end subroutine
  end interface
Pavel Kus's avatar
Pavel Kus committed
411 412 413 414 415 416

  !> \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
417
  !> \param   error       integer, optional
418
  !> Prints the autotuning state
Pavel Kus's avatar
Pavel Kus committed
419
  abstract interface
420
    subroutine elpa_autotune_print_state_i(self, tune_state, error)
Pavel Kus's avatar
Pavel Kus committed
421 422
      import elpa_t, elpa_autotune_t
      implicit none
423
      class(elpa_t), intent(inout)               :: self
Pavel Kus's avatar
Pavel Kus committed
424
      class(elpa_autotune_t), intent(in), target :: tune_state
Andreas Marek's avatar
Andreas Marek committed
425
#ifdef USE_FORTRAN2008
426
      integer, optional, intent(out)             :: error
Andreas Marek's avatar
Andreas Marek committed
427 428 429
#else
      integer,  intent(out)                      :: error
#endif
Pavel Kus's avatar
Pavel Kus committed
430 431
    end subroutine
  end interface
432 433 434 435 436 437 438

  !> \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
439
  !> \param   error       integer, optional
440
  !> Saves the autotuning state
441
  abstract interface
442
    subroutine elpa_autotune_save_state_i(self, tune_state, file_name, error)
443 444
      import elpa_t, elpa_autotune_t
      implicit none
445
      class(elpa_t), intent(inout)               :: self
446
      class(elpa_autotune_t), intent(in), target :: tune_state
447
      character(*), intent(in)                   :: file_name
Andreas Marek's avatar
Andreas Marek committed
448
#ifdef USE_FORTRAN2008
449
      integer, optional, intent(out)             :: error
Andreas Marek's avatar
Andreas Marek committed
450 451 452
#else
      integer, intent(out)                       :: error
#endif
453 454
    end subroutine
  end interface
455 456 457 458 459 460 461

  !> \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
462
  !> \param   error       integer, optional
463 464
  !> Loads all the elpa parameters
  abstract interface
465
    subroutine elpa_autotune_load_state_i(self, tune_state, file_name, error)
466 467
      import elpa_t, elpa_autotune_t
      implicit none
468
      class(elpa_t), intent(inout)               :: self
469
      class(elpa_autotune_t), intent(in), target :: tune_state
470
      character(*), intent(in)                   :: file_name
Andreas Marek's avatar
Andreas Marek committed
471
#ifdef USE_FORTRAN2008
472
      integer, optional, intent(out)             :: error
Andreas Marek's avatar
Andreas Marek committed
473 474 475
#else
      integer, intent(out)                       :: error
#endif
476 477
    end subroutine
  end interface
Andreas Marek's avatar
Andreas Marek committed
478
#endif
479

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

503

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

527

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

545

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

565

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

589

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

613

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

631 632 633

  ! Timer routines

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

651

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

665

666 667 668 669 670
  !> \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
671 672 673 674 675 676 677 678 679
  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

680

681 682 683 684 685
  !> \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
686 687 688 689 690 691
  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
692 693 694
    end subroutine
  end interface

695
  ! Actual math routines
696

Andreas Marek's avatar
Andreas Marek committed
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 722 723 724 725
#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
726

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

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

759 760 761
    end subroutine
  end interface

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

Pavel Kus's avatar
Pavel Kus committed
780 781 782 783 784 785 786 787
  abstract interface
    subroutine elpa_creating_from_legacy_api_i(self)
      import elpa_t
      implicit none
      class(elpa_t), intent(inout)          :: self
    end subroutine
  end interface

788 789
  contains

790

Andreas Marek's avatar
Andreas Marek committed
791
    !> \brief function to intialize the ELPA library
792
    !> Parameters
793 794
    !> \param   api_version integer: api_version that ELPA should use
    !> \result  error       integer: error code, which can be queried with elpa_strerr
795 796 797
    !
    !c> int elpa_init(int api_version);
    function elpa_init(api_version) result(error) bind(C, name="elpa_init")
798
      use elpa_utilities, only : error_unit
Andreas Marek's avatar
Andreas Marek committed
799 800 801
      use iso_c_binding
      integer(kind=c_int), intent(in), value :: api_version
      integer(kind=c_int)                    :: error
802 803 804

      if (earliest_api_version <= api_version .and. api_version <= current_api_version) then
        initDone = .true.
Andreas Marek's avatar
Andreas Marek committed
805
        api_version_set = api_version
806 807 808
        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
809
        error = ELPA_ERROR_API_VERSION
810 811 812
      endif
    end function

813

814 815
    !> \brief function to check whether the ELPA library has been correctly initialised
    !> Parameters
816
    !> \result  state      integer: state is either ELPA_OK or ELPA_ERROR, which can be queried with elpa_strerr
817
    function elpa_initialized() result(state)
818 819 820 821
      integer :: state
      if (initDone) then
        state = ELPA_OK
      else
822
        state = ELPA_ERROR_CRITICAL
823
      endif
824 825
    end function

Andreas Marek's avatar
Andreas Marek committed
826 827 828 829 830 831
    function elpa_get_api_version() result(api_version)
       integer :: api_version

       api_version = api_version_set
    end function

832

833
    !> \brief subroutine to uninit the ELPA library. Does nothing at the moment. Might do sth. later
834
    !
835 836 837 838 839 840 841 842
    !c> void elpa_uninit(int *error);
    subroutine elpa_uninit(error) bind(C, name="elpa_uninit")
#ifdef USE_FORTRAN2008
     integer, optional, intent(out) :: error
#else
     integer, intent(out)           :: error
#endif
     if (present(error)) error = ELPA_OK
843 844
    end subroutine

845

846
    !> \brief helper function for error strings
847
    !> Parameters
848 849
    !> \param   elpa_error  integer: error code to querry
    !> \result  string      string:  error string
850 851 852 853 854 855
    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

856

857
    !> \brief helper function for c strings
858 859 860
    !> Parameters
    !> \param   ptr         type(c_ptr)
    !> \result  string      string
861 862 863 864 865 866 867
    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

868

869
    !> \brief function to convert an integer in its string representation
870
    !> Parameters
871 872 873 874
    !> \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
875 876 877 878 879 880
    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
881 882 883 884 885

#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
886
      character(kind=c_char, len=elpa_int_value_to_strlen_c(name // C_NULL_CHAR, value)), pointer :: string
887 888
#endif

889 890 891
      integer(kind=c_int) :: actual_error
      type(c_ptr) :: ptr

892
      actual_error = elpa_int_value_to_string_c(name // C_NULL_CHAR, value, ptr)
893
      if (c_associated(ptr)) then
894 895 896 897
#ifdef PGI_VARIABLE_STRING_BUG
        call c_f_pointer(ptr, string_ptr)
        string = string_ptr
#else
898
        call c_f_pointer(ptr, string)
899
#endif
900
      else
901 902 903
#ifdef PGI_VARIABLE_STRING_BUG
        nullify(string_ptr)
#else
904
        nullify(string)
905
#endif
906 907 908 909 910 911 912 913 914 915
      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

916

917
    !> \brief function to convert a string in its integer representation:
918
    !> Parameters
919 920 921 922
    !> \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
923 924 925 926
    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
927
      character(kind=c_char, len=*), intent(in)         :: name
928
      character(kind=c_char, len=*), intent(in), target :: string
Andreas Marek's avatar
Andreas Marek committed
929 930
      integer(kind=c_int), intent(out), optional        :: error
      integer(kind=c_int)                               :: actual_error
931

Andreas Marek's avatar
Andreas Marek committed
932
      integer(kind=c_int)                               :: value
933

934
      actual_error = elpa_int_string_to_value_c(name // C_NULL_CHAR, string // C_NULL_CHAR, value)
935 936 937 938 939 940 941 942 943

      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

944

945
    !> \brief function to get the number of possible choices for an option
946
    !> Parameters
947 948
    !> \param   option_name string:   the option
    !> \result  number      integer:  the total number of possible values to be chosen
949 950 951 952 953 954 955
    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

956

957