1 subroutine da_check_eof_decomposition(be_eigenval, be_eigenvec, name)
3 !---------------------------------------------------------------------------
4 ! Purpose: Check eigenvectors E of vertical covariance matrix B_{x} which
5 ! have been read in from NMC-statistics file.
7 ! Method: E and L (eigenvalues) are computed using LAPACK/BLAS software in
8 ! the NMC code using the definition E^{T} B_{x} E = L. This routine checks
9 ! for eigenvector orthogonality and completeness as defined below.
10 !---------------------------------------------------------------------------
14 real*8, intent(in) :: be_eigenval(:) ! Back. error eigenvalues.
15 real*8, intent(in) :: be_eigenvec(:,:) ! Back. error eigenvector
16 character(len=*), intent(in) :: name ! Variable name.
18 integer :: kz ! Size of 3rd dimension.
19 integer :: k, k1, k2, m ! Loop counters
20 real :: tot_variance ! Total variance.
21 real :: cum_variance ! Cumulative variance.
22 real :: max_off_diag ! Maximum off-diagonal.
24 real, allocatable :: matrix2(:,:) ! 2D Work matrix.
25 logical, allocatable :: array_mask(:) ! Array mask for MAXVAL.
27 if (trace_use) call da_trace_entry("da_check_eof_decomposition")
29 !----------------------------------------------------------------------
31 !----------------------------------------------------------------------
33 kz = size(be_eigenval)
35 !----------------------------------------------------------------------
36 ! [2.0]: Print out global eigenvalues (used for truncation):
37 !----------------------------------------------------------------------
40 tot_variance = sum(be_eigenval(1:kz))
42 write(unit=stdout,fmt='(A)') 'Name Mode Eigenvalue Normalised Variance'
44 cum_variance = be_eigenval(k) + cum_variance
45 write(unit=stdout,fmt='(A,I4,e14.4,f10.4)') &
46 trim(name), k, be_eigenval(k), cum_variance / tot_variance
48 write(unit=stdout,fmt=*) ' '
49 write(unit=stdout,fmt='(A,e13.5)') 'Total variance = Tr(Bv) = ', tot_variance
50 write(unit=stdout,fmt=*) ' '
52 !--------------------------------------------------------------------------
53 ! [2.0]: Test global eigenvectors:
54 !--------------------------------------------------------------------------
56 ! [2.1] Print out global eigenvectors:
58 write(unit=stdout,fmt='(2A)') 'Domain eigenvectors for ', trim(name)
60 write(unit=stdout,fmt='(50i13)')(m, m=1,kz)
62 write(unit=stdout,fmt='(I3,50e13.5)')k, (be_eigenvec(k,m), m=1,kz)
64 write(unit=stdout,fmt='(A)') " "
66 ! [2.2]: Test eigenvector orthogonality: sum_k (e_m(k) e_n(k)) = delta_mn:
68 allocate(array_mask(1:kz))
69 allocate(matrix2(1:kz,1:kz))
71 write(unit=stdout,fmt='(2A)') &
72 'Eigenvector orthogonality check for ', trim(name)
73 write(unit=stdout,fmt='(A)')' Mode Diagonal Maximum off-diagonal'
76 matrix2(k1,k2) = sum(be_eigenvec(:,k1) * be_eigenvec(:,k2))
79 array_mask(1:kz) =.true.
80 array_mask(k1) = .false.
81 max_off_diag = MAXVAL(ABS(matrix2(k1,:)),mask=array_mask(:))
82 write(unit=stdout,fmt='(I4,4x,1pe12.4,10x,1pe12.4)')k1, matrix2(k1,k1), &
85 write(unit=stdout,fmt=*) ' '
87 ! [2.3] Test eigenvectors completeness - sum_m (e_m(k1) e_m(k2)) = delta_k1k2
89 write(unit=stdout,fmt='(2A)') &
90 'Eigenvector completeness check for ', trim(name)
91 write(unit=stdout,fmt='(A)')' Level Diagonal Maximum off-diagonal'
94 matrix2(k1,k2) = sum(be_eigenvec(k1,:) * be_eigenvec(k2,:))
97 array_mask(1:kz) =.true.
98 array_mask(k1) = .false.
99 max_off_diag = MAXVAL(ABS(matrix2(k1,:)),mask=array_mask(:))
100 write(unit=stdout,fmt='(I4,4x,1pe12.4,10x,1pe12.4)')k1, matrix2(k1,k1), &
103 write(unit=stdout,fmt=*) ' '
105 !-------------------------------------------------------------------------
107 !-------------------------------------------------------------------------
110 deallocate(array_mask)
112 if (trace_use) call da_trace_exit("da_check_eof_decomposition")
114 end subroutine da_check_eof_decomposition