LAPACK 3.12.1
LAPACK: Linear Algebra PACKage
Loading...
Searching...
No Matches
zgedmd.f90
Go to the documentation of this file.
1
2!
3! =========== DOCUMENTATION ===========
4!
5! Definition:
6! ===========
7!
8! SUBROUTINE ZGEDMD( JOBS, JOBZ, JOBR, JOBF, WHTSVD, &
9! M, N, X, LDX, Y, LDY, NRNK, TOL, &
10! K, EIGS, Z, LDZ, RES, B, LDB, &
11! W, LDW, S, LDS, ZWORK, LZWORK, &
12! RWORK, LRWORK, IWORK, LIWORK, INFO )
13!......
14! USE, INTRINSIC :: iso_fortran_env, only: real64
15! IMPLICIT NONE
16! INTEGER, PARAMETER :: WP = real64
17!
18!......
19! Scalar arguments
20! CHARACTER, INTENT(IN) :: JOBS, JOBZ, JOBR, JOBF
21! INTEGER, INTENT(IN) :: WHTSVD, M, N, LDX, LDY, &
22! NRNK, LDZ, LDB, LDW, LDS, &
23! LIWORK, LRWORK, LZWORK
24! INTEGER, INTENT(OUT) :: K, INFO
25! REAL(KIND=WP), INTENT(IN) :: TOL
26! Array arguments
27! COMPLEX(KIND=WP), INTENT(INOUT) :: X(LDX,*), Y(LDY,*)
28! COMPLEX(KIND=WP), INTENT(OUT) :: Z(LDZ,*), B(LDB,*), &
29! W(LDW,*), S(LDS,*)
30! COMPLEX(KIND=WP), INTENT(OUT) :: EIGS(*)
31! COMPLEX(KIND=WP), INTENT(OUT) :: ZWORK(*)
32! REAL(KIND=WP), INTENT(OUT) :: RES(*)
33! REAL(KIND=WP), INTENT(OUT) :: RWORK(*)
34! INTEGER, INTENT(OUT) :: IWORK(*)
35!
36!............................................................
38! =============
53!............................................................
55! ================
71!......................................................................
73! ================================
93!......................................................................
95! ==============================
100!............................................................
101! Arguments
102! =========
103!
122!.....
139!.....
150!.....
164!.....
188!.....
194!.....
201!.....
214!.....
220!.....
232!.....
238!.....
263!.....
270!.....
280!.....
288!.....
301!.....
307!.....
316!.....
329!.....
335!.....
347!.....
353!.....
362!.....
368!.....
381!.....
402!.....
418!.....
441!.....
451!.....
465!.....
486!
487! Authors:
488! ========
489!
491!
493!
494!.............................................................
495!.............................................................
496 SUBROUTINE zgedmd( JOBS, JOBZ, JOBR, JOBF, WHTSVD, &
497 M, N, X, LDX, Y, LDY, NRNK, TOL, &
498 K, EIGS, Z, LDZ, RES, B, LDB, &
499 W, LDW, S, LDS, ZWORK, LZWORK, &
500 RWORK, LRWORK, IWORK, LIWORK, INFO )
501!
502! -- LAPACK driver routine --
503!
504! -- LAPACK is a software package provided by University of --
505! -- Tennessee, University of California Berkeley, University of --
506! -- Colorado Denver and NAG Ltd.. --
507!
508!.....
509 use, INTRINSIC :: iso_fortran_env, only: real64
510 IMPLICIT NONE
511 INTEGER, PARAMETER :: WP = real64
512!
513! Scalar arguments
514! ~~~~~~~~~~~~~~~~
515 CHARACTER, INTENT(IN) :: JOBS, JOBZ, JOBR, JOBF
516 INTEGER, INTENT(IN) :: WHTSVD, M, N, LDX, LDY, &
517 NRNK, LDZ, LDB, LDW, LDS, &
518 LIWORK, LRWORK, LZWORK
519 INTEGER, INTENT(OUT) :: K, INFO
520 REAL(KIND=wp), INTENT(IN) :: tol
521!
522! Array arguments
523! ~~~~~~~~~~~~~~~
524 COMPLEX(KIND=WP), INTENT(INOUT) :: X(LDX,*), Y(LDY,*)
525 COMPLEX(KIND=WP), INTENT(OUT) :: Z(LDZ,*), B(LDB,*), &
526 W(LDW,*), S(LDS,*)
527 COMPLEX(KIND=WP), INTENT(OUT) :: EIGS(*)
528 COMPLEX(KIND=WP), INTENT(OUT) :: ZWORK(*)
529 REAL(KIND=wp), INTENT(OUT) :: res(*)
530 REAL(KIND=wp), INTENT(OUT) :: rwork(*)
531 INTEGER, INTENT(OUT) :: IWORK(*)
532!
533! Parameters
534! ~~~~~~~~~~
535 REAL(KIND=wp), PARAMETER :: one = 1.0_wp
536 REAL(KIND=wp), PARAMETER :: zero = 0.0_wp
537 COMPLEX(KIND=WP), PARAMETER :: ZONE = ( 1.0_wp, 0.0_wp )
538 COMPLEX(KIND=WP), PARAMETER :: ZZERO = ( 0.0_wp, 0.0_wp )
539!
540! Local scalars
541! ~~~~~~~~~~~~~
542 REAL(KIND=wp) :: ofl, rootsc, scale, small, &
543 ssum, xscl1, xscl2
544 INTEGER :: i, j, IMINWR, INFO1, INFO2, &
545 LWRKEV, LWRSDD, LWRSVD, LWRSVJ, &
546 lwrsvq, mlwork, mwrkev, mwrsdd, &
547 mwrsvd, mwrsvj, mwrsvq, numrnk, &
548 olwork, mlrwrk
549 LOGICAL :: BADXY, LQUERY, SCCOLX, SCCOLY, &
550 wntex, wntref, wntres, wntvec
551 CHARACTER :: JOBZL, T_OR_N
552 CHARACTER :: JSVOPT
553!
554! Local arrays
555! ~~~~~~~~~~~~
556 REAL(KIND=wp) :: rdummy(2)
557!
558! External functions (BLAS and LAPACK)
559! ~~~~~~~~~~~~~~~~~
560 REAL(KIND=wp) zlange, dlamch, dznrm2
561 EXTERNAL zlange, dlamch, dznrm2, izamax
562 INTEGER IZAMAX
563 LOGICAL DISNAN, LSAME
564 EXTERNAL disnan, lsame
565!
566! External subroutines (BLAS and LAPACK)
567! ~~~~~~~~~~~~~~~~~~~~
568 EXTERNAL zaxpy, zgemm, zdscal
569 EXTERNAL zgeev, zgejsv, zgesdd, zgesvd, zgesvdq, &
571!
572! Intrinsic functions
573! ~~~~~~~~~~~~~~~~~~~
574 INTRINSIC dble, int, max, sqrt
575!............................................................
576!
577! Test the input arguments
578!
579 wntres = lsame(jobr,'R')
580 sccolx = lsame(jobs,'S') .OR. lsame(jobs,'C')
581 sccoly = lsame(jobs,'Y')
582 wntvec = lsame(jobz,'V')
583 wntref = lsame(jobf,'R')
584 wntex = lsame(jobf,'E')
585 info = 0
586 lquery = ( ( lzwork == -1 ) .OR. ( liwork == -1 ) &
587 .OR. ( lrwork == -1 ) )
588!
589 IF ( .NOT. (sccolx .OR. sccoly .OR. &
590 lsame(jobs,'N')) ) THEN
591 info = -1
592 ELSE IF ( .NOT. (wntvec .OR. lsame(jobz,'N') &
593 .OR. lsame(jobz,'F')) ) THEN
594 info = -2
595 ELSE IF ( .NOT. (wntres .OR. lsame(jobr,'N')) .OR. &
596 ( wntres .AND. (.NOT.wntvec) ) ) THEN
597 info = -3
598 ELSE IF ( .NOT. (wntref .OR. wntex .OR. &
599 lsame(jobf,'N') ) ) THEN
600 info = -4
601 ELSE IF ( .NOT.((whtsvd == 1) .OR. (whtsvd == 2) .OR. &
602 (whtsvd == 3) .OR. (whtsvd == 4) )) THEN
603 info = -5
604 ELSE IF ( m < 0 ) THEN
605 info = -6
606 ELSE IF ( ( n < 0 ) .OR. ( n > m ) ) THEN
607 info = -7
608 ELSE IF ( ldx < m ) THEN
609 info = -9
610 ELSE IF ( ldy < m ) THEN
611 info = -11
612 ELSE IF ( .NOT. (( nrnk == -2).OR.(nrnk == -1).OR. &
613 ((nrnk >= 1).AND.(nrnk <=n ))) ) THEN
614 info = -12
615 ELSE IF ( ( tol < zero ) .OR. ( tol >= one ) ) THEN
616 info = -13
617 ELSE IF ( ldz < m ) THEN
618 info = -17
619 ELSE IF ( (wntref .OR. wntex ) .AND. ( ldb < m ) ) THEN
620 info = -20
621 ELSE IF ( ldw < n ) THEN
622 info = -22
623 ELSE IF ( lds < n ) THEN
624 info = -24
625 END IF
626!
627 IF ( info == 0 ) THEN
628 ! Compute the minimal and the optimal workspace
629 ! requirements. Simulate running the code and
630 ! determine minimal and optimal sizes of the
631 ! workspace at any moment of the run.
632 IF ( n == 0 ) THEN
633 ! Quick return. All output except K is void.
634 ! INFO=1 signals the void input.
635 ! In case of a workspace query, the default
636 ! minimal workspace lengths are returned.
637 IF ( lquery ) THEN
638 iwork(1) = 1
639 rwork(1) = 1
640 zwork(1) = 2
641 zwork(2) = 2
642 ELSE
643 k = 0
644 END IF
645 info = 1
646 RETURN
647 END IF
648
649 iminwr = 1
650 mlrwrk = max(1,n)
651 mlwork = 2
652 olwork = 2
653 SELECT CASE ( whtsvd )
654 CASE (1)
655 ! The following is specified as the minimal
656 ! length of WORK in the definition of ZGESVD:
657 ! MWRSVD = MAX(1,2*MIN(M,N)+MAX(M,N))
658 mwrsvd = max(1,2*min(m,n)+max(m,n))
659 mlwork = max(mlwork,mwrsvd)
660 mlrwrk = max(mlrwrk,n + 5*min(m,n))
661 IF ( lquery ) THEN
662 CALL zgesvd( 'O', 'S', m, n, x, ldx, rwork, &
663 b, ldb, w, ldw, zwork, -1, rdummy, info1 )
664 lwrsvd = int( zwork(1) )
665 olwork = max(olwork,lwrsvd)
666 END IF
667 CASE (2)
668 ! The following is specified as the minimal
669 ! length of WORK in the definition of ZGESDD:
670 ! MWRSDD = 2*min(M,N)*min(M,N)+2*min(M,N)+max(M,N).
671 ! RWORK length: 5*MIN(M,N)*MIN(M,N)+7*MIN(M,N)
672 ! In LAPACK 3.10.1 RWORK is defined differently.
673 ! Below we take max over the two versions.
674 ! IMINWR = 8*MIN(M,N)
675 mwrsdd = 2*min(m,n)*min(m,n)+2*min(m,n)+max(m,n)
676 mlwork = max(mlwork,mwrsdd)
677 iminwr = 8*min(m,n)
678 mlrwrk = max( mlrwrk, n + &
679 max( 5*min(m,n)*min(m,n)+7*min(m,n), &
680 5*min(m,n)*min(m,n)+5*min(m,n), &
681 2*max(m,n)*min(m,n)+ &
682 2*min(m,n)*min(m,n)+min(m,n) ) )
683 IF ( lquery ) THEN
684 CALL zgesdd( 'O', m, n, x, ldx, rwork, b,ldb,&
685 w, ldw, zwork, -1, rdummy, iwork, info1 )
686 lwrsdd = max( mwrsdd,int( zwork(1) ))
687 ! Possible bug in ZGESDD optimal workspace size.
688 olwork = max(olwork,lwrsdd)
689 END IF
690 CASE (3)
691 CALL zgesvdq( 'H', 'P', 'N', 'R', 'R', m, n, &
692 x, ldx, rwork, z, ldz, w, ldw, numrnk, &
693 iwork, -1, zwork, -1, rdummy, -1, info1 )
694 iminwr = iwork(1)
695 mwrsvq = int(zwork(2))
696 mlwork = max(mlwork,mwrsvq)
697 mlrwrk = max(mlrwrk,n + int(rdummy(1)))
698 IF ( lquery ) THEN
699 lwrsvq = int(zwork(1))
700 olwork = max(olwork,lwrsvq)
701 END IF
702 CASE (4)
703 jsvopt = 'J'
704 CALL zgejsv( 'F', 'U', jsvopt, 'R', 'N', 'P', m, &
705 n, x, ldx, rwork, z, ldz, w, ldw, &
706 zwork, -1, rdummy, -1, iwork, info1 )
707 iminwr = iwork(1)
708 mwrsvj = int(zwork(2))
709 mlwork = max(mlwork,mwrsvj)
710 mlrwrk = max(mlrwrk,n + max(7,int(rdummy(1))))
711 IF ( lquery ) THEN
712 lwrsvj = int(zwork(1))
713 olwork = max(olwork,lwrsvj)
714 END IF
715 END SELECT
716 IF ( wntvec .OR. wntex .OR. lsame(jobz,'F') ) THEN
717 jobzl = 'V'
718 ELSE
719 jobzl = 'N'
720 END IF
721 ! Workspace calculation to the ZGEEV call
722 mwrkev = max( 1, 2*n )
723 mlwork = max(mlwork,mwrkev)
724 mlrwrk = max(mlrwrk,n+2*n)
725 IF ( lquery ) THEN
726 CALL zgeev( 'N', jobzl, n, s, lds, eigs, &
727 w, ldw, w, ldw, zwork, -1, rwork, info1 )
728 lwrkev = int(zwork(1))
729 olwork = max( olwork, lwrkev )
730 END IF
731!
732 IF ( liwork < iminwr .AND. (.NOT.lquery) ) info = -30
733 IF ( lrwork < mlrwrk .AND. (.NOT.lquery) ) info = -28
734 IF ( lzwork < mlwork .AND. (.NOT.lquery) ) info = -26
735
736 END IF
737!
738 IF( info /= 0 ) THEN
739 CALL xerbla( 'ZGEDMD', -info )
740 RETURN
741 ELSE IF ( lquery ) THEN
742! Return minimal and optimal workspace sizes
743 iwork(1) = iminwr
744 rwork(1) = mlrwrk
745 zwork(1) = mlwork
746 zwork(2) = olwork
747 RETURN
748 END IF
749!............................................................
750!
751 ofl = dlamch('O')
752 small = dlamch('S')
753 badxy = .false.
754!
755! <1> Optional scaling of the snapshots (columns of X, Y)
756! ==========================================================
757 IF ( sccolx ) THEN
758 ! The columns of X will be normalized.
759 ! To prevent overflows, the column norms of X are
760 ! carefully computed using ZLASSQ.
761 k = 0
762 DO i = 1, n
763 !WORK(i) = DZNRM2( M, X(1,i), 1 )
764 ssum = one
765 scale = zero
766 CALL zlassq( m, x(1,i), 1, scale, ssum )
767 IF ( disnan(scale) .OR. disnan(ssum) ) THEN
768 k = 0
769 info = -8
770 CALL xerbla('ZGEDMD',-info)
771 END IF
772 IF ( (scale /= zero) .AND. (ssum /= zero) ) THEN
773 rootsc = sqrt(ssum)
774 IF ( scale .GE. (ofl / rootsc) ) THEN
775! Norm of X(:,i) overflows. First, X(:,i)
776! is scaled by
777! ( ONE / ROOTSC ) / SCALE = 1/||X(:,i)||_2.
778! Next, the norm of X(:,i) is stored without
779! overflow as RWORK(i) = - SCALE * (ROOTSC/M),
780! the minus sign indicating the 1/M factor.
781! Scaling is performed without overflow, and
782! underflow may occur in the smallest entries
783! of X(:,i). The relative backward and forward
784! errors are small in the ell_2 norm.
785 CALL zlascl( 'G', 0, 0, scale, one/rootsc, &
786 m, 1, x(1,i), ldx, info2 )
787 rwork(i) = - scale * ( rootsc / dble(m) )
788 ELSE
789! X(:,i) will be scaled to unit 2-norm
790 rwork(i) = scale * rootsc
791 CALL zlascl( 'G',0, 0, rwork(i), one, m, 1, &
792 x(1,i), ldx, info2 ) ! LAPACK CALL
793! X(1:M,i) = (ONE/RWORK(i)) * X(1:M,i) ! INTRINSIC
794 END IF
795 ELSE
796 rwork(i) = zero
797 k = k + 1
798 END IF
799 END DO
800 IF ( k == n ) THEN
801 ! All columns of X are zero. Return error code -8.
802 ! (the 8th input variable had an illegal value)
803 k = 0
804 info = -8
805 CALL xerbla('ZGEDMD',-info)
806 RETURN
807 END IF
808 DO i = 1, n
809! Now, apply the same scaling to the columns of Y.
810 IF ( rwork(i) > zero ) THEN
811 CALL zdscal( m, one/rwork(i), y(1,i), 1 ) ! BLAS CALL
812! Y(1:M,i) = (ONE/RWORK(i)) * Y(1:M,i) ! INTRINSIC
813 ELSE IF ( rwork(i) < zero ) THEN
814 CALL zlascl( 'G', 0, 0, -rwork(i), &
815 one/dble(m), m, 1, y(1,i), ldy, info2 ) ! LAPACK CALL
816 ELSE IF ( abs(y(izamax(m, y(1,i),1),i )) &
817 /= zero ) THEN
818! X(:,i) is zero vector. For consistency,
819! Y(:,i) should also be zero. If Y(:,i) is not
820! zero, then the data might be inconsistent or
821! corrupted. If JOBS == 'C', Y(:,i) is set to
822! zero and a warning flag is raised.
823! The computation continues but the
824! situation will be reported in the output.
825 badxy = .true.
826 IF ( lsame(jobs,'C')) &
827 CALL zdscal( m, zero, y(1,i), 1 ) ! BLAS CALL
828 END IF
829 END DO
830 END IF
831 !
832 IF ( sccoly ) THEN
833 ! The columns of Y will be normalized.
834 ! To prevent overflows, the column norms of Y are
835 ! carefully computed using ZLASSQ.
836 DO i = 1, n
837 !RWORK(i) = DZNRM2( M, Y(1,i), 1 )
838 ssum = one
839 scale = zero
840 CALL zlassq( m, y(1,i), 1, scale, ssum )
841 IF ( disnan(scale) .OR. disnan(ssum) ) THEN
842 k = 0
843 info = -10
844 CALL xerbla('ZGEDMD',-info)
845 END IF
846 IF ( scale /= zero .AND. (ssum /= zero) ) THEN
847 rootsc = sqrt(ssum)
848 IF ( scale .GE. (ofl / rootsc) ) THEN
849! Norm of Y(:,i) overflows. First, Y(:,i)
850! is scaled by
851! ( ONE / ROOTSC ) / SCALE = 1/||Y(:,i)||_2.
852! Next, the norm of Y(:,i) is stored without
853! overflow as RWORK(i) = - SCALE * (ROOTSC/M),
854! the minus sign indicating the 1/M factor.
855! Scaling is performed without overflow, and
856! underflow may occur in the smallest entries
857! of Y(:,i). The relative backward and forward
858! errors are small in the ell_2 norm.
859 CALL zlascl( 'G', 0, 0, scale, one/rootsc, &
860 m, 1, y(1,i), ldy, info2 )
861 rwork(i) = - scale * ( rootsc / dble(m) )
862 ELSE
863! Y(:,i) will be scaled to unit 2-norm
864 rwork(i) = scale * rootsc
865 CALL zlascl( 'G',0, 0, rwork(i), one, m, 1, &
866 y(1,i), ldy, info2 ) ! LAPACK CALL
867! Y(1:M,i) = (ONE/RWORK(i)) * Y(1:M,i) ! INTRINSIC
868 END IF
869 ELSE
870 rwork(i) = zero
871 END IF
872 END DO
873 DO i = 1, n
874! Now, apply the same scaling to the columns of X.
875 IF ( rwork(i) > zero ) THEN
876 CALL zdscal( m, one/rwork(i), x(1,i), 1 ) ! BLAS CALL
877! X(1:M,i) = (ONE/RWORK(i)) * X(1:M,i) ! INTRINSIC
878 ELSE IF ( rwork(i) < zero ) THEN
879 CALL zlascl( 'G', 0, 0, -rwork(i), &
880 one/dble(m), m, 1, x(1,i), ldx, info2 ) ! LAPACK CALL
881 ELSE IF ( abs(x(izamax(m, x(1,i),1),i )) &
882 /= zero ) THEN
883! Y(:,i) is zero vector. If X(:,i) is not
884! zero, then a warning flag is raised.
885! The computation continues but the
886! situation will be reported in the output.
887 badxy = .true.
888 END IF
889 END DO
890 END IF
891!
892! <2> SVD of the data snapshot matrix X.
893! =====================================
894! The left singular vectors are stored in the array X.
895! The right singular vectors are in the array W.
896! The array W will later on contain the eigenvectors
897! of a Rayleigh quotient.
898 numrnk = n
899 SELECT CASE ( whtsvd )
900 CASE (1)
901 CALL zgesvd( 'O', 'S', m, n, x, ldx, rwork, b, &
902 ldb, w, ldw, zwork, lzwork, rwork(n+1), info1 ) ! LAPACK CALL
903 t_or_n = 'C'
904 CASE (2)
905 CALL zgesdd( 'O', m, n, x, ldx, rwork, b, ldb, w, &
906 ldw, zwork, lzwork, rwork(n+1), iwork, info1 ) ! LAPACK CALL
907 t_or_n = 'C'
908 CASE (3)
909 CALL zgesvdq( 'H', 'P', 'N', 'R', 'R', m, n, &
910 x, ldx, rwork, z, ldz, w, ldw, &
911 numrnk, iwork, liwork, zwork, &
912 lzwork, rwork(n+1), lrwork-n, info1) ! LAPACK CALL
913 CALL zlacpy( 'A', m, numrnk, z, ldz, x, ldx ) ! LAPACK CALL
914 t_or_n = 'C'
915 CASE (4)
916 CALL zgejsv( 'F', 'U', jsvopt, 'R', 'N', 'P', m, &
917 n, x, ldx, rwork, z, ldz, w, ldw, &
918 zwork, lzwork, rwork(n+1), lrwork-n, iwork, info1 ) ! LAPACK CALL
919 CALL zlacpy( 'A', m, n, z, ldz, x, ldx ) ! LAPACK CALL
920 t_or_n = 'N'
921 xscl1 = rwork(n+1)
922 xscl2 = rwork(n+2)
923 IF ( xscl1 /= xscl2 ) THEN
924 ! This is an exceptional situation. If the
925 ! data matrices are not scaled and the
926 ! largest singular value of X overflows.
927 ! In that case ZGEJSV can return the SVD
928 ! in scaled form. The scaling factor can be used
929 ! to rescale the data (X and Y).
930 CALL zlascl( 'G', 0, 0, xscl1, xscl2, m, n, y, ldy, info2 )
931 END IF
932 END SELECT
933!
934 IF ( info1 > 0 ) THEN
935 ! The SVD selected subroutine did not converge.
936 ! Return with an error code.
937 info = 2
938 RETURN
939 END IF
940!
941 IF ( rwork(1) == zero ) THEN
942 ! The largest computed singular value of (scaled)
943 ! X is zero. Return error code -8
944 ! (the 8th input variable had an illegal value).
945 k = 0
946 info = -8
947 CALL xerbla('ZGEDMD',-info)
948 RETURN
949 END IF
950!
951
952 ! snapshots matrix X. This depends on the
953 ! parameters NRNK and TOL.
954
955 SELECT CASE ( nrnk )
956 CASE ( -1 )
957 k = 1
958 DO i = 2, numrnk
959 IF ( ( rwork(i) <= rwork(1)*tol ) .OR. &
960 ( rwork(i) <= small ) ) EXIT
961 k = k + 1
962 END DO
963 CASE ( -2 )
964 k = 1
965 DO i = 1, numrnk-1
966 IF ( ( rwork(i+1) <= rwork(i)*tol ) .OR. &
967 ( rwork(i) <= small ) ) EXIT
968 k = k + 1
969 END DO
970 CASE DEFAULT
971 k = 1
972 DO i = 2, nrnk
973 IF ( rwork(i) <= small ) EXIT
974 k = k + 1
975 END DO
976 END SELECT
977 ! Now, U = X(1:M,1:K) is the SVD/POD basis for the
978 ! snapshot data in the input matrix X.
979
980
981 ! Depending on the requested outputs, the computation
982 ! is organized to compute additional auxiliary
983 ! matrices (for the residuals and refinements).
984 !
985 ! In all formulas below, we need V_k*Sigma_k^(-1)
986 ! where either V_k is in W(1:N,1:K), or V_k^H is in
987 ! W(1:K,1:N). Here Sigma_k=diag(WORK(1:K)).
988 IF ( lsame(t_or_n, 'N') ) THEN
989 DO i = 1, k
990 CALL zdscal( n, one/rwork(i), w(1,i), 1 ) ! BLAS CALL
991 ! W(1:N,i) = (ONE/RWORK(i)) * W(1:N,i) ! INTRINSIC
992 END DO
993 ELSE
994 ! This non-unit stride access is due to the fact
995 ! that ZGESVD, ZGESVDQ and ZGESDD return the
996 ! adjoint matrix of the right singular vectors.
997 !DO i = 1, K
998 ! CALL ZDSCAL( N, ONE/RWORK(i), W(i,1), LDW ) ! BLAS CALL
999 ! ! W(i,1:N) = (ONE/RWORK(i)) * W(i,1:N) ! INTRINSIC
1000 !END DO
1001 DO i = 1, k
1002 rwork(n+i) = one/rwork(i)
1003 END DO
1004 DO j = 1, n
1005 DO i = 1, k
1006 w(i,j) = cmplx(rwork(n+i),zero,kind=wp)*w(i,j)
1007 END DO
1008 END DO
1009 END IF
1010!
1011 IF ( wntref ) THEN
1012 !
1013 ! Need A*U(:,1:K)=Y*V_k*inv(diag(WORK(1:K)))
1014 ! for computing the refined Ritz vectors
1015 ! (optionally, outside ZGEDMD).
1016 CALL zgemm( 'N', t_or_n, m, k, n, zone, y, ldy, w, &
1017 ldw, zzero, z, ldz ) ! BLAS CALL
1018 ! Z(1:M,1:K)=MATMUL(Y(1:M,1:N),TRANSPOSE(CONJG(W(1:K,1:N)))) ! INTRINSIC, for T_OR_N=='C'
1019 ! Z(1:M,1:K)=MATMUL(Y(1:M,1:N),W(1:N,1:K)) ! INTRINSIC, for T_OR_N=='N'
1020 !
1021 ! At this point Z contains
1022 ! A * U(:,1:K) = Y * V_k * Sigma_k^(-1), and
1023 ! this is needed for computing the residuals.
1024 ! This matrix is returned in the array B and
1025 ! it can be used to compute refined Ritz vectors.
1026 CALL zlacpy( 'A', m, k, z, ldz, b, ldb ) ! BLAS CALL
1027 ! B(1:M,1:K) = Z(1:M,1:K) ! INTRINSIC
1028
1029 CALL zgemm( 'C', 'N', k, k, m, zone, x, ldx, z, &
1030 ldz, zzero, s, lds ) ! BLAS CALL
1031 ! S(1:K,1:K) = MATMUL(TRANSPOSE(CONJG(X(1:M,1:K))),Z(1:M,1:K)) ! INTRINSIC
1032 ! At this point S = U^H * A * U is the Rayleigh quotient.
1033 ELSE
1034 ! A * U(:,1:K) is not explicitly needed and the
1035 ! computation is organized differently. The Rayleigh
1036 ! quotient is computed more efficiently.
1037 CALL zgemm( 'C', 'N', k, n, m, zone, x, ldx, y, ldy, &
1038 zzero, z, ldz ) ! BLAS CALL
1039 ! Z(1:K,1:N) = MATMUL( TRANSPOSE(CONJG(X(1:M,1:K))), Y(1:M,1:N) ) ! INTRINSIC
1040 !
1041 CALL zgemm( 'N', t_or_n, k, k, n, zone, z, ldz, w, &
1042 ldw, zzero, s, lds ) ! BLAS CALL
1043 ! S(1:K,1:K) = MATMUL(Z(1:K,1:N),TRANSPOSE(CONJG(W(1:K,1:N)))) ! INTRINSIC, for T_OR_N=='T'
1044 ! S(1:K,1:K) = MATMUL(Z(1:K,1:N),(W(1:N,1:K))) ! INTRINSIC, for T_OR_N=='N'
1045 ! At this point S = U^H * A * U is the Rayleigh quotient.
1046 ! If the residuals are requested, save scaled V_k into Z.
1047 ! Recall that V_k or V_k^H is stored in W.
1048 IF ( wntres .OR. wntex ) THEN
1049 IF ( lsame(t_or_n, 'N') ) THEN
1050 CALL zlacpy( 'A', n, k, w, ldw, z, ldz )
1051 ELSE
1052 CALL zlacpy( 'A', k, n, w, ldw, z, ldz )
1053 END IF
1054 END IF
1055 END IF
1056!
1057
1058 ! right eigenvectors of the Rayleigh quotient.
1059 !
1060 CALL zgeev( 'N', jobzl, k, s, lds, eigs, w, ldw, &
1061 w, ldw, zwork, lzwork, rwork(n+1), info1 ) ! LAPACK CALL
1062 !
1063 ! W(1:K,1:K) contains the eigenvectors of the Rayleigh
1064 ! quotient. See the description of Z.
1065 ! Also, see the description of ZGEEV.
1066 IF ( info1 > 0 ) THEN
1067 ! ZGEEV failed to compute the eigenvalues and
1068 ! eigenvectors of the Rayleigh quotient.
1069 info = 3
1070 RETURN
1071 END IF
1072!
1073 ! <6> Compute the eigenvectors (if requested) and,
1074 ! the residuals (if requested).
1075 !
1076 IF ( wntvec .OR. wntex ) THEN
1077 IF ( wntres ) THEN
1078 IF ( wntref ) THEN
1079 ! Here, if the refinement is requested, we have
1080 ! A*U(:,1:K) already computed and stored in Z.
1081 ! For the residuals, need Y = A * U(:,1;K) * W.
1082 CALL zgemm( 'N', 'N', m, k, k, zone, z, ldz, w, &
1083 ldw, zzero, y, ldy ) ! BLAS CALL
1084 ! Y(1:M,1:K) = Z(1:M,1:K) * W(1:K,1:K) ! INTRINSIC
1085 ! This frees Z; Y contains A * U(:,1:K) * W.
1086 ELSE
1087 ! Compute S = V_k * Sigma_k^(-1) * W, where
1088 ! V_k * Sigma_k^(-1) (or its adjoint) is stored in Z
1089 CALL zgemm( t_or_n, 'N', n, k, k, zone, z, ldz, &
1090 w, ldw, zzero, s, lds )
1091 ! Then, compute Z = Y * S =
1092 ! = Y * V_k * Sigma_k^(-1) * W(1:K,1:K) =
1093 ! = A * U(:,1:K) * W(1:K,1:K)
1094 CALL zgemm( 'N', 'N', m, k, n, zone, y, ldy, s, &
1095 lds, zzero, z, ldz )
1096 ! Save a copy of Z into Y and free Z for holding
1097 ! the Ritz vectors.
1098 CALL zlacpy( 'A', m, k, z, ldz, y, ldy )
1099 IF ( wntex ) CALL zlacpy( 'A', m, k, z, ldz, b, ldb )
1100 END IF
1101 ELSE IF ( wntex ) THEN
1102 ! Compute S = V_k * Sigma_k^(-1) * W, where
1103 ! V_k * Sigma_k^(-1) is stored in Z
1104 CALL zgemm( t_or_n, 'N', n, k, k, zone, z, ldz, &
1105 w, ldw, zzero, s, lds )
1106 ! Then, compute Z = Y * S =
1107 ! = Y * V_k * Sigma_k^(-1) * W(1:K,1:K) =
1108 ! = A * U(:,1:K) * W(1:K,1:K)
1109 CALL zgemm( 'N', 'N', m, k, n, zone, y, ldy, s, &
1110 lds, zzero, b, ldb )
1111 ! The above call replaces the following two calls
1112 ! that were used in the developing-testing phase.
1113 ! CALL ZGEMM( 'N', 'N', M, K, N, ZONE, Y, LDY, S, &
1114 ! LDS, ZZERO, Z, LDZ)
1115 ! Save a copy of Z into B and free Z for holding
1116 ! the Ritz vectors.
1117 ! CALL ZLACPY( 'A', M, K, Z, LDZ, B, LDB )
1118 END IF
1119!
1120 ! Compute the Ritz vectors
1121 IF ( wntvec ) CALL zgemm( 'N', 'N', m, k, k, zone, x, ldx, w, ldw, &
1122 zzero, z, ldz ) ! BLAS CALL
1123 ! Z(1:M,1:K) = MATMUL(X(1:M,1:K), W(1:K,1:K)) ! INTRINSIC
1124!
1125 IF ( wntres ) THEN
1126 DO i = 1, k
1127 CALL zaxpy( m, -eigs(i), z(1,i), 1, y(1,i), 1 ) ! BLAS CALL
1128 ! Y(1:M,i) = Y(1:M,i) - EIGS(i) * Z(1:M,i) ! INTRINSIC
1129 res(i) = dznrm2( m, y(1,i), 1 ) ! BLAS CALL
1130 END DO
1131 END IF
1132 END IF
1133!
1134 IF ( whtsvd == 4 ) THEN
1135 rwork(n+1) = xscl1
1136 rwork(n+2) = xscl2
1137 END IF
1138!
1139! Successful exit.
1140 IF ( .NOT. badxy ) THEN
1141 info = 0
1142 ELSE
1143 ! A warning on possible data inconsistency.
1144 ! This should be a rare event.
1145 info = 4
1146 END IF
1147!............................................................
1148 RETURN
1149! ......
1150 END SUBROUTINE zgedmd
subroutine xerbla(srname, info)
Definition cblat2.f:3285
subroutine zaxpy(n, za, zx, incx, zy, incy)
ZAXPY
Definition zaxpy.f:88
subroutine zgedmd(jobs, jobz, jobr, jobf, whtsvd, m, n, x, ldx, y, ldy, nrnk, tol, k, eigs, z, ldz, res, b, ldb, w, ldw, s, lds, zwork, lzwork, rwork, lrwork, iwork, liwork, info)
ZGEDMD computes the Dynamic Mode Decomposition (DMD) for a pair of data snapshot matrices.
Definition zgedmd.f90:501
subroutine zgeev(jobvl, jobvr, n, a, lda, w, vl, ldvl, vr, ldvr, work, lwork, rwork, info)
ZGEEV computes the eigenvalues and, optionally, the left and/or right eigenvectors for GE matrices
Definition zgeev.f:179
subroutine zgejsv(joba, jobu, jobv, jobr, jobt, jobp, m, n, a, lda, sva, u, ldu, v, ldv, cwork, lwork, rwork, lrwork, iwork, info)
ZGEJSV
Definition zgejsv.f:567
subroutine zgemm(transa, transb, m, n, k, alpha, a, lda, b, ldb, beta, c, ldc)
ZGEMM
Definition zgemm.f:188
subroutine zgesdd(jobz, m, n, a, lda, s, u, ldu, vt, ldvt, work, lwork, rwork, iwork, info)
ZGESDD
Definition zgesdd.f:219
subroutine zgesvd(jobu, jobvt, m, n, a, lda, s, u, ldu, vt, ldvt, work, lwork, rwork, info)
ZGESVD computes the singular value decomposition (SVD) for GE matrices
Definition zgesvd.f:212
subroutine zgesvdq(joba, jobp, jobr, jobu, jobv, m, n, a, lda, s, u, ldu, v, ldv, numrank, iwork, liwork, cwork, lcwork, rwork, lrwork, info)
ZGESVDQ computes the singular value decomposition (SVD) with a QR-Preconditioned QR SVD Method for GE...
Definition zgesvdq.f:411
integer function izamax(n, zx, incx)
IZAMAX
Definition izamax.f:71
subroutine zlacpy(uplo, m, n, a, lda, b, ldb)
ZLACPY copies all or part of one two-dimensional array to another.
Definition zlacpy.f:101
double precision function dlamch(cmach)
DLAMCH
Definition dlamch.f:69
double precision function zlange(norm, m, n, a, lda, work)
ZLANGE returns the value of the 1-norm, Frobenius norm, infinity-norm, or the largest absolute value ...
Definition zlange.f:113
subroutine zlascl(type, kl, ku, cfrom, cto, m, n, a, lda, info)
ZLASCL multiplies a general rectangular matrix by a real scalar defined as cto/cfrom.
Definition zlascl.f:142
subroutine zlassq(n, x, incx, scale, sumsq)
ZLASSQ updates a sum of squares represented in scaled form.
Definition zlassq.f90:122
real(wp) function dznrm2(n, x, incx)
DZNRM2
Definition dznrm2.f90:90
subroutine zdscal(n, da, zx, incx)
ZDSCAL
Definition zdscal.f:78