elpa2_utilities.F90 34.7 KB
Newer Older
1
2
3
4
5
!    This file is part of ELPA.
!
!    The ELPA library was originally created by the ELPA consortium,
!    consisting of the following organizations:
!
6
7
!    - Max Planck Computing and Data Facility (MPCDF), formerly known as
!      Rechenzentrum Garching der Max-Planck-Gesellschaft (RZG),
8
9
10
11
12
13
14
15
16
17
18
19
!    - 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 Naturwissenschaftrn,
!      Leipzig, Abt. Komplexe Strukutren in Biologie und Kognition,
!      and
!    - IBM Deutschland GmbH
!
!
!    More information can be found here:
20
!    http://elpa.mpcdf.mpg.de/
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
!
!    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.
!
!
! ELPA1 -- Faster replacements for ScaLAPACK symmetric eigenvalue routines
!
! Copyright of the original code rests with the authors inside the ELPA
! consortium. The copyright of any additional modifications shall rest
! with their original authors, but shall adhere to the licensing terms
! distributed along with the original code in the file "COPYING".



! ELPA2 -- 2-stage solver for ELPA
!
! Copyright of the original code rests with the authors inside the ELPA
! consortium. The copyright of any additional modifications shall rest
! with their original authors, but shall adhere to the licensing terms
! distributed along with the original code in the file "COPYING".


60

61
#include "config-f90.h"
Andreas Marek's avatar
Andreas Marek committed
62
#include <elpa/elpa_kernel_constants.h>
63
64

module ELPA2_utilities
65
  use ELPA_utilities
66
  use precision
67
68
69
70
71
72
73
74
75
  implicit none

  PRIVATE ! By default, all routines contained are private

  ! The following routines are public:

  public :: get_actual_real_kernel_name, get_actual_complex_kernel_name
  public :: REAL_ELPA_KERNEL_GENERIC, REAL_ELPA_KERNEL_GENERIC_SIMPLE, &
            REAL_ELPA_KERNEL_BGP, REAL_ELPA_KERNEL_BGQ,                &
76
77
            REAL_ELPA_KERNEL_SSE, REAL_ELPA_KERNEL_SSE_BLOCK2,         &
            REAL_ELPA_KERNEL_SSE_BLOCK4, REAL_ELPA_KERNEL_SSE_BLOCK6,  &
78
            REAL_ELPA_KERNEL_AVX_BLOCK2,                               &
79
            REAL_ELPA_KERNEL_AVX_BLOCK4, REAL_ELPA_KERNEL_AVX_BLOCK6,  &
80
            REAL_ELPA_KERNEL_AVX2_BLOCK2,                              &
81
            REAL_ELPA_KERNEL_AVX2_BLOCK4, REAL_ELPA_KERNEL_AVX2_BLOCK6, &
82
            REAL_ELPA_KERNEL_GPU,  DEFAULT_REAL_ELPA_KERNEL
83
84
85

  public :: COMPLEX_ELPA_KERNEL_GENERIC, COMPLEX_ELPA_KERNEL_GENERIC_SIMPLE, &
            COMPLEX_ELPA_KERNEL_BGP, COMPLEX_ELPA_KERNEL_BGQ,                &
86
87
            COMPLEX_ELPA_KERNEL_SSE, COMPLEX_ELPA_KERNEL_SSE_BLOCK1,         &
            COMPLEX_ELPA_KERNEL_SSE_BLOCK2,                                  &
88
            COMPLEX_ELPA_KERNEL_AVX_BLOCK1,COMPLEX_ELPA_KERNEL_AVX_BLOCK2,   &
89
            COMPLEX_ELPA_KERNEL_AVX2_BLOCK1,COMPLEX_ELPA_KERNEL_AVX2_BLOCK2, &
90
            COMPLEX_ELPA_KERNEL_GPU,  DEFAULT_COMPLEX_ELPA_KERNEL
91
92
93
94
95
96
97
98
99
100

  public :: REAL_ELPA_KERNEL_NAMES, COMPLEX_ELPA_KERNEL_NAMES

  public :: get_actual_complex_kernel, get_actual_real_kernel

  public :: check_allowed_complex_kernels, check_allowed_real_kernels

  public :: AVAILABLE_COMPLEX_ELPA_KERNELS, AVAILABLE_REAL_ELPA_KERNELS

  public :: print_available_real_kernels, print_available_complex_kernels
101
  public :: query_available_real_kernels, query_available_complex_kernels
102
103
104

  public :: qr_decomposition_via_environment_variable

Andreas Marek's avatar
Andreas Marek committed
105
106
107
108
109
110
  integer, parameter :: number_of_real_kernels           = ELPA2_NUMBER_OF_REAL_KERNELS
  integer, parameter :: REAL_ELPA_KERNEL_GENERIC         = ELPA2_REAL_KERNEL_GENERIC
  integer, parameter :: REAL_ELPA_KERNEL_GENERIC_SIMPLE  = ELPA2_REAL_KERNEL_GENERIC_SIMPLE
  integer, parameter :: REAL_ELPA_KERNEL_BGP             = ELPA2_REAL_KERNEL_BGP
  integer, parameter :: REAL_ELPA_KERNEL_BGQ             = ELPA2_REAL_KERNEL_BGQ
  integer, parameter :: REAL_ELPA_KERNEL_SSE             = ELPA2_REAL_KERNEL_SSE
111
112
113
  integer, parameter :: REAL_ELPA_KERNEL_SSE_BLOCK2      = ELPA2_REAL_KERNEL_SSE_BLOCK2
  integer, parameter :: REAL_ELPA_KERNEL_SSE_BLOCK4      = ELPA2_REAL_KERNEL_SSE_BLOCK4
  integer, parameter :: REAL_ELPA_KERNEL_SSE_BLOCK6      = ELPA2_REAL_KERNEL_SSE_BLOCK6
Andreas Marek's avatar
Andreas Marek committed
114
115
116
  integer, parameter :: REAL_ELPA_KERNEL_AVX_BLOCK2      = ELPA2_REAL_KERNEL_AVX_BLOCK2
  integer, parameter :: REAL_ELPA_KERNEL_AVX_BLOCK4      = ELPA2_REAL_KERNEL_AVX_BLOCK4
  integer, parameter :: REAL_ELPA_KERNEL_AVX_BLOCK6      = ELPA2_REAL_KERNEL_AVX_BLOCK6
