7submodule(
linalg) linalg_eigen
12 module subroutine eigen_symm(vecs, a, vals, work, olwork, err)
14 logical,
intent(in) :: vecs
15 real(real64),
intent(inout),
dimension(:,:) :: a
16 real(real64),
intent(out),
dimension(:) :: vals
17 real(real64),
intent(out),
pointer,
optional,
dimension(:) :: work
18 integer(int32),
intent(out),
optional :: olwork
19 class(errors),
intent(inout),
optional,
target :: err
23 integer(int32) :: n, istat, flag, lwork
24 real(real64),
pointer,
dimension(:) :: wptr
25 real(real64),
allocatable,
target,
dimension(:) :: wrk
26 real(real64),
dimension(1) :: temp
27 class(errors),
pointer :: errmgr
28 type(errors),
target :: deferr
29 character(len = :),
allocatable :: errmsg
38 if (
present(err))
then
46 if (
size(a, 2) /= n)
then
48 else if (
size(vals) /= n)
then
53 allocate(
character(len = 256) :: errmsg)
54 write(errmsg, 100)
"Input number ", flag, &
55 " is not sized correctly."
56 call errmgr%report_error(
"eigen_symm", trim(errmsg), &
62 call dsyev(jobz,
'L', n, a, n, vals, temp, -1, flag)
63 lwork = int(temp(1), int32)
64 if (
present(olwork))
then
70 if (
present(work))
then
71 if (
size(work) < lwork)
then
73 call errmgr%report_error(
"eigen_symm", &
74 "Incorrectly sized input array WORK, argument 5.", &
80 allocate(wrk(lwork), stat = istat)
83 call errmgr%report_error(
"eigen_symm", &
84 "Insufficient memory available.", &
85 la_out_of_memory_error)
92 call dsyev(jobz,
'L', n, a, n, vals, wptr, lwork, flag)
94 call errmgr%report_error(
"eigen_symm", &
95 "The algorithm failed to converge.", la_convergence_error)
103 module subroutine eigen_asymm(a, vals, vecs, work, olwork, err)
105 real(real64),
intent(inout),
dimension(:,:) :: a
106 complex(real64),
intent(out),
dimension(:) :: vals
107 complex(real64),
intent(out),
optional,
dimension(:,:) :: vecs
108 real(real64),
intent(out),
pointer,
optional,
dimension(:) :: work
109 integer(int32),
intent(out),
optional :: olwork
110 class(errors),
intent(inout),
optional,
target :: err
113 real(real64),
parameter :: zero = 0.0d0
114 real(real64),
parameter :: two = 2.0d0
117 character :: jobvl, jobvr
118 integer(int32) :: i, j, jp1, n, n1, n2a, n2b, n3a, n3b, istat, flag, &
121 real(real64),
dimension(1) :: dummy, temp
122 real(real64),
dimension(1,1) :: dummy_mtx
123 real(real64),
pointer,
dimension(:) :: wr, wi, wptr, w
124 real(real64),
pointer,
dimension(:,:) :: vr
125 real(real64),
allocatable,
target,
dimension(:) :: wrk
126 class(errors),
pointer :: errmgr
127 type(errors),
target :: deferr
128 character(len = :),
allocatable :: errmsg
132 if (
present(vecs))
then
138 eps = two * epsilon(eps)
139 if (
present(err))
then
147 if (
size(a, 2) /= n)
then
149 else if (
size(vals) /= n)
then
151 else if (
present(vecs))
then
152 if (
size(vecs, 1) /= n .or.
size(vecs, 2) /= n)
then
158 allocate(
character(len = 256) :: errmsg)
159 write(errmsg, 100)
"Input number ", flag, &
160 " is not sized correctly."
161 call errmgr%report_error(
"eigen_asymm", trim(errmsg), &
167 call dgeev(jobvl, jobvr, n, a, n, dummy, dummy, dummy_mtx, n, &
168 dummy_mtx, n, temp, -1, flag)
169 lwork1 = int(temp(1), int32)
170 if (
present(vecs))
then
171 lwork = lwork1 + 2 * n + n * n
173 lwork = lwork1 + 2 * n
175 if (
present(olwork))
then
181 if (
present(work))
then
182 if (
size(work) < lwork)
then
184 call errmgr%report_error(
"eigen_asymm", &
185 "Incorrectly sized input array WORK, argument 5.", &
189 wptr => work(1:lwork)
191 allocate(wrk(lwork), stat = istat)
194 call errmgr%report_error(
"eigen_asymm", &
195 "Insufficient memory available.", &
196 la_out_of_memory_error)
207 n3b = n3a + lwork1 - 1
215 if (
present(vecs))
then
217 vr(1:n,1:n) => wptr(n3b+1:lwork)
220 call dgeev(jobvl, jobvr, n, a, n, wr, wi, dummy_mtx, n, vr, n, &
225 call errmgr%report_error(
"eigen_asymm", &
226 "The algorithm failed to converge.", la_convergence_error)
233 if (abs(wi(j)) < eps)
then
235 vals(j) = cmplx(wr(j), zero, real64)
237 vecs(i,j) = cmplx(vr(i,j), zero, real64)
242 vals(j) = cmplx(wr(j), wi(j), real64)
243 vals(jp1) = conjg(vals(j))
245 vecs(i,j) = cmplx(vr(i,j), vr(i,jp1), real64)
246 vecs(i,jp1) = conjg(vecs(i,j))
259 call dgeev(jobvl, jobvr, n, a, n, wr, wi, dummy_mtx, n, &
260 dummy_mtx, n, w, lwork1, flag)
264 call errmgr%report_error(
"eigen_asymm", &
265 "The algorithm failed to converge.", la_convergence_error)
271 vals(i) = cmplx(wr(i), wi(i), real64)
280 module subroutine eigen_gen(a, b, alpha, beta, vecs, work, olwork, err)
282 real(real64),
intent(inout),
dimension(:,:) :: a, b
283 complex(real64),
intent(out),
dimension(:) :: alpha
284 real(real64),
intent(out),
optional,
dimension(:) :: beta
285 complex(real64),
intent(out),
optional,
dimension(:,:) :: vecs
286 real(real64),
intent(out),
optional,
pointer,
dimension(:) :: work
287 integer(int32),
intent(out),
optional :: olwork
288 class(errors),
intent(inout),
optional,
target :: err
291 real(real64),
parameter :: zero = 0.0d0
292 real(real64),
parameter :: two = 2.0d0
295 character :: jobvl, jobvr
296 integer(int32) :: i, j, jp1, n, n1, n2a, n2b, n3a, n3b, n4a, n4b, &
297 istat, flag, lwork, lwork1
298 real(real64),
dimension(1) :: temp
299 real(real64),
dimension(1,1) :: dummy
300 real(real64),
pointer,
dimension(:) :: wptr, w, alphar, alphai, bptr
301 real(real64),
pointer,
dimension(:,:) :: vr
302 real(real64),
allocatable,
target,
dimension(:) :: wrk
304 class(errors),
pointer :: errmgr
305 type(errors),
target :: deferr
306 character(len = :),
allocatable :: errmsg
311 if (
present(vecs))
then
317 eps = two * epsilon(eps)
318 if (
present(err))
then
326 if (
size(a, 2) /= n)
then
328 else if (
size(b, 1) /= n .or.
size(b, 2) /= n)
then
330 else if (
size(alpha) /= n)
then
332 else if (
present(beta))
then
333 if (
size(beta) /= n) flag = 4
334 else if (
present(vecs))
then
335 if (
size(vecs, 1) /= n .or.
size(vecs, 2) /= n) flag = 5
339 allocate(
character(len = 256) :: errmsg)
340 write(errmsg, 100)
"Input number ", flag, &
341 " is not sized correctly."
342 call errmgr%report_error(
"eigen_gen", trim(errmsg), &
348 call dggev(jobvl, jobvr, n, a, n, b, n, temp, temp, temp, dummy, n, &
349 dummy, n, temp, -1, flag)
350 lwork1 = int(temp(1), int32)
351 lwork = lwork1 + 2 * n
352 if (.not.
present(beta))
then
355 if (
present(vecs))
then
356 lwork = lwork + n * n
358 if (
present(olwork))
then
364 if (
present(work))
then
365 if (
size(work) < lwork)
then
367 call errmgr%report_error(
"eigen_gen", &
368 "Incorrectly sized input array WORK, argument 5.", &
372 wptr => work(1:lwork)
374 allocate(wrk(lwork), stat = istat)
377 call errmgr%report_error(
"eigen_gen", &
378 "Insufficient memory available.", &
379 la_out_of_memory_error)
390 n3b = n3a + lwork1 - 1
393 alphai => wptr(n2a:n2b)
395 if (.not.
present(beta))
then
398 bptr => wptr(n4a:n4b)
402 if (
present(vecs))
then
404 vr(1:n,1:n) => wptr(n4b+1:lwork)
407 if (
present(beta))
then
408 call dggev(jobvl, jobvr, n, a, n, b, n, alphar, alphai, &
409 beta, dummy, n, vr, n, w, lwork1, flag)
411 call dggev(jobvl, jobvr, n, a, n, b, n, alphar, alphai, &
412 bptr, dummy, n, vr, n, w, lwork1, flag)
417 call errmgr%report_error(
"eigen_gen", &
418 "The algorithm failed to converge.", la_convergence_error)
425 if (abs(alphai(j)) < eps)
then
427 alpha(j) = cmplx(alphar(j), zero, real64)
429 vecs(i,j) = cmplx(vr(i,j), zero, real64)
434 alpha(j) = cmplx(alphar(j), alphai(j), real64)
435 alpha(jp1) = cmplx(alphar(jp1), alphai(jp1), real64)
437 vecs(i,j) = cmplx(vr(i,j), vr(i,jp1), real64)
438 vecs(i,jp1) = conjg(vecs(i,j))
449 if (.not.
present(beta)) alpha = alpha / bptr
452 if (
present(beta))
then
453 call dggev(jobvl, jobvr, n, a, n, b, n, alphar, alphai, &
454 beta, dummy, n, dummy, n, w, lwork1, flag)
456 call dggev(jobvl, jobvr, n, a, n, b, n, alphar, alphai, &
457 bptr, dummy, n, dummy, n, w, lwork1, flag)
462 call errmgr%report_error(
"eigen_gen", &
463 "The algorithm failed to converge.", la_convergence_error)
469 alpha(i) = cmplx(alphar(i), alphai(i), real64)
471 if (.not.
present(beta)) alpha = alpha / bptr
479 module subroutine eigen_cmplx(a, vals, vecs, work, olwork, rwork, err)
481 complex(real64),
intent(inout),
dimension(:,:) :: a
482 complex(real64),
intent(out),
dimension(:) :: vals
483 complex(real64),
intent(out),
optional,
dimension(:,:) :: vecs
484 complex(real64),
intent(out),
target,
optional,
dimension(:) :: work
485 real(real64),
intent(out),
target,
optional,
dimension(:) :: rwork
486 integer(int32),
intent(out),
optional :: olwork
487 class(errors),
intent(inout),
optional,
target :: err
490 character :: jobvl, jobvr
491 character(len = :),
allocatable :: errmsg
492 integer(int32) :: n, flag, lwork, lrwork
493 real(real64) :: rdummy(1)
494 complex(real64) :: temp(1), dummy(1), dummy_mtx(1,1)
495 complex(real64),
allocatable,
target,
dimension(:) :: wrk
496 complex(real64),
pointer,
dimension(:) :: wptr
497 real(real64),
allocatable,
target,
dimension(:) :: rwrk
498 real(real64),
pointer,
dimension(:) :: rwptr
499 class(errors),
pointer :: errmgr
500 type(errors),
target :: deferr
503 if (
present(err))
then
509 if (
present(vecs))
then
519 if (
size(a, 2) /= n)
then
521 else if (
size(vals) /= n)
then
523 else if (
present(vecs))
then
524 if (
size(vecs, 1) /= n .or.
size(vecs, 2) /= n)
then
530 allocate(
character(len = 256) :: errmsg)
531 write(errmsg, 100)
"Input number ", flag, &
532 " is not sized correctly."
533 call errmgr%report_error(
"eigen_cmplx", trim(errmsg), &
539 call zgeev(jobvl, jobvr, n, a, n, dummy, dummy_mtx, n, dummy_mtx, n, temp, &
541 lwork = int(temp(1), int32)
542 if (
present(olwork))
then
548 if (
present(work))
then
549 if (
size(work) < lwork)
then
551 call errmgr%report_error(
"eigen_cmplx", &
552 "Incorrectly sized input array WORK.", &
558 allocate(wrk(lwork), stat = flag)
561 call errmgr%report_error(
"eigen_cmplx", &
562 "Insufficient memory available.", &
563 la_out_of_memory_error)
569 if (
present(rwork))
then
570 if (
size(work) < lrwork)
then
572 call errmgr%report_error(
"eigen_cmplx", &
573 "Incorrectly sized input array RWORK.", &
579 allocate(rwrk(lrwork), stat = flag)
582 call errmgr%report_error(
"eigen_cmplx", &
583 "Insufficient memory available.", &
584 la_out_of_memory_error)
591 if (
present(vecs))
then
592 call zgeev(jobvl, jobvr, n, a, n, vals, dummy_mtx, n, vecs, n, &
593 wptr, lwork, rwptr, flag)
595 call zgeev(jobvl, jobvr, n, a, n, vals, dummy_mtx, n, dummy_mtx, n, &
596 wptr, lwork, rwptr, flag)
600 call errmgr%report_error(
"eigen_cmplx", &
601 "The algorithm failed to converge.", &
602 la_convergence_error)
Provides a set of common linear algebra routines.