34 use blas_lapack_gbl,
only: blasint
35 use const_gbl,
only: stdout
37 use mpi_gbl,
only: master, myrank, mpi_xermsg
67 class(
basematrix),
intent(in) :: matrix_elements
69 type(
options),
intent(in) :: option
70 integer,
intent(in) :: num_eigenpair
71 logical,
intent(in) :: all_procs
73 real(wp),
allocatable :: z_mat(:,:), w(:)
76 write (stdout,
"('Utilizing Optimized SCALAPACK matrix')")
77 write (stdout,
"('N: ',I0)") matrix_elements % get_matrix_size()
78 write (stdout,
"('Requested # of eigenpairs ',I0)") num_eigenpair
81 select type(matrix_elements)
83 call this % diagonalize_backend(matrix_elements, num_eigenpair, z_mat, w, all_procs, option, integrals)
84 call this % process_solution(matrix_elements, num_eigenpair, z_mat, w, dresult, all_procs, option, integrals)
95 type(
options),
intent(in) :: option
96 integer,
intent(in) :: num_eigenpair
97 logical,
intent(in) :: all_procs
98 real(wp),
allocatable,
intent(inout) :: z_mat(:,:), w(:)
100 real(wp),
allocatable :: work(:), pdsyevd_lwork(:), pdormtr_lwork(:)
101 integer(blasint),
allocatable :: iwork(:)
102 integer(blasint) :: lwork, liwork, npcol, mat_dimen, info, loc_r, loc_c, one = 1
105 write (stdout,
"('Diagonalization will be done with SCALAPACK')")
107 npcol = grid % gpcols
108 loc_r = matrix_elements % local_row_dimen
109 loc_c = matrix_elements % local_col_dimen
110 mat_dimen = matrix_elements % get_matrix_size()
113 allocate(z_mat(loc_r, loc_c), w(mat_dimen), stat = ierr)
115 call mpi_xermsg(
'SCALAPACKDiagonalizer_module',
'diagonalize_backend_SCALAPACK',
'Memory allocation error.', ierr, 1)
130 liwork = 7*mat_dimen + 8*npcol + 2
132 allocate(pdsyevd_lwork(1), pdormtr_lwork(1), iwork(liwork))
134 call pdsyevd(
'V',
'L', mat_dimen, matrix_elements % a_local_matrix, one, one, matrix_elements % descr_a_mat, w, z_mat, &
135 one, one, matrix_elements % descr_z_mat, pdsyevd_lwork, -one, iwork, liwork, info)
136 call pdormtr(
'L',
'L',
'N', mat_dimen, mat_dimen, matrix_elements % a_local_matrix, one, one, &
137 matrix_elements % descr_a_mat, w, z_mat, one, one, matrix_elements % descr_z_mat, pdormtr_lwork, -one, info)
139 lwork = ceiling(max(pdsyevd_lwork(1), pdormtr_lwork(1) + 2 * mat_dimen))
141 allocate(work(lwork), stat = info)
144 write (stdout,
"('ScaLAPACK workspace size: lwork = ',I0,', liwork = ',I0)") lwork, liwork
146 call mpi_xermsg(
'SCALAPACKDiagonalizer_module',
'DoSCALAPACKMat',
'Memory allocation error', int(info), 1)
151 call pdsyevd(
'V',
'L', mat_dimen, matrix_elements % a_local_matrix, one, one, matrix_elements % descr_a_mat, w, z_mat, &
152 one, one, matrix_elements % descr_z_mat, work, lwork, iwork, liwork, info)
155 write (stdout,
"(/'Diagonalization finished successfully!')")
157 call mpi_xermsg(
'SCALAPACKDiagonalizer_module',
'DoSCALAPACKMat',
'PDSYEVD returned non-zero code', int(info), 1)
163 subroutine process_solution (this, matrix_elements, num_eigenpair, z_mat, w, dresult, all_procs, option, integrals)
169 type(
options),
intent(in) :: option
170 integer,
intent(in) :: num_eigenpair
171 logical,
intent(in) :: all_procs
172 real(wp),
allocatable,
intent(inout) :: z_mat(:,:), w(:)
174 real(wp),
allocatable :: global_vector(:)
176 integer(blasint) :: myrow, mycol, nprow, npcol, blacs_context, i, j, iprow, ipcol
177 integer(blasint) :: mat_dimen, nb, loc_r, loc_c, jdimen, idimen
179 blacs_context = grid % gcntxt
180 myrow = grid % mygrow
181 mycol = grid % mygcol
182 nprow = grid % gprows
183 npcol = grid % gpcols
185 mat_dimen = matrix_elements % get_matrix_size()
186 loc_r = matrix_elements % local_row_dimen
187 loc_c = matrix_elements % local_col_dimen
188 nb = matrix_elements % scal_block_size
192 write (stdout,
'(/," Only the continuum part of the eigenvectors will be saved to disk.")')
193 write (stdout,
'(" Index of the last continuum configuration: ",i10)') dresult % continuum_dimen
197 allocate(global_vector(mat_dimen))
198 call blacs_barrier(blacs_context,
'a')
202 call dresult % export_header(option, integrals)
206 if (grid % grank == master)
then
207 call dresult % write_header(option, integrals)
211 if (all_procs .or. grid % grank == master)
then
212 call dresult % handle_eigenvalues(w(1:num_eigenpair), matrix_elements % diagonal, num_eigenpair, int(mat_dimen))
217 do jdimen = 1, num_eigenpair
223 do idimen = 1, mat_dimen
224 call infog2l(idimen, jdimen, matrix_elements % descr_z_mat, nprow, npcol, myrow, mycol, i, j, iprow, ipcol)
225 if (myrow == iprow .and. mycol == ipcol)
then
226 global_vector(idimen) = z_mat(i,j)
233 call dgsum2d(blacs_context,
'all',
' ', mat_dimen, 1, global_vector, mat_dimen, -1, -1)
234 call dresult % handle_eigenvector(global_vector, int(mat_dimen))
237 call dgsum2d(blacs_context,
'all',
' ', mat_dimen, 1, global_vector, mat_dimen, 0, 0)
238 if (grid % grank == master)
then
239 call dresult % handle_eigenvector(global_vector, int(mat_dimen))
249 if (
allocated(dresult % ci_vec % CV))
deallocate(dresult % ci_vec % CV)
250 call move_alloc(z_mat, dresult % ci_vec % CV)
251 dresult % ci_vec % blacs_context = blacs_context
252 dresult % ci_vec % local_row_dimen = loc_r
253 dresult % ci_vec % local_col_dimen = loc_c
254 dresult % ci_vec % scal_block_size = nb
255 dresult % ci_vec % myrow = myrow
256 dresult % ci_vec % mycol = mycol
257 dresult % ci_vec % nprow = nprow
258 dresult % ci_vec % npcol = npcol
259 dresult % ci_vec % mat_dimen = matrix_elements % get_matrix_size()
260 dresult % ci_vec % descr_CV_mat = matrix_elements % descr_z_mat
261 dresult % ci_vec % lda = matrix_elements % lda
262 dresult % ci_vec % CV_is_scalapack = .true.
264 dresult % ci_vec % mat_dimen_r = dresult % ci_vec % mat_dimen
265 dresult % ci_vec % mat_dimen_c = dresult % ci_vec % mat_dimen
268 call dresult % export_eigenvalues(w(1:num_eigenpair), matrix_elements % diagonal, num_eigenpair, &
269 int(mat_dimen), dresult % ci_vec % ei, dresult % ci_vec % iphz)
271 write (stdout,
'(/," Eigensolutions exported into the CIVect structure.",/)')
275 if (grid % grank == master)
then
276 call dresult % finalize_solutions(option)
279 if (
allocated(z_mat))
deallocate(z_mat)
281 call blacs_barrier(blacs_context,
'a')