18 #include "../base/base_uses.f90"
24 CHARACTER(len=*),
PARAMETER,
PRIVATE :: moduleN =
'arnoldi_geev'
26 PUBLIC :: arnoldi_general_local_diag, arnoldi_tridiag_local_diag, arnoldi_symm_local_diag
28 INTERFACE arnoldi_general_local_diag
29 MODULE PROCEDURE arnoldi_sgeev, arnoldi_dgeev, arnoldi_zgeev, arnoldi_cgeev
33 INTERFACE arnoldi_tridiag_local_diag
34 MODULE PROCEDURE arnoldi_sstev, arnoldi_dstev, arnoldi_zgeev, arnoldi_cgeev
38 INTERFACE arnoldi_symm_local_diag
39 MODULE PROCEDURE arnoldi_dsyevd, arnoldi_ssyevd, arnoldi_cheevd, arnoldi_zheevd
52 SUBROUTINE arnoldi_zheevd(jobvr, matrix, ndim, evals, revec)
54 COMPLEX(real_8),
DIMENSION(:, :) :: matrix
56 COMPLEX(real_8),
DIMENSION(:) :: evals
57 COMPLEX(real_8),
DIMENSION(:, :) :: revec
59 INTEGER :: i, info, liwork, lrwork, lwork, &
61 COMPLEX(real_8) :: work(2*ndim + ndim**2), &
63 REAL(real_8) :: rwork(1 + 5*ndim + 2*ndim**2)
65 tmp_array(:, :) = matrix(:, :)
66 lwork = 2*ndim + ndim**2
67 lrwork = 1 + 5*ndim + 2*ndim**2
70 CALL zheevd(jobvr,
'U', ndim, tmp_array, evals, ndim, work, lwork, rwork, lrwork, iwork, liwork, info)
73 revec(:, i) = tmp_array(:, i)
76 END SUBROUTINE arnoldi_zheevd
86 SUBROUTINE arnoldi_cheevd(jobvr, matrix, ndim, evals, revec)
88 COMPLEX(real_4),
DIMENSION(:, :) :: matrix
90 COMPLEX(real_4),
DIMENSION(:) :: evals
91 COMPLEX(real_4),
DIMENSION(:, :) :: revec
93 INTEGER :: i, info, liwork, lrwork, lwork, &
95 COMPLEX(real_4) :: work(2*ndim + ndim**2), &
97 REAL(real_4) :: rwork(1 + 5*ndim + 2*ndim**2)
99 tmp_array(:, :) = matrix(:, :)
100 lwork = 2*ndim + ndim**2
101 lrwork = 1 + 5*ndim + 2*ndim**2
104 CALL cheevd(jobvr,
'U', ndim, tmp_array, evals, ndim, work, lwork, rwork, lrwork, iwork, liwork, info)
107 revec(:, i) = tmp_array(:, i)
110 END SUBROUTINE arnoldi_cheevd
120 SUBROUTINE arnoldi_dsyevd(jobvr, matrix, ndim, evals, revec)
121 CHARACTER(1) :: jobvr
122 REAL(real_8),
DIMENSION(:, :) :: matrix
124 COMPLEX(real_8),
DIMENSION(:) :: evals
125 COMPLEX(real_8),
DIMENSION(:, :) :: revec
127 INTEGER :: i, info, liwork, lwork, iwork(3 + 5*ndim)
128 REAL(real_8) :: tmp_array(ndim, ndim), &
129 work(1 + 6*ndim + 2*ndim**2)
130 REAL(real_8),
DIMENSION(ndim) :: eval
132 lwork = 1 + 6*ndim + 2*ndim**2
135 tmp_array(:, :) = matrix(:, :)
136 CALL dsyevd(jobvr,
"U", ndim, tmp_array, ndim, eval, work, lwork, iwork, liwork, info)
139 revec(:, i) = cmplx(tmp_array(:, i), real(0.0, real_8), real_8)
140 evals(i) = cmplx(eval(i), 0.0, real_8)
143 END SUBROUTINE arnoldi_dsyevd
153 SUBROUTINE arnoldi_ssyevd(jobvr, matrix, ndim, evals, revec)
154 CHARACTER(1) :: jobvr
155 REAL(real_4),
DIMENSION(:, :) :: matrix
157 COMPLEX(real_4),
DIMENSION(:) :: evals
158 COMPLEX(real_4),
DIMENSION(:, :) :: revec
160 INTEGER :: i, info, liwork, lwork, iwork(3 + 5*ndim)
161 REAL(real_4) :: tmp_array(ndim, ndim), &
162 work(1 + 6*ndim + 2*ndim**2)
163 REAL(real_4),
DIMENSION(ndim) :: eval
166 lwork = 1 + 6*ndim + 2*ndim**2
169 tmp_array(:, :) = matrix(:, :)
170 CALL ssyevd(
"V",
"U", ndim, tmp_array, ndim, eval, work, lwork, iwork, liwork, info)
173 revec(:, i) = cmplx(tmp_array(:, i), real(0.0, real_4), real_4)
174 evals(i) = cmplx(eval(i), 0.0, real_4)
177 END SUBROUTINE arnoldi_ssyevd
189 SUBROUTINE arnoldi_sstev(jobvl, jobvr, matrix, ndim, evals, revec, levec)
190 CHARACTER(1) :: jobvl, jobvr
191 REAL(real_4),
DIMENSION(:, :) :: matrix
193 COMPLEX(real_4),
DIMENSION(:) :: evals
194 COMPLEX(real_4),
DIMENSION(:, :) :: revec, levec
197 REAL(real_4) :: work(20*ndim)
198 REAL(real_4),
DIMENSION(ndim) :: diag, offdiag
199 REAL(real_4),
DIMENSION(ndim, ndim) :: evec_r
203 levec(1, 1) = cmplx(0.0, 0.0, real_4)
205 diag(ndim) = matrix(ndim, ndim)
207 diag(i) = matrix(i, i)
208 offdiag(i) = matrix(i + 1, i)
211 CALL sstev(jobvr, ndim, diag, offdiag, evec_r, ndim, work, info)
214 revec(:, i) = cmplx(evec_r(:, i), real(0.0, real_4), real_4)
215 evals(i) = cmplx(diag(i), 0.0, real_4)
217 END SUBROUTINE arnoldi_sstev
229 SUBROUTINE arnoldi_dstev(jobvl, jobvr, matrix, ndim, evals, revec, levec)
230 CHARACTER(1) :: jobvl, jobvr
231 REAL(real_8),
DIMENSION(:, :) :: matrix
233 COMPLEX(real_8),
DIMENSION(:) :: evals
234 COMPLEX(real_8),
DIMENSION(:, :) :: revec, levec
237 REAL(real_8) :: work(20*ndim)
238 REAL(real_8),
DIMENSION(ndim) :: diag, offdiag
239 REAL(real_8),
DIMENSION(ndim, ndim) :: evec_r
243 levec(1, 1) = cmplx(0.0, 0.0, real_8)
245 diag(ndim) = matrix(ndim, ndim)
247 diag(i) = matrix(i, i)
248 offdiag(i) = matrix(i + 1, i)
252 CALL dstev(jobvr, ndim, diag, offdiag, evec_r, ndim, work, info)
255 revec(:, i) = cmplx(evec_r(:, i), real(0.0, real_8), real_8)
256 evals(i) = cmplx(diag(i), 0.0, real_8)
258 END SUBROUTINE arnoldi_dstev
269 SUBROUTINE arnoldi_sgeev(jobvl, jobvr, matrix, ndim, evals, revec, levec)
270 CHARACTER(1) :: jobvl, jobvr
271 REAL(real_4),
DIMENSION(:, :) :: matrix
273 COMPLEX(real_4),
DIMENSION(:) :: evals
274 COMPLEX(real_4),
DIMENSION(:, :) :: revec, levec
276 INTEGER :: i, info, lwork
277 LOGICAL :: selects(ndim)
278 REAL(real_4) :: norm, tmp_array(ndim, ndim), &
280 REAL(real_4),
DIMENSION(ndim) :: eval1, eval2
281 REAL(real_4),
DIMENSION(ndim, ndim) :: evec_l, evec_r
286 eval1 = real(0.0, real_4); eval2 = real(0.0, real_4)
287 tmp_array(:, :) = matrix(:, :)
290 CALL shseqr(
'S',
'I', ndim, 1, ndim, tmp_array, ndim, eval1, eval2, evec_r, ndim, work, lwork, info)
292 lwork = min(20*ndim, int(work(1)))
293 CALL shseqr(
'S',
'I', ndim, 1, ndim, tmp_array, ndim, eval1, eval2, evec_r, ndim, work, lwork, info)
294 CALL strevc(
'R',
'B', selects, ndim, tmp_array, ndim, evec_l, ndim, evec_r, ndim, ndim, ndim, work, info)
300 DO WHILE (i .LE. ndim)
301 IF (abs(eval2(i)) .LT. epsilon(real(0.0, real_4)))
THEN
302 evec_r(:, i) = evec_r(:, i)/sqrt(dot_product(evec_r(:, i), evec_r(:, i)))
303 revec(:, i) = cmplx(evec_r(:, i), real(0.0, real_4), real_4)
304 levec(:, i) = cmplx(evec_l(:, i), real(0.0, real_4), real_4)
306 ELSE IF (eval2(i) .GT. epsilon(real(0.0, real_4)))
THEN
307 norm = sqrt(sum(evec_r(:, i)**2.0_real_4) + sum(evec_r(:, i + 1)**2.0_real_4))
308 revec(:, i) = cmplx(evec_r(:, i), evec_r(:, i + 1), real_4)/norm
309 revec(:, i + 1) = cmplx(evec_r(:, i), -evec_r(:, i + 1), real_4)/norm
310 levec(:, i) = cmplx(evec_l(:, i), evec_l(:, i + 1), real_4)
311 levec(:, i + 1) = cmplx(evec_l(:, i), -evec_l(:, i + 1), real_4)
314 cpabort(
'something went wrong while sorting the EV in arnoldi_geev')
320 evals(i) = cmplx(eval1(i), eval2(i), real_4)
323 END SUBROUTINE arnoldi_sgeev
335 SUBROUTINE arnoldi_dgeev(jobvl, jobvr, matrix, ndim, evals, revec, levec)
336 CHARACTER(1) :: jobvl, jobvr
337 REAL(real_8),
DIMENSION(:, :) :: matrix
339 COMPLEX(real_8),
DIMENSION(:) :: evals
340 COMPLEX(real_8),
DIMENSION(:, :) :: revec, levec
342 INTEGER :: i, info, lwork
343 LOGICAL :: selects(ndim)
344 REAL(real_8) :: norm, tmp_array(ndim, ndim), &
346 REAL(real_8),
DIMENSION(ndim) :: eval1, eval2
347 REAL(real_8),
DIMENSION(ndim, ndim) :: evec_l, evec_r
352 eval1 = real(0.0, real_8); eval2 = real(0.0, real_8)
353 tmp_array(:, :) = matrix(:, :)
356 CALL dhseqr(
'S',
'I', ndim, 1, ndim, tmp_array, ndim, eval1, eval2, evec_r, ndim, work, lwork, info)
358 lwork = min(20*ndim, int(work(1)))
359 CALL dhseqr(
'S',
'I', ndim, 1, ndim, tmp_array, ndim, eval1, eval2, evec_r, ndim, work, lwork, info)
360 CALL dtrevc(
'R',
'B', selects, ndim, tmp_array, ndim, evec_l, ndim, evec_r, ndim, ndim, ndim, work, info)
366 DO WHILE (i .LE. ndim)
367 IF (abs(eval2(i)) .LT. epsilon(real(0.0, real_8)))
THEN
368 evec_r(:, i) = evec_r(:, i)/sqrt(dot_product(evec_r(:, i), evec_r(:, i)))
369 revec(:, i) = cmplx(evec_r(:, i), real(0.0, real_8), real_8)
370 levec(:, i) = cmplx(evec_l(:, i), real(0.0, real_8), real_8)
372 ELSE IF (eval2(i) .GT. epsilon(real(0.0, real_8)))
THEN
373 norm = sqrt(sum(evec_r(:, i)**2.0_real_8) + sum(evec_r(:, i + 1)**2.0_real_8))
374 revec(:, i) = cmplx(evec_r(:, i), evec_r(:, i + 1), real_8)/norm
375 revec(:, i + 1) = cmplx(evec_r(:, i), -evec_r(:, i + 1), real_8)/norm
376 levec(:, i) = cmplx(evec_l(:, i), evec_l(:, i + 1), real_8)
377 levec(:, i + 1) = cmplx(evec_l(:, i), -evec_l(:, i + 1), real_8)
380 cpabort(
'something went wrong while sorting the EV in arnoldi_geev')
386 evals(i) = cmplx(eval1(i), eval2(i), real_8)
389 END SUBROUTINE arnoldi_dgeev
401 SUBROUTINE arnoldi_zgeev(jobvl, jobvr, matrix, ndim, evals, revec, levec)
402 CHARACTER(1) :: jobvl, jobvr
403 COMPLEX(real_8),
DIMENSION(:, :) :: matrix
405 COMPLEX(real_8),
DIMENSION(:) :: evals
406 COMPLEX(real_8),
DIMENSION(:, :) :: revec, levec
408 INTEGER :: info, lwork
409 COMPLEX(real_8) :: work(20*ndim), tmp_array(ndim, ndim)
410 REAL(real_8) :: work2(2*ndim)
412 evals = cmplx(0.0, 0.0, real_8)
415 CALL zgeev(jobvl, jobvr, ndim, tmp_array, ndim, evals, levec, ndim, revec, ndim, work, lwork, work2, info)
416 lwork = min(20*ndim, int(work(1)))
418 tmp_array(:, :) = matrix(:, :)
419 CALL zgeev(jobvl, jobvr, ndim, tmp_array, ndim, evals, levec, ndim, revec, ndim, work, lwork, work2, info)
421 END SUBROUTINE arnoldi_zgeev
433 SUBROUTINE arnoldi_cgeev(jobvl, jobvr, matrix, ndim, evals, revec, levec)
434 CHARACTER(1) :: jobvl, jobvr
435 COMPLEX(real_4),
DIMENSION(:, :) :: matrix
437 COMPLEX(real_4),
DIMENSION(:) :: evals
438 COMPLEX(real_4),
DIMENSION(:, :) :: revec, levec
440 INTEGER :: info, lwork
441 COMPLEX(real_4) :: work(20*ndim), tmp_array(ndim, ndim)
442 REAL(real_4) :: work2(2*ndim)
444 evals = cmplx(0.0, 0.0, real_4)
447 CALL cgeev(jobvl, jobvr, ndim, tmp_array, ndim, evals, levec, ndim, revec, ndim, work, lwork, work2, info)
448 lwork = min(20*ndim, int(work(1)))
450 tmp_array(:, :) = matrix(:, :)
451 CALL cgeev(jobvl, jobvr, ndim, tmp_array, ndim, evals, levec, ndim, revec, ndim, work, lwork, work2, info)
453 END SUBROUTINE arnoldi_cgeev
provides a unified interface to lapack geev routines
Defines the basic variable types.
integer, parameter, public real_4
integer, parameter, public real_8