Line data Source code
1 : !-------------------------------------------------------------------------------
2 : ! Copyright (c) 2025 Peter Grünberg Institut, Forschungszentrum Jülich, Germany
3 : ! This file is part of FLEUR and available as free software under the conditions
4 : ! of the MIT license as expressed in the LICENSE file in more detail.
5 : !--------------------------------------------------------------------------------
6 :
7 : module m_elsi
8 : use m_types_solver
9 : implicit none
10 :
11 : type, extends(t_solver)::t_solver_elsi
12 : contains
13 : procedure :: solve_gev => elsi_GEV
14 : end type
15 : public :: get_solver_elsi
16 :
17 : contains
18 :
19 91 : function get_solver_elsi() result(solver)
20 : class(t_solver), allocatable :: solver
21 91 : allocate (t_solver_elsi :: solver)
22 91 : solver%name = "elsi"
23 : #ifdef CPP_ELSI
24 : solver%available = .true.
25 : #else
26 91 : solver%available = .false.
27 : #endif
28 91 : solver%parallel = .true.
29 91 : solver%serial = .true.
30 91 : solver%generalized = .true.
31 91 : solver%standard = .false.
32 91 : solver%single_precision = .false.
33 91 : solver%transform = .false.
34 91 : solver%GPU = .false.
35 91 : solver%use_sp = .false.
36 91 : end function
37 :
38 0 : subroutine elsi_gev(self, hmat, smat, ne, eig, zmat, ikpt)
39 :
40 : use m_juDFT
41 : use m_types_mpimat
42 : use m_types_mat
43 : #ifdef CPP_ELSI
44 : use elsi
45 : use mpi
46 : #endif
47 : implicit none
48 : class(t_solver_elsi) ::self
49 : class(t_mat), intent(INOUT) :: hmat, smat
50 : class(t_mat), allocatable, intent(OUT)::zmat
51 : real, intent(out) :: eig(:)
52 : integer, intent(INOUT) :: ne
53 : integer, intent(IN) :: ikpt
54 :
55 : integer, parameter :: solver = 1 !Use 1 for ELPA, 9 for ChASE. See ELSI manual for more solvers.
56 :
57 : #ifdef CPP_ELSI
58 : !... Local variables
59 : !
60 : integer :: blk
61 : integer, parameter :: BLACS_DENSE = 0
62 : type(elsi_handle) :: eh
63 : class(t_mat), allocatable :: evec
64 : real, allocatable :: eig_tmp(:)
65 :
66 : call timestart("ELSI")
67 :
68 : call hmat%u2l()
69 : call smat%u2l()
70 :
71 : select type (hmat)
72 : type IS (t_mpimat)
73 : select type (smat)
74 : type IS (t_mpimat)
75 : if (hmat%blacsdata%blacs_desc(5) == hmat%blacsdata%blacs_desc(6)) then
76 : blk = hmat%blacsdata%blacs_desc(5)
77 : else
78 : call judft_error("BUG: in ELSI the row/column blocksize must be equal")
79 : end if
80 : call elsi_init(eh, solver, 1, BLACS_DENSE, hmat%global_size1, 1.0*ne, ne)
81 : call elsi_set_mpi(eh, hmat%blacsdata%mpi_com)
82 : call elsi_set_blacs(eh, hmat%blacsdata%blacs_desc(2), blk)
83 : allocate (t_mpimat::evec)
84 : call evec%init(hmat)
85 : allocate (eig_tmp(hmat%global_size1))
86 : class DEFAULT
87 : call judft_error("BUG: Inconsistent matrixes in ELSI call")
88 : end select
89 : type IS (t_mat)
90 : select type (smat)
91 : type IS (t_mat)
92 : call elsi_init(eh, solver, 0, BLACS_DENSE, hmat%matsize1, 1.*ne, ne)
93 : allocate (t_mat::evec)
94 : call evec%init(hmat)
95 : allocate (eig_tmp(hmat%matsize1))
96 :
97 : class DEFAULT
98 : call judft_error("BUG: Inconsistent matrixes in ELSI call")
99 : end select
100 : end select
101 : call timestart("elsi_ev")
102 : #ifdef _OPENACC
103 : call elsi_set_elpa_gpu(eh, 1)
104 : #endif
105 : !Now perform diagonalization
106 : call elsi_set_output(eh, 3)
107 : call elsi_set_output_unit(eh, 7)
108 : call elsi_set_illcond_check(eh, 0)
109 : call elsi_reinit(eh)
110 : if (hmat%l_real) then
111 : call elsi_ev_real(eh, hmat%data_r, smat%data_r, eig_tmp, evec%data_r)
112 : else
113 : call elsi_ev_complex(eh, hmat%data_c, smat%data_c, eig_tmp, evec%data_c)
114 : end if
115 : call timestop("elsi_ev")
116 : call timestart("set output")
117 : !Copy data into correct data structures
118 : eig = eig_tmp(:size(eig))
119 : select type (evec)
120 : type IS (t_mat)
121 : allocate (t_mat::zmat)
122 : call zmat%init(evec%l_real, evec%matsize1, ne)
123 : if (evec%l_real) then
124 : zmat%data_r = evec%data_r(:, :ne)
125 : else
126 : zmat%data_c = evec%data_c(:, :ne)
127 : end if
128 : type IS (t_mpimat)
129 : allocate (t_mpimat::zmat)
130 : call zmat%init(evec)
131 : call zmat%copy(evec, 1, 1)
132 :
133 : end select
134 : call evec%free()
135 : call timestop("set output")
136 : call elsi_finalize(eh)
137 : call timestop("ELSI")
138 :
139 : #endif
140 0 : end subroutine elsi_gev
141 182 : end module m_elsi
|