530 SUBROUTINE sgedmd( JOBS, JOBZ, JOBR, JOBF, WHTSVD, &
531 M, N, X, LDX, Y, LDY, NRNK, TOL, &
532 K, REIG, IMEIG, Z, LDZ, RES, &
533 B, LDB, W, LDW, S, LDS, &
534 WORK, LWORK, IWORK, LIWORK, INFO )
545 INTEGER,
PARAMETER :: WP = real32
549 CHARACTER,
INTENT(IN) :: JOBS, JOBZ, JOBR, JOBF
550 INTEGER,
INTENT(IN) :: WHTSVD, M, N, LDX, LDY, &
551 NRNK, LDZ, LDB, LDW, LDS, &
553 INTEGER,
INTENT(OUT) :: K, INFO
554 REAL(KIND=wp),
INTENT(IN) :: tol
558 REAL(KIND=wp),
INTENT(INOUT) :: x(ldx,*), y(ldy,*)
559 REAL(KIND=wp),
INTENT(OUT) :: z(ldz,*), b(ldb,*), &
561 REAL(KIND=wp),
INTENT(OUT) :: reig(*), imeig(*), &
563 REAL(KIND=wp),
INTENT(OUT) :: work(*)
564 INTEGER,
INTENT(OUT) :: IWORK(*)
568 REAL(KIND=wp),
PARAMETER :: one = 1.0_wp
569 REAL(KIND=wp),
PARAMETER :: zero = 0.0_wp
573 REAL(KIND=wp) :: ofl, rootsc, scale, small, &
575 INTEGER :: i, j, IMINWR, INFO1, INFO2, &
576 LWRKEV, LWRSDD, LWRSVD, &
577 lwrsvq, mlwork, mwrkev, mwrsdd, &
578 mwrsvd, mwrsvj, mwrsvq, numrnk, &
580 LOGICAL :: BADXY, LQUERY, SCCOLX, SCCOLY, &
581 wntex, wntref, wntres, wntvec
582 CHARACTER :: JOBZL, T_OR_N
587 REAL(KIND=wp) :: ab(2,2), rdummy(2), rdummy2(2)
594 LOGICAL SISNAN, LSAME
595 EXTERNAL sisnan, lsame
605 INTRINSIC int, float, max, sqrt
610 wntres = lsame(jobr,
'R')
611 sccolx = lsame(jobs,
'S') .OR. lsame(jobs,
'C')
612 sccoly = lsame(jobs,
'Y')
613 wntvec = lsame(jobz,
'V')
614 wntref = lsame(jobf,
'R')
615 wntex = lsame(jobf,
'E')
617 lquery = ( ( lwork == -1 ) .OR. ( liwork == -1 ) )
619 IF ( .NOT. (sccolx .OR. sccoly .OR. &
620 lsame(jobs,
'N')) )
THEN
622 ELSE IF ( .NOT. (wntvec .OR. lsame(jobz,
'N') &
623 .OR. lsame(jobz,
'F')) )
THEN
625 ELSE IF ( .NOT. (wntres .OR. lsame(jobr,
'N')) .OR. &
626 ( wntres .AND. (.NOT.wntvec) ) )
THEN
628 ELSE IF ( .NOT. (wntref .OR. wntex .OR. &
629 lsame(jobf,
'N') ) )
THEN
631 ELSE IF ( .NOT.((whtsvd == 1) .OR. (whtsvd == 2) .OR. &
632 (whtsvd == 3) .OR. (whtsvd == 4) ))
THEN
634 ELSE IF ( m < 0 )
THEN
636 ELSE IF ( ( n < 0 ) .OR. ( n > m ) )
THEN
638 ELSE IF ( ldx < m )
THEN
640 ELSE IF ( ldy < m )
THEN
642 ELSE IF ( .NOT. (( nrnk == -2).OR.(nrnk == -1).OR. &
643 ((nrnk >= 1).AND.(nrnk <=n ))) )
THEN
645 ELSE IF ( ( tol < zero ) .OR. ( tol >= one ) )
THEN
647 ELSE IF ( ldz < m )
THEN
649 ELSE IF ( (wntref .OR. wntex ) .AND. ( ldb < m ) )
THEN
651 ELSE IF ( ldw < n )
THEN
653 ELSE IF ( lds < n )
THEN
657 IF ( info == 0 )
THEN
680 SELECT CASE ( whtsvd )
685 mwrsvd = max(1,3*min(m,n)+max(m,n),5*min(m,n))
686 mlwork = max(mlwork,n + mwrsvd)
688 CALL sgesvd(
'O',
'S', m, n, x, ldx, work, &
689 b, ldb, w, ldw, rdummy, -1, info1 )
690 lwrsvd = max( mwrsvd, int( rdummy(1) ) )
691 olwork = max(olwork,n + lwrsvd)
699 mwrsdd = 3*min(m,n)*min(m,n) + &
700 max( max(m,n),5*min(m,n)*min(m,n)+4*min(m,n) )
701 mlwork = max(mlwork,n + mwrsdd)
704 CALL sgesdd(
'O', m, n, x, ldx, work, b, &
705 ldb, w, ldw, rdummy, -1, iwork, info1 )
706 lwrsdd = max( mwrsdd, int( rdummy(1) ) )
707 olwork = max(olwork,n + lwrsdd)
716 CALL sgesvdq(
'H',
'P',
'N',
'R',
'R', m, n, &
717 x, ldx, work, z, ldz, w, ldw, &
718 numrnk, iwork, -1, rdummy, &
719 -1, rdummy2, -1, info1 )
721 mwrsvq = int(rdummy(2))
722 mlwork = max(mlwork,n+mwrsvq+int(rdummy2(1)))
724 lwrsvq = int(rdummy(1))
725 olwork = max(olwork,n+lwrsvq+int(rdummy2(1)))
730 mwrsvj = max( 7, 2*m+n, 4*n+n*n, 2*n+n*n+6 )
731 mlwork = max(mlwork,n+mwrsvj)
732 iminwr = max( 3, m+3*n )
734 olwork = max(olwork,n+mwrsvj)
737 IF ( wntvec .OR. wntex .OR. lsame(jobz,
'F') )
THEN
743 IF ( lsame(jobzl,
'V') )
THEN
744 mwrkev = max( 1, 4*n )
746 mwrkev = max( 1, 3*n )
748 mlwork = max(mlwork,n+mwrkev)
750 CALL sgeev(
'N', jobzl, n, s, lds, reig, &
751 imeig, w, ldw, w, ldw, rdummy, -1, info1 )
752 lwrkev = max( mwrkev, int(rdummy(1)) )
753 olwork = max( olwork, n+lwrkev )
756 IF ( liwork < iminwr .AND. (.NOT.lquery) ) info = -29
757 IF ( lwork < mlwork .AND. (.NOT.lquery) ) info = -27
761 CALL xerbla(
'SGEDMD', -info )
763 ELSE IF ( lquery )
THEN
786 CALL slassq( m, x(1,i), 1, scale, ssum )
787 IF ( sisnan(scale) .OR. sisnan(ssum) )
THEN
790 CALL xerbla(
'SGEDMD',-info)
792 IF ( (scale /= zero) .AND. (ssum /= zero) )
THEN
794 IF ( scale .GE. (ofl / rootsc) )
THEN
805 CALL slascl(
'G', 0, 0, scale, one/rootsc, &
806 m, 1, x(1,i), m, info2 )
807 work(i) = - scale * ( rootsc / float(m) )
810 work(i) = scale * rootsc
811 CALL slascl(
'G',0, 0, work(i), one, m, 1, &
825 CALL xerbla(
'SGEDMD',-info)
830 IF ( work(i) > zero )
THEN
831 CALL sscal( m, one/work(i), y(1,i), 1 )
833 ELSE IF ( work(i) < zero )
THEN
834 CALL slascl(
'G', 0, 0, -work(i), &
835 one/float(m), m, 1, y(1,i), m, info2 )
836 ELSE IF ( y(isamax(m, y(1,i),1),i ) &
846 IF ( lsame(jobs,
'C')) &
847 CALL sscal( m, zero, y(1,i), 1 )
859 CALL slassq( m, y(1,i), 1, scale, ssum )
860 IF ( sisnan(scale) .OR. sisnan(ssum) )
THEN
863 CALL xerbla(
'SGEDMD',-info)
865 IF ( scale /= zero .AND. (ssum /= zero) )
THEN
867 IF ( scale .GE. (ofl / rootsc) )
THEN
878 CALL slascl(
'G', 0, 0, scale, one/rootsc, &
879 m, 1, y(1,i), m, info2 )
880 work(i) = - scale * ( rootsc / float(m) )
883 work(i) = scale * rootsc
884 CALL slascl(
'G',0, 0, work(i), one, m, 1, &
894 IF ( work(i) > zero )
THEN
895 CALL sscal( m, one/work(i), x(1,i), 1 )
897 ELSE IF ( work(i) < zero )
THEN
898 CALL slascl(
'G', 0, 0, -work(i), &
899 one/float(m), m, 1, x(1,i), m, info2 )
900 ELSE IF ( x(isamax(m, x(1,i),1),i ) &
918 SELECT CASE ( whtsvd )
920 CALL sgesvd(
'O',
'S', m, n, x, ldx, work, b, &
921 ldb, w, ldw, work(n+1), lwork-n, info1 )
924 CALL sgesdd(
'O', m, n, x, ldx, work, b, ldb, w, &
925 ldw, work(n+1), lwork-n, iwork, info1 )
928 CALL sgesvdq(
'H',
'P',
'N',
'R',
'R', m, n, &
929 x, ldx, work, z, ldz, w, ldw, &
930 numrnk, iwork, liwork, work(n+max(2,m)+1),&
931 lwork-n-max(2,m), work(n+1), max(2,m), info1)
932 CALL slacpy(
'A', m, numrnk, z, ldz, x, ldx )
935 CALL sgejsv(
'F',
'U', jsvopt,
'N',
'N',
'P', m, &
936 n, x, ldx, work, z, ldz, w, ldw, &
937 work(n+1), lwork-n, iwork, info1 )
938 CALL slacpy(
'A', m, n, z, ldz, x, ldx )
942 IF ( xscl1 /= xscl2 )
THEN
949 CALL slascl(
'G', 0, 0, xscl1, xscl2, m, n, y, ldy, info2
953 IF ( info1 > 0 )
THEN
960 IF ( work(1) == zero )
THEN
966 CALL xerbla(
'SGEDMD',-info)
978 IF ( ( work(i) <= work(1)*tol ) .OR. &
979 ( work(i) <= small ) )
EXIT
985 IF ( ( work(i+1) <= work(i)*tol ) .OR. &
986 ( work(i) <= small ) )
EXIT
992 IF ( work(i) <= small )
EXIT
1007 IF ( lsame(t_or_n,
'N') )
THEN
1009 CALL sscal( n, one/work(i), w(1,i), 1 )
1021 work(n+i) = one/work(i)
1025 w(i,j) = (work(n+i))*w(i,j)
1035 CALL sgemm(
'N', t_or_n, m, k, n, one, y, ldy, w, &
1045 CALL slacpy(
'A', m, k, z, ldz, b, ldb )
1048 CALL sgemm(
'T',
'N', k, k, m, one, x, ldx, z, &
1056 CALL sgemm(
'T',
'N', k, n, m, one, x, ldx, y, ldy, &
1060 CALL sgemm(
'N', t_or_n, k, k, n, one, z, ldz, w, &
1067 IF ( wntres .OR. wntex )
THEN
1068 IF ( lsame(t_or_n,
'N') )
THEN
1069 CALL slacpy(
'A', n, k, w, ldw, z, ldz )
1071 CALL slacpy(
'A', k, n, w, ldw, z, ldz )
1079 CALL sgeev(
'N', jobzl, k, s, lds, reig, imeig, w, &
1080 ldw, w, ldw, work(n+1), lwork-n, info1 )
1095 IF ( info1 > 0 )
THEN
1105 IF ( wntvec .OR. wntex )
THEN
1111 CALL sgemm(
'N',
'N', m, k, k, one, z, ldz, w, &
1118 CALL sgemm( t_or_n,
'N', n, k, k, one, z, ldz, &
1119 w, ldw, zero, s, lds )
1123 CALL sgemm(
'N',
'N', m, k, n, one, y, ldy, s, &
1127 CALL slacpy(
'A', m, k, z, ldz, y, ldy )
1128 IF ( wntex )
CALL slacpy(
'A', m, k, z, ldz, b, ldb )
1130 ELSE IF ( wntex )
THEN
1133 CALL sgemm( t_or_n,
'N', n, k, k, one, z, ldz, &
1134 w, ldw, zero, s, lds )
1138 CALL sgemm(
'N',
'N', m, k, n, one, y, ldy, s, &
1150 IF ( wntvec )
CALL sgemm(
'N',
'N', m, k, k, one, x, ldx, w, ldw,
1157 IF ( imeig(i) == zero )
THEN
1159 CALL saxpy( m, -reig(i), z(1,i), 1, y(1,i), 1 )
1161 res(i) =
snrm2( m, y(1,i), 1 )
1175 CALL sgemm(
'N',
'N', m, 2, 2, -one, z(1,i), &
1176 ldz, ab, 2, one, y(1,i), ldy )
1178 res(i) =
slange(
'F', m, 2, y(1,i), ldy, &
1187 IF ( whtsvd == 4 )
THEN
1193 IF ( .NOT. badxy )
THEN
subroutine xerbla(srname, info)
subroutine saxpy(n, sa, sx, incx, sy, incy)
SAXPY
subroutine sgedmd(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)
SGEDMD computes the Dynamic Mode Decomposition (DMD) for a pair of data snapshot matrices.
subroutine sgeev(jobvl, jobvr, n, a, lda, wr, wi, vl, ldvl, vr, ldvr, work, lwork, info)
SGEEV computes the eigenvalues and, optionally, the left and/or right eigenvectors for GE matrices
subroutine sgejsv(joba, jobu, jobv, jobr, jobt, jobp, m, n, a, lda, sva, u, ldu, v, ldv, work, lwork, iwork, info)
SGEJSV
subroutine sgemm(transa, transb, m, n, k, alpha, a, lda, b, ldb, beta, c, ldc)
SGEMM
subroutine sgesdd(jobz, m, n, a, lda, s, u, ldu, vt, ldvt, work, lwork, iwork, info)
SGESDD
subroutine sgesvd(jobu, jobvt, m, n, a, lda, s, u, ldu, vt, ldvt, work, lwork, info)
SGESVD computes the singular value decomposition (SVD) for GE matrices
subroutine sgesvdq(joba, jobp, jobr, jobu, jobv, m, n, a, lda, s, u, ldu, v, ldv, numrank, iwork, liwork, work, lwork, rwork, lrwork, info)
SGESVDQ computes the singular value decomposition (SVD) with a QR-Preconditioned QR SVD Method for GE...
integer function isamax(n, sx, incx)
ISAMAX
subroutine slacpy(uplo, m, n, a, lda, b, ldb)
SLACPY copies all or part of one two-dimensional array to another.
real function slamch(cmach)
SLAMCH
real function slange(norm, m, n, a, lda, work)
SLANGE returns the value of the 1-norm, Frobenius norm, infinity-norm, or the largest absolute value ...
subroutine slascl(type, kl, ku, cfrom, cto, m, n, a, lda, info)
SLASCL multiplies a general rectangular matrix by a real scalar defined as cto/cfrom.
subroutine slassq(n, x, incx, scale, sumsq)
SLASSQ updates a sum of squares represented in scaled form.
real(wp) function snrm2(n, x, incx)
SNRM2
subroutine sscal(n, sa, sx, incx)
SSCAL