117
118
119
  integer, parameter :: REAL_ELPA_KERNEL_AVX2_BLOCK2     = ELPA2_REAL_KERNEL_AVX2_BLOCK2
  integer, parameter :: REAL_ELPA_KERNEL_AVX2_BLOCK4     = ELPA2_REAL_KERNEL_AVX2_BLOCK4
  integer, parameter :: REAL_ELPA_KERNEL_AVX2_BLOCK6     = ELPA2_REAL_KERNEL_AVX2_BLOCK6
120
  integer(kind=ik), parameter :: REAL_ELPA_KERNEL_GPU    = ELPA2_REAL_KERNEL_GPU
121
122

#if defined(WITH_REAL_AVX_BLOCK2_KERNEL)
123
124

#ifndef WITH_ONE_SPECIFIC_REAL_KERNEL
125
  integer(kind=ik), parameter :: DEFAULT_REAL_ELPA_KERNEL = REAL_ELPA_KERNEL_GENERIC
126
127
128
#else /* WITH_ONE_SPECIFIC_REAL_KERNEL */

#ifdef WITH_REAL_GENERIC_KERNEL
129
  integer(kind=ik), parameter :: DEFAULT_REAL_ELPA_KERNEL = REAL_ELPA_KERNEL_GENERIC
130
131
#endif
#ifdef WITH_REAL_GENERIC_SIMPLE_KERNEL
132
  integer(kind=ik), parameter :: DEFAULT_REAL_ELPA_KERNEL = REAL_ELPA_KERNEL_GENERIC_SIMPLE
133
#endif
134
#ifdef WITH_REAL_SSE_ASSEMBLY_KERNEL
135
  integer(kind=ik), parameter :: DEFAULT_REAL_ELPA_KERNEL = REAL_ELPA_KERNEL_SSE
136
#endif
137
138
139
140
141
142
143
144
145
146
147
#if defined(WITH_REAL_SSE_BLOCK2_KERNEL) || defined(WITH_REAL_SSE_BLOCK4_KERNEL) || defined(WITH_REAL_SSE_BLOCK6_KERNEL)

#ifdef WITH_REAL_SSE_BLOCK6_KERNEL
  integer(kind=ik), parameter :: DEFAULT_REAL_ELPA_KERNEL = REAL_ELPA_KERNEL_SSE_BLOCK6
#else

#ifdef WITH_REAL_SSE_BLOCK4_KERNEL
  integer(kind=ik), parameter :: DEFAULT_REAL_ELPA_KERNEL = REAL_ELPA_KERNEL_SSE_BLOCK4
#else
#ifdef WITH_REAL_SSE_BLOCK2_KERNEL
  integer(kind=ik), parameter :: DEFAULT_REAL_ELPA_KERNEL = REAL_ELPA_KERNEL_SSE_BLOCK2
148
149
#endif
#endif
150
151
152
153
#endif
#endif /*  #if defined(WITH_REAL_SSE_BLOCK2_KERNEL) || defined(WITH_REAL_SSE_BLOCK4_KERNEL) || defined(WITH_REAL_SSE_BLOCK6_KERNEL) */

#if defined(WITH_REAL_AVX_BLOCK2_KERNEL) || defined(WITH_REAL_AVX_BLOCK4_KERNEL) || defined(WITH_REAL_AVX_BLOCK6_KERNEL)
154
#ifdef WITH_REAL_AVX_BLOCK6_KERNEL
155
  integer(kind=ik), parameter :: DEFAULT_REAL_ELPA_KERNEL = REAL_ELPA_KERNEL_AVX_BLOCK6
156
157
158
159
160
161
162
163
#else
#ifdef WITH_REAL_AVX_BLOCK4_KERNEL
  integer(kind=ik), parameter :: DEFAULT_REAL_ELPA_KERNEL = REAL_ELPA_KERNEL_AVX_BLOCK4
#else
#ifdef WITH_REAL_AVX_BLOCK2_KERNEL
  integer(kind=ik), parameter :: DEFAULT_REAL_ELPA_KERNEL = REAL_ELPA_KERNEL_AVX_BLOCK2
#endif
#endif
164
#endif
165
166
#endif /*  #if defined(WITH_REAL_AVX_BLOCK2_KERNEL) || defined(WITH_REAL_AVX_BLOCK4_KERNEL) || defined(WITH_REAL_AVX_BLOCK6_KERNEL) */

167
168
169
170
171
172
173
174
175
176
177
178
179
180
#if defined(WITH_REAL_AVX2_BLOCK2_KERNEL) || defined(WITH_REAL_AVX2_BLOCK4_KERNEL) || defined(WITH_REAL_AVX2_BLOCK6_KERNEL)
#ifdef WITH_REAL_AVX2_BLOCK6_KERNEL
  integer, parameter :: DEFAULT_REAL_ELPA_KERNEL = REAL_ELPA_KERNEL_AVX2_BLOCK6
#else
#ifdef WITH_REAL_AVX2_BLOCK4_KERNEL
  integer, parameter :: DEFAULT_REAL_ELPA_KERNEL = REAL_ELPA_KERNEL_AVX2_BLOCK4
#else
#ifdef WITH_REAL_AVX2_BLOCK2_KERNEL
  integer, parameter :: DEFAULT_REAL_ELPA_KERNEL = REAL_ELPA_KERNEL_AVX2_BLOCK2
#endif
#endif
#endif
#endif /*  #if defined(WITH_REAL_AVX2_BLOCK2_KERNEL) || defined(WITH_REAL_AVX2_BLOCK4_KERNEL) || defined(WITH_REAL_AVX2_BLOCK6_KERNEL) */

181
#ifdef WITH_REAL_BGP_KERNEL
182
  integer(kind=ik), parameter :: DEFAULT_REAL_ELPA_KERNEL = REAL_ELPA_KERNEL_AVX_BGP
183
184
#endif
#ifdef WITH_REAL_BGQ_KERNEL
185
  integer(kind=ik), parameter :: DEFAULT_REAL_ELPA_KERNEL = REAL_ELPA_KERNEL_AVX_BGQ
