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

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
      class(elpa_t), intent(inout) :: self
251
      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
Pavel Kus's avatar
Pavel Kus committed
259 260
  !> Prints all the elpa parameters
  abstract interface
261
    subroutine print_settings_i(self)
Pavel Kus's avatar
Pavel Kus committed
262 263 264 265 266 267
      import elpa_t
      implicit none
      class(elpa_t), intent(inout) :: self
    end subroutine
  end interface

268
  !> \brief abstract definition of the store_settings method
Pavel Kus's avatar
Pavel Kus committed
269 270
  !> Parameters
  !> \details
Pavel Kus's avatar
Pavel Kus committed
271
  !> \param   self        class(elpa_t): the ELPA object
Pavel Kus's avatar
Pavel Kus committed
272 273 274
  !> \param   file_name   string, the name of the file where to save the parameters
  !> Saves all the elpa parameters
  abstract interface
275
    subroutine store_settings_i(self, file_name)
Pavel Kus's avatar
Pavel Kus committed
276 277 278
      import elpa_t
      implicit none
      class(elpa_t), intent(inout) :: self
Pavel Kus's avatar
Pavel Kus committed
279 280 281 282
      character(*), intent(in)     :: file_name
    end subroutine
  end interface

283
  !> \brief abstract definition of the load_settings method
Pavel Kus's avatar
Pavel Kus committed
284 285 286 287 288 289
  !> 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
  !> Loads all the elpa parameters
  abstract interface
290
    subroutine load_settings_i(self, file_name)
Pavel Kus's avatar
Pavel Kus committed
291 292 293 294
      import elpa_t
      implicit none
      class(elpa_t), intent(inout) :: self
      character(*), intent(in)     :: file_name
Pavel Kus's avatar
Pavel Kus committed
295 296 297
    end subroutine
  end interface

Andreas Marek's avatar
Andreas Marek committed
298
#ifdef ENABLE_AUTOTUNING
299 300 301 302 303 304 305
  !> \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
306
  abstract interface
307
    function elpa_autotune_setup_i(self, level, domain, error) result(tune_state)
308 309 310
      import elpa_t, elpa_autotune_t
      implicit none
      class(elpa_t), intent(inout), target :: self
311 312 313 314 315 316 317
      integer, intent(in)                  :: level, domain
      class(elpa_autotune_t), pointer      :: tune_state
#ifdef USE_FORTRAN2008
      integer , optional                   :: error
#else
      integer                              :: error
#endif
318 319 320 321
    end function
  end interface


322 323 324 325 326 327
  !> \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
328
  !> \param   error       integer, optional
329
  abstract interface
330
    function elpa_autotune_step_i(self, tune_state, error) result(unfinished)
331 332
      import elpa_t, elpa_autotune_t
      implicit none
333
      class(elpa_t), intent(inout)                  :: self
334
      class(elpa_autotune_t), intent(inout), target :: tune_state
335 336
      logical                                       :: unfinished
      integer, optional, intent(out)                :: error
337 338 339
    end function
  end interface

340 341 342 343 344 345
  
  !> \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
346
  !> \param   error       integer, optional
347
  !> Sets the best combination of ELPA options
348
  abstract interface
349
    subroutine elpa_autotune_set_best_i(self, tune_state, error)
350 351
      import elpa_t, elpa_autotune_t
      implicit none
352
      class(elpa_t), intent(inout)               :: self
353
      class(elpa_autotune_t), intent(in), target :: tune_state
354
      integer, optional, intent(out)             :: error
355 356
    end subroutine
  end interface
357 358 359 360 361 362 363

  
  !> \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
364
  !> \param   error       integer, optional
365 366
  !> Prints the best combination of ELPA options
  abstract interface
367
    subroutine elpa_autotune_print_best_i(self, tune_state, error)
368 369
      import elpa_t, elpa_autotune_t
      implicit none
370
      class(elpa_t), intent(inout)               :: self
371
      class(elpa_autotune_t), intent(in), target :: tune_state
372
      integer, optional, intent(out)             :: error
373 374
    end subroutine
  end interface
Pavel Kus's avatar
Pavel Kus committed
375 376 377 378 379 380

  !> \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
