LAPACK 3.12.0
LAPACK: Linear Algebra PACKage
Loading...
Searching...
No Matches
schkdmd.f90
Go to the documentation of this file.
1! This is a test program for checking the implementations of
2! the implementations of the following subroutines
3!
4! SGEDMD for computation of the
5! Dynamic Mode Decomposition (DMD)
6! SGEDMDQ for computation of a
7! QR factorization based compressed DMD
8!
9! Developed and supported by:
10! ===========================
11! Developed and coded by Zlatko Drmac, Faculty of Science,
12! University of Zagreb; drmac@math.hr
13! In cooperation with
14! AIMdyn Inc., Santa Barbara, CA.
15! ========================================================
16! How to run the code (compiler, link info)
17! ========================================================
18! Compile as FORTRAN 90 (or later) and link with BLAS and
19! LAPACK libraries.
20! NOTE: The code is developed and tested on top of the
21! Intel MKL library (versions 2022.0.3 and 2022.2.0),
22! using the Intel Fortran compiler.
23!
24! For developers of the C++ implementation
25! ========================================================
26! See the LAPACK++ and Template Numerical Toolkit (TNT)
27!
28! Note on a development of the GPU HP implementation
29! ========================================================
30! Work in progress. See CUDA, MAGMA, SLATE.
31! NOTE: The four SVD subroutines used in this code are
32! included as a part of R&D and for the completeness.
33! This was also an opportunity to test those SVD codes.
34! If the scaling option is used all four are essentially
35! equally good. For implementations on HP platforms,
36! one can use whichever SVD is available.
37!... .........................................................
38! NOTE:
39! When using the Intel MKL 2022.0.3 the subroutine xGESVDQ
40! (optionally used in xGEDMD) may cause access violation
41! error for x = S, D, C, Z, but only if called with the
42! work space query. (At least in our Windows 10 MSVS 2019.)
43! The problem can be mitigated by downloading the source
44! code of xGESVDQ from the LAPACK repository and use it
45! localy instead of the one in the MKL. This seems to
46! indicate that the problem is indeed in the MKL.
47! This problem did not appear whith Intel MKL 2022.2.0.
48!
49! NOTE:
50! xGESDD seems to have a problem with workspace. In some
51! cases the length of the optimal workspace is returned
52! smaller than the minimal workspace, as specified in the
53! code. As a precaution, all optimal workspaces are
54! set as MAX(minimal, optimal).
55! Latest implementations of complex xGESDD have different
56! length of the real worksapce. We use max value over
57! two versions.
58!............................................................
59!............................................................
60!
61 PROGRAM dmd_test
62 use iso_fortran_env, only: real32
63 IMPLICIT NONE
64 integer, parameter :: WP = real32
65
66!............................................................
67 REAL(KIND=wp), PARAMETER :: one = 1.0_wp
68 REAL(KIND=wp), PARAMETER :: zero = 0.0_wp
69!............................................................
70 REAL(KIND=wp), ALLOCATABLE, DIMENSION(:,:) :: &
71 a, ac, eiga, lambda, lambdaq, f, f1, f2,&
72 z, z1, s, au, w, va, x, x0, y, y0, y1
73 REAL(KIND=wp), ALLOCATABLE, DIMENSION(:) :: &
74 da, dl, dr, reig, reiga, reigq, ieig, &
75 ieiga, ieigq, res, res1, resex, singvx,&
76 singvqx, work
77 INTEGER , ALLOCATABLE, DIMENSION(:) :: IWORK
78 REAL(KIND=wp) :: ab(2,2), wdummy(2)
79 INTEGER :: IDUMMY(2), ISEED(4), RJOBDATA(8)
80 REAL(KIND=wp) :: anorm, cond, condl, condr, dmax, eps, &
81 tol, tol2, svdiff, tmp, tmp_au, &
82 tmp_fqr, tmp_rez, tmp_rezq, tmp_zxw, &
83 tmp_ex, xnorm, ynorm
84!............................................................
85 INTEGER :: K, KQ, LDF, LDS, LDA, LDAU, LDW, LDX, LDY, &
86 ldz, liwork, lwork, m, n, l, lloop, nrnk
87 INTEGER :: i, iJOBREF, iJOBZ, iSCALE, INFO, KDIFF, &
88 nfail, nfail_au, nfail_f_qr, nfail_rez, &
89 nfail_rezq, nfail_svdiff, nfail_total, nfailq_total, &
90 nfail_z_xv, mode, model, moder, whtsvd
91 INTEGER iNRNK, iWHTSVD, K_TRAJ, LWMINOPT
92 CHARACTER(LEN=1) GRADE, JOBREF, JOBZ, PIVTNG, RSIGN, &
93 scale, resids, wantq, wantr
94
95 LOGICAL TEST_QRDMD
96!..... external subroutines (BLAS and LAPACK)
97 EXTERNAL saxpy, sgeev, sgemm, sgemv, slacpy, slascl
98 EXTERNAL slarnv, slatmr
99!.....external subroutines DMD package, part 1
100! subroutines under test
101 EXTERNAL sgedmd, sgedmdq
102
103!..... external functions (BLAS and LAPACK)
104 EXTERNAL slamch, slange, snrm2
105 REAL(KIND=wp) :: slamch, slange, snrm2
106 EXTERNAL lsame
107 LOGICAL LSAME
108
109 INTRINSIC abs, int, min, max
110!............................................................
111
112 ! The test is always in pairs : ( SGEDMD and SGEDMDQ )
113 ! because the test includes comparing the results (in pairs).
114!.....................................................................................
115 test_qrdmd = .true. ! This code by default performs tests on SGEDMDQ
116 ! Since the QR factorizations based algorithm is designed for
117 ! single trajectory data, only single trajectory tests will
118 ! be performed with xGEDMDQ.
119 wantq = 'Q'
120 wantr = 'R'
121!.................................................................................
122
123 eps = slamch( 'P' ) ! machine precision SP
124
125 ! Global counters of failures of some particular tests
126 nfail = 0
127 nfail_rez = 0
128 nfail_rezq = 0
129 nfail_z_xv = 0
130 nfail_f_qr = 0
131 nfail_au = 0
132 kdiff = 0
133 nfail_svdiff = 0
134 nfail_total = 0
135 nfailq_total = 0
136
137
138 DO lloop = 1, 4
139
140 WRITE(*,*) 'L Loop Index = ', lloop
141
142 ! Set the dimensions of the problem ...
143 WRITE(*,*) 'M = '
144 READ(*,*) m
145 WRITE(*,*) m
146 ! ... and the number of snapshots.
147 WRITE(*,*) 'N = '
148 READ(*,*) n
149 WRITE(*,*) n
150
151 ! ... Test the dimensions
152 IF ( ( min(m,n) == 0 ) .OR. ( m < n ) ) THEN
153 WRITE(*,*) 'Bad dimensions. Required: M >= N > 0.'
154 stop
155 END IF
156!.............
157 ! The seed inside the LLOOP so that each pass can be reproduced easily.
158
159 iseed(1) = 4
160 iseed(2) = 3
161 iseed(3) = 2
162 iseed(4) = 1
163
164 lda = m
165 ldf = m
166 ldx = max(m,n+1)
167 ldy = max(m,n+1)
168 ldw = n
169 ldz = m
170 ldau = max(m,n+1)
171 lds = n
172
173 tmp_zxw = zero
174 tmp_au = zero
175 tmp_rez = zero
176 tmp_rezq = zero
177 svdiff = zero
178 tmp_ex = zero
179
180 !
181 ! Test the subroutines on real data snapshots. All
182 ! computation is done in real arithmetic, even when
183 ! Koopman eigenvalues and modes are real.
184 !
185 ! Allocate memory space
186 ALLOCATE( a(lda,m) )
187 ALLOCATE( ac(lda,m) )
188 ALLOCATE( da(m) )
189 ALLOCATE( dl(m) )
190 ALLOCATE( f(ldf,n+1) )
191 ALLOCATE( f1(ldf,n+1) )
192 ALLOCATE( f2(ldf,n+1) )
193 ALLOCATE( x(ldx,n) )
194 ALLOCATE( x0(ldx,n) )
195 ALLOCATE( singvx(n) )
196 ALLOCATE( singvqx(n) )
197 ALLOCATE( y(ldy,n+1) )
198 ALLOCATE( y0(ldy,n+1) )
199 ALLOCATE( y1(m,n+1) )
200 ALLOCATE( z(ldz,n) )
201 ALLOCATE( z1(ldz,n) )
202 ALLOCATE( res(n) )
203 ALLOCATE( res1(n) )
204 ALLOCATE( resex(n) )
205 ALLOCATE( reig(n) )
206 ALLOCATE( ieig(n) )
207 ALLOCATE( reigq(n) )
208 ALLOCATE( ieigq(n) )
209 ALLOCATE( reiga(m) )
210 ALLOCATE( ieiga(m) )
211 ALLOCATE( va(lda,m) )
212 ALLOCATE( lambda(n,2) )
213 ALLOCATE( lambdaq(n,2) )
214 ALLOCATE( eiga(m,2) )
215 ALLOCATE( w(ldw,n) )
216 ALLOCATE( au(ldau,n) )
217 ALLOCATE( s(n,n) )
218
219 tol = m*eps
220 ! This mimics O(M*N)*EPS bound for accumulated roundoff error.
221 ! The factor 10 is somewhat arbitrary.
222 tol2 = 10*m*n*eps
223
224!.............
225
226 DO k_traj = 1, 2
227 ! Number of intial conditions in the simulation/trajectories (1 or 2)
228
229 cond = 1.0d8
230 dmax = 1.0d2
231 rsign = 'F'
232 grade = 'N'
233 model = 6
234 condl = 1.0d2
235 moder = 6
236 condr = 1.0d2
237 pivtng = 'N'
238
239 ! Loop over all parameter MODE values for ZLATMR (+1,..,+6)
240 DO mode = 1, 6
241
242 ALLOCATE( iwork(2*m) )
243 ALLOCATE(dr(n))
244 CALL slatmr( m, m, 'S', iseed, 'N', da, mode, cond, &
245 dmax, rsign, grade, dl, model, condl, &
246 dr, moder, condr, pivtng, iwork, m, m, &
247 zero, -one, 'N', a, lda, iwork(m+1), info )
248 DEALLOCATE(iwork)
249 DEALLOCATE(dr)
250
251 lwork = 4*m+1
252 ALLOCATE(work(lwork))
253 ac = a
254 CALL sgeev( 'N','V', m, ac, m, reiga, ieiga, va, m, &
255 va, m, work, lwork, info ) ! LAPACK CALL
256 DEALLOCATE(work)
257 tmp = zero
258 DO i = 1, m
259 eiga(i,1) = reiga(i)
260 eiga(i,2) = ieiga(i)
261 tmp = max( tmp, sqrt(reiga(i)**2+ieiga(i)**2))
262 END DO
263
264 ! Scale A to have the desirable spectral radius.
265 CALL slascl( 'G', 0, 0, tmp, one, m, m, a, m, info )
266 CALL slascl( 'G', 0, 0, tmp, one, m, 2, eiga, m, info )
267
268 ! Compute the norm of A
269 anorm = slange( 'F', n, n, a, m, wdummy )
270
271 IF ( k_traj == 2 ) THEN
272 ! generate data with two inital conditions
273 CALL slarnv(2, iseed, m, f1(1,1) )
274 f1(1:m,1) = 1.0e-10*f1(1:m,1)
275 DO i = 1, n/2
276 CALL sgemv( 'N', m, m, one, a, m, f1(1,i), 1, zero, &
277 f1(1,i+1), 1 )
278 END DO
279 x0(1:m,1:n/2) = f1(1:m,1:n/2)
280 y0(1:m,1:n/2) = f1(1:m,2:n/2+1)
281
282 CALL slarnv(2, iseed, m, f1(1,1) )
283 DO i = 1, n-n/2
284 CALL sgemv( 'N', m, m, one, a, m, f1(1,i), 1, zero, &
285 f1(1,i+1), 1 )
286 END DO
287 x0(1:m,n/2+1:n) = f1(1:m,1:n-n/2)
288 y0(1:m,n/2+1:n) = f1(1:m,2:n-n/2+1)
289 ELSE
290 ! single trajectory
291 CALL slarnv(2, iseed, m, f(1,1) )
292 DO i = 1, n
293 CALL sgemv( 'N', m, m, one, a, m, f(1,i), 1, zero, &
294 f(1,i+1), 1 )
295 END DO
296 x0(1:m,1:n) = f(1:m,1:n)
297 y0(1:m,1:n) = f(1:m,2:n+1)
298 END IF
299
300 xnorm = slange( 'F', m, n, x0, ldx, wdummy )
301 ynorm = slange( 'F', m, n, y0, ldx, wdummy )
302!............................................................
303
304 DO ijobz = 1, 4
305
306 SELECT CASE ( ijobz )
307 CASE(1)
308 jobz = 'V' ! Ritz vectors will be computed
309 resids = 'R' ! Residuals will be computed
310 CASE(2)
311 jobz = 'V'
312 resids = 'N'
313 CASE(3)
314 jobz = 'F' ! Ritz vectors in factored form
315 resids = 'N'
316 CASE(4)
317 jobz = 'N'
318 resids = 'N'
319 END SELECT
320
321 DO ijobref = 1, 3
322
323 SELECT CASE ( ijobref )
324 CASE(1)
325 jobref = 'R' ! Data for refined Ritz vectors
326 CASE(2)
327 jobref = 'E' ! Exact DMD vectors
328 CASE(3)
329 jobref = 'N'
330 END SELECT
331
332 DO iscale = 1, 4
333
334 SELECT CASE ( iscale )
335 CASE(1)
336 scale = 'S' ! X data normalized
337 CASE(2)
338 scale = 'C' ! X normalized, consist. check
339 CASE(3)
340 scale = 'Y' ! Y data normalized
341 CASE(4)
342 scale = 'N'
343 END SELECT
344
345 DO inrnk = -1, -2, -1
346 ! Two truncation strategies. The "-2" case for R&D
347 ! purposes only - it uses possibly low accuracy small
348 ! singular values, in which case the formulas used in
349 ! the DMD are highly sensitive.
350 nrnk = inrnk
351
352 DO iwhtsvd = 1, 4
353 ! Check all four options to compute the POD basis
354 ! via the SVD.
355 whtsvd = iwhtsvd
356
357 DO lwminopt = 1, 2
358 ! Workspace query for the minimal (1) and for the optimal
359 ! (2) workspace lengths determined by workspace query.
360
361 x(1:m,1:n) = x0(1:m,1:n)
362 y(1:m,1:n) = y0(1:m,1:n)
363
364 ! SGEDMD: Workspace query and workspace allocation
365 CALL sgedmd( scale, jobz, resids, jobref, whtsvd, m, &
366 n, x, ldx, y, ldy, nrnk, tol, k, reig, ieig, z, &
367 ldz, res, au, ldau, w, ldw, s, lds, wdummy, -1, &
368 idummy, -1, info )
369
370 liwork = idummy(1)
371 ALLOCATE( iwork(liwork) )
372 lwork = int(wdummy(lwminopt))
373 ALLOCATE( work(lwork) )
374
375 ! SGEDMD test: CALL SGEDMD
376 CALL sgedmd( scale, jobz, resids, jobref, whtsvd, m, &
377 n, x, ldx, y, ldy, nrnk, tol, k, reig, ieig, z, &
378 ldz, res, au, ldau, w, ldw, s, lds, work, lwork,&
379 iwork, liwork, info )
380
381 singvx(1:n) = work(1:n)
382
383 !...... SGEDMD check point
384 IF ( lsame(jobz,'V') ) THEN
385 ! Check that Z = X*W, on return from SGEDMD
386 ! This checks that the returned aigenvectors in Z are
387 ! the product of the SVD'POD basis returned in X
388 ! and the eigenvectors of the rayleigh quotient
389 ! returned in W
390 CALL sgemm( 'N', 'N', m, k, k, one, x, ldx, w, ldw, &
391 zero, z1, ldz )
392 tmp = zero
393 DO i = 1, k
394 CALL saxpy( m, -one, z(1,i), 1, z1(1,i), 1)
395 tmp = max(tmp, snrm2( m, z1(1,i), 1 ) )
396 END DO
397 tmp_zxw = max(tmp_zxw, tmp )
398
399 IF ( tmp_zxw > 10*m*eps ) THEN
400 nfail_z_xv = nfail_z_xv + 1
401 END IF
402
403 END IF
404
405 !...... SGEDMD check point
406 IF ( lsame(jobref,'R') ) THEN
407 ! The matrix A*U is returned for computing refined Ritz vectors.
408 ! Check that A*U is computed correctly using the formula
409 ! A*U = Y * V * inv(SIGMA). This depends on the
410 ! accuracy in the computed singular values and vectors of X.
411 ! See the paper for an error analysis.
412 ! Note that the left singular vectors of the input matrix X
413 ! are returned in the array X.
414 CALL sgemm( 'N', 'N', m, k, m, one, a, lda, x, ldx, &
415 zero, z1, ldz )
416 tmp = zero
417 DO i = 1, k
418 CALL saxpy( m, -one, au(1,i), 1, z1(1,i), 1)
419 tmp = max( tmp, snrm2( m, z1(1,i),1 ) * &
420 singvx(k)/(anorm*singvx(1)) )
421 END DO
422 tmp_au = max( tmp_au, tmp )
423
424 IF ( tmp > tol2 ) THEN
425 nfail_au = nfail_au + 1
426 END IF
427
428 ELSEIF ( lsame(jobref,'E') ) THEN
429 ! The unscaled vectors of the Exact DMD are computed.
430 ! This option is included for the sake of completeness,
431 ! for users who prefer the Exact DMD vectors. The
432 ! returned vectors are in the real form, in the same way
433 ! as the Ritz vectors. Here we just save the vectors
434 ! and test them separately using a Matlab script.
435
436 CALL sgemm( 'N', 'N', m, k, m, one, a, lda, au, ldau, zero, y1, m )
437 i=1
438 DO WHILE ( i <= k )
439 IF ( ieig(i) == zero ) THEN
440 ! have a real eigenvalue with real eigenvector
441 CALL saxpy( m, -reig(i), au(1,i), 1, y1(1,i), 1 )
442 resex(i) = snrm2( m, y1(1,i), 1) / snrm2(m,au(1,i),1)
443 i = i + 1
444 ELSE
445 ! Have a complex conjugate pair
446 ! REIG(i) +- sqrt(-1)*IMEIG(i).
447 ! Since all computation is done in real
448 ! arithmetic, the formula for the residual
449 ! is recast for real representation of the
450 ! complex conjugate eigenpair. See the
451 ! description of RES.
452 ab(1,1) = reig(i)
453 ab(2,1) = -ieig(i)
454 ab(1,2) = ieig(i)
455 ab(2,2) = reig(i)
456 CALL sgemm( 'N', 'N', m, 2, 2, -one, au(1,i), &
457 m, ab, 2, one, y1(1,i), m )
458 resex(i) = slange( 'F', m, 2, y1(1,i), m, &
459 work )/ slange( 'F', m, 2, au(1,i), m, &
460 work )
461 resex(i+1) = resex(i)
462 i = i + 2
463 END IF
464 END DO
465
466 END IF
467
468 !...... SGEDMD check point
469 IF ( lsame(resids, 'R') ) THEN
470 ! Compare the residuals returned by SGEDMD with the
471 ! explicitly computed residuals using the matrix A.
472 ! Compute explicitly Y1 = A*Z
473 CALL sgemm( 'N', 'N', m, k, m, one, a, lda, z, ldz, zero, y1, m )
474 ! ... and then A*Z(:,i) - LAMBDA(i)*Z(:,i), using the real forms
475 ! of the invariant subspaces that correspond to complex conjugate
476 ! pairs of eigencalues. (See the description of Z in SGEDMD,)
477 i = 1
478 DO WHILE ( i <= k )
479 IF ( ieig(i) == zero ) THEN
480 ! have a real eigenvalue with real eigenvector
481 CALL saxpy( m, -reig(i), z(1,i), 1, y1(1,i), 1 )
482 res1(i) = snrm2( m, y1(1,i), 1)
483 i = i + 1
484 ELSE
485 ! Have a complex conjugate pair
486 ! REIG(i) +- sqrt(-1)*IMEIG(i).
487 ! Since all computation is done in real
488 ! arithmetic, the formula for the residual
489 ! is recast for real representation of the
490 ! complex conjugate eigenpair. See the
491 ! description of RES.
492 ab(1,1) = reig(i)
493 ab(2,1) = -ieig(i)
494 ab(1,2) = ieig(i)
495 ab(2,2) = reig(i)
496 CALL sgemm( 'N', 'N', m, 2, 2, -one, z(1,i), &
497 m, ab, 2, one, y1(1,i), m )
498 res1(i) = slange( 'F', m, 2, y1(1,i), m, &
499 work )
500 res1(i+1) = res1(i)
501 i = i + 2
502 END IF
503 END DO
504 tmp = zero
505 DO i = 1, k
506 tmp = max( tmp, abs(res(i) - res1(i)) * &
507 singvx(k)/(anorm*singvx(1)) )
508 END DO
509 tmp_rez = max( tmp_rez, tmp )
510
511 IF ( tmp > tol2 ) THEN
512 nfail_rez = nfail_rez + 1
513 END IF
514
515 IF ( lsame(jobref,'E') ) THEN
516 tmp = zero
517 DO i = 1, k
518 tmp = max( tmp, abs(res1(i) - resex(i))/(res1(i)+resex(i)) )
519 END DO
520 tmp_ex = max(tmp_ex,tmp)
521 END IF
522
523 END IF
524
525 ! ... store the results for inspection
526 DO i = 1, k
527 lambda(i,1) = reig(i)
528 lambda(i,2) = ieig(i)
529 END DO
530
531 DEALLOCATE(iwork)
532 DEALLOCATE(work)
533
534 !======================================================================
535 ! Now test the SGEDMDQ, if requested.
536 !======================================================================
537 IF ( test_qrdmd .AND. (k_traj == 1) ) THEN
538 rjobdata(2) = 1
539 f1 = f
540
541 ! SGEDMDQ test: Workspace query and workspace allocation
542 CALL sgedmdq( scale, jobz, resids, wantq, wantr, &
543 jobref, whtsvd, m, n+1, f1, ldf, x, ldx, y, &
544 ldy, nrnk, tol, kq, reigq, ieigq, z, ldz, &
545 res, au, ldau, w, ldw, s, lds, wdummy, &
546 -1, idummy, -1, info )
547 liwork = idummy(1)
548 ALLOCATE( iwork(liwork) )
549 lwork = int(wdummy(lwminopt))
550 ALLOCATE(work(lwork))
551
552 ! SGEDMDQ test: CALL SGEDMDQ
553 CALL sgedmdq( scale, jobz, resids, wantq, wantr, &
554 jobref, whtsvd, m, n+1, f1, ldf, x, ldx, y, &
555 ldy, nrnk, tol, kq, reigq, ieigq, z, ldz, &
556 res, au, ldau, w, ldw, s, lds, &
557 work, lwork, iwork, liwork, info )
558
559 singvqx(1:kq) = work(min(m,n+1)+1: min(m,n+1)+kq)
560
561 !..... SGEDMDQ check point
562 IF ( kq /= k ) THEN
563 kdiff = kdiff+1
564 END IF
565
566 tmp = zero
567 DO i = 1, min(k, kq)
568 tmp = max(tmp, abs(singvx(i)-singvqx(i)) / &
569 singvx(1) )
570 END DO
571 svdiff = max( svdiff, tmp )
572 IF ( tmp > m*n*eps ) THEN
573 nfail_svdiff = nfail_svdiff + 1
574 END IF
575
576 !..... SGEDMDQ check point
577 IF ( lsame(wantq,'Q') .AND. lsame(wantr,'R') ) THEN
578 ! Check that the QR factors are computed and returned
579 ! as requested. The residual ||F-Q*R||_F / ||F||_F
580 ! is compared to M*N*EPS.
581 f2 = f
582 CALL sgemm( 'N', 'N', m, n+1, min(m,n+1), -one, f1, &
583 ldf, y, ldy, one, f2, ldf )
584 tmp_fqr = slange( 'F', m, n+1, f2, ldf, work ) / &
585 slange( 'F', m, n+1, f, ldf, work )
586 IF ( tmp_fqr > tol2 ) THEN
587 nfail_f_qr = nfail_f_qr + 1
588 END IF
589 END IF
590
591 !..... SGEDMDQ checkpoint
592 IF ( lsame(resids, 'R') ) THEN
593 ! Compare the residuals returned by SGEDMDQ with the
594 ! explicitly computed residuals using the matrix A.
595 ! Compute explicitly Y1 = A*Z
596 CALL sgemm( 'N', 'N', m, kq, m, one, a, m, z, m, zero, y1, m )
597 ! ... and then A*Z(:,i) - LAMBDA(i)*Z(:,i), using the real forms
598 ! of the invariant subspaces that correspond to complex conjugate
599 ! pairs of eigencalues. (See the description of Z in SGEDMDQ)
600 i = 1
601 DO WHILE ( i <= kq )
602 IF ( ieigq(i) == zero ) THEN
603 ! have a real eigenvalue with real eigenvector
604 CALL saxpy( m, -reigq(i), z(1,i), 1, y1(1,i), 1 )
605 ! Y(1:M,i) = Y(1:M,i) - REIG(i)*Z(1:M,i)
606 res1(i) = snrm2( m, y1(1,i), 1)
607 i = i + 1
608 ELSE
609 ! Have a complex conjugate pair
610 ! REIG(i) +- sqrt(-1)*IMEIG(i).
611 ! Since all computation is done in real
612 ! arithmetic, the formula for the residual
613 ! is recast for real representation of the
614 ! complex conjugate eigenpair. See the
615 ! description of RES.
616 ab(1,1) = reigq(i)
617 ab(2,1) = -ieigq(i)
618 ab(1,2) = ieigq(i)
619 ab(2,2) = reigq(i)
620 CALL sgemm( 'N', 'N', m, 2, 2, -one, z(1,i), &
621 m, ab, 2, one, y1(1,i), m ) ! BLAS CALL
622 ! Y(1:M,i:i+1) = Y(1:M,i:i+1) - Z(1:M,i:i+1) * AB ! INTRINSIC
623 res1(i) = slange( 'F', m, 2, y1(1,i), m, &
624 work ) ! LAPACK CALL
625 res1(i+1) = res1(i)
626 i = i + 2
627 END IF
628 END DO
629 tmp = zero
630 DO i = 1, kq
631 tmp = max( tmp, abs(res(i) - res1(i)) * &
632 singvqx(k)/(anorm*singvqx(1)) )
633 END DO
634 tmp_rezq = max( tmp_rezq, tmp )
635 IF ( tmp > tol2 ) THEN
636 nfail_rezq = nfail_rezq + 1
637 END IF
638
639 END IF
640
641 DO i = 1, kq
642 lambdaq(i,1) = reigq(i)
643 lambdaq(i,2) = ieigq(i)
644 END DO
645
646 DEALLOCATE(work)
647 DEALLOCATE(iwork)
648 END IF ! TEST_QRDMD
649!======================================================================
650
651 END DO ! LWMINOPT
652 !write(*,*) 'LWMINOPT loop completed'
653 END DO ! WHTSVD LOOP
654 !write(*,*) 'WHTSVD loop completed'
655 END DO ! NRNK LOOP
656 !write(*,*) 'NRNK loop completed'
657 END DO ! SCALE LOOP
658 !write(*,*) 'SCALE loop completed'
659 END DO ! JOBF LOOP
660 !write(*,*) 'JOBREF loop completed'
661 END DO ! JOBZ LOOP
662 !write(*,*) 'JOBZ loop completed'
663
664 END DO ! MODE -6:6
665 !write(*,*) 'MODE loop completed'
666 END DO ! 1 or 2 trajectories
667 !write(*,*) 'trajectories loop completed'
668
669 DEALLOCATE(a)
670 DEALLOCATE(ac)
671 DEALLOCATE(da)
672 DEALLOCATE(dl)
673 DEALLOCATE(f)
674 DEALLOCATE(f1)
675 DEALLOCATE(f2)
676 DEALLOCATE(x)
677 DEALLOCATE(x0)
678 DEALLOCATE(singvx)
679 DEALLOCATE(singvqx)
680 DEALLOCATE(y)
681 DEALLOCATE(y0)
682 DEALLOCATE(y1)
683 DEALLOCATE(z)
684 DEALLOCATE(z1)
685 DEALLOCATE(res)
686 DEALLOCATE(res1)
687 DEALLOCATE(resex)
688 DEALLOCATE(reig)
689 DEALLOCATE(ieig)
690 DEALLOCATE(reigq)
691 DEALLOCATE(ieigq)
692 DEALLOCATE(reiga)
693 DEALLOCATE(ieiga)
694 DEALLOCATE(va)
695 DEALLOCATE(lambda)
696 DEALLOCATE(lambdaq)
697 DEALLOCATE(eiga)
698 DEALLOCATE(w)
699 DEALLOCATE(au)
700 DEALLOCATE(s)
701
702!............................................................
703 ! Generate random M-by-M matrix A. Use DLATMR from
704 END DO ! LLOOP
705
706
707 WRITE(*,*) '>>>>>>>>>>>>>>>>>>>>>>>>>>'
708 WRITE(*,*) ' Test summary for SGEDMD :'
709 WRITE(*,*) '>>>>>>>>>>>>>>>>>>>>>>>>>>'
710 WRITE(*,*)
711 IF ( nfail_z_xv == 0 ) THEN
712 WRITE(*,*) '>>>> Z - U*V test PASSED.'
713 ELSE
714 WRITE(*,*) 'Z - U*V test FAILED ', nfail_z_xv, ' time(s)'
715 WRITE(*,*) 'Max error ||Z-U*V||_F was ', tmp_zxw
716 nfail_total = nfail_total + nfail_z_xv
717 END IF
718 IF ( nfail_au == 0 ) THEN
719 WRITE(*,*) '>>>> A*U test PASSED. '
720 ELSE
721 WRITE(*,*) 'A*U test FAILED ', nfail_au, ' time(s)'
722 WRITE(*,*) 'Max A*U test adjusted error measure was ', tmp_au
723 WRITE(*,*) 'It should be up to O(M*N) times EPS, EPS = ', eps
724 nfail_total = nfail_total + nfail_au
725 END IF
726
727 IF ( nfail_rez == 0 ) THEN
728 WRITE(*,*) '>>>> Rezidual computation test PASSED.'
729 ELSE
730 WRITE(*,*) 'Rezidual computation test FAILED ', nfail_rez, 'time(s)'
731 WRITE(*,*) 'Max residual computing test adjusted error measure was ', tmp_rez
732 WRITE(*,*) 'It should be up to O(M*N) times EPS, EPS = ', eps
733 nfail_total = nfail_total + nfail_rez
734 END IF
735
736 IF ( nfail_total == 0 ) THEN
737 WRITE(*,*) '>>>> SGEDMD :: ALL TESTS PASSED.'
738 ELSE
739 WRITE(*,*) nfail_total, 'FAILURES!'
740 WRITE(*,*) '>>>>>>>>>>>>>> SGEDMD :: TESTS FAILED. CHECK THE IMPLEMENTATION.'
741 END IF
742
743 IF ( test_qrdmd ) THEN
744 WRITE(*,*)
745 WRITE(*,*) '>>>>>>>>>>>>>>>>>>>>>>>>>>'
746 WRITE(*,*) ' Test summary for SGEDMDQ :'
747 WRITE(*,*) '>>>>>>>>>>>>>>>>>>>>>>>>>>'
748 WRITE(*,*)
749
750 IF ( nfail_svdiff == 0 ) THEN
751 WRITE(*,*) '>>>> SGEDMD and SGEDMDQ computed singular &
752 &values test PASSED.'
753 ELSE
754 WRITE(*,*) 'SGEDMD and SGEDMDQ discrepancies in &
755 &the singular values unacceptable ', &
756 nfail_svdiff, ' times. Test FAILED.'
757 WRITE(*,*) 'The maximal discrepancy in the singular values (relative to the norm) was ', svdiff
758 WRITE(*,*) 'It should be up to O(M*N) times EPS, EPS = ', eps
759 nfailq_total = nfailq_total + nfail_svdiff
760 END IF
761
762 IF ( nfail_f_qr == 0 ) THEN
763 WRITE(*,*) '>>>> F - Q*R test PASSED.'
764 ELSE
765 WRITE(*,*) 'F - Q*R test FAILED ', nfail_f_qr, ' time(s)'
766 WRITE(*,*) 'The largest relative residual was ', tmp_fqr
767 WRITE(*,*) 'It should be up to O(M*N) times EPS, EPS = ', eps
768 nfailq_total = nfailq_total + nfail_f_qr
769 END IF
770
771 IF ( nfail_rezq == 0 ) THEN
772 WRITE(*,*) '>>>> Rezidual computation test PASSED.'
773 ELSE
774 WRITE(*,*) 'Rezidual computation test FAILED ', nfail_rezq, 'time(s)'
775 WRITE(*,*) 'Max residual computing test adjusted error measure was ', tmp_rezq
776 WRITE(*,*) 'It should be up to O(M*N) times EPS, EPS = ', eps
777 nfailq_total = nfailq_total + nfail_rezq
778 END IF
779
780 IF ( nfailq_total == 0 ) THEN
781 WRITE(*,*) '>>>>>>> SGEDMDQ :: ALL TESTS PASSED.'
782 ELSE
783 WRITE(*,*) nfailq_total, 'FAILURES!'
784 WRITE(*,*) '>>>>>>> SGEDMDQ :: TESTS FAILED. CHECK THE IMPLEMENTATION.'
785 END IF
786
787 END IF
788
789 WRITE(*,*)
790 WRITE(*,*) 'Test completed.'
791 stop
792 END
subroutine saxpy(n, sa, sx, incx, sy, incy)
SAXPY
Definition saxpy.f:89
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.
Definition sgedmd.f90:535
subroutine sgedmdq(jobs, jobz, jobr, jobq, jobt, jobf, whtsvd, m, n, f, ldf, x, ldx, y, ldy, nrnk, tol, k, reig, imeig, z, ldz, res, b, ldb, v, ldv, s, lds, work, lwork, iwork, liwork, info)
SGEDMDQ computes the Dynamic Mode Decomposition (DMD) for a pair of data snapshot matrices.
Definition sgedmdq.f90:576
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
Definition sgeev.f:192
subroutine sgemm(transa, transb, m, n, k, alpha, a, lda, b, ldb, beta, c, ldc)
SGEMM
Definition sgemm.f:188
subroutine sgemv(trans, m, n, alpha, a, lda, x, incx, beta, y, incy)
SGEMV
Definition sgemv.f:158
subroutine slacpy(uplo, m, n, a, lda, b, ldb)
SLACPY copies all or part of one two-dimensional array to another.
Definition slacpy.f:103
real function slamch(cmach)
SLAMCH
Definition slamch.f:68
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 ...
Definition slange.f:114
subroutine slarnv(idist, iseed, n, x)
SLARNV returns a vector of random numbers from a uniform or normal distribution.
Definition slarnv.f:97
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.
Definition slascl.f:143
logical function lsame(ca, cb)
LSAME
Definition lsame.f:48
real(wp) function snrm2(n, x, incx)
SNRM2
Definition snrm2.f90:89
subroutine slatmr(m, n, dist, iseed, sym, d, mode, cond, dmax, rsign, grade, dl, model, condl, dr, moder, condr, pivtng, ipivot, kl, ku, sparse, anorm, pack, a, lda, iwork, info)
SLATMR
Definition slatmr.f:471