186
187
#endif
#ifdef WITH_GPU_VERSION
188
  integer(kind=ik), parameter :: DEFAULT_REAL_ELPA_KERNEL = REAL_ELPA_KERNEL_GPU
189
190
191
192
#endif

#endif /* WITH_ONE_SPECIFIC_REAL_KERNEL */

Andreas Marek's avatar
Andreas Marek committed
193
#else /* WITH_REAL_AVX_BLOCK2_KERNEL */
194
195

#ifndef WITH_ONE_SPECIFIC_REAL_KERNEL
196
  integer(kind=ik), parameter :: DEFAULT_REAL_ELPA_KERNEL = REAL_ELPA_KERNEL_GENERIC
197
198
199
#else /* WITH_ONE_SPECIFIC_REAL_KERNEL */

#ifdef WITH_REAL_GENERIC_KERNEL
200
  integer(kind=ik), parameter :: DEFAULT_REAL_ELPA_KERNEL = REAL_ELPA_KERNEL_GENERIC
201
202
#endif
#ifdef WITH_REAL_GENERIC_SIMPLE_KERNEL
203
  integer(kind=ik), parameter :: DEFAULT_REAL_ELPA_KERNEL = REAL_ELPA_KERNEL_GENERIC_SIMPLE
204
#endif
205
#ifdef WITH_REAL_SSE_ASSEMBLY_KERNEL
206
  integer(kind=ik), parameter :: DEFAULT_REAL_ELPA_KERNEL = REAL_ELPA_KERNEL_SSE
207
#endif
208
209
210
211
212
213
214
215
216
217

#if defined(WITH_REAL_SSE_BLOCK2_KERNEL) || defined(WITH_REAL_SSE_BLOCK4_KERNEL) || defined(WITH_REAL_SSE_BLOCK6_KERNEL)
#ifdef WITH_REAL_SSE_BLOCK6_KERNEL
  integer(kind=ik), parameter :: DEFAULT_REAL_ELPA_KERNEL = REAL_ELPA_KERNEL_SSE_BLOCK6
#else
#ifdef WITH_REAL_SSE_BLOCK4_KERNEL
  integer(kind=ik), parameter :: DEFAULT_REAL_ELPA_KERNEL = REAL_ELPA_KERNEL_SSE_BLOCK4
#else
#ifdef WITH_REAL_SSE_BLOCK2_KERNEL
  integer(kind=ik), parameter :: DEFAULT_REAL_ELPA_KERNEL = REAL_ELPA_KERNEL_SSE_BLOCK2
218
219
#endif
#endif
220
221
222
223
#endif
#endif /*  #if defined(WITH_REAL_SSE_BLOCK2_KERNEL) || defined(WITH_REAL_SSE_BLOCK4_KERNEL) || defined(WITH_REAL_SSE_BLOCK6_KERNEL) */

#if defined(WITH_REAL_AVX_BLOCK2_KERNEL) || defined(WITH_REAL_AVX_BLOCK4_KERNEL) || defined(WITH_REAL_AVX_BLOCK6_KERNEL)
224
#ifdef WITH_REAL_AVX_BLOCK6_KERNEL
225
  integer(kind=ik), parameter :: DEFAULT_REAL_ELPA_KERNEL = REAL_ELPA_KERNEL_AVX_BLOCK6
226
227
228
229
230
231
232
233
#else
#ifdef WITH_REAL_AVX_BLOCK4_KERNEL
  integer(kind=ik), parameter :: DEFAULT_REAL_ELPA_KERNEL = REAL_ELPA_KERNEL_AVX_BLOCK4
#else
#ifdef WITH_REAL_AVX_BLOCK2_KERNEL
  integer(kind=ik), parameter :: DEFAULT_REAL_ELPA_KERNEL = REAL_ELPA_KERNEL_AVX_BLOCK2
#endif
#endif
234
#endif
235
236
#endif /*  #if defined(WITH_REAL_AVX_BLOCK2_KERNEL) || defined(WITH_REAL_AVX_BLOCK4_KERNEL) || defined(WITH_REAL_AVX_BLOCK6_KERNEL) */

237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
#if defined(WITH_REAL_AVX2_BLOCK2_KERNEL) || defined(WITH_REAL_AVX2_BLOCK4_KERNEL) || defined(WITH_REAL_AVX2_BLOCK6_KERNEL)
#ifdef WITH_REAL_AVX2_BLOCK6_KERNEL
  integer, parameter :: DEFAULT_REAL_ELPA_KERNEL = REAL_ELPA_KERNEL_AVX2_BLOCK6
#else
#ifdef WITH_REAL_AVX2_BLOCK4_KERNEL
  integer, parameter :: DEFAULT_REAL_ELPA_KERNEL = REAL_ELPA_KERNEL_AVX2_BLOCK4
#else
#ifdef WITH_REAL_AVX2_BLOCK2_KERNEL
  integer, parameter :: DEFAULT_REAL_ELPA_KERNEL = REAL_ELPA_KERNEL_AVX2_BLOCK2
#endif
#endif
#endif
#endif /*  #if defined(WITH_REAL_AVX2_BLOCK2_KERNEL) || defined(WITH_REAL_AVX2_BLOCK4_KERNEL) || defined(WITH_REAL_AVX2_BLOCK6_KERNEL) */


252
#ifdef WITH_REAL_BGP_KERNEL
253
  integer(kind=ik), parameter :: DEFAULT_REAL_ELPA_KERNEL = REAL_ELPA_KERNEL_AVX_BGP
254
255
#endif
#ifdef WITH_REAL_BGQ_KERNEL
256
  integer(kind=ik), parameter :: DEFAULT_REAL_ELPA_KERNEL = REAL_ELPA_KERNEL_AVX_BGQ
257
#endif
258
#ifdef WITH_GPU_VERSION
259
  integer(kind=ik), parameter :: DEFAULT_REAL_ELPA_KERNEL = REAL_ELPA_KERNEL_GPU
260
261
262
263
#endif

#endif  /* WITH_ONE_SPECIFIC_REAL_KERNEL */

Andreas Marek's avatar
Andreas Marek committed
264
#endif /* WITH_REAL_AVX_BLOCK2_KERNEL */
265

