|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745 |
- ! This is a test program for checking the implementations of
- ! the implementations of the following subroutines
- !
- ! ZGEDMD, for computation of the
- ! Dynamic Mode Decomposition (DMD)
- ! ZGEDMDQ, for computation of a
- ! QR factorization based compressed DMD
- !
- ! Developed and supported by:
- ! ===========================
- ! Developed and coded by Zlatko Drmac, Faculty of Science,
- ! University of Zagreb; drmac@math.hr
- ! In cooperation with
- ! AIMdyn Inc., Santa Barbara, CA.
- ! ========================================================
- ! How to run the code (compiler, link info)
- ! ========================================================
- ! Compile as FORTRAN 90 (or later) and link with BLAS and
- ! LAPACK libraries.
- ! NOTE: The code is developed and tested on top of the
- ! Intel MKL library (versions 2022.0.3 and 2022.2.0),
- ! using the Intel Fortran compiler.
- !
- ! For developers of the C++ implementation
- ! ========================================================
- ! See the LAPACK++ and Template Numerical Toolkit (TNT)
- !
- ! Note on a development of the GPU HP implementation
- ! ========================================================
- ! Work in progress. See CUDA, MAGMA, SLATE.
- ! NOTE: The four SVD subroutines used in this code are
- ! included as a part of R&D and for the completeness.
- ! This was also an opportunity to test those SVD codes.
- ! If the scaling option is used all four are essentially
- ! equally good. For implementations on HP platforms,
- ! one can use whichever SVD is available.
- !............................................................
-
- !............................................................
- !............................................................
- !
- PROGRAM DMD_TEST
- use iso_fortran_env, only: real64
- IMPLICIT NONE
- integer, parameter :: WP = real64
-
- !............................................................
- REAL(KIND=WP), PARAMETER :: ONE = 1.0_WP
- REAL(KIND=WP), PARAMETER :: ZERO = 0.0_WP
-
- COMPLEX(KIND=WP), PARAMETER :: ZONE = ( 1.0_WP, 0.0_WP )
- COMPLEX(KIND=WP), PARAMETER :: ZZERO = ( 0.0_WP, 0.0_WP )
- !............................................................
- REAL(KIND=WP), ALLOCATABLE, DIMENSION(:) :: RES, &
- RES1, RESEX, SINGVX, SINGVQX, WORK
- INTEGER , ALLOCATABLE, DIMENSION(:) :: IWORK
- REAL(KIND=WP) :: WDUMMY(2)
- INTEGER :: IDUMMY(4), ISEED(4)
- REAL(KIND=WP) :: ANORM, COND, CONDL, CONDR, EPS, &
- TOL, TOL2, SVDIFF, TMP, TMP_AU, &
- TMP_FQR, TMP_REZ, TMP_REZQ, TMP_ZXW, &
- TMP_EX
-
- !............................................................
- COMPLEX(KIND=WP) :: ZMAX
- INTEGER :: LZWORK
- COMPLEX(KIND=WP), ALLOCATABLE, DIMENSION(:,:) :: ZA, ZAC, &
- ZAU, ZF, ZF0, ZF1, ZS, ZW, &
- ZX, ZX0, ZY, ZY0, ZY1, ZZ, ZZ1
- COMPLEX(KIND=WP), ALLOCATABLE, DIMENSION(:) :: ZDA, ZDR, &
- ZDL, ZEIGS, ZEIGSA, ZWORK
- COMPLEX(KIND=WP) :: ZDUMMY(22), ZDUM2X2(2,2)
- !............................................................
- INTEGER :: K, KQ, LDF, LDS, LDA, LDAU, LDW, LDX, LDY, &
- LDZ, LIWORK, LWORK, M, N, LLOOP, NRNK, NRNKsp
- INTEGER :: i, iJOBREF, iJOBZ, iSCALE, INFO, j, &
- NFAIL, NFAIL_AU, NFAIL_F_QR, NFAIL_REZ, &
- NFAIL_REZQ, NFAIL_SVDIFF, NFAIL_TOTAL, NFAILQ_TOTAL, &
- NFAIL_Z_XV, MODE, MODEL, MODER, WHTSVD, &
- WHTSVDsp
- INTEGER :: iNRNK, iWHTSVD, K_TRAJ, LWMINOPT
- CHARACTER :: GRADE, JOBREF, JOBZ, PIVTNG, RSIGN, &
- SCALE, RESIDS, WANTQ, WANTR
- LOGICAL :: TEST_QRDMD
-
- !.....external subroutines (BLAS and LAPACK)
- EXTERNAL DAXPY, DGEEV, DGEMM, DGEMV, DLACPY, DLASCL
- EXTERNAL ZGEEV, ZGEMV, ZLASCL
- EXTERNAL ZLARNV, ZLATMR
- EXTERNAL ZAXPY, ZGEMM
- !.....external subroutines DMD package, part 1
- ! subroutines under test
- EXTERNAL ZGEDMD, ZGEDMDQ
- !.....external functions (BLAS and LAPACK)
- EXTERNAL DLAMCH, DZNRM2
- REAL(KIND=WP) :: DLAMCH, DZNRM2
- REAL(KIND=WP) :: ZLANGE
- EXTERNAL IZAMAX
- INTEGER IZAMAX
- EXTERNAL LSAME
- LOGICAL LSAME
-
- INTRINSIC ABS, INT, MIN, MAX, SIGN
- !............................................................
-
- ! The test is always in pairs : ( ZGEDMD and ZGEDMDQ )
- ! because the test includes comparing the results (in pairs).
- !.....................................................................................
- TEST_QRDMD = .TRUE. ! This code by default performs tests on ZGEDMDQ
- ! Since the QR factorizations based algorithm is designed for
- ! single trajectory data, only single trajectory tests will
- ! be performed with xGEDMDQ.
- WANTQ = 'Q'
- WANTR = 'R'
- !.................................................................................
-
- EPS = DLAMCH( 'P' ) ! machine precision DP
-
- ! Global counters of failures of some particular tests
- NFAIL = 0
- NFAIL_REZ = 0
- NFAIL_REZQ = 0
- NFAIL_Z_XV = 0
- NFAIL_F_QR = 0
- NFAIL_AU = 0
- NFAIL_SVDIFF = 0
- NFAIL_TOTAL = 0
- NFAILQ_TOTAL = 0
-
- DO LLOOP = 1, 4
-
- WRITE(*,*) 'L Loop Index = ', LLOOP
-
- ! Set the dimensions of the problem ...
- WRITE(*,*) 'M = '
- READ(*,*) M
- WRITE(*,*) M
- ! ... and the number of snapshots.
- WRITE(*,*) 'N = '
- READ(*,*) N
- WRITE(*,*) N
-
- ! ... Test the dimensions
- IF ( ( MIN(M,N) == 0 ) .OR. ( M < N ) ) THEN
- WRITE(*,*) 'Bad dimensions. Required: M >= N > 0.'
- STOP
- END IF
- !.............
- ! The seed inside the LLOOP so that each pass can be reproduced easily.
- ISEED(1) = 4
- ISEED(2) = 3
- ISEED(3) = 2
- ISEED(4) = 1
-
- LDA = M
- LDF = M
- LDX = M
- LDY = M
- LDW = N
- LDZ = M
- LDAU = M
- LDS = N
-
- TMP_ZXW = ZERO
- TMP_AU = ZERO
- TMP_REZ = ZERO
- TMP_REZQ = ZERO
- SVDIFF = ZERO
- TMP_EX = ZERO
-
- ALLOCATE( ZA(LDA,M) )
- ALLOCATE( ZAC(LDA,M) )
- ALLOCATE( ZF(LDF,N+1) )
- ALLOCATE( ZF0(LDF,N+1) )
- ALLOCATE( ZF1(LDF,N+1) )
- ALLOCATE( ZX(LDX,N) )
- ALLOCATE( ZX0(LDX,N) )
- ALLOCATE( ZY(LDY,N+1) )
- ALLOCATE( ZY0(LDY,N+1) )
- ALLOCATE( ZY1(LDY,N+1) )
- ALLOCATE( ZAU(LDAU,N) )
- ALLOCATE( ZW(LDW,N) )
- ALLOCATE( ZS(LDS,N) )
- ALLOCATE( ZZ(LDZ,N) )
- ALLOCATE( ZZ1(LDZ,N) )
- ALLOCATE( RES(N) )
- ALLOCATE( RES1(N) )
- ALLOCATE( RESEX(N) )
- ALLOCATE( ZEIGS(N) )
- ALLOCATE( SINGVX(N) )
- ALLOCATE( SINGVQX(N) )
-
- TOL = M*EPS
- ! This mimics O(M*N)*EPS bound for accumulated roundoff error.
- ! The factor 10 is somewhat arbitrary.
- TOL2 = 10*M*N*EPS
-
- !.............
-
- DO K_TRAJ = 1, 2
- ! Number of intial conditions in the simulation/trajectories (1 or 2)
-
- COND = 1.0D4
- ZMAX = (1.0D1,1.0D1)
- RSIGN = 'F'
- GRADE = 'N'
- MODEL = 6
- CONDL = 1.0D1
- MODER = 6
- CONDR = 1.0D1
- PIVTNG = 'N'
-
- ! Loop over all parameter MODE values for ZLATMR (+1,..,+6)
- DO MODE = 1, 6
-
- ALLOCATE( IWORK(2*M) )
- ALLOCATE( ZDA(M) )
- ALLOCATE( ZDL(M) )
- ALLOCATE( ZDR(M) )
-
- CALL ZLATMR( M, M, 'N', ISEED, 'N', ZDA, MODE, COND, &
- ZMAX, RSIGN, GRADE, ZDL, MODEL, CONDL, &
- ZDR, MODER, CONDR, PIVTNG, IWORK, M, M, &
- ZERO, -ONE, 'N', ZA, LDA, IWORK(M+1), INFO )
- DEALLOCATE( ZDR )
- DEALLOCATE( ZDL )
- DEALLOCATE( ZDA )
- DEALLOCATE( IWORK )
-
- LZWORK = MAX(1,2*M)
- ALLOCATE( ZEIGSA(M) )
- ALLOCATE( ZWORK(LZWORK) )
- ALLOCATE( WORK(2*M) )
- ZAC(1:M,1:M) = ZA(1:M,1:M)
- CALL ZGEEV( 'N','N', M, ZAC, LDA, ZEIGSA, ZDUM2X2, 2, &
- ZDUM2X2, 2, ZWORK, LZWORK, WORK, INFO ) ! LAPACK CALL
- DEALLOCATE(WORK)
- DEALLOCATE(ZWORK)
-
- TMP = ABS(ZEIGSA(IZAMAX(M, ZEIGSA, 1))) ! The spectral radius of ZA
- ! Scale the matrix ZA to have unit spectral radius.
- CALL ZLASCL( 'G',0, 0, TMP, ONE, M, M, &
- ZA, LDA, INFO )
- CALL ZLASCL( 'G',0, 0, TMP, ONE, M, 1, &
- ZEIGSA, M, INFO )
- ANORM = ZLANGE( 'F', M, M, ZA, LDA, WDUMMY )
-
- IF ( K_TRAJ == 2 ) THEN
- ! generate data as two trajectories
- ! with two inital conditions
- CALL ZLARNV(2, ISEED, M, ZF(1,1) )
- DO i = 1, N/2
- CALL ZGEMV( 'N', M, M, ZONE, ZA, LDA, ZF(1,i), 1, &
- ZZERO, ZF(1,i+1), 1 )
- END DO
- ZX0(1:M,1:N/2) = ZF(1:M,1:N/2)
- ZY0(1:M,1:N/2) = ZF(1:M,2:N/2+1)
-
- CALL ZLARNV(2, ISEED, M, ZF(1,1) )
- DO i = 1, N-N/2
- CALL ZGEMV( 'N', M, M, ZONE, ZA, LDA, ZF(1,i), 1, &
- ZZERO, ZF(1,i+1), 1 )
- END DO
- ZX0(1:M,N/2+1:N) = ZF(1:M,1:N-N/2)
- ZY0(1:M,N/2+1:N) = ZF(1:M,2:N-N/2+1)
- ELSE
- CALL ZLARNV(2, ISEED, M, ZF(1,1) )
- DO i = 1, N
- CALL ZGEMV( 'N', M, M, ZONE, ZA, M, ZF(1,i), 1, &
- ZZERO, ZF(1,i+1), 1 )
- END DO
- ZF0(1:M,1:N+1) = ZF(1:M,1:N+1)
- ZX0(1:M,1:N) = ZF0(1:M,1:N)
- ZY0(1:M,1:N) = ZF0(1:M,2:N+1)
- END IF
-
- DEALLOCATE( ZEIGSA )
- !........................................................................
-
- DO iJOBZ = 1, 4
-
- SELECT CASE ( iJOBZ )
- CASE(1)
- JOBZ = 'V'
- RESIDS = 'R'
- CASE(2)
- JOBZ = 'V'
- RESIDS = 'N'
- CASE(3)
- JOBZ = 'F'
- RESIDS = 'N'
- CASE(4)
- JOBZ = 'N'
- RESIDS = 'N'
- END SELECT
-
- DO iJOBREF = 1, 3
-
- SELECT CASE ( iJOBREF )
- CASE(1)
- JOBREF = 'R'
- CASE(2)
- JOBREF = 'E'
- CASE(3)
- JOBREF = 'N'
- END SELECT
-
- DO iSCALE = 1, 4
-
- SELECT CASE ( iSCALE )
- CASE(1)
- SCALE = 'S'
- CASE(2)
- SCALE = 'C'
- CASE(3)
- SCALE = 'Y'
- CASE(4)
- SCALE = 'N'
- END SELECT
-
- DO iNRNK = -1, -2, -1
- NRNK = iNRNK
- NRNKsp = iNRNK
-
- DO iWHTSVD = 1, 3
- ! Check all four options to compute the POD basis
- ! via the SVD.
- WHTSVD = iWHTSVD
- WHTSVDsp = iWHTSVD
-
- DO LWMINOPT = 1, 2
- ! Workspace query for the minimal (1) and for the optimal
- ! (2) workspace lengths determined by workspace query.
-
- ! ZGEDMD is always tested and its results are also used for
- ! comparisons with ZGEDMDQ.
-
- ZX(1:M,1:N) = ZX0(1:M,1:N)
- ZY(1:M,1:N) = ZY0(1:M,1:N)
-
- CALL ZGEDMD( SCALE, JOBZ, RESIDS, JOBREF, WHTSVD, &
- M, N, ZX, LDX, ZY, LDY, NRNK, TOL, &
- K, ZEIGS, ZZ, LDZ, RES, ZAU, LDAU, &
- ZW, LDW, ZS, LDS, ZDUMMY, -1, &
- WDUMMY, -1, IDUMMY, -1, INFO )
- IF ( (INFO .EQ. 2) .OR. ( INFO .EQ. 3 ) &
- .OR. ( INFO < 0 ) ) THEN
- WRITE(*,*) 'Call to ZGEDMD workspace query failed. &
- &Check the calling sequence and the code.'
- WRITE(*,*) 'The error code is ', INFO
- WRITE(*,*) 'The input parameters were ', &
- SCALE, JOBZ, RESIDS, JOBREF, WHTSVD, &
- M, N, LDX, LDY, NRNK, TOL, LDZ, LDAU, LDW, LDS
- STOP
- END IF
-
- LZWORK = INT(ZDUMMY(LWMINOPT))
- LWORK = INT(WDUMMY(1))
- LIWORK = IDUMMY(1)
-
- ALLOCATE(ZWORK(LZWORK))
- ALLOCATE( WORK(LWORK))
- ALLOCATE(IWORK(LIWORK))
-
- CALL ZGEDMD( SCALE, JOBZ, RESIDS, JOBREF, WHTSVD, &
- M, N, ZX, LDX, ZY, LDY, NRNK, TOL, &
- K, ZEIGS, ZZ, LDZ, RES, ZAU, LDAU, &
- ZW, LDW, ZS, LDS, ZWORK, LZWORK, &
- WORK, LWORK, IWORK, LIWORK, INFO )
-
- IF ( INFO /= 0 ) THEN
- WRITE(*,*) 'Call to ZGEDMD failed. &
- &Check the calling sequence and the code.'
- WRITE(*,*) 'The error code is ', INFO
- WRITE(*,*) 'The input parameters were ',&
- SCALE, JOBZ, RESIDS, JOBREF, WHTSVD, &
- M, N, LDX, LDY, NRNK, TOL
- STOP
- END IF
-
- SINGVX(1:N) = WORK(1:N)
-
- !...... ZGEDMD check point
- IF ( LSAME(JOBZ,'V') ) THEN
- ! Check that Z = X*W, on return from ZGEDMD
- ! This checks that the returned eigenvectors in Z are
- ! the product of the SVD'POD basis returned in X
- ! and the eigenvectors of the rayleigh quotient
- ! returned in W
- CALL ZGEMM( 'N', 'N', M, K, K, ZONE, ZX, LDX, ZW, LDW, &
- ZZERO, ZZ1, LDZ )
- TMP = ZERO
- DO i = 1, K
- CALL ZAXPY( M, -ZONE, ZZ(1,i), 1, ZZ1(1,i), 1)
- TMP = MAX(TMP, DZNRM2( M, ZZ1(1,i), 1 ) )
- END DO
- TMP_ZXW = MAX(TMP_ZXW, TMP )
- IF ( TMP_ZXW <= 10*M*EPS ) THEN
- !WRITE(*,*) ' :) .... OK .........ZGEDMD PASSED.'
- ELSE
- NFAIL_Z_XV = NFAIL_Z_XV + 1
- WRITE(*,*) ':( .................ZGEDMD FAILED!', &
- 'Check the code for implementation errors.'
- WRITE(*,*) 'The input parameters were ',&
- SCALE, JOBZ, RESIDS, JOBREF, WHTSVD, &
- M, N, LDX, LDY, NRNK, TOL
- END IF
- END IF
-
-
- !...... ZGEDMD check point
- IF ( LSAME(JOBREF,'R') ) THEN
- ! The matrix A*U is returned for computing refined Ritz vectors.
- ! Check that A*U is computed correctly using the formula
- ! A*U = Y * V * inv(SIGMA). This depends on the
- ! accuracy in the computed singular values and vectors of X.
- ! See the paper for an error analysis.
- ! Note that the left singular vectors of the input matrix X
- ! are returned in the array X.
- CALL ZGEMM( 'N', 'N', M, K, M, ZONE, ZA, LDA, ZX, LDX, &
- ZZERO, ZZ1, LDZ )
- TMP = ZERO
- DO i = 1, K
- CALL ZAXPY( M, -ZONE, ZAU(1,i), 1, ZZ1(1,i), 1)
- TMP = MAX( TMP, DZNRM2( M, ZZ1(1,i),1 ) * &
- SINGVX(K)/(ANORM*SINGVX(1)) )
- END DO
- TMP_AU = MAX( TMP_AU, TMP )
- IF ( TMP <= TOL2 ) THEN
- !WRITE(*,*) ':) .... OK .........ZGEDMD PASSED.'
- ELSE
- NFAIL_AU = NFAIL_AU + 1
- WRITE(*,*) ':( .................ZGEDMD FAILED!', &
- 'Check the code for implementation errors.'
- WRITE(*,*) 'The input parameters were ',&
- SCALE, JOBZ, RESIDS, JOBREF, WHTSVD, &
- M, N, LDX, LDY, NRNK, TOL
- END IF
- ELSEIF ( LSAME(JOBREF,'E') ) THEN
- ! The unscaled vectors of the Exact DMD are computed.
- ! This option is included for the sake of completeness,
- ! for users who prefer the Exact DMD vectors. The
- ! returned vectors are in the real form, in the same way
- ! as the Ritz vectors. Here we just save the vectors
- ! and test them separately using a Matlab script.
-
-
- CALL ZGEMM( 'N', 'N', M, K, M, ZONE, ZA, LDA, ZAU, LDAU, ZZERO, ZY1, LDY )
-
- DO i=1, K
- ! have a real eigenvalue with real eigenvector
- CALL ZAXPY( M, -ZEIGS(i), ZAU(1,i), 1, ZY1(1,i), 1 )
- RESEX(i) = DZNRM2( M, ZY1(1,i), 1) / DZNRM2(M,ZAU(1,i),1)
- END DO
- END IF
- !...... ZGEDMD check point
-
- IF ( LSAME(RESIDS, 'R') ) THEN
- ! Compare the residuals returned by ZGEDMD with the
- ! explicitly computed residuals using the matrix A.
- ! Compute explicitly Y1 = A*Z
- CALL ZGEMM( 'N', 'N', M, K, M, ZONE, ZA, LDA, ZZ, LDZ, ZZERO, ZY1, LDY )
- ! ... and then A*Z(:,i) - LAMBDA(i)*Z(:,i), using the real forms
- ! of the invariant subspaces that correspond to complex conjugate
- ! pairs of eigencalues. (See the description of Z in ZGEDMD,)
-
- DO i=1, K
- ! have a real eigenvalue with real eigenvector
- CALL ZAXPY( M, -ZEIGS(i), ZZ(1,i), 1, ZY1(1,i), 1 )
- RES1(i) = DZNRM2( M, ZY1(1,i), 1)
- END DO
- TMP = ZERO
- DO i = 1, K
- TMP = MAX( TMP, ABS(RES(i) - RES1(i)) * &
- SINGVX(K)/(ANORM*SINGVX(1)) )
- END DO
- TMP_REZ = MAX( TMP_REZ, TMP )
- IF ( TMP <= TOL2 ) THEN
- !WRITE(*,*) ':) .... OK ..........ZGEDMD PASSED.'
- ELSE
- NFAIL_REZ = NFAIL_REZ + 1
- WRITE(*,*) ':( ..................ZGEDMD FAILED!', &
- 'Check the code for implementation errors.'
- WRITE(*,*) 'The input parameters were ',&
- SCALE, JOBZ, RESIDS, JOBREF, WHTSVD, &
- M, N, LDX, LDY, NRNK, TOL
- END IF
-
-
- IF ( LSAME(JOBREF,'E') ) THEN
- TMP = ZERO
- DO i = 1, K
- TMP = MAX( TMP, ABS(RES1(i) - RESEX(i))/(RES1(i)+RESEX(i)) )
- END DO
- TMP_EX = MAX(TMP_EX,TMP)
- END IF
-
- END IF
-
- DEALLOCATE(ZWORK)
- DEALLOCATE(WORK)
- DEALLOCATE(IWORK)
-
- IF ( TEST_QRDMD .AND. (K_TRAJ == 1) ) THEN
-
- ZF(1:M,1:N+1) = ZF0(1:M,1:N+1)
-
- CALL ZGEDMDQ( SCALE, JOBZ, RESIDS, WANTQ, WANTR, JOBREF, &
- WHTSVD, M, N+1, ZF, LDF, ZX, LDX, ZY, LDY, &
- NRNK, TOL, K, ZEIGS, ZZ, LDZ, RES, ZAU, &
- LDAU, ZW, LDW, ZS, LDS, ZDUMMY, -1, &
- WDUMMY, -1, IDUMMY, -1, INFO )
-
- LZWORK = INT(ZDUMMY(LWMINOPT))
- ALLOCATE( ZWORK(LZWORK) )
- LIWORK = IDUMMY(1)
- ALLOCATE(IWORK(LIWORK))
- LWORK = INT(WDUMMY(1))
- ALLOCATE(WORK(LWORK))
-
- CALL ZGEDMDQ( SCALE, JOBZ, RESIDS, WANTQ, WANTR, JOBREF, &
- WHTSVD, M, N+1, ZF, LDF, ZX, LDX, ZY, LDY, &
- NRNK, TOL, KQ, ZEIGS, ZZ, LDZ, RES, ZAU, &
- LDAU, ZW, LDW, ZS, LDS, ZWORK, LZWORK, &
- WORK, LWORK, IWORK, LIWORK, INFO )
-
- IF ( INFO /= 0 ) THEN
- WRITE(*,*) 'Call to ZGEDMDQ failed. &
- &Check the calling sequence and the code.'
- WRITE(*,*) 'The error code is ', INFO
- WRITE(*,*) 'The input parameters were ',&
- SCALE, JOBZ, RESIDS, WANTQ, WANTR, WHTSVD, &
- M, N, LDX, LDY, NRNK, TOL
- STOP
- END IF
- SINGVQX(1:N) = WORK(1:N)
-
- !..... ZGEDMDQ check point
-
- IF ( 1 == 0 ) THEN
- ! Comparison of ZGEDMD and ZGEDMDQ singular values disabled
- TMP = ZERO
- DO i = 1, MIN(K, KQ)
- TMP = MAX(TMP, ABS(SINGVX(i)-SINGVQX(i)) / &
- SINGVX(1) )
- END DO
- SVDIFF = MAX( SVDIFF, TMP )
- IF ( TMP > M*N*EPS ) THEN
- WRITE(*,*) 'FAILED! Something was wrong with the run.'
- NFAIL_SVDIFF = NFAIL_SVDIFF + 1
- DO j =1, 3
- write(*,*) j, SINGVX(j), SINGVQX(j)
- read(*,*)
- END DO
-
- END IF
- END IF
-
- !..... ZGEDMDQ check point
- IF ( LSAME(WANTQ,'Q') .AND. LSAME(WANTR,'R') ) THEN
- ! Check that the QR factors are computed and returned
- ! as requested. The residual ||F-Q*R||_F / ||F||_F
- ! is compared to M*N*EPS.
- ZF1(1:M,1:N+1) = ZF0(1:M,1:N+1)
- CALL ZGEMM( 'N', 'N', M, N+1, MIN(M,N+1), -ZONE, ZF, &
- LDF, ZY, LDY, ZONE, ZF1, LDF )
- TMP_FQR = ZLANGE( 'F', M, N+1, ZF1, LDF, WORK ) / &
- ZLANGE( 'F', M, N+1, ZF0, LDF, WORK )
- IF ( TMP_FQR > TOL2 ) THEN
- WRITE(*,*) 'FAILED! Something was wrong with the run.'
- NFAIL_F_QR = NFAIL_F_QR + 1
- ELSE
- !WRITE(*,*) '........ PASSED.'
- END IF
- END IF
-
- !..... ZGEDMDQ check point
- IF ( LSAME(RESIDS, 'R') ) THEN
- ! Compare the residuals returned by ZGEDMDQ with the
- ! explicitly computed residuals using the matrix A.
- ! Compute explicitly Y1 = A*Z
- CALL ZGEMM( 'N', 'N', M, KQ, M, ZONE, ZA, LDA, ZZ, LDZ, ZZERO, ZY1, LDY )
- ! ... and then A*Z(:,i) - LAMBDA(i)*Z(:,i), using the real forms
- ! of the invariant subspaces that correspond to complex conjugate
- ! pairs of eigencalues. (See the description of Z in ZGEDMDQ)
-
- DO i=1, KQ
- ! have a real eigenvalue with real eigenvector
- CALL ZAXPY( M, -ZEIGS(i), ZZ(1,i), 1, ZY1(1,i), 1 )
- ! Y(1:M,i) = Y(1:M,i) - REIG(i)*Z(1:M,i)
- RES1(i) = DZNRM2( M, ZY1(1,i), 1)
- END DO
- TMP = ZERO
- DO i = 1, KQ
- TMP = MAX( TMP, ABS(RES(i) - RES1(i)) * &
- SINGVQX(KQ)/(ANORM*SINGVQX(1)) )
- END DO
- TMP_REZQ = MAX( TMP_REZQ, TMP )
- IF ( TMP <= TOL2 ) THEN
- !WRITE(*,*) '.... OK ........ ZGEDMDQ PASSED.'
- ELSE
- NFAIL_REZQ = NFAIL_REZQ + 1
- WRITE(*,*) '................ ZGEDMDQ FAILED!', &
- 'Check the code for implementation errors.'
- STOP
- END IF
-
- END IF
-
- DEALLOCATE( ZWORK )
- DEALLOCATE( WORK )
- DEALLOCATE( IWORK )
-
- END IF ! ZGEDMDQ
-
- !.......................................................................................................
-
- END DO ! LWMINOPT
- !write(*,*) 'LWMINOPT loop completed'
- END DO ! iWHTSVD
- !write(*,*) 'WHTSVD loop completed'
- END DO ! iNRNK -2:-1
- !write(*,*) 'NRNK loop completed'
- END DO ! iSCALE 1:4
- !write(*,*) 'SCALE loop completed'
- END DO
- !write(*,*) 'JOBREF loop completed'
- END DO ! iJOBZ
- !write(*,*) 'JOBZ loop completed'
-
- END DO ! MODE -6:6
- !write(*,*) 'MODE loop completed'
- END DO ! 1 or 2 trajectories
- !write(*,*) 'trajectories loop completed'
-
- DEALLOCATE( ZA )
- DEALLOCATE( ZAC )
- DEALLOCATE( ZZ )
- DEALLOCATE( ZF )
- DEALLOCATE( ZF0 )
- DEALLOCATE( ZF1 )
- DEALLOCATE( ZX )
- DEALLOCATE( ZX0 )
- DEALLOCATE( ZY )
- DEALLOCATE( ZY0 )
- DEALLOCATE( ZY1 )
- DEALLOCATE( ZAU )
- DEALLOCATE( ZW )
- DEALLOCATE( ZS )
- DEALLOCATE( ZZ1 )
- DEALLOCATE( RES )
- DEALLOCATE( RES1 )
- DEALLOCATE( RESEX )
- DEALLOCATE( ZEIGS )
- DEALLOCATE( SINGVX )
- DEALLOCATE( SINGVQX )
-
- END DO ! LLOOP
-
- WRITE(*,*) '>>>>>>>>>>>>>>>>>>>>>>>>>>'
- WRITE(*,*) ' Test summary for ZGEDMD :'
- WRITE(*,*) '>>>>>>>>>>>>>>>>>>>>>>>>>>'
- WRITE(*,*)
- IF ( NFAIL_Z_XV == 0 ) THEN
- WRITE(*,*) '>>>> Z - U*V test PASSED.'
- ELSE
- WRITE(*,*) 'Z - U*V test FAILED ', NFAIL_Z_XV, ' time(s)'
- WRITE(*,*) 'Max error ||Z-U*V||_F was ', TMP_ZXW
- NFAIL_TOTAL = NFAIL_TOTAL + NFAIL_Z_XV
- END IF
- IF ( NFAIL_AU == 0 ) THEN
- WRITE(*,*) '>>>> A*U test PASSED. '
- ELSE
- WRITE(*,*) 'A*U test FAILED ', NFAIL_AU, ' time(s)'
- WRITE(*,*) 'Max A*U test adjusted error measure was ', TMP_AU
- WRITE(*,*) 'It should be up to O(M*N) times EPS, EPS = ', EPS
- NFAIL_TOTAL = NFAIL_TOTAL + NFAIL_AU
- END IF
-
- IF ( NFAIL_REZ == 0 ) THEN
- WRITE(*,*) '>>>> Rezidual computation test PASSED.'
- ELSE
- WRITE(*,*) 'Rezidual computation test FAILED ', NFAIL_REZ, 'time(s)'
- WRITE(*,*) 'Max residual computing test adjusted error measure was ', TMP_REZ
- WRITE(*,*) 'It should be up to O(M*N) times EPS, EPS = ', EPS
- NFAIL_TOTAL = NFAIL_TOTAL + NFAIL_REZ
- END IF
-
- IF ( NFAIL_TOTAL == 0 ) THEN
- WRITE(*,*) '>>>> ZGEDMD :: ALL TESTS PASSED.'
- ELSE
- WRITE(*,*) NFAIL_TOTAL, 'FAILURES!'
- WRITE(*,*) '>>>>>>>>>>>>>> ZGEDMD :: TESTS FAILED. CHECK THE IMPLEMENTATION.'
- END IF
-
- IF ( TEST_QRDMD ) THEN
- WRITE(*,*)
- WRITE(*,*) '>>>>>>>>>>>>>>>>>>>>>>>>>>'
- WRITE(*,*) ' Test summary for ZGEDMDQ :'
- WRITE(*,*) '>>>>>>>>>>>>>>>>>>>>>>>>>>'
- WRITE(*,*)
-
- IF ( NFAIL_SVDIFF == 0 ) THEN
- WRITE(*,*) '>>>> ZGEDMD and ZGEDMDQ computed singular &
- &values test PASSED.'
- ELSE
- WRITE(*,*) 'ZGEDMD and ZGEDMDQ discrepancies in &
- &the singular values unacceptable ', &
- NFAIL_SVDIFF, ' times. Test FAILED.'
- WRITE(*,*) 'The maximal discrepancy in the singular values (relative to the norm) was ', SVDIFF
- WRITE(*,*) 'It should be up to O(M*N) times EPS, EPS = ', EPS
- NFAILQ_TOTAL = NFAILQ_TOTAL + NFAIL_SVDIFF
- END IF
-
- IF ( NFAIL_F_QR == 0 ) THEN
- WRITE(*,*) '>>>> F - Q*R test PASSED.'
- ELSE
- WRITE(*,*) 'F - Q*R test FAILED ', NFAIL_F_QR, ' time(s)'
- WRITE(*,*) 'The largest relative residual was ', TMP_FQR
- WRITE(*,*) 'It should be up to O(M*N) times EPS, EPS = ', EPS
- NFAILQ_TOTAL = NFAILQ_TOTAL + NFAIL_F_QR
- END IF
-
- IF ( NFAIL_REZQ == 0 ) THEN
- WRITE(*,*) '>>>> Rezidual computation test PASSED.'
- ELSE
- WRITE(*,*) 'Rezidual computation test FAILED ', NFAIL_REZQ, 'time(s)'
- WRITE(*,*) 'Max residual computing test adjusted error measure was ', TMP_REZQ
- WRITE(*,*) 'It should be up to O(M*N) times EPS, EPS = ', EPS
- NFAILQ_TOTAL = NFAILQ_TOTAL + NFAIL_REZQ
- END IF
-
- IF ( NFAILQ_TOTAL == 0 ) THEN
- WRITE(*,*) '>>>>>>> ZGEDMDQ :: ALL TESTS PASSED.'
- ELSE
- WRITE(*,*) NFAILQ_TOTAL, 'FAILURES!'
- WRITE(*,*) '>>>>>>> ZGEDMDQ :: TESTS FAILED. CHECK THE IMPLEMENTATION.'
- END IF
-
- END IF
-
- WRITE(*,*)
- WRITE(*,*) 'Test completed.'
- STOP
- END
|