13 USE ieee_arithmetic,
ONLY: ieee_is_finite
14#if defined(__HAS_IEEE_EXCEPTIONS)
15 USE ieee_exceptions,
ONLY: ieee_all, ieee_get_halting_mode, ieee_set_halting_mode
23 REAL(
dp),
ALLOCATABLE :: eigenvalues(:), residuals(:), errors(:, :), means(:, :)
24 REAL(
dp),
ALLOCATABLE :: projected_errors(:, :), leakage(:, :)
25 COMPLEX(dp),
ALLOCATABLE :: states(:, :), complex_means(:, :)
26 INTEGER :: iterations = 0
33 MODULE PROCEDURE quadratic_solve_real, quadratic_solve_complex
44 SUBROUTINE operator_apply(OPERATOR, v, y, status)
46 INTEGER,
INTENT(IN) :: operator
47 COMPLEX(dp),
INTENT(IN) :: v(:, :)
48 COMPLEX(dp),
INTENT(OUT) :: y(:, :)
49 INTEGER,
INTENT(OUT) :: status
50 END SUBROUTINE operator_apply
57 SUBROUTINE metric_solve(v, y, status)
59 COMPLEX(dp),
INTENT(IN) :: v(:, :)
60 COMPLEX(dp),
INTENT(OUT) :: y(:, :)
61 INTEGER,
INTENT(OUT) :: status
62 END SUBROUTINE metric_solve
65 TYPE,
ABSTRACT :: quadratic_operator_type
67 PROCEDURE(operator_method),
DEFERRED :: apply
68 PROCEDURE(operator_method),
DEFERRED :: adjoint
69 PROCEDURE(metric_method),
DEFERRED :: solve
70 END TYPE quadratic_operator_type
82 IMPORT dp, quadratic_operator_type
83 CLASS(quadratic_operator_type),
INTENT(INOUT) :: this
84 INTEGER,
INTENT(IN) :: operator
85 COMPLEX(dp),
INTENT(IN) :: v(:, :)
86 COMPLEX(dp),
INTENT(OUT) :: y(:, :)
87 INTEGER,
INTENT(OUT) :: status
97 SUBROUTINE metric_method(this, v, y, status)
98 IMPORT dp, quadratic_operator_type
99 CLASS(quadratic_operator_type),
INTENT(INOUT) :: this
100 COMPLEX(dp),
INTENT(IN) :: v(:, :)
101 COMPLEX(dp),
INTENT(OUT) :: y(:, :)
102 INTEGER,
INTENT(OUT) :: status
103 END SUBROUTINE metric_method
106 TYPE,
EXTENDS(quadratic_operator_type) :: dense_operator_type
107 COMPLEX(dp),
POINTER :: operators(:, :, :) => null(), metric(:, :) => null()
108 COMPLEX(dp),
ALLOCATABLE :: factor(:, :)
110 PROCEDURE :: apply => dense_apply
111 PROCEDURE :: adjoint => dense_adjoint
112 PROCEDURE :: solve => dense_solve
113 END TYPE dense_operator_type
115 TYPE,
EXTENDS(quadratic_operator_type) :: callback_operator_type
116 PROCEDURE(operator_apply),
POINTER,
NOPASS :: apply_callback => null()
117 PROCEDURE(operator_apply),
POINTER,
NOPASS :: adjoint_callback => null()
118 PROCEDURE(metric_solve),
POINTER,
NOPASS :: solve_callback => null()
120 PROCEDURE :: apply => callback_apply
121 PROCEDURE :: adjoint => callback_adjoint
122 PROCEDURE :: solve => callback_solve
123 END TYPE callback_operator_type
143 max_iter, tolerance, metric_tolerance, RESULT, status)
144 COMPLEX(dp),
INTENT(IN) :: operators(:, :, :), metric(:, :)
145 REAL(dp),
INTENT(IN) :: shift(:), weights(:)
146 INTEGER,
INTENT(IN) :: nstates
147 LOGICAL,
INTENT(IN) :: iterative
148 INTEGER,
INTENT(IN) :: max_subspace, max_iter
149 REAL(dp),
INTENT(IN) :: tolerance, metric_tolerance
151 INTEGER,
INTENT(OUT) :: status
156 IF (
SIZE(operators, 1) < 1 .OR.
SIZE(operators, 1) /=
SIZE(operators, 2))
RETURN
157 DO j = 1,
SIZE(operators, 3)
158 IF (.NOT. hermitian(operators(:, :, j)))
RETURN
160 CALL quadratic_dense_complex(operators, metric, cmplx(shift, 0.0_dp, dp), weights, nstates, iterative, &
161 max_subspace, max_iter, tolerance, metric_tolerance, result, status)
180 SUBROUTINE quadratic_dense_complex(operators, metric, shift, weights, nstates, iterative, max_subspace, &
181 max_iter, tolerance, metric_tolerance, RESULT, status, unitary)
182 COMPLEX(dp),
INTENT(IN),
TARGET :: operators(:, :, :), metric(:, :)
183 COMPLEX(dp),
INTENT(IN) :: shift(:)
184 REAL(dp),
INTENT(IN) :: weights(:), tolerance, metric_tolerance
185 INTEGER,
INTENT(IN) :: nstates, max_subspace, max_iter
186 LOGICAL,
INTENT(IN) :: iterative
188 INTEGER,
INTENT(OUT) :: status
189 LOGICAL,
INTENT(IN),
OPTIONAL :: unitary(:)
190 TYPE(dense_operator_type) :: operator_backend
191 REAL(dp),
ALLOCATABLE :: eigenvalues(:)
193#if defined(__HAS_IEEE_EXCEPTIONS)
194 LOGICAL :: halt(SIZE(IEEE_ALL))
199 IF (n < 1 .OR.
SIZE(metric, 2) /= n)
RETURN
200 IF (
SIZE(shift) < 1 .OR.
SIZE(weights) /=
SIZE(shift))
RETURN
201 IF (any(shape(operators) /= [n, n,
SIZE(shift)]))
RETURN
202 IF (.NOT. ieee_is_finite(metric_tolerance))
RETURN
203 IF (metric_tolerance <= 0.0_dp .OR. metric_tolerance >= 1.0_dp)
RETURN
204 IF (.NOT. hermitian(metric))
RETURN
205 IF (.NOT. all(ieee_is_finite(real(operators, dp))) .OR. &
206 .NOT. all(ieee_is_finite(aimag(operators))))
RETURN
207 operator_backend%operators => operators
208 operator_backend%metric => metric
209 ALLOCATE (operator_backend%factor(n, n), eigenvalues(n))
210 operator_backend%factor(:, :) = metric
211 CALL diagonalize(operator_backend%factor, eigenvalues, status)
212 IF (status /= 0)
RETURN
214 IF (eigenvalues(n) <= 0.0_dp)
RETURN
215 IF (eigenvalues(1) <= metric_tolerance*eigenvalues(n))
RETURN
216 operator_backend%factor(:, :) = metric
217#if defined(__HAS_IEEE_EXCEPTIONS)
218 CALL ieee_get_halting_mode(ieee_all, halt)
219 CALL ieee_set_halting_mode(ieee_all, .false.)
221 CALL zpotrf(
'L', n, operator_backend%factor, n, status)
222#if defined(__HAS_IEEE_EXCEPTIONS)
223 CALL ieee_set_halting_mode(ieee_all, halt)
225 IF (status /= 0)
THEN
229 CALL quadratic_solve_core(n, shift, weights, nstates, iterative, max_subspace, max_iter, tolerance, &
230 operator_backend, result, status, unitary)
231 END SUBROUTINE quadratic_dense_complex
241 SUBROUTINE dense_apply(this, OPERATOR, v, y, status)
242 CLASS(dense_operator_type),
INTENT(INOUT) :: this
243 INTEGER,
INTENT(IN) :: operator
244 COMPLEX(dp),
INTENT(IN) :: v(:, :)
245 COMPLEX(dp),
INTENT(OUT) :: y(:, :)
246 INTEGER,
INTENT(OUT) :: status
249 IF (operator == 0)
THEN
250 y = matmul(this%metric, v)
252 y = matmul(this%operators(:, :, operator), v)
254 END SUBROUTINE dense_apply
264 SUBROUTINE dense_adjoint(this, OPERATOR, v, y, status)
265 CLASS(dense_operator_type),
INTENT(INOUT) :: this
266 INTEGER,
INTENT(IN) :: operator
267 COMPLEX(dp),
INTENT(IN) :: v(:, :)
268 COMPLEX(dp),
INTENT(OUT) :: y(:, :)
269 INTEGER,
INTENT(OUT) :: status
271 y = matmul(conjg(transpose(this%operators(:, :, operator))), v)
273 END SUBROUTINE dense_adjoint
282 SUBROUTINE dense_solve(this, v, y, status)
283 CLASS(dense_operator_type),
INTENT(INOUT) :: this
284 COMPLEX(dp),
INTENT(IN) :: v(:, :)
285 COMPLEX(dp),
INTENT(OUT) :: y(:, :)
286 INTEGER,
INTENT(OUT) :: status
289#if defined(__HAS_IEEE_EXCEPTIONS)
290 LOGICAL :: halt(SIZE(IEEE_ALL))
293 n =
SIZE(this%factor, 1)
295#if defined(__HAS_IEEE_EXCEPTIONS)
296 CALL ieee_get_halting_mode(ieee_all, halt)
297 CALL ieee_set_halting_mode(ieee_all, .false.)
299 CALL zpotrs(
'L', n,
SIZE(v, 2), this%factor, n, y, n, status)
300#if defined(__HAS_IEEE_EXCEPTIONS)
301 CALL ieee_set_halting_mode(ieee_all, halt)
303 IF (status /= 0) status = -4
304 END SUBROUTINE dense_solve
321 SUBROUTINE quadratic_solve_real(n, shift, weights, nstates, iterative, max_subspace, max_iter, tolerance, &
322 apply, solve, RESULT, status)
323 INTEGER,
INTENT(IN) :: n
324 REAL(dp),
INTENT(IN) :: shift(:), weights(:)
325 INTEGER,
INTENT(IN) :: nstates
326 LOGICAL,
INTENT(IN) :: iterative
327 INTEGER,
INTENT(IN) :: max_subspace, max_iter
328 REAL(dp),
INTENT(IN) :: tolerance
330 PROCEDURE(operator_apply) :: apply
331 PROCEDURE(metric_solve) :: solve
333 INTEGER,
INTENT(OUT) :: status
335 CALL quadratic_solve_complex(n, cmplx(shift, 0.0_dp, dp), weights, nstates, iterative, max_subspace, &
336 max_iter, tolerance, apply, solve, result, status, apply)
337 END SUBROUTINE quadratic_solve_real
356 SUBROUTINE quadratic_solve_complex(n, shift, weights, nstates, iterative, max_subspace, max_iter, tolerance, &
357 apply, solve, RESULT, status, adjoint, unitary)
358 INTEGER,
INTENT(IN) :: n
359 COMPLEX(dp),
INTENT(IN) :: shift(:)
360 REAL(dp),
INTENT(IN) :: weights(:)
361 INTEGER,
INTENT(IN) :: nstates
362 LOGICAL,
INTENT(IN) :: iterative
363 INTEGER,
INTENT(IN) :: max_subspace, max_iter
364 REAL(dp),
INTENT(IN) :: tolerance
366 PROCEDURE(operator_apply) :: apply, adjoint
367 PROCEDURE(metric_solve) :: solve
369 INTEGER,
INTENT(OUT) :: status
370 LOGICAL,
INTENT(IN),
OPTIONAL :: unitary(:)
372 TYPE(callback_operator_type) :: operator_backend
374 operator_backend%apply_callback => apply
375 operator_backend%adjoint_callback => adjoint
376 operator_backend%solve_callback => solve
377 CALL quadratic_solve_core(n, shift, weights, nstates, iterative, max_subspace, max_iter, tolerance, &
378 operator_backend, result, status, unitary)
379 END SUBROUTINE quadratic_solve_complex
396 SUBROUTINE quadratic_solve_core(n, shift, weights, nstates, iterative, max_subspace, max_iter, tolerance, &
397 operator_backend, RESULT, status, unitary)
398 INTEGER,
INTENT(IN) :: n, nstates, max_subspace, max_iter
399 COMPLEX(dp),
INTENT(IN) :: shift(:)
400 REAL(dp),
INTENT(IN) :: weights(:), tolerance
401 LOGICAL,
INTENT(IN) :: iterative
402 CLASS(quadratic_operator_type),
INTENT(INOUT) :: operator_backend
404 INTEGER,
INTENT(OUT) :: status
405 LOGICAL,
INTENT(IN),
OPTIONAL :: unitary(:)
406 COMPLEX(dp),
ALLOCATABLE :: v(:, :), sv(:, :), qv(:, :), projected(:, :), sc(:, :), qc(:, :), &
407 r(:, :), z(:, :), trial(:, :), strial(:, :), work(:, :), invwork(:, :), &
409 REAL(dp),
ALLOCATABLE :: eigenvalues(:)
410 REAL(dp) :: square, scale, norm_before, norm_after, full_square, lost_square
411 COMPLEX(dp) :: coefficient
412 INTEGER :: capacity, m, old, i, j, p, iteration, seed, initial, pass, keep
414 LOGICAL,
ALLOCATABLE :: continuum(:)
417 IF (n < 1 .OR. nstates < 1 .OR. nstates > n .OR. max_iter < 1)
RETURN
418 IF (
SIZE(shift) < 1 .OR.
SIZE(weights) /=
SIZE(shift))
RETURN
419 ALLOCATE (continuum(
SIZE(shift)))
421 IF (
PRESENT(unitary))
THEN
422 IF (
SIZE(unitary) /=
SIZE(shift))
RETURN
423 continuum(:) = unitary
425 IF (.NOT. all(ieee_is_finite([real(shift, dp), aimag(shift), weights, tolerance])))
RETURN
426 IF (any(weights < 0.0_dp) .OR. maxval(weights) <= 0.0_dp .OR. tolerance <= 0.0_dp)
RETURN
428 IF (iterative) capacity = min(n, max_subspace)
429 IF (capacity < nstates .OR. (capacity < n .AND. capacity < 2*nstates))
RETURN
430 ALLOCATE (v(n, capacity), sv(n, capacity), qv(n, capacity), sc(n, nstates), qc(n, nstates), &
431 r(n, nstates), z(n, nstates), trial(n, 1), strial(n, 1), work(n, nstates), invwork(n, nstates))
432 ALLOCATE (result%states(n, nstates), result%eigenvalues(nstates), result%residuals(nstates), &
433 result%errors(
SIZE(shift), nstates), result%means(
SIZE(shift), nstates), &
434 result%complex_means(
SIZE(shift), nstates), &
435 result%projected_errors(
SIZE(shift), nstates), result%leakage(
SIZE(shift), nstates))
436 result%leakage = 0.0_dp
440 IF (iterative) initial = min(capacity, max(nstates + 2, 2*nstates))
442 trial = cmplx(0.0_dp, 0.0_dp, dp)
443 IF (.NOT. iterative)
THEN
449 CALL append_vector(accepted)
450 IF (status /= 0)
RETURN
451 IF (.NOT. accepted)
THEN
456 CALL apply_q(v(:, :m), qv(:, :m), status)
457 IF (status /= 0)
RETURN
458 DO iteration = 1, max_iter
459 result%iterations = iteration
460 ALLOCATE (projected(m, m), eigenvalues(m))
461 projected(:, :) = matmul(conjg(transpose(v(:, :m))), qv(:, :m))
462 scale = max(1.0_dp, maxval(abs(projected)))
463 IF (maxval(abs(projected - conjg(transpose(projected)))) > 1.e-8_dp*scale)
THEN
467 projected(:, :) = 0.5_dp*(projected + conjg(transpose(projected)))
468 CALL diagonalize(projected, eigenvalues, status)
469 IF (status /= 0)
RETURN
470 result%eigenvalues(:) = eigenvalues(:nstates)
471 result%states(:, :) = matmul(v(:, :m), projected(:, :nstates))
472 sc(:, :) = matmul(sv(:, :m), projected(:, :nstates))
473 qc(:, :) = matmul(qv(:, :m), projected(:, :nstates))
477 CALL operator_backend%apply(0, result%states, sc, status)
478 IF (status /= 0)
RETURN
480 square = real(dot_product(result%states(:, j), sc(:, j)), dp)
481 IF (.NOT. ieee_is_finite(square) .OR. square <= 0.0_dp)
THEN
485 result%states(:, j) = result%states(:, j)/sqrt(square)
487 CALL operator_backend%apply(0, result%states, sc, status)
488 IF (status /= 0)
RETURN
489 CALL apply_q(result%states, qc, status)
490 IF (status /= 0)
RETURN
493 r(:, j) = qc(:, j) - result%eigenvalues(j)*sc(:, j)
495 CALL operator_backend%solve(r, z, status)
496 IF (status /= 0)
RETURN
498 square = real(dot_product(r(:, j), z(:, j)), dp)
499 IF (.NOT. ieee_is_finite(square) .OR. square < -epsilon(square)*scale)
THEN
503 result%residuals(j) = sqrt(max(0.0_dp, square))
505 IF (any(result%residuals > tolerance*max(1.0_dp, abs(result%eigenvalues))))
EXIT
507 IF (all(result%residuals <= tolerance*max(1.0_dp, abs(result%eigenvalues))))
THEN
508 DEALLOCATE (projected, eigenvalues)
511 IF (.NOT. iterative .OR. m == n .OR. iteration == max_iter)
THEN
516 IF (m == capacity)
THEN
518 keep = min(m, max(nstates, capacity/2))
519 ALLOCATE (restarted(n, keep))
520 restarted(:, :) = matmul(v(:, :m), projected(:, :keep))
521 v(:, :keep) = restarted
522 restarted(:, :) = matmul(sv(:, :m), projected(:, :keep))
523 sv(:, :keep) = restarted
524 restarted(:, :) = matmul(qv(:, :m), projected(:, :keep))
525 qv(:, :keep) = restarted
526 DEALLOCATE (restarted)
529 DEALLOCATE (projected, eigenvalues)
532 IF (m == capacity)
EXIT
533 trial(:, 1) = z(:, j)
534 CALL append_vector(accepted)
535 IF (status /= 0)
RETURN
540 CALL append_vector(accepted)
541 IF (status /= 0)
RETURN
542 IF (.NOT. accepted)
THEN
547 CALL apply_q(v(:, old + 1:m), qv(:, old + 1:m), status)
548 IF (status /= 0)
RETURN
550 IF (any(result%eigenvalues < -tolerance*max(1.0_dp, maxval(abs(result%eigenvalues)))))
THEN
554 result%eigenvalues = max(0.0_dp, result%eigenvalues)
555 DO p = 1,
SIZE(shift)
556 CALL operator_backend%apply(p, result%states, work, status)
557 IF (status /= 0)
RETURN
559 result%complex_means(p, j) = dot_product(result%states(:, j), work(:, j))
560 result%means(p, j) = real(result%complex_means(p, j), dp)
562 work(:, :) = work - shift(p)*sc
563 CALL operator_backend%solve(work, invwork, status)
564 IF (status /= 0)
RETURN
566 square = real(dot_product(work(:, j), invwork(:, j)), dp)
567 IF (.NOT. ieee_is_finite(square) .OR. square < -tolerance)
THEN
571 result%projected_errors(p, j) = sqrt(max(0.0_dp, square))
572 IF (continuum(p))
THEN
573 full_square = (1.0_dp + abs(shift(p))**2)*real(dot_product(result%states(:, j), sc(:, j)), dp) &
574 - 2.0_dp*real(conjg(shift(p))*result%complex_means(p, j), dp)
575 lost_square = full_square - square
576 scale = max(1.0_dp, abs(full_square), abs(square))
577 IF (.NOT. ieee_is_finite(full_square) .OR. full_square < -tolerance*scale .OR. &
578 lost_square < -tolerance*scale)
THEN
582 result%leakage(p, j) = sqrt(max(0.0_dp, lost_square))
585 result%errors(p, j) = sqrt(max(0.0_dp, square))
589 square = sum((weights*result%errors(:, j))**2)
590 IF (abs(square - result%eigenvalues(j)) > 10.0_dp*tolerance*max(1.0_dp, square))
THEN
600 SUBROUTINE seed_vector()
604 trial(k, 1) = cmplx(sin(real(k, dp)*real(seed + 1, dp)*1.4142135623730951_dp), &
605 cos(real(k, dp)*real(seed + 2, dp)*1.7320508075688772_dp), dp)
607 END SUBROUTINE seed_vector
612 SUBROUTINE append_vector(accepted)
613 LOGICAL,
INTENT(OUT) :: accepted
616 CALL operator_backend%apply(0, trial, strial, status)
617 IF (status /= 0)
RETURN
618 norm_before = real(dot_product(trial(:, 1), strial(:, 1)), dp)
619 IF (.NOT. ieee_is_finite(norm_before) .OR. norm_before < 0.0_dp)
THEN
625 coefficient = dot_product(v(:, i), strial(:, 1))
626 trial(:, 1) = trial(:, 1) - coefficient*v(:, i)
627 strial(:, 1) = strial(:, 1) - coefficient*sv(:, i)
630 norm_after = real(dot_product(trial(:, 1), strial(:, 1)), dp)
631 IF (.NOT. ieee_is_finite(norm_after))
THEN
635 IF (norm_after <= 1.e-24_dp*max(tiny(1.0_dp), norm_before))
RETURN
637 v(:, m) = trial(:, 1)/sqrt(norm_after)
638 sv(:, m) = strial(:, 1)/sqrt(norm_after)
640 END SUBROUTINE append_vector
647 SUBROUTINE apply_q(block, image, status)
648 COMPLEX(dp),
INTENT(IN) :: block(:, :)
649 COMPLEX(dp),
INTENT(OUT) :: image(:, :)
650 INTEGER,
INTENT(OUT) :: status
652 COMPLEX(dp),
ALLOCATABLE :: ab(:, :), sb(:, :), second(:, :), &
653 solved(:, :), ss(:, :)
656 nrhs =
SIZE(block, 2)
657 ALLOCATE (sb(n, nrhs), ab(n, nrhs), solved(n, nrhs), second(n, nrhs), ss(n, nrhs))
658 CALL operator_backend%apply(0, block, sb, status)
659 IF (status /= 0)
RETURN
660 image = cmplx(0.0_dp, 0.0_dp, dp)
661 DO op = 1,
SIZE(shift)
662 IF (weights(op) == 0.0_dp) cycle
663 CALL operator_backend%apply(op, block, ab, status)
664 IF (status /= 0)
RETURN
665 IF (continuum(op))
THEN
666 CALL operator_backend%adjoint(op, block, second, status)
667 IF (status /= 0)
RETURN
668 image = image + weights(op)**2*((1.0_dp + abs(shift(op))**2)*sb &
669 - conjg(shift(op))*ab - shift(op)*second)
672 ab(:, :) = ab - shift(op)*sb
673 CALL operator_backend%solve(ab, solved, status)
674 IF (status /= 0)
RETURN
675 CALL operator_backend%adjoint(op, solved, second, status)
676 IF (status /= 0)
RETURN
677 CALL operator_backend%apply(0, solved, ss, status)
678 IF (status /= 0)
RETURN
679 image = image + weights(op)**2*(second - conjg(shift(op))*ss)
681 END SUBROUTINE apply_q
682 END SUBROUTINE quadratic_solve_core
692 SUBROUTINE callback_apply(this, OPERATOR, v, y, status)
693 CLASS(callback_operator_type),
INTENT(INOUT) :: this
694 INTEGER,
INTENT(IN) :: operator
695 COMPLEX(dp),
INTENT(IN) :: v(:, :)
696 COMPLEX(dp),
INTENT(OUT) :: y(:, :)
697 INTEGER,
INTENT(OUT) :: status
699 CALL this%apply_callback(operator, v, y, status)
700 END SUBROUTINE callback_apply
710 SUBROUTINE callback_adjoint(this, OPERATOR, v, y, status)
711 CLASS(callback_operator_type),
INTENT(INOUT) :: this
712 INTEGER,
INTENT(IN) :: operator
713 COMPLEX(dp),
INTENT(IN) :: v(:, :)
714 COMPLEX(dp),
INTENT(OUT) :: y(:, :)
715 INTEGER,
INTENT(OUT) :: status
717 CALL this%adjoint_callback(operator, v, y, status)
718 END SUBROUTINE callback_adjoint
727 SUBROUTINE callback_solve(this, v, y, status)
728 CLASS(callback_operator_type),
INTENT(INOUT) :: this
729 COMPLEX(dp),
INTENT(IN) :: v(:, :)
730 COMPLEX(dp),
INTENT(OUT) :: y(:, :)
731 INTEGER,
INTENT(OUT) :: status
733 CALL this%solve_callback(v, y, status)
734 END SUBROUTINE callback_solve
741 FUNCTION hermitian(matrix)
RESULT(valid)
742 COMPLEX(dp),
INTENT(IN) :: matrix(:, :)
746 IF (.NOT. all(ieee_is_finite(real(matrix,
dp))) .OR. .NOT. all(ieee_is_finite(aimag(matrix))))
RETURN
747 valid = maxval(abs(matrix - conjg(transpose(matrix)))) <= 1.e-10_dp*max(tiny(1.0_dp), maxval(abs(matrix)))
748 END FUNCTION hermitian
756 SUBROUTINE diagonalize(matrix, values, status)
757 COMPLEX(dp),
INTENT(INOUT) :: matrix(:, :)
758 REAL(dp),
INTENT(OUT) :: values(:)
759 INTEGER,
INTENT(OUT) :: status
760 COMPLEX(dp),
ALLOCATABLE :: workspace(:)
761 REAL(dp),
ALLOCATABLE :: rwork(:)
763#if defined(__HAS_IEEE_EXCEPTIONS)
764 LOGICAL :: halt(SIZE(IEEE_ALL))
767 ALLOCATE (workspace(max(1, 2*n)), rwork(max(1, 3*n - 2)))
768#if defined(__HAS_IEEE_EXCEPTIONS)
769 CALL ieee_get_halting_mode(ieee_all, halt)
770 CALL ieee_set_halting_mode(ieee_all, .false.)
772 CALL zheev(
'V',
'L', n, matrix, n, values, workspace,
SIZE(workspace), rwork, status)
773#if defined(__HAS_IEEE_EXCEPTIONS)
774 CALL ieee_set_halting_mode(ieee_all, halt)
776 IF (status /= 0 .OR. .NOT. all(ieee_is_finite(values))) status = -4
777 END SUBROUTINE diagonalize
Defines the basic variable types.
integer, parameter, public dp
Metric-aware quadratic pseudospectra for finite AO operators.
subroutine quadratic_dense_real(operators, metric, shift, weights, nstates, iterative, max_subspace, max_iter, tolerance, metric_tolerance, result, status)
Dense AO oracle, also providing a dense-metric reference for the iterative solver.