266
267
268
269
270
271
  character(35), parameter, dimension(number_of_real_kernels) :: &
  REAL_ELPA_KERNEL_NAMES =    (/"REAL_ELPA_KERNEL_GENERIC         ", &
                                "REAL_ELPA_KERNEL_GENERIC_SIMPLE  ", &
                                "REAL_ELPA_KERNEL_BGP             ", &
                                "REAL_ELPA_KERNEL_BGQ             ", &
                                "REAL_ELPA_KERNEL_SSE             ", &
272
273
274
                                "REAL_ELPA_KERNEL_SSE_BLOCK2      ", &
                                "REAL_ELPA_KERNEL_SSE_BLOCK4      ", &
                                "REAL_ELPA_KERNEL_SSE_BLOCK6      ", &
275
276
                                "REAL_ELPA_KERNEL_AVX_BLOCK2      ", &
                                "REAL_ELPA_KERNEL_AVX_BLOCK4      ", &
277
                                "REAL_ELPA_KERNEL_AVX_BLOCK6      ", &
278
279
                                "REAL_ELPA_KERNEL_AVX2_BLOCK2     ", &
                                "REAL_ELPA_KERNEL_AVX2_BLOCK4     ", &
280
                                "REAL_ELPA_KERNEL_AVX2_BLOCK6     ", &
281
                                "REAL_ELPA_KERNEL_GPU             "/)
282

Andreas Marek's avatar
Andreas Marek committed
283
284
285
286
287
288
  integer, parameter :: number_of_complex_kernels           = ELPA2_NUMBER_OF_COMPLEX_KERNELS
  integer, parameter :: COMPLEX_ELPA_KERNEL_GENERIC         = ELPA2_COMPLEX_KERNEL_GENERIC
  integer, parameter :: COMPLEX_ELPA_KERNEL_GENERIC_SIMPLE  = ELPA2_COMPLEX_KERNEL_GENERIC_SIMPLE
  integer, parameter :: COMPLEX_ELPA_KERNEL_BGP             = ELPA2_COMPLEX_KERNEL_BGP
  integer, parameter :: COMPLEX_ELPA_KERNEL_BGQ             = ELPA2_COMPLEX_KERNEL_BGQ
  integer, parameter :: COMPLEX_ELPA_KERNEL_SSE             = ELPA2_COMPLEX_KERNEL_SSE
289
290
  integer, parameter :: COMPLEX_ELPA_KERNEL_SSE_BLOCK1      = ELPA2_COMPLEX_KERNEL_SSE_BLOCK1
  integer, parameter :: COMPLEX_ELPA_KERNEL_SSE_BLOCK2      = ELPA2_COMPLEX_KERNEL_SSE_BLOCK2
Andreas Marek's avatar
Andreas Marek committed
291
292
  integer, parameter :: COMPLEX_ELPA_KERNEL_AVX_BLOCK1      = ELPA2_COMPLEX_KERNEL_AVX_BLOCK1
  integer, parameter :: COMPLEX_ELPA_KERNEL_AVX_BLOCK2      = ELPA2_COMPLEX_KERNEL_AVX_BLOCK2
293
294
  integer, parameter :: COMPLEX_ELPA_KERNEL_AVX2_BLOCK1     = ELPA2_COMPLEX_KERNEL_AVX2_BLOCK1
  integer, parameter :: COMPLEX_ELPA_KERNEL_AVX2_BLOCK2     = ELPA2_COMPLEX_KERNEL_AVX2_BLOCK2
295
  integer(kind=ik), parameter :: COMPLEX_ELPA_KERNEL_GPU    = ELPA2_COMPLEX_KERNEL_GPU
296
297

#if defined(WITH_COMPLEX_AVX_BLOCK1_KERNEL)
298
299

#ifndef WITH_ONE_SPECIFIC_COMPLEX_KERNEL
300
  integer(kind=ik), parameter :: DEFAULT_COMPLEX_ELPA_KERNEL = COMPLEX_ELPA_KERNEL_GENERIC
301
302
303
304
#else /* WITH_ONE_SPECIFIC_COMPLEX_KERNEL */

! go through all kernels and set them
#ifdef WITH_COMPLEX_GENERIC_KERNEL
305
  integer(kind=ik), parameter :: DEFAULT_COMPLEX_ELPA_KERNEL = COMPLEX_ELPA_KERNEL_GENERIC
306
#endif
307
#ifdef WITH_COMPLEX_GENERIC_SIMPLE_KERNEL
308
  integer(kind=ik), parameter :: DEFAULT_COMPLEX_ELPA_KERNEL = COMPLEX_ELPA_KERNEL_GENERIC_SIMPLE
309
#endif
310
#ifdef WITH_COMPLEX_SSE_ASSEMBLY_KERNEL
311
  integer(kind=ik), parameter :: DEFAULT_COMPLEX_ELPA_KERNEL = COMPLEX_ELPA_KERNEL_SSE
312
#endif
313
314
315
316

#if defined(WITH_COMPLEX_SSE_BLOCK1_KERNEL) || defined(WITH_COMPLEX_SSE_BLOCK2_KERNEL)
#ifdef WITH_COMPLEX_SSE_BLOCK2_KERNEL
  integer(kind=ik), parameter :: DEFAULT_COMPLEX_ELPA_KERNEL = COMPLEX_ELPA_KERNEL_SSE_BLOCK2
317
#else
318
319
320
#ifdef WITH_COMPLEX_SSE_BLOCK1_KERNEL
  integer(kind=ik), parameter :: DEFAULT_COMPLEX_ELPA_KERNEL = COMPLEX_ELPA_KERNEL_SSE_BLOCK1
#endif
321
#endif
322
323
324
325
#endif /* defined(WITH_COMPLEXL_SSE_BLOCK1_KERNEL) || defined(WITH_COMPLEX_SSE_BLOCK2_KERNEL) */

#if defined(WITH_COMPLEX_AVX_BLOCK1_KERNEL) || defined(WITH_COMPLEX_AVX_BLOCK2_KERNEL)
#ifdef WITH_COMPLEX_AVX_BLOCK2_KERNEL
326
  integer(kind=ik), parameter :: DEFAULT_COMPLEX_ELPA_KERNEL = COMPLEX_ELPA_KERNEL_AVX_BLOCK2