381
  !> Prints the autotuning state
Pavel Kus's avatar
Pavel Kus committed
382 383 384 385 386 387 388 389
  abstract interface
    subroutine elpa_autotune_print_state_i(self, tune_state)
      import elpa_t, elpa_autotune_t
      implicit none
      class(elpa_t), intent(inout) :: self
      class(elpa_autotune_t), intent(in), target :: tune_state
    end subroutine
  end interface
390 391 392 393 394 395 396

  !> \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
397
  !> Saves the autotuning state
398 399 400 401 402 403 404 405 406
  abstract interface
    subroutine elpa_autotune_save_state_i(self, tune_state, file_name)
      import elpa_t, elpa_autotune_t
      implicit none
      class(elpa_t), intent(inout) :: self
      class(elpa_autotune_t), intent(in), target :: tune_state
      character(*), intent(in)        :: file_name
    end subroutine
  end interface
407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423

  !> \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
  !> Loads all the elpa parameters
  abstract interface
    subroutine elpa_autotune_load_state_i(self, tune_state, file_name)
      import elpa_t, elpa_autotune_t
      implicit none
      class(elpa_t), intent(inout) :: self
      class(elpa_autotune_t), intent(in), target :: tune_state
      character(*), intent(in)     :: file_name
    end subroutine
  end interface
Andreas Marek's avatar
Andreas Marek committed
424
#endif
425

426 427 428 429 430 431 432
  !> \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()
433
  abstract interface
434
    subroutine elpa_set_integer_i(self, name, value, error)
435 436
      use iso_c_binding
      import elpa_t
437
      implicit none
438 439 440
      class(elpa_t)                   :: self
      character(*), intent(in)        :: name
      integer(kind=c_int), intent(in) :: value
Andreas Marek's avatar
Andreas Marek committed
441
#ifdef USE_FORTRAN2008
442
      integer, optional               :: error
Andreas Marek's avatar
Andreas Marek committed
443 444 445
#else
      integer                         :: error
#endif
446 447 448
    end subroutine
  end interface

449

450 451 452 453 454
  !> \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
455
  !> \param   value       integer : the value corresponding to the key
456
  !> \param   error       integer, optional : error code, which can be queried with elpa_strerr()
457
  abstract interface
458
    subroutine elpa_get_integer_i(self, name, value, error)
459 460
      use iso_c_binding
      import elpa_t
461
      implicit none
462 463 464
      class(elpa_t)                  :: self
      character(*), intent(in)       :: name
      integer(kind=c_int)            :: value
Andreas Marek's avatar
Andreas Marek committed
465
#ifdef USE_FORTRAN2008
466
      integer, intent(out), optional :: error
Andreas Marek's avatar
Andreas Marek committed
467 468 469
#else
      integer, intent(out)           :: error
#endif
470
    end subroutine
471 472
  end interface

473

474 475 476 477 478 479 480
  !> \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
481
  abstract interface
482
    function elpa_is_set_i(self, name) result(state)
483
      import elpa_t
484
      implicit none
485 486
      class(elpa_t)            :: self
      character(*), intent(in) :: name
487
      integer                  :: state
488 489 490
    end function
  end interface

491

492 493 494 495 496 497 498 499
  !> \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
500
  abstract interface
501
    function elpa_can_set_i(self, name, value) result(state)
502
      import elpa_t, c_int
503
      implicit none
504 505 506
      class(elpa_t)                   :: self
      character(*), intent(in)        :: name
      integer(kind=c_int), intent(in) :: value
507
      integer                         :: state
508
    end function
509 510
  end interface

511

512 513 514 515 516 517 518
  !> \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
519
  abstract interface
520
    subroutine elpa_set_double_i(self, name, value, error)
521 522
      use iso_c_binding
      import elpa_t
523
      implicit none
524 525 526
      class(elpa_t)                   :: self
      character(*), intent(in)        :: name
      real(kind=c_double), intent(in) :: value
Andreas Marek's avatar
Andreas Marek committed
527
#ifdef USE_FORTRAN2008
528
      integer, optional               :: error
Andreas Marek's avatar
Andreas Marek committed
529 530 531
#else
      integer                         :: error
