! bn_eof_simple2
! Define a simple function with four known functions, two of which are degenerate.
! decompose with EOFs.
! 7/2012 
! In version 6.8 (double precision), the old eof functions are not available
! Run the script calling eofsvd functions and exit, leaving old eof function calls.
! 11/2017 - still try to test old eof functions, if they are re-implemented

! Define four locations.
def axis /X=1:2:1 xaxis
def axis /Y=1:2:1 yaxis

! Thinking of the time axis as number of months.
def axis /T=0.0:23.9:0.1 taxis
def grid /X=xaxis /Y=yaxis /T=taxis xytgrid
set grid xytgrid

! Make standing waves with a period of 12 months.
let cosT = cos(T * 3.141592653589793 / 6.0)
let sinT = sin(T * 3.141592653589793 / 6.0)

! Put a products of the standing waves at each location.
let spacetime12 = if (i eq 1) and (j eq 1) then cost * cost else cost * sint + 1
let spacetime123 = if (i eq 2) and (j eq 1) then cost * sint + 2 else spacetime12
let spacetime = if (i eq 2) and (j eq 2) then sint * sint + 3 else spacetime123
show grid spacetime

show func eofsvd_stat
! Two are of equal significance with eigenvalues of 0.25.
! Two are negligable (eigenvalues of zero or close to it).
list eofsvd_stat(spacetime)

show func eofsvd_space
! Ideally:
! +- [ 0.35355,  0.0,  
!      0.0,     -0.35355 ]  (norm^2 = 0.25)
!      corresponding to 0.25 * sqrt(2.0) * (cosT^2 - sinT^2) 
!                     = 0.25 * sqrt(2.0) * cos2T
! and
! +- [ 0.0,      0.35355,  
!      0.35355,  0.0     ]  (norm^2 = 0.25)
!      corresponding to 0.25 * sqrt(2.0) * 2 * cosT * sinT 
!                     = 0.25 * sqrt(2.0) * sin2T
! The norm^2 of an EOF should be the eigenvalue.
! The two EOFs should be orthogonal to each other.
! Rotation (mixing) of these two may occur.
let eofs = eofsvd_space(spacetime[I=1:2])
load eofs
let v1 = eofs[I=1]
show grid v1
let v2 = eofs[I=2]
show grid v2
list dot_t(v1, v1)
list dot_t(v1, v2)
list dot_t(v2, v1)
list dot_t(v2, v2)

show func eofsvd_tfunc
! Ideally:
! +- sqrt(2.0) * cos2T  (norm^2 = 240)
! +- sqrt(2.0) * sin2T  (norm^2 = 240)
! The norm^2 of a TAF should be the number of time values.
! The two TAFs should be orthogonal to each other.
! Rotation (mixing) of these two may occur.
let tafs = eofsvd_tfunc(spacetime[I=1:2])
load tafs
let v1 = tafs[I=1]
show grid v1
let v2 = tafs[I=2]
show grid v2
list dot_t(v1, v1)
list dot_t(v1, v2)
list dot_t(v2, v1)
list dot_t(v2, v2)

! Explanation:
! Time series means = (0.5, 0.0, 0.0, 0.5) + (0, 1, 2, 3)
! EOF1 * TAF1 = (0.5 * cos2T,  0.0, 0.0, -0.5 * cos2T)
!             = (cosT^2 - 0.5, 0.0, 0.0, sinT^2 - 0.5)
! EOF2 * TAF2 = (0.0, 0.5 * sin2T, 0.5 * sin2T, 0.0)
!             = (0.0, cosT * sinT, cosT * sinT, 0.0)
! Adding these three gives the original data

! -----------------------------------------------
! previous commands that called eof_space, eof_stat, eof_tfunc
! these functions all now bail out - do not work properly in double precision

set mode ignore

show func eof_stat
! Two are of equal significance with eigenvalues of 0.25.
! Two are negligable (eigenvalues of zero or close to it).
list eof_stat(spacetime, 1.0)

show func eof_space
! Ideally:
! +- [ 0.35355,  0.0,  
!      0.0,     -0.35355 ]  (norm^2 = 0.25)
!      corresponding to 0.25 * sqrt(2.0) * (cosT^2 - sinT^2) 
!                     = 0.25 * sqrt(2.0) * cos2T
! and
! +- [ 0.0,      0.35355,  
!      0.35355,  0.0     ]  (norm^2 = 0.25)
!      corresponding to 0.25 * sqrt(2.0) * 2 * cosT * sinT 
!                     = 0.25 * sqrt(2.0) * sin2T
! The norm^2 of an EOF should be the eigenvalue.
! The two EOFs should be orthogonal to each other.
! Rotation (mixing) of these two may occur.
let eofs = eof_space(spacetime[I=1:2], 1.0)
load eofs
let v1 = eofs[I=1]
show grid v1
let v2 = eofs[I=2]
show grid v2
list dot_t(v1, v1)
list dot_t(v1, v2)
list dot_t(v2, v1)
list dot_t(v2, v2)

show func eof_tfunc
! Ideally:
! +- sqrt(2.0) * cos2T  (norm^2 = 240)
! +- sqrt(2.0) * sin2T  (norm^2 = 240)
! The norm^2 of a TAF should be the number of time values.
! The two TAFs should be orthogonal to each other.
! Rotation (mixing) of these two may occur.
let tafs = eof_tfunc(spacetime, 1.0)
load tafs
let v1 = tafs[I=1]
show grid v1
let v2 = tafs[I=2]
show grid v2
list dot_t(v1, v1)
list dot_t(v1, v2)
list dot_t(v2, v1)
list dot_t(v2, v2)

! Explanation:
! Time series means = (0.5, 0.0, 0.0, 0.5) + (0, 1, 2, 3)
! EOF1 * TAF1 = (0.5 * cos2T,  0.0, 0.0, -0.5 * cos2T)
!             = (cosT^2 - 0.5, 0.0, 0.0, sinT^2 - 0.5)
	! EOF2 * TAF2 = (0.0, 0.5 * sin2T, 0.5 * sin2T, 0.0)
!             = (0.0, cosT * sinT, cosT * sinT, 0.0)
! Adding these three gives the original data

set mode/last ignore

! clean-up 
set grid abstract
can var /all
can grid xytgrid