327
#else
328
329
330
#ifdef WITH_COMPLEX_AVX_BLOCK1_KERNEL
  integer(kind=ik), parameter :: DEFAULT_COMPLEX_ELPA_KERNEL = COMPLEX_ELPA_KERNEL_AVX_BLOCK1
#endif
331
#endif
332
333
#endif /* defined(WITH_COMPLEX_AVX_BLOCK1_KERNEL) || defined(WITH_COMPLEX_AVX_BLOCK2_KERNEL) */

334
335
336
337
338
339
340
341
342
#if defined(WITH_COMPLEX_AVX2_BLOCK1_KERNEL) || defined(WITH_COMPLEX_AVX2_BLOCK2_KERNEL)
#ifdef WITH_COMPLEX_AVX2_BLOCK2_KERNEL
  integer, parameter :: DEFAULT_COMPLEX_ELPA_KERNEL = COMPLEX_ELPA_KERNEL_AVX2_BLOCK2
#else
#ifdef WITH_COMPLEX_AVX2_BLOCK1_KERNEL
  integer, parameter :: DEFAULT_COMPLEX_ELPA_KERNEL = COMPLEX_ELPA_KERNEL_AVX2_BLOCK1
#endif
#endif
#endif /* defined(WITH_COMPLEX_AVX2_BLOCK1_KERNEL) || defined(WITH_COMPLEX_AVX2_BLOCK2_KERNEL) */
343
344


345
#ifdef WITH_GPU_VERSION
346
  integer(kind=ik), parameter :: DEFAULT_COMPLEX_ELPA_KERNEL = COMPLEX_ELPA_KERNEL_GPU
347
348
349
350
351
352
353
#endif

#endif /* WITH_ONE_SPECIFIC_COMPLEX_KERNEL */

#else /* WITH_COMPLEX_AVX_BLOCK1_KERNEL */

#ifndef WITH_ONE_SPECIFIC_COMPLEX_KERNEL
354
  integer(kind=ik), parameter :: DEFAULT_COMPLEX_ELPA_KERNEL = COMPLEX_ELPA_KERNEL_GENERIC
355
356
357
358
359

#else /* WITH_ONE_SPECIFIC_COMPLEX_KERNEL */

! go through all kernels and set them
#ifdef WITH_COMPLEX_GENERIC_KERNEL
360
  integer(kind=ik), parameter :: DEFAULT_COMPLEX_ELPA_KERNEL = COMPLEX_ELPA_KERNEL_GENERIC
361
362
#endif
#ifdef WITH_COMPLEX_GENERIC_SIMPLE_KERNEL
363
  integer(kind=ik), parameter :: DEFAULT_COMPLEX_ELPA_KERNEL = COMPLEX_ELPA_KERNEL_GENERIC_SIMPLE
364
#endif
365
#ifdef WITH_COMPLEX_SSE_ASSEMBLY_KERNEL
366
  integer(kind=ik), parameter :: DEFAULT_COMPLEX_ELPA_KERNEL = COMPLEX_ELPA_KERNEL_SSE
367
#endif
368
369
370
371

#if defined(WITH_COMPLEX_SSE_BLOCK1_KERNEL) || defined(WITH_COMPLEX_SSE_BLOCK2_KERNEL)
#ifdef WITH_COMPLEX_SSE_BLOCK2_KERNEL
  integer(kind=ik), parameter :: DEFAULT_COMPLEX_ELPA_KERNEL = COMPLEX_ELPA_KERNEL_SSE_BLOCK2
372
#else
373
374
375
#ifdef WITH_COMPLEX_SSE_BLOCK1_KERNEL
  integer(kind=ik), parameter :: DEFAULT_COMPLEX_ELPA_KERNEL = COMPLEX_ELPA_KERNEL_SSE_BLOCK1
#endif
376
#endif
377
378
379
380
#endif /* defined(WITH_COMPLEXL_SSE_BLOCK1_KERNEL) || defined(WITH_COMPLEX_SSE_BLOCK2_KERNEL) */

#if defined(WITH_COMPLEX_AVX_BLOCK1_KERNEL) || defined(WITH_COMPLEX_AVX_BLOCK2_KERNEL)
#ifdef WITH_COMPLEX_AVX_BLOCK2_KERNEL
381
  integer(kind=ik), parameter :: DEFAULT_COMPLEX_ELPA_KERNEL = COMPLEX_ELPA_KERNEL_AVX_BLOCK2
382
#else
383
384
385
#ifdef WITH_COMPLEX_AVX_BLOCK1_KERNEL
  integer(kind=ik), parameter :: DEFAULT_COMPLEX_ELPA_KERNEL = COMPLEX_ELPA_KERNEL_AVX_BLOCK1
#endif
386
#endif
387
388
#endif /* defined(WITH_COMPLEX_AVX_BLOCK1_KERNEL) || defined(WITH_COMPLEX_AVX_BLOCK2_KERNEL) */

389
390
391
392
393
394
395
396
397
398
#if defined(WITH_COMPLEX_AVX2_BLOCK1_KERNEL) || defined(WITH_COMPLEX_AVX2_BLOCK2_KERNEL)
#ifdef WITH_COMPLEX_AVX2_BLOCK2_KERNEL
  integer, parameter :: DEFAULT_COMPLEX_ELPA_KERNEL = COMPLEX_ELPA_KERNEL_AVX2_BLOCK2
#else
#ifdef WITH_COMPLEX_AVX2_BLOCK1_KERNEL
  integer, parameter :: DEFAULT_COMPLEX_ELPA_KERNEL = COMPLEX_ELPA_KERNEL_AVX2_BLOCK1
#endif
#endif
#endif /* defined(WITH_COMPLEX_AVX2_BLOCK1_KERNEL) || defined(WITH_COMPLEX_AVX2_BLOCK2_KERNEL) */

399
#ifdef WITH_GPU_VERSION
400
  integer(kind=ik), parameter :: DEFAULT_COMPLEX_ELPA_KERNEL = COMPLEX_ELPA_KERNEL_GPU
401
402
403
404
405
406
#endif

#endif /* WITH_ONE_SPECIFIC_COMPLEX_KERNEL */

#endif /* WITH_COMPLEX_AVX_BLOCK1_KERNEL */