#endif
532 533 534
    end subroutine
  end interface

535

536 537 538 539 540
  !> \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
541
  !> \param   value       double: the value associated with the key
542
  !> \param   error       integer, optional : error code, which can be queried with elpa_strerr
543
  abstract interface
544
    subroutine elpa_get_double_i(self, name, value, error)
545 546
      use iso_c_binding
      import elpa_t
547
      implicit none
548 549 550
      class(elpa_t)                  :: self
      character(*), intent(in)       :: name
      real(kind=c_double)            :: value
Andreas Marek's avatar
Andreas Marek committed
551
#ifdef USE_FORTRAN2008
552
      integer, intent(out), optional :: error
Andreas Marek's avatar
Andreas Marek committed
553 554 555
#else
      integer, intent(out)           :: error
#endif
556
    end subroutine
557 558
  end interface

559

560 561 562 563 564
  !> \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
565
  !> \result  value       integer, pointer: the value associated with the key
566 567 568 569
  abstract interface
    function elpa_associate_int_i(self, name) result(value)
      use iso_c_binding
      import elpa_t
570
      implicit none
571 572 573 574 575 576
      class(elpa_t)                  :: self
      character(*), intent(in)       :: name
      integer(kind=c_int), pointer   :: value
    end function
  end interface

577 578 579

  ! Timer routines

580 581 582 583 584 585
  !> \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
586 587 588
  abstract interface
    function elpa_get_time_i(self, name1, name2, name3, name4, name5, name6) result(s)
      import elpa_t, c_double
589
      implicit none
590 591 592 593 594 595 596
      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

597

598 599 600 601
  !> \brief abstract definition of print method for timer
  !> Parameters
  !> \details
  !> \param   self        class(elpa_t): the ELPA object
602
  abstract interface
603
    subroutine elpa_print_times_i(self, name1, name2, name3, name4)
604
      import elpa_t
605
      implicit none
606
      class(elpa_t), intent(in) :: self
607 608 609 610
      character(len=*), intent(in), optional :: name1, name2, name3, name4
    end subroutine
  end interface

611

612 613 614 615 616
  !> \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
617 618 619 620 621 622 623 624 625
  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

626

627 628 629 630 631
  !> \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
632 633 634 635 636 637
  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
638 639 640
    end subroutine
  end interface

641
  ! Actual math routines
642

Andreas Marek's avatar
Andreas Marek committed
643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671
#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
672

673
  !> \brief abstract definition of interface to destroy an ELPA object
674 675
  !> Parameters
  !> \param   self        class(elpa_t), the ELPA object
676 677 678
  abstract interface
    subroutine elpa_destroy_i(self)
      import elpa_t
679
      implicit none
680 681 682 683
      class(elpa_t) :: self
    end subroutine
  end interface

Andreas Marek's avatar
Andreas Marek committed
684
#ifdef ENABLE_AUTOTUNING
685 686 687
  !> \brief abstract definition of interface to print the autotuning state
  !> Parameters
  !> \param   self        class(elpa_autotune_t): the ELPA autotune object
688 689 690 691 692 693 694 695
  abstract interface
    subroutine elpa_autotune_print_i(self)
      import elpa_autotune_t
      implicit none
      class(elpa_autotune_t), intent(in) :: self
    end subroutine
  end interface

696 697 698 699
 
  !> \brief abstract definition of interface to destroy the autotuning state
  !> Parameters
  !> \param   self        class(elpa_autotune_t): the ELPA autotune object
700 701 702 703 704 705 706
  abstract interface
    subroutine elpa_autotune_destroy_i(self)
      import elpa_autotune_t
      implicit none
      class(elpa_autotune_t), intent(inout) :: self
    end subroutine
  end interface
Andreas Marek's avatar
Andreas Marek committed
707
#endif
708

709 710
  contains

711

Andreas Marek's avatar
Andreas Marek committed
712
    !> \brief function to intialize the ELPA library
713
    !> Parameters
714 715
    !> \param   api_version integer: api_version that ELPA should use
    !> \result  error       integer: error code, which can be queried with elpa_strerr
