1!--------------------------------------------------------------------------------------------------!
2!  DFTB+: general package for performing fast atomistic simulations                                !
3!  Copyright (C) 2006 - 2019  DFTB+ developers group                                               !
4!                                                                                                  !
5!  See the LICENSE file for terms of usage and distribution.                                       !
6!--------------------------------------------------------------------------------------------------!
7
8#:include 'common.fypp'
9
10
11!> Interface wrapper for the ELSI library
12!>
13module dftbp_elsiiface
14  use dftbp_accuracy, only : dp
15#:if WITH_ELSI
16  use elsi
17#:else
18  use iso_c_binding, only : r8 => c_double, i4 => c_int32_t
19  use dftbp_message, only : error
20#:endif
21  implicit none
22  private
23
24  public :: withElsi, withPexsi
25  public :: elsi_handle, elsi_rw_handle
26  public :: elsi_init, elsi_reinit, elsi_finalize
27  public :: elsi_init_rw, elsi_finalize_rw
28  public :: elsi_set_csc, elsi_set_csc_blk, elsi_set_zero_def, elsi_set_rw_zero_def
29  public :: elsi_dm_real, elsi_dm_complex
30  public :: elsi_dm_real_sparse, elsi_dm_complex_sparse
31  public :: elsi_get_edm_real, elsi_get_edm_complex
32  public :: elsi_get_edm_real_sparse, elsi_get_edm_complex_sparse
33  public :: elsi_write_mat_real_sparse, elsi_write_mat_complex_sparse
34  public :: elsi_write_mat_real, elsi_write_mat_complex
35  public :: elsi_get_pexsi_mu_min, elsi_get_pexsi_mu_max
36  public :: elsi_set_pexsi_mu_min, elsi_set_pexsi_mu_max
37  public :: elsi_get_mu, elsi_get_entropy
38  public :: elsi_set_mu_mp_order, elsi_set_mu_broaden_width, elsi_set_mu_broaden_scheme
39  public :: elsi_set_elpa_solver
40  public :: elsi_set_omm_flavor, elsi_set_omm_n_elpa, elsi_set_omm_tol
41  public :: elsi_set_pexsi_np_per_pole, elsi_set_pexsi_temp, elsi_set_pexsi_n_pole
42  public :: elsi_set_pexsi_n_mu, elsi_set_pexsi_np_symbo, elsi_set_pexsi_delta_e
43  public :: elsi_set_ntpoly_method, elsi_set_ntpoly_filter, elsi_set_ntpoly_tol
44  public :: elsi_set_spin, elsi_set_kpoint
45  public :: elsi_set_output, elsi_set_output_log
46  public :: elsi_ev_complex, elsi_ev_real
47  public :: elsi_set_rw_csc
48  public :: elsi_set_rw_mpi, elsi_set_rw_blacs
49  public :: elsi_set_mpi, elsi_set_mpi_global
50  public :: elsi_set_blacs
51  public :: elsi_set_sing_check
52
53
54  !> Whether code was built with ELSI support
55  logical, parameter :: withElsi = #{if WITH_ELSI}# .true. #{else}# .false. #{endif}#
56
57  !> Whether code was built with PEXSI support
58  logical, parameter :: withPexsi = #{if WITH_PEXSI}# .true. #{else}# .false. #{endif}#
59
60
61#:if not WITH_ELSI
62
63  ! Placeholder types when compiled without ELSI support
64
65  type :: elsi_handle
66  end type elsi_handle
67
68  type :: elsi_rw_handle
69  end type elsi_rw_handle
70
71#:endif
72
73
74contains
75
76#:if not WITH_ELSI
77
78  !> Generates error message, if a stub was called
79  subroutine stubError(routineName)
80    character(*), intent(in) :: routineName
81
82    call error("Internal error: " // trim(routineName) // "() called in a build without ELSI&
83        & support")
84
85  end subroutine stubError
86
87
88  !
89  ! Placeholder routines when compiled without ELSI support
90  !
91
92  subroutine elsi_init(eh, solver, parallel_mode, matrix_format, n_basis, n_electron, n_state)
93    type(elsi_handle), intent(out) :: eh
94    integer(i4), intent(in) :: solver
95    integer(i4), intent(in) :: parallel_mode
96    integer(i4), intent(in) :: matrix_format
97    integer(i4), intent(in) :: n_basis
98    real(r8), intent(in) :: n_electron
99    integer(i4), intent(in) :: n_state
100    call stubError("elsi_init")
101  end subroutine elsi_init
102
103  subroutine elsi_reinit(eh)
104    type(elsi_handle), intent(inout) :: eh
105    call stubError("elsi_reinit")
106  end subroutine elsi_reinit
107
108  subroutine elsi_finalize(eh)
109    type(elsi_handle), intent(inout) :: eh
110    call stubError("elsi_finalize")
111  end subroutine elsi_finalize
112
113
114  subroutine elsi_set_csc(eh, nnz_g, nnz_l, n_lcol, row_ind, col_ptr)
115    type(elsi_handle), intent(inout) :: eh
116    integer(i4), intent(in) :: nnz_g
117    integer(i4), intent(in) :: nnz_l
118    integer(i4), intent(in) :: n_lcol
119    integer(i4), intent(in) :: row_ind(:)
120    integer(i4), intent(in) :: col_ptr(:)
121    call stubError("elsi_set_csc")
122  end subroutine elsi_set_csc
123
124
125  subroutine elsi_set_csc_blk(eh, blk)
126    type(elsi_handle), intent(inout) :: eh
127    integer(i4), intent(in) :: blk
128    call stubError("elsi_set_csc_blk")
129  end subroutine elsi_set_csc_blk
130
131
132  subroutine elsi_set_zero_def(eh, zero)
133    type(elsi_handle), intent(inout) :: eh
134    real(r8), intent(in) :: zero
135  end subroutine elsi_set_zero_def
136
137  subroutine elsi_set_rw_zero_def(eh, zero)
138    type(elsi_rw_handle), intent(inout) :: eh
139    real(r8), intent(in) :: zero
140  end subroutine elsi_set_rw_zero_def
141
142
143  subroutine elsi_dm_real(eh, ham, ovlp, dm, ebs)
144    type(elsi_handle), intent(inout) :: eh
145    real(r8), intent(inout) :: ham(:,:)
146    real(r8), intent(inout) :: ovlp(:,:)
147    real(r8), intent(inout) :: dm(:,:)
148    real(r8), intent(inout) :: ebs
149    call stubError("elsi_dm_real")
150  end subroutine elsi_dm_real
151
152
153  subroutine elsi_dm_complex(eh, ham, ovlp, dm, ebs)
154    type(elsi_handle), intent(inout) :: eh
155    complex(r8), intent(inout) :: ham(:,:)
156    complex(r8), intent(inout) :: ovlp(:,:)
157    complex(r8), intent(inout) :: dm(:,:)
158    real(r8), intent(inout) :: ebs
159    call stubError("elsi_dm_complex")
160  end subroutine elsi_dm_complex
161
162
163  subroutine elsi_dm_real_sparse(eh, ham, ovlp, dm, ebs)
164    type(elsi_handle), intent(inout) :: eh
165    real(r8), intent(inout) :: ham(:)
166    real(r8), intent(inout) :: ovlp(:)
167    real(r8), intent(inout) :: dm(:)
168    real(r8), intent(inout) :: ebs
169    call stubError("elsi_dm_real_sparse")
170  end subroutine elsi_dm_real_sparse
171
172
173  subroutine elsi_dm_complex_sparse(eh, ham, ovlp, dm, ebs)
174    type(elsi_handle), intent(inout) :: eh
175    complex(r8), intent(inout) :: ham(:)
176    complex(r8), intent(inout) :: ovlp(:)
177    complex(r8), intent(inout) :: dm(:)
178    real(r8), intent(inout) :: ebs
179    call stubError("elsi_dm_complex_sparse")
180  end subroutine elsi_dm_complex_sparse
181
182
183  subroutine elsi_get_edm_real(eh, edm)
184    type(elsi_handle), intent(inout) :: eh
185    real(r8), intent(out) :: edm(:,:)
186    call stubError("elsi_get_edm_real")
187  end subroutine elsi_get_edm_real
188
189
190  subroutine elsi_get_edm_complex(eh, edm)
191    type(elsi_handle), intent(inout) :: eh
192    complex(r8), intent(out) :: edm(:,:)
193    call stubError("elsi_get_edm_complex")
194  end subroutine elsi_get_edm_complex
195
196
197  subroutine elsi_get_edm_real_sparse(eh, edm)
198    type(elsi_handle), intent(inout) :: eh
199    real(r8), intent(out) :: edm(:)
200    call stubError("elsi_get_edm_real_sparse")
201  end subroutine elsi_get_edm_real_sparse
202
203
204  subroutine elsi_get_edm_complex_sparse(eh, edm)
205    type(elsi_handle), intent(inout) :: eh
206    complex(r8), intent(out) :: edm(:)
207    call stubError("elsi_get_edm_complex_sparse")
208  end subroutine elsi_get_edm_complex_sparse
209
210
211  subroutine elsi_get_mu(eh, mu)
212    type(elsi_handle), intent(inout) :: eh
213    real(r8), intent(out) :: mu
214    call stubError("elsi_get_mu")
215  end subroutine elsi_get_mu
216
217
218  subroutine elsi_get_entropy(eh, entropy)
219    type(elsi_handle), intent(inout) :: eh
220    real(r8), intent(out) :: entropy
221    call stubError("elsi_get_entropy")
222  end subroutine elsi_get_entropy
223
224
225  subroutine elsi_ev_real(eh, ham, ovlp, eval, evec)
226    type(elsi_handle), intent(inout) :: eh
227    real(r8), intent(inout) :: ham(:,:)
228    real(r8), intent(inout) :: ovlp(:,:)
229    real(r8), intent(inout) :: eval(:)
230    real(r8), intent(inout) :: evec(:,:)
231    call stubError("elsi_ev_real")
232  end subroutine elsi_ev_real
233
234
235  subroutine elsi_ev_complex(eh, ham, ovlp, eval, evec)
236    type(elsi_handle), intent(inout) :: eh
237    complex(r8), intent(inout) :: ham(:,:)
238    complex(r8), intent(inout) :: ovlp(:,:)
239    real(r8), intent(inout) :: eval(:)
240    complex(r8), intent(inout) :: evec(:,:)
241    call stubError("elsi_ev_complex")
242  end subroutine elsi_ev_complex
243
244
245  subroutine elsi_set_blacs(eh, blacs_ctxt, block_size)
246    type(elsi_handle), intent(inout) :: eh
247    integer(i4), intent(in) :: blacs_ctxt
248    integer(i4), intent(in) :: block_size
249    call stubError("elsi_set_blacs")
250  end subroutine elsi_set_blacs
251
252
253  subroutine elsi_set_elpa_solver(eh, solver)
254    type(elsi_handle), intent(inout) :: eh
255    integer(i4), intent(in) :: solver
256    call stubError("elsi_set_set_elpa_solver")
257  end subroutine elsi_set_elpa_solver
258
259
260  subroutine elsi_set_kpoint(eh, n_kpt, i_kpt, i_wt)
261    type(elsi_handle), intent(inout) :: eh
262    integer(i4), intent(in) :: n_kpt
263    integer(i4), intent(in) :: i_kpt
264    real(r8), intent(in) :: i_wt
265    call stubError("elsi_set_kpoint")
266  end subroutine elsi_set_kpoint
267
268
269  subroutine elsi_set_spin(eh, n_spin, i_spin)
270    type(elsi_handle), intent(inout) :: eh
271    integer(i4), intent(in) :: n_spin
272    integer(i4), intent(in) :: i_spin
273    call stubError("elsi_set_spin")
274  end subroutine elsi_set_spin
275
276
277  subroutine elsi_set_mpi(eh, comm)
278    type(elsi_handle), intent(inout) :: eh
279    integer(i4), intent(in) :: comm
280    call stubError("elsi_set_mpi")
281  end subroutine elsi_set_mpi
282
283
284  subroutine elsi_set_mpi_global(eh, comm_all)
285    type(elsi_handle), intent(inout) :: eh
286    integer(i4), intent(in) :: comm_all
287    call stubError("elsi_set_mpi_global")
288  end subroutine elsi_set_mpi_global
289
290
291  subroutine elsi_set_sing_check(eh, illcond_check)
292    type(elsi_handle), intent(inout) :: eh
293    integer(i4), intent(in) :: illcond_check
294    call stubError("elsi_set_sing_check")
295  end subroutine elsi_set_sing_check
296
297
298  subroutine elsi_set_mu_broaden_scheme(eh, broaden_scheme)
299    type(elsi_handle), intent(inout) :: eh
300    integer(i4), intent(in) :: broaden_scheme
301    call stubError("elsi_set_mu_broaden_scheme")
302  end subroutine elsi_set_mu_broaden_scheme
303
304
305  subroutine elsi_set_mu_broaden_width(eh, broaden_width)
306    type(elsi_handle), intent(inout) :: eh
307    real(r8), intent(in) :: broaden_width
308    call stubError("elsi_set_mu_broaden_width")
309  end subroutine elsi_set_mu_broaden_width
310
311
312  subroutine elsi_set_mu_mp_order(eh, mp_order)
313    type(elsi_handle), intent(inout) :: eh
314    integer(i4), intent(in) :: mp_order
315    call stubError("elsi_set_mu_broaden_width")
316  end subroutine elsi_set_mu_mp_order
317
318
319  subroutine elsi_set_ntpoly_method(eh, method)
320    type(elsi_handle), intent(inout) :: eh
321    integer(i4), intent(in) :: method
322    call stubError("elsi_set_ntpoly_method")
323  end subroutine elsi_set_ntpoly_method
324
325
326  subroutine elsi_set_ntpoly_filter(eh, filter)
327    type(elsi_handle), intent(inout) :: eh
328    real(r8), intent(in) :: filter
329    call stubError("elsi_set_ntpoly_filter")
330  end subroutine elsi_set_ntpoly_filter
331
332
333  subroutine elsi_set_ntpoly_tol(eh, tol)
334    type(elsi_handle), intent(inout) :: eh
335    real(r8), intent(in) :: tol
336    call stubError("elsi_set_ntpoly_tol")
337  end subroutine elsi_set_ntpoly_tol
338
339
340  subroutine elsi_set_omm_flavor(eh, flavor)
341    type(elsi_handle), intent(inout) :: eh
342    integer(i4), intent(in) :: flavor
343    call stubError("elsi_set_omm_flavor")
344  end subroutine elsi_set_omm_flavor
345
346
347  subroutine elsi_set_omm_n_elpa(eh, n_elpa)
348    type(elsi_handle), intent(inout) :: eh
349    integer(i4), intent(in) :: n_elpa
350    call stubError("elsi_set_omm_n_elpa")
351  end subroutine elsi_set_omm_n_elpa
352
353
354  subroutine elsi_set_omm_tol(eh, tol)
355    type(elsi_handle), intent(inout) :: eh
356    real(r8), intent(in) :: tol
357    call stubError("elsi_set_omm_tol")
358  end subroutine elsi_set_omm_tol
359
360
361  subroutine elsi_set_pexsi_mu_min(eh, mu_min)
362    type(elsi_handle), intent(inout) :: eh
363    real(r8), intent(in) :: mu_min
364    call stubError("elsi_set_pexsi_mu_min")
365  end subroutine elsi_set_pexsi_mu_min
366
367
368  subroutine elsi_set_pexsi_mu_max(eh, mu_max)
369    type(elsi_handle), intent(inout) :: eh
370    real(r8), intent(in) :: mu_max
371    call stubError("elsi_set_pexsi_mu_max")
372  end subroutine elsi_set_pexsi_mu_max
373
374
375  subroutine elsi_get_pexsi_mu_min(eh, mu_min)
376    type(elsi_handle), intent(inout) :: eh
377    real(r8), intent(out) :: mu_min
378    call stubError("elsi_get_pexsi_mu_min")
379  end subroutine elsi_get_pexsi_mu_min
380
381
382  subroutine elsi_get_pexsi_mu_max(eh, mu_max)
383    type(elsi_handle), intent(inout) :: eh
384    real(r8), intent(out) :: mu_max
385    call stubError("elsi_get_pexsi_mu_max")
386  end subroutine elsi_get_pexsi_mu_max
387
388
389  subroutine elsi_set_pexsi_delta_e(eh, delta_e)
390    type(elsi_handle), intent(inout) :: eh
391    real(r8), intent(in) :: delta_e
392    call stubError("elsi_get_pexsi_delta_e")
393  end subroutine elsi_set_pexsi_delta_e
394
395
396  subroutine elsi_set_pexsi_temp(eh, temp)
397    type(elsi_handle), intent(inout) :: eh
398    real(r8), intent(in) :: temp
399    call stubError("elsi_set_pexsi_temp")
400  end subroutine elsi_set_pexsi_temp
401
402
403  subroutine elsi_set_pexsi_n_mu(eh, n_mu)
404    type(elsi_handle), intent(inout) :: eh
405    integer(i4), intent(in) :: n_mu
406    call stubError("elsi_set_pexsi_n_mu")
407  end subroutine elsi_set_pexsi_n_mu
408
409
410  subroutine elsi_set_pexsi_np_symbo(eh, np_symbo)
411    type(elsi_handle), intent(inout) :: eh
412    integer(i4), intent(in) :: np_symbo
413    call stubError("elsi_set_pexsi_np_symbo")
414  end subroutine elsi_set_pexsi_np_symbo
415
416
417  subroutine elsi_set_pexsi_n_pole(eh, n_pole)
418    type(elsi_handle), intent(inout) :: eh
419    integer(i4), intent(in) :: n_pole
420    call stubError("elsi_set_pexsi_np_pole")
421  end subroutine elsi_set_pexsi_n_pole
422
423
424  subroutine elsi_set_pexsi_np_per_pole(eh, np_per_pole)
425    type(elsi_handle), intent(inout) :: eh
426    integer(i4), intent(in) :: np_per_pole
427    call stubError("elsi_set_pexsi_np_per_pole")
428  end subroutine elsi_set_pexsi_np_per_pole
429
430
431  subroutine elsi_set_output(eh, output)
432    type(elsi_handle), intent(inout) :: eh
433    integer(i4), intent(in) :: output
434    call stubError("elsi_set_output")
435  end subroutine elsi_set_output
436
437
438  subroutine elsi_set_output_log(eh, output_log)
439    type(elsi_handle), intent(inout) :: eh
440    integer(i4), intent(in) :: output_log
441    call stubError("elsi_set_output_log")
442  end subroutine elsi_set_output_log
443
444
445  subroutine elsi_init_rw(rwh, task, parallel_mode, n_basis, n_electron)
446    type(elsi_rw_handle), intent(out) :: rwh
447    integer(i4), intent(in) :: task
448    integer(i4), intent(in) :: parallel_mode
449    integer(i4), intent(in) :: n_basis
450    real(r8), intent(in) :: n_electron
451    call stubError("elsi_init_rw")
452  end subroutine elsi_init_rw
453
454
455  subroutine elsi_finalize_rw(rwh)
456    type(elsi_rw_handle), intent(inout) :: rwh
457    call stubError("elsi_finalize_rw")
458  end subroutine elsi_finalize_rw
459
460
461  subroutine elsi_set_rw_csc(rwh, nnz_g, nnz_l_sp, n_lcol_sp)
462    type(elsi_rw_handle), intent(inout) :: rwh
463    integer(i4), intent(in) :: nnz_g
464    integer(i4), intent(in) :: nnz_l_sp
465    integer(i4), intent(in) :: n_lcol_sp
466    call stubError("elsi_set_rw_csc")
467  end subroutine elsi_set_rw_csc
468
469
470  subroutine elsi_set_rw_mpi(rwh, mpi_comm)
471    type(elsi_rw_handle), intent(inout) :: rwh
472    integer(i4), intent(in) :: mpi_comm
473    call stubError("elsi_set_rw_mpi")
474  end subroutine elsi_set_rw_mpi
475
476
477
478  subroutine elsi_set_rw_blacs(rwh, blacs_ctxt, block_size)
479    type(elsi_rw_handle), intent(inout) :: rwh
480    integer(i4), intent(in) :: blacs_ctxt
481    integer(i4), intent(in) :: block_size
482    call stubError("elsi_set_rw_blacs")
483  end subroutine elsi_set_rw_blacs
484
485
486  subroutine elsi_write_mat_real_sparse(rwh, f_name, row_ind, col_ptr, mat)
487    type(elsi_rw_handle), intent(in) :: rwh
488    character(*), intent(in) :: f_name
489    integer(i4), intent(in) :: row_ind(:)
490    integer(i4), intent(in) :: col_ptr(:)
491    real(r8), intent(in) :: mat(:)
492    call stubError("elsi_write_mat_real_sparse")
493  end subroutine elsi_write_mat_real_sparse
494
495
496  subroutine elsi_write_mat_complex_sparse(rwh, f_name, row_ind, col_ptr, mat)
497    type(elsi_rw_handle), intent(in) :: rwh
498    character(*), intent(in) :: f_name
499    integer(i4), intent(in) :: row_ind(:)
500    integer(i4), intent(in) :: col_ptr(:)
501    complex(r8), intent(in) :: mat(:)
502    call stubError("elsi_write_mat_complex_sparse")
503  end subroutine elsi_write_mat_complex_sparse
504
505
506  subroutine elsi_write_mat_real(rwh, f_name, mat)
507    type(elsi_rw_handle), intent(in) :: rwh
508    character(*), intent(in) :: f_name
509    real(r8), intent(in) :: mat(:,:)
510    call stubError("elsi_write_mat_real")
511  end subroutine elsi_write_mat_real
512
513
514  subroutine elsi_write_mat_complex(rwh, f_name, mat)
515    type(elsi_rw_handle), intent(in) :: rwh
516    character(*), intent(in) :: f_name
517    complex(r8), intent(in) :: mat(:,:)
518    call stubError("elsi_write_mat_complex")
519  end subroutine elsi_write_mat_complex
520
521#:endif
522
523end module dftbp_elsiiface
524