407
408
409
410
411
412
  character(35), parameter, dimension(number_of_complex_kernels) :: &
  COMPLEX_ELPA_KERNEL_NAMES = (/"COMPLEX_ELPA_KERNEL_GENERIC         ", &
                                "COMPLEX_ELPA_KERNEL_GENERIC_SIMPLE  ", &
                                "COMPLEX_ELPA_KERNEL_BGP             ", &
                                "COMPLEX_ELPA_KERNEL_BGQ             ", &
                                "COMPLEX_ELPA_KERNEL_SSE             ", &
413
414
                                "COMPLEX_ELPA_KERNEL_SSE_BLOCK1      ", &
                                "COMPLEX_ELPA_KERNEL_SSE_BLOCK2      ", &
415
                                "COMPLEX_ELPA_KERNEL_AVX_BLOCK1      ", &
416
                                "COMPLEX_ELPA_KERNEL_AVX_BLOCK2      ", &
417
                                "COMPLEX_ELPA_KERNEL_AVX2_BLOCK1     ", &
418
                                "COMPLEX_ELPA_KERNEL_AVX2_BLOCK2     ", &
419
                                "COMPLEX_ELPA_KERNEL_GPU             "/)
420

421
  integer(kind=ik), parameter                           ::             &
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
           AVAILABLE_REAL_ELPA_KERNELS(number_of_real_kernels) =       &
                                      (/                               &
#if WITH_REAL_GENERIC_KERNEL
                                        1                              &
#else
                                        0                              &
#endif
#if WITH_REAL_GENERIC_SIMPLE_KERNEL
                                          ,1                           &
#else
                                          ,0                           &
#endif
#if WITH_REAL_BGP_KERNEL
                                            ,1                         &
#else
                                            ,0                         &
#endif
#if WITH_REAL_BGQ_KERNEL
                                              ,1                       &
#else
                                              ,0                       &
#endif
444
#if WITH_REAL_SSE_ASSEMBLY_KERNEL
445
446
447
448
                                                ,1                     &
#else
                                                ,0                     &
#endif
449
#if WITH_REAL_SSE_BLOCK2_KERNEL
450
451
452
453
                                                  ,1                   &
#else
                                                  ,0                   &
#endif
454
#if WITH_REAL_SSE_BLOCK4_KERNEL
455
456
457
458
                                                    ,1                 &
#else
                                                    ,0                 &
#endif
459
#if WITH_REAL_SSE_BLOCK6_KERNEL
460
461
462
                                                      ,1               &
#else
                                                      ,0               &
463

464
#endif
465
#if WITH_REAL_AVX_BLOCK2_KERNEL
466
467
468
469
                                                        ,1             &
#else
                                                        ,0             &
#endif
470
471
472
473
474
475
476
477
478
#if WITH_REAL_AVX_BLOCK4_KERNEL
                                                          ,1           &
#else
                                                          ,0           &
#endif
#if WITH_REAL_AVX_BLOCK6_KERNEL
                                                            ,1         &
#else
                                                            ,0         &
479
#endif
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
#if WITH_REAL_AVX2_BLOCK2_KERNEL
                                                              ,1       &
#else
                                                              ,0       &
#endif
#if WITH_REAL_AVX2_BLOCK4_KERNEL
                                                               ,1      &
#else
                                                               ,0      &
#endif
#if WITH_REAL_AVX2_BLOCK6_KERNEL
                                                               ,1      &
#else
                                                               ,0      &
#endif
495
496
497
498
499
#ifdef WITH_GPU_VERSION
                                                                 ,1    &
#else
                                                                 ,0    &
#endif
500
501
                                                       /)

502
  integer(kind=ik), parameter ::                                          &
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
           AVAILABLE_COMPLEX_ELPA_KERNELS(number_of_complex_kernels) =    &
                                      (/                                  &
#if WITH_COMPLEX_GENERIC_KERNEL
                                        1                                 &
#else
                                        0                                 &
#endif
#if WITH_COMPLEX_GENERIC_SIMPLE_KERNEL
                                          ,1                              &
#else
                                          ,0                              &
#endif
#if WITH_COMPLEX_BGP_KERNEL
                                            ,1                            &
#else
                                            ,0                            &
#endif
#if WITH_COMPLEX_BGQ_KERNEL
                                              ,1                          &
#else
                                              ,0                          &
#endif
525
#if WITH_COMPLEX_SSE_ASSEMBLY_KERNEL
526
527
528
529
                                                ,1                        &
#else
                                                ,0                        &
#endif
530
#if WITH_COMPLEX_SSE_BLOCK1_KERNEL
531
532
533
534
                                                  ,1                      &
#else
                                                  ,0                      &
#endif
535
#if WITH_COMPLEX_SSE_BLOCK2_KERNEL
536
537
538
539
                                                    ,1                    &
#else
                                                    ,0                    &
#endif
540
#if WITH_COMPLEX_AVX_BLOCK1_KERNEL
541
542
543
544
                                                      ,1                  &
#else
                                                      ,0                  &
#endif
545
546
547
548
549
#if WITH_COMPLEX_AVX_BLOCK2_KERNEL
                                                        ,1                &
#else
                                                        ,0                &
#endif
550
551
552
553
554
555
556
557
558
559
#if WITH_COMPLEX_AVX2_BLOCK1_KERNEL
                                                         ,1               &
#else
                                                         ,0               &
#endif
#if WITH_COMPLEX_AVX2_BLOCK2_KERNEL
                                                           ,1             &
#else
                                                           ,0             &
#endif
560
561
562
563
564
565
#ifdef WITH_GPU_VERSION
                                                             ,1           &
#else
                                                             ,0           &
#endif
                                                               /)
566
567
568
569
570
571
572

!******
  contains
    subroutine print_available_real_kernels
#ifdef HAVE_DETAILED_TIMINGS
      use timings
#endif
573
      use precision
574
575
      implicit none

576
      integer(kind=ik) :: i
577
578
579
580
581

#ifdef HAVE_DETAILED_TIMINGS
      call timer%start("print_available_real_kernels")
#endif