716 717 718
    !
    !c> int elpa_init(int api_version);
    function elpa_init(api_version) result(error) bind(C, name="elpa_init")
719
      use elpa_utilities, only : error_unit
Andreas Marek's avatar
Andreas Marek committed
720 721 722
      use iso_c_binding
      integer(kind=c_int), intent(in), value :: api_version
      integer(kind=c_int)                    :: error
723 724 725

      if (earliest_api_version <= api_version .and. api_version <= current_api_version) then
        initDone = .true.
Andreas Marek's avatar
Andreas Marek committed
726
        api_version_set = api_version
727 728 729 730 731 732 733
        error = ELPA_OK
      else
        write(error_unit, "(a,i0,a)") "ELPA: Error API version ", api_version," is not supported by this library"
        error = ELPA_ERROR
      endif
    end function

734

735 736
    !> \brief function to check whether the ELPA library has been correctly initialised
    !> Parameters
737
    !> \result  state      integer: state is either ELPA_OK or ELPA_ERROR, which can be queried with elpa_strerr
738
    function elpa_initialized() result(state)
739 740 741 742 743 744
      integer :: state
      if (initDone) then
        state = ELPA_OK
      else
        state = ELPA_ERROR
      endif
745 746
    end function

Andreas Marek's avatar
Andreas Marek committed
747 748 749 750 751 752
    function elpa_get_api_version() result(api_version)
       integer :: api_version

       api_version = api_version_set
    end function

753

754
    !> \brief subroutine to uninit the ELPA library. Does nothing at the moment. Might do sth. later
755 756 757
    !
    !c> void elpa_uninit(void);
    subroutine elpa_uninit() bind(C, name="elpa_uninit")
758 759
    end subroutine

760

761
    !> \brief helper function for error strings
762
    !> Parameters
763 764
    !> \param   elpa_error  integer: error code to querry
    !> \result  string      string:  error string
765 766 767 768 769 770
    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

771

772
    !> \brief helper function for c strings
773 774 775
    !> Parameters
    !> \param   ptr         type(c_ptr)
    !> \result  string      string
776 777 778 779 780 781 782
    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

783

784
    !> \brief function to convert an integer in its string representation
785
    !> Parameters
786 787 788 789
    !> \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
790 791 792 793 794 795
    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
796 797 798 799 800

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

804 805 806
      integer(kind=c_int) :: actual_error
      type(c_ptr) :: ptr

807
      actual_error = elpa_int_value_to_string_c(name // C_NULL_CHAR, value, ptr)
808
      if (c_associated(ptr)) then
809 810 811 812
#ifdef PGI_VARIABLE_STRING_BUG
        call c_f_pointer(ptr, string_ptr)
        string = string_ptr
#else
813
        call c_f_pointer(ptr, string)
814
#endif
815
      else
816 817 818
#ifdef PGI_VARIABLE_STRING_BUG
        nullify(string_ptr)
#else
819
        nullify(string)
820
#endif
821 822 823 824 825 826 827 828 829 830
      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

831

832
    !> \brief function to convert a string in its integer representation:
833
    !> Parameters
834 835 836 837
    !> \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
838 839 840 841
    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
842
      character(kind=c_char, len=*), intent(in)         :: name
843
      character(kind=c_char, len=*), intent(in), target :: string
Andreas Marek's avatar
Andreas Marek committed
844 845
      integer(kind=c_int), intent(out), optional        :: error
      integer(kind=c_int)                               :: actual_error
846

Andreas Marek's avatar
Andreas Marek committed
847
      integer(kind=c_int)                               :: value
848

849
      actual_error = elpa_int_string_to_value_c(name // C_NULL_CHAR, string // C_NULL_CHAR, value)
850 851 852 853 854 855 856 857 858

      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

859

860
    !> \brief function to get the number of possible choices for an option
861
    !> Parameters
862 863
    !> \param   option_name string:   the option
    !> \result  number      integer:  the total number of possible values to be chosen
864 865 866 867 868 869 870
    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

871

872
    !> \brief function to enumerate an option
873
    !> Parameters
874
    !> \param   option_name string: the option
875 876
    !> \param   i           integer
    !> \result  option      integer
877 878 879 880 881 882 883 884
    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

885
end module