531 SUBROUTINE dgedmd( JOBS, JOBZ, JOBR, JOBF, WHTSVD, &
532 M, N, X, LDX, Y, LDY, NRNK, TOL, &
533 K, REIG, IMEIG, Z, LDZ, RES, &
534 B, LDB, W, LDW, S, LDS, &
535 WORK, LWORK, IWORK, LIWORK, INFO )
546 INTEGER,
PARAMETER :: WP = real64
550 CHARACTER,
INTENT(IN) :: JOBS, JOBZ, JOBR, JOBF
551 INTEGER,
INTENT(IN) :: WHTSVD, M, N, LDX, LDY, &
552 NRNK, LDZ, LDB, LDW, LDS, &
554 INTEGER,
INTENT(OUT) :: K, INFO
555 REAL(KIND=wp),
INTENT(IN) :: tol
559 REAL(KIND=wp),
INTENT(INOUT) :: x(ldx,*), y(ldy,*)
560 REAL(KIND=wp),
INTENT(OUT) :: z(ldz,*), b(ldb,*), &
562 REAL(KIND=wp),
INTENT(OUT) :: reig(*), imeig(*), &
564 REAL(KIND=wp),
INTENT(OUT) :: work(*)
565 INTEGER,
INTENT(OUT) :: IWORK(*)
569 REAL(KIND=wp),
PARAMETER :: one = 1.0_wp
570 REAL(KIND=wp),
PARAMETER :: zero = 0.0_wp
574 REAL(KIND=wp) :: ofl, rootsc, scale, small, &
576 INTEGER :: i, j, IMINWR, INFO1, INFO2, &
577 LWRKEV, LWRSDD, LWRSVD, &
578 lwrsvq, mlwork, mwrkev, mwrsdd, &
579 mwrsvd, mwrsvj, mwrsvq, numrnk, &
581 LOGICAL :: BADXY, LQUERY, SCCOLX, SCCOLY, &
582 wntex, wntref, wntres, wntvec
583 CHARACTER :: JOBZL, T_OR_N
588 REAL(KIND=wp) :: ab(2,2), rdummy(2), rdummy2(2)
595 LOGICAL DISNAN, LSAME
596 EXTERNAL disnan, lsame
606 INTRINSIC dble, int, max, sqrt
611 wntres = lsame(jobr,
'R')
612 sccolx = lsame(jobs,
'S') .OR. lsame(jobs,
'C')
613 sccoly = lsame(jobs,
'Y')
614 wntvec = lsame(jobz,
'V')
615 wntref = lsame(jobf,
'R')
616 wntex = lsame(jobf,
'E')
618 lquery = ( ( lwork == -1 ) .OR. ( liwork == -1 ) )
620 IF ( .NOT. (sccolx .OR. sccoly .OR. &
621 lsame(jobs,
'N')) )
THEN
623 ELSE IF ( .NOT. (wntvec .OR. lsame(jobz,
'N') &
624 .OR. lsame(jobz,
'F')) )
THEN
626 ELSE IF ( .NOT. (wntres .OR. lsame(jobr,
'N')) .OR. &
627 ( wntres .AND. (.NOT.wntvec) ) )
THEN
629 ELSE IF ( .NOT. (wntref .OR. wntex .OR. &
630 lsame(jobf,
'N') ) )
THEN
632 ELSE IF ( .NOT.((whtsvd == 1) .OR. (whtsvd == 2) .OR. &
633 (whtsvd == 3) .OR. (whtsvd == 4) ))
THEN
635 ELSE IF ( m < 0 )
THEN
637 ELSE IF ( ( n < 0 ) .OR. ( n > m ) )
THEN
639 ELSE IF ( ldx < m )
THEN
641 ELSE IF ( ldy < m )
THEN
643 ELSE IF ( .NOT. (( nrnk == -2).OR.(nrnk == -1).OR. &
644 ((nrnk >= 1).AND.(nrnk <=n ))) )
THEN
646 ELSE IF ( ( tol < zero ) .OR. ( tol >= one ) )
THEN
648 ELSE IF ( ldz < m )
THEN
650 ELSE IF ( (wntref .OR. wntex ) .AND. ( ldb < m ) )
THEN
652 ELSE IF ( ldw < n )
THEN
654 ELSE IF ( lds < n )
THEN
658 IF ( info == 0 )
THEN
681 SELECT CASE ( whtsvd )
686 mwrsvd = max(1,3*min(m,n)+max(m,n),5*min(m,n))
687 mlwork = max(mlwork,n + mwrsvd)
689 CALL dgesvd(
'O',
'S', m, n, x, ldx, work, &
690 b, ldb, w, ldw, rdummy, -1, info1 )
691 lwrsvd = max( mwrsvd, int( rdummy(1) ) )
692 olwork = max(olwork,n + lwrsvd)
700 mwrsdd = 3*min(m,n)*min(m,n) + &
701 max( max(m,n),5*min(m,n)*min(m,n)+4*min(m,n) )
702 mlwork = max(mlwork,n + mwrsdd)
705 CALL dgesdd(
'O', m, n, x, ldx, work, b, &
706 ldb, w, ldw, rdummy, -1, iwork, info1 )
707 lwrsdd = max( mwrsdd, int( rdummy(1) ) )
708 olwork = max(olwork,n + lwrsdd)
717 CALL dgesvdq(
'H',
'P',
'N',
'R',
'R', m, n, &
718 x, ldx, work, z, ldz, w, ldw, &
719 numrnk, iwork, liwork, rdummy, &
720 -1, rdummy2, -1, info1 )
722 mwrsvq = int(rdummy(2))
723 mlwork = max(mlwork,n+mwrsvq+int(rdummy2(1)))
725 lwrsvq = max( mwrsvq, int(rdummy(1)) )
726 olwork = max(olwork,n+lwrsvq+int(rdummy2(1)))
731 mwrsvj = max( 7, 2*m+n, 4*n+n*n, 2*n+n*n+6 )
732 mlwork = max(mlwork,n+mwrsvj)
733 iminwr = max( 3, m+3*n )
735 olwork = max(olwork,n+mwrsvj)
738 IF ( wntvec .OR. wntex .OR. lsame(jobz,
'F') )
THEN
744 IF ( lsame(jobzl,
'V') )
THEN
745 mwrkev = max( 1, 4*n )
747 mwrkev = max( 1, 3*n )
749 mlwork = max(mlwork,n+mwrkev)
751 CALL dgeev(
'N', jobzl, n, s, lds, reig, &
752 imeig, w, ldw, w, ldw, rdummy, -1, info1 )
753 lwrkev = max( mwrkev, int(rdummy(1)) )
754 olwork = max( olwork, n+lwrkev )
757 IF ( liwork < iminwr .AND. (.NOT.lquery) ) info = -29
758 IF ( lwork < mlwork .AND. (.NOT.lquery) ) info = -27
762 CALL xerbla(
'DGEDMD', -info )
764 ELSE IF ( lquery )
THEN
787 CALL dlassq( m, x(1,i), 1, scale, ssum )
788 IF ( disnan(scale) .OR. disnan(ssum) )
THEN
791 CALL xerbla(
'DGEDMD',-info)
793 IF ( (scale /= zero) .AND. (ssum /= zero) )
THEN
795 IF ( scale .GE. (ofl / rootsc) )
THEN
806 CALL dlascl(
'G', 0, 0, scale, one/rootsc, &
807 m, 1, x(1,i), m, info2 )
808 work(i) = - scale * ( rootsc / dble(m) )
811 work(i) = scale * rootsc
812 CALL dlascl(
'G',0, 0, work(i), one, m, 1, &
826 CALL xerbla(
'DGEDMD',-info)
831 IF ( work(i) > zero )
THEN
832 CALL dscal( m, one/work(i), y(1,i), 1 )
834 ELSE IF ( work(i) < zero )
THEN
835 CALL dlascl(
'G', 0, 0, -work(i), &
836 one/dble(m), m, 1, y(1,i), m, info2 )
837 ELSE IF ( y(idamax(m, y(1,i),1),i ) &
847 IF ( lsame(jobs,
'C')) &
848 CALL dscal( m, zero, y(1,i), 1 )
860 CALL dlassq( m, y(1,i), 1, scale, ssum )
861 IF ( disnan(scale) .OR. disnan(ssum) )
THEN
864 CALL xerbla(
'DGEDMD',-info)
866 IF ( scale /= zero .AND. (ssum /= zero) )
THEN
868 IF ( scale .GE. (ofl / rootsc) )
THEN
879 CALL dlascl(
'G', 0, 0, scale, one/rootsc, &
880 m, 1, y(1,i), m, info2 )
881 work(i) = - scale * ( rootsc / dble(m) )
884 work(i) = scale * rootsc
885 CALL dlascl(
'G',0, 0, work(i), one, m, 1, &
895 IF ( work(i) > zero )
THEN
896 CALL dscal( m, one/work(i), x(1,i), 1 )
898 ELSE IF ( work(i) < zero )
THEN
899 CALL dlascl(
'G', 0, 0, -work(i), &
900 one/dble(m), m, 1, x(1,i), m, info2 )
901 ELSE IF ( x(idamax(m, x(1,i),1),i ) &
919 SELECT CASE ( whtsvd )
921 CALL dgesvd(
'O',
'S', m, n, x, ldx, work, b, &
922 ldb, w, ldw, work(n+1), lwork-n, info1 )
925 CALL dgesdd(
'O', m, n, x, ldx, work, b, ldb, w, &
926 ldw, work(n+1), lwork-n, iwork, info1 )
929 CALL dgesvdq(
'H',
'P',
'N',
'R',
'R', m, n, &
930 x, ldx, work, z, ldz, w, ldw, &
931 numrnk, iwork, liwork, work(n+max(2,m)+1),&
932 lwork-n-max(2,m), work(n+1), max(2,m), info1)
933 CALL dlacpy(
'A', m, numrnk, z, ldz, x, ldx )
936 CALL dgejsv(
'F',
'U', jsvopt,
'N',
'N',
'P', m, &
937 n, x, ldx, work, z, ldz, w, ldw, &
938 work(n+1), lwork-n, iwork, info1 )
939 CALL dlacpy(
'A', m, n, z, ldz, x, ldx )
943 IF ( xscl1 /= xscl2 )
THEN
950 CALL dlascl(
'G', 0, 0, xscl1, xscl2, m, n, y, ldy, info2
954 IF ( info1 > 0 )
THEN
961 IF ( work(1) == zero )
THEN
967 CALL xerbla(
'DGEDMD',-info)
979 IF ( ( work(i) <= work(1)*tol ) .OR. &
980 ( work(i) <= small ) )
EXIT
986 IF ( ( work(i+1) <= work(i)*tol ) .OR. &
987 ( work(i) <= small ) )
EXIT
993 IF ( work(i) <= small )
EXIT
1008 IF ( lsame(t_or_n,
'N') )
THEN
1010 CALL dscal( n, one/work(i), w(1,i), 1 )
1022 work(n+i) = one/work(i)
1026 w(i,j) = (work(n+i))*w(i,j)
1036 CALL dgemm(
'N', t_or_n, m, k, n, one, y, ldy, w, &
1046 CALL dlacpy(
'A', m, k, z, ldz, b, ldb )
1049 CALL dgemm(
'T',
'N', k, k, m, one, x, ldx, z, &
1057 CALL dgemm(
'T',
'N', k, n, m, one, x, ldx, y, ldy, &
1061 CALL dgemm(
'N', t_or_n, k, k, n, one, z, ldz, w, &
1068 IF ( wntres .OR. wntex )
THEN
1069 IF ( lsame(t_or_n,
'N') )
THEN
1070 CALL dlacpy(
'A', n, k, w, ldw, z, ldz )
1072 CALL dlacpy(
'A', k, n, w, ldw, z, ldz )
1080 CALL dgeev(
'N', jobzl, k, s, lds, reig, imeig, w, &
1081 ldw, w, ldw, work(n+1), lwork-n, info1 )
1096 IF ( info1 > 0 )
THEN
1106 IF ( wntvec .OR. wntex )
THEN
1112 CALL dgemm(
'N',
'N', m, k, k, one, z, ldz, w, &
1119 CALL dgemm( t_or_n,
'N', n, k, k, one, z, ldz, &
1120 w, ldw, zero, s, lds)
1124 CALL dgemm(
'N',
'N', m, k, n, one, y, ldy, s, &
1128 CALL dlacpy(
'A', m, k, z, ldz, y, ldy )
1129 IF ( wntex )
CALL dlacpy(
'A', m, k, z, ldz, b, ldb )
1131 ELSE IF ( wntex )
THEN
1134 CALL dgemm( t_or_n,
'N', n, k, k, one, z, ldz, &
1135 w, ldw, zero, s, lds )
1139 CALL dgemm(
'N',
'N', m, k, n, one, y, ldy, s, &
1151 IF ( wntvec )
CALL dgemm(
'N',
'N', m, k, k, one, x, ldx, w, ldw,
1158 IF ( imeig(i) == zero )
THEN
1160 CALL daxpy( m, -reig(i), z(1,i), 1, y(1,i), 1 )
1162 res(i) =
dnrm2( m, y(1,i), 1)
1176 CALL dgemm(
'N',
'N', m, 2, 2, -one, z(1,i), &
1177 ldz, ab, 2, one, y(1,i), ldy )
1179 res(i) =
dlange(
'F', m, 2, y(1,i), ldy, &
1188 IF ( whtsvd == 4 )
THEN
1194 IF ( .NOT. badxy )
THEN
subroutine xerbla(srname, info)
subroutine daxpy(n, da, dx, incx, dy, incy)
DAXPY
subroutine dgedmd(jobs, jobz, jobr, jobf, whtsvd, m, n, x, ldx, y, ldy, nrnk, tol, k, reig, imeig, z, ldz, res, b, ldb, w, ldw, s, lds, work, lwork, iwork, liwork, info)
DGEDMD computes the Dynamic Mode Decomposition (DMD) for a pair of data snapshot matrices.
subroutine dgeev(jobvl, jobvr, n, a, lda, wr, wi, vl, ldvl, vr, ldvr, work, lwork, info)
DGEEV computes the eigenvalues and, optionally, the left and/or right eigenvectors for GE matrices
subroutine dgejsv(joba, jobu, jobv, jobr, jobt, jobp, m, n, a, lda, sva, u, ldu, v, ldv, work, lwork, iwork, info)
DGEJSV
subroutine dgemm(transa, transb, m, n, k, alpha, a, lda, b, ldb, beta, c, ldc)
DGEMM
subroutine dgesdd(jobz, m, n, a, lda, s, u, ldu, vt, ldvt, work, lwork, iwork, info)
DGESDD
subroutine dgesvd(jobu, jobvt, m, n, a, lda, s, u, ldu, vt, ldvt, work, lwork, info)
DGESVD computes the singular value decomposition (SVD) for GE matrices
subroutine dgesvdq(joba, jobp, jobr, jobu, jobv, m, n, a, lda, s, u, ldu, v, ldv, numrank, iwork, liwork, work, lwork, rwork, lrwork, info)
DGESVDQ computes the singular value decomposition (SVD) with a QR-Preconditioned QR SVD Method for GE...
integer function idamax(n, dx, incx)
IDAMAX
subroutine dlacpy(uplo, m, n, a, lda, b, ldb)
DLACPY copies all or part of one two-dimensional array to another.
double precision function dlamch(cmach)
DLAMCH
double precision function dlange(norm, m, n, a, lda, work)
DLANGE returns the value of the 1-norm, Frobenius norm, infinity-norm, or the largest absolute value ...
subroutine dlascl(type, kl, ku, cfrom, cto, m, n, a, lda, info)
DLASCL multiplies a general rectangular matrix by a real scalar defined as cto/cfrom.
subroutine dlassq(n, x, incx, scale, sumsq)
DLASSQ updates a sum of squares represented in scaled form.
real(wp) function dnrm2(n, x, incx)
DNRM2
subroutine dscal(n, da, dx, incx)
DSCAL