582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
      do i=1, number_of_real_kernels
        if (AVAILABLE_REAL_ELPA_KERNELS(i) .eq. 1) then
          write(*,*) REAL_ELPA_KERNEL_NAMES(i)
        endif
      enddo
      write(*,*) " "
      write(*,*) " At the moment the following kernel would be choosen:"
      write(*,*) get_actual_real_kernel_name()

#ifdef HAVE_DETAILED_TIMINGS
      call timer%stop("print_available_real_kernels")
#endif

    end subroutine print_available_real_kernels

    subroutine query_available_real_kernels
#ifdef HAVE_DETAILED_TIMINGS
      use timings
#endif
      implicit none

      integer :: i

#ifdef HAVE_DETAILED_TIMINGS
      call timer%start("query_available_real_kernels")
#endif

609
610
611
612
613
614
615
616
617
618
      do i=1, number_of_real_kernels
        if (AVAILABLE_REAL_ELPA_KERNELS(i) .eq. 1) then
          write(error_unit,*) REAL_ELPA_KERNEL_NAMES(i)
        endif
      enddo
      write(error_unit,*) " "
      write(error_unit,*) " At the moment the following kernel would be choosen:"
      write(error_unit,*) get_actual_real_kernel_name()

#ifdef HAVE_DETAILED_TIMINGS
619
      call timer%stop("query_available_real_kernels")
620
621
#endif

622
    end subroutine query_available_real_kernels
623
624
625
626
627

    subroutine print_available_complex_kernels
#ifdef HAVE_DETAILED_TIMINGS
      use timings
#endif
628
      use precision
629
630
      implicit none

631
      integer(kind=ik) :: i
632
633
634
635
#ifdef HAVE_DETAILED_TIMINGS
      call timer%start("print_available_complex_kernels")
#endif

636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
      do i=1, number_of_complex_kernels
        if (AVAILABLE_COMPLEX_ELPA_KERNELS(i) .eq. 1) then
           write(*,*) COMPLEX_ELPA_KERNEL_NAMES(i)
        endif
      enddo
      write(*,*) " "
      write(*,*) " At the moment the following kernel would be choosen:"
      write(*,*) get_actual_complex_kernel_name()

#ifdef HAVE_DETAILED_TIMINGS
      call timer%stop("print_available_complex_kernels")
#endif

    end subroutine print_available_complex_kernels

    subroutine query_available_complex_kernels
#ifdef HAVE_DETAILED_TIMINGS
      use timings
#endif

      implicit none

      integer :: i
#ifdef HAVE_DETAILED_TIMINGS
      call timer%start("query_available_complex_kernels")
#endif

663
664
665
666
667
668
669
670
671
672
      do i=1, number_of_complex_kernels
        if (AVAILABLE_COMPLEX_ELPA_KERNELS(i) .eq. 1) then
           write(error_unit,*) COMPLEX_ELPA_KERNEL_NAMES(i)
        endif
      enddo
      write(error_unit,*) " "
      write(error_unit,*) " At the moment the following kernel would be choosen:"
      write(error_unit,*) get_actual_complex_kernel_name()

#ifdef HAVE_DETAILED_TIMINGS
673
      call timer%stop("query_available_complex_kernels")
674
675
#endif

676
    end subroutine query_available_complex_kernels
677
678
679
680
681

    function get_actual_real_kernel() result(actual_kernel)
#ifdef HAVE_DETAILED_TIMINGS
      use timings
#endif
682
      use precision
683
684
      implicit none

685
      integer(kind=ik) :: actual_kernel
686
687
688
689
690
691
692
693
694
695

#ifdef HAVE_DETAILED_TIMINGS
      call timer%start("get_actual_real_kernel")
#endif


      ! if kernel is not choosen via api
      ! check whether set by environment variable
      actual_kernel = real_kernel_via_environment_variable()

696
697
698
!#ifdef WITH_GPU_VERSION
!      actual_kernel = REAL_ELPA_KERNEL_GPU
!#endif
699
700
701
702
703
      if (actual_kernel .eq. 0) then
        ! if not then set default kernel
        actual_kernel = DEFAULT_REAL_ELPA_KERNEL
      endif

704
705
706
707
708
709
!#ifdef WITH_GPU_VERSION
!      if (actual_kernel .ne. REAL_ELPA_KERNEL_GPU) then
!        print *,"if build with GPU you cannot choose another real kernel"
!        stop
!      endif
!#endif
710

711
712
713
714
715
716
717
718
719
720
#ifdef HAVE_DETAILED_TIMINGS
      call timer%stop("get_actual_real_kernel")
#endif

    end function get_actual_real_kernel

    function get_actual_real_kernel_name() result(actual_kernel_name)
#ifdef HAVE_DETAILED_TIMINGS
      use timings
#endif
721
      use precision
722
723
      implicit none

724
725
      character(35)    :: actual_kernel_name
      integer(kind=ik) :: actual_kernel
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743

#ifdef HAVE_DETAILED_TIMINGS
      call timer%start("get_actual_real_kernel_name")
#endif

      actual_kernel = get_actual_real_kernel()
      actual_kernel_name = REAL_ELPA_KERNEL_NAMES(actual_kernel)

#ifdef HAVE_DETAILED_TIMINGS
      call timer%stop("get_actual_real_kernel_name")
#endif

    end function get_actual_real_kernel_name

    function get_actual_complex_kernel() result(actual_kernel)
#ifdef HAVE_DETAILED_TIMINGS
      use timings
#endif
744
      use precision
745
      implicit none
746
      integer(kind=ik) :: actual_kernel
747
748
749
750
751
752
753
754
755
756

#ifdef HAVE_DETAILED_TIMINGS
      call timer%start("get_actual_complex_kernel")
#endif


     ! if kernel is not choosen via api
     ! check whether set by environment variable
     actual_kernel = complex_kernel_via_environment_variable()

757
758
759
!#ifdef WITH_GPU_VERSION
!     actual_kernel = COMPLEX_ELPA_KERNEL_GPU
!#endif
760
761
762
763
764
     if (actual_kernel .eq. 0) then
       ! if not then set default kernel
       actual_kernel = DEFAULT_COMPLEX_ELPA_KERNEL
     endif

765
766
767
768
769
770
!#ifdef WITH_GPU_VERSION
!      if (actual_kernel .ne. COMPLEX_ELPA_KERNEL_GPU) then
!        print *,"if build with GPU you cannot choose another complex kernel"
!        stop
!      endif
!#endif
771
772


