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

820

821
    !> \brief subroutine to uninit the ELPA library. Does nothing at the moment. Might do sth. later
822
    !
823 824 825 826 827 828 829 830
    !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
831 832
    end subroutine

833

834
    !> \brief helper function for error strings
835
    !> Parameters
836 837
    !> \param   elpa_error  integer: error code to querry
    !> \result  string      string:  error string
838 839 840 841 842 843
    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

844

845
    !> \brief helper function for c strings
846 847 848
    !> Parameters
    !> \param   ptr         type(c_ptr)
    !> \result  string      string
849 850 851 852 853 854 855
    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

856

857
    !> \brief function to convert an integer in its string representation
858
    !> Parameters
859 860 861 862
    !> \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
863 864 865 866 867 868
    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
869 870 871 872 873

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

877 878 879
      integer(kind=c_int) :: actual_error
      type(c_ptr) :: ptr

880
      actual_error = elpa_int_value_to_string_c(name // C_NULL_CHAR, value, ptr)
881
      if (c_associated(ptr)) then
882 883 884 885
#ifdef PGI_VARIABLE_STRING_BUG
        call c_f_pointer(ptr, string_ptr)
        string = string_ptr
#else
886
        call c_f_pointer(ptr, string)
887
#endif
888
      else
889 890 891
#ifdef PGI_VARIABLE_STRING_BUG
        nullify(string_ptr)
#else
892
        nullify(string)
893
#endif
894 895 896 897 898 899 900 901 902 903
      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

904

905
    !> \brief function to convert a string in its integer representation:
906
    !> Parameters
907 908 909 910
    !> \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
911 912 913 914
    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
915
      character(kind=c_char, len=*), intent(in)         :: name
916
      character(kind=c_char, len=*), intent(in), target :: string
Andreas Marek's avatar
Andreas Marek committed
917 918
      integer(kind=c_int), intent(out), optional        :: error
      integer(kind=c_int)                               :: actual_error
919

Andreas Marek's avatar
Andreas Marek committed
920
      integer(kind=c_int)                               :: value
921

922
      actual_error = elpa_int_string_to_value_c(name // C_NULL_CHAR, string // C_NULL_CHAR, value)
923 924 925 926 927 928 929 930 931

      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

932

933
    !> \brief function to get the number of possible choices for an option
934
    !> Parameters
935 936
    !> \param   option_name string:   the option
    !> \result  number      integer:  the total number of possible values to be chosen
937 938 939 940 941 942 943
    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

944

945
    !> \brief function to enumerate an option
946
    !> Parameters
947
    !> \param   option_name string: the option
948 949
    !> \param   i           integer
    !> \result  option      integer
950 951 952 953 954 955 956 957
    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

958
end module