773
774
775
776
777
778
779
780
781
782
#ifdef HAVE_DETAILED_TIMINGS
     call timer%stop("get_actual_complex_kernel")
#endif

   end function get_actual_complex_kernel

   function get_actual_complex_kernel_name() result(actual_kernel_name)
#ifdef HAVE_DETAILED_TIMINGS
     use timings
#endif
783
     use precision
784
     implicit none
785
786
     character(35)    :: actual_kernel_name
     integer(kind=ik) :: actual_kernel
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804

#ifdef HAVE_DETAILED_TIMINGS
     call timer%start("get_actual_complex_kernel_name")
#endif

     actual_kernel = get_actual_complex_kernel()
     actual_kernel_name = COMPLEX_ELPA_KERNEL_NAMES(actual_kernel)

#ifdef HAVE_DETAILED_TIMINGS
     call timer%stop("get_actual_complex_kernel_name")
#endif

   end function get_actual_complex_kernel_name

   function check_allowed_real_kernels(THIS_REAL_ELPA_KERNEL) result(err)
#ifdef HAVE_DETAILED_TIMINGS
     use timings
#endif
805
     use precision
806
     implicit none
807
808
     integer(kind=ik), intent(in) :: THIS_REAL_ELPA_KERNEL
     logical                      :: err
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826

#ifdef HAVE_DETAILED_TIMINGS
     call timer%start("check_allowed_real_kernels")
#endif
     err = .false.

     if (AVAILABLE_REAL_ELPA_KERNELS(THIS_REAL_ELPA_KERNEL) .ne. 1) err=.true.

#ifdef HAVE_DETAILED_TIMINGS
     call timer%stop("check_allowed_real_kernels")
#endif

   end function check_allowed_real_kernels

   function check_allowed_complex_kernels(THIS_COMPLEX_ELPA_KERNEL) result(err)
#ifdef HAVE_DETAILED_TIMINGS
     use timings
#endif
827
     use precision
828
     implicit none
829
830
     integer(kind=ik), intent(in) :: THIS_COMPLEX_ELPA_KERNEL
     logical                      :: err
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
#ifdef HAVE_DETAILED_TIMINGS
     call timer%start("check_allowed_complex_kernels")
#endif
     err = .false.

     if (AVAILABLE_COMPLEX_ELPA_KERNELS(THIS_COMPLEX_ELPA_KERNEL) .ne. 1) err=.true.

#ifdef HAVE_DETAILED_TIMINGS
     call timer%stop("check_allowed_complex_kernels")
#endif

   end function check_allowed_complex_kernels

   function qr_decomposition_via_environment_variable(useQR) result(isSet)
#ifdef HAVE_DETAILED_TIMINGS
     use timings
#endif
848
     use precision
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
     implicit none
     logical, intent(out) :: useQR
     logical              :: isSet
     CHARACTER(len=255)   :: ELPA_QR_DECOMPOSITION

#ifdef HAVE_DETAILED_TIMINGS
     call timer%start("qr_decomposition_via_environment_variable")
#endif

     isSet = .false.

#if defined(HAVE_ENVIRONMENT_CHECKING)
     call get_environment_variable("ELPA_QR_DECOMPOSITION",ELPA_QR_DECOMPOSITION)
#endif
     if (trim(ELPA_QR_DECOMPOSITION) .eq. "yes") then
       useQR = .true.
       isSet = .true.
     endif
     if (trim(ELPA_QR_DECOMPOSITION) .eq. "no") then
       useQR = .false.
       isSet = .true.
     endif

#ifdef HAVE_DETAILED_TIMINGS
     call timer%stop("qr_decomposition_via_environment_variable")
#endif

   end function qr_decomposition_via_environment_variable

   function real_kernel_via_environment_variable() result(kernel)
#ifdef HAVE_DETAILED_TIMINGS
     use timings
#endif
882
     use precision
883
     implicit none
884
     integer(kind=ik)   :: kernel
885
     CHARACTER(len=255) :: REAL_KERNEL_ENVIRONMENT
886
     integer(kind=ik)   :: i
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914

#ifdef HAVE_DETAILED_TIMINGS
     call timer%start("real_kernel_via_environment_variable")
#endif

#if defined(HAVE_ENVIRONMENT_CHECKING)
     call get_environment_variable("REAL_ELPA_KERNEL",REAL_KERNEL_ENVIRONMENT)
#endif
     do i=1,size(REAL_ELPA_KERNEL_NAMES(:))
       !     if (trim(dummy_char) .eq. trim(REAL_ELPA_KERNEL_NAMES(i))) then
       if (trim(REAL_KERNEL_ENVIRONMENT) .eq. trim(REAL_ELPA_KERNEL_NAMES(i))) then
         kernel = i
         exit
       else
         kernel = 0
       endif
     enddo

#ifdef HAVE_DETAILED_TIMINGS
     call timer%stop("real_kernel_via_environment_variable")
#endif

   end function real_kernel_via_environment_variable

   function complex_kernel_via_environment_variable() result(kernel)
#ifdef HAVE_DETAILED_TIMINGS
     use timings
#endif
915
     use precision
916
917
918
919
     implicit none
     integer :: kernel

     CHARACTER(len=255) :: COMPLEX_KERNEL_ENVIRONMENT
920
     integer(kind=ik)   :: i
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946

#ifdef HAVE_DETAILED_TIMINGS
     call timer%start("complex_kernel_via_environment_variable")
#endif

#if defined(HAVE_ENVIRONMENT_CHECKING)
     call get_environment_variable("COMPLEX_ELPA_KERNEL",COMPLEX_KERNEL_ENVIRONMENT)
#endif

     do i=1,size(COMPLEX_ELPA_KERNEL_NAMES(:))
       if (trim(COMPLEX_ELPA_KERNEL_NAMES(i)) .eq. trim(COMPLEX_KERNEL_ENVIRONMENT)) then
         kernel = i
         exit
       else
         kernel = 0
       endif
     enddo

#ifdef HAVE_DETAILED_TIMINGS
     call timer%stop("complex_kernel_via_environment_variable")
#endif

   end function
!-------------------------------------------------------------------------------

end module ELPA2_utilities