! bn_4dvar_gather.jnl
! 11/2016

! force a split/gather operation due on multi-axis @idn

define axis/x=1:200:1 xax
define axis/y=1:200:1 yax
define axis/z=1:201:1 zax
define axis/T=1:200:1 tax
! adding a constant doesn't effect variance
let constant = 0*X[gx=xax] + 0*Y[gy=yax] + 0*Z[gz=zax] + 1234
let xyz = 0*X[gx=xax] + 0*Y[gy=yax] + Z[gz=zax] + 1
let xyz_zero_mean = 0*X[gx=xax] + 0*Y[gy=yax] + (Z[gz=zax]-101)

* note: sum of a sequence 1 to N of square integers is [N*(N+1)*(2N+1)]/6
* Z-101 is 2 sequences: -100 to -1 and 1 to 100, therefore sum is 
* 2 * [100*101*201]/6 = 676700
* so the average is 676700/201 = 3366.666666 ...
* At every XY point we have the identical sequence in Z, so the variance is
* the same as the single Z sequence

* 3D XYZ test
* 2d slice size = 200*200 = 40,000
* 3d full size is 8,000,000  - so 10,000,000 is bigger
cancel memory/all
set mode desp: 2000000  ! 2,000,000 small -- requires split/gather
! will split into 4 pieces (1/4 of 8,000,000 fits into 2,000,000)
! so z=1:50; then =51:100, Z=101:150, Z=151:200
set mode diag
LIST/PREC=12 constant[x=@var,y=@var,z=@var]

cancel mode diag
! variance of a constant is zero
GO bn_compressed_gather.sub constant[x=@var,y=@var,z=@var] 10000000 2000000

! confirm that we get the result computed above
GO bn_compressed_gather.sub xyz_zero_mean[x=@var,y=@var,z=@var]  10000000 2000000
LIST/PREC=12 xyz_zero_mean[x=@var,y=@var,z=@var]

! confirm that adding a constant does not change the result
GO bn_compressed_gather.sub xyz[x=@var,y=@var,z=@var]  10000000 2000000
LIST/PREC=12 xyz[x=@var,y=@var,z=@var]

CANCEL MEMORY/ALL  ! IF PRESENT THIS PREVENTS THE MEMORY CORRUPTION
! confirm the @std gives the square root of the variance
! SQRT(676700/201) = 58.022983951764034269074805569046
GO bn_compressed_gather.sub xyz[x=@std,y=@std,z=@std]  10000000 2000000
LIST/PREC=12 xyz[x=@std,y=@std,z=@std]


!!!! other directions ZEF

set mode diag

define axis/Z=1:200:1 Zax
define axis/E=1:200:1 Eax
define axis/F=1:200:1 Fax
let zef = 0*Z[gz=zax] + 0*_E[ge=eax] + _F[gF=fax]

let zef = 0*Z[gz=zax] + 0*_E[ge=eax] + _F[gF=fax] + 1
let zef_zero_mean = 0*Z[gz=zax] + 0*_E[ge=eax]  + (_F[gF=fax]-101)

GO bn_compressed_gather.sub zef_zero_mean[z=@var,e=@var,f=@var]  10000000 2000000
LIST/PREC=12 zef_zero_mean[z=@var,e=@var,f=@var]


!!!! other directions ZTE

let zte = 0*Z[gz=zax] + _T[gt=tax] + 0*_E[ge=eax] + 1
let zte_zero_mean = 0*Z[gz=zax] + 0*t[gt=tax]  + (_E[gE=eax]-101)

GO bn_compressed_gather.sub zte_zero_mean[z=@var,t=@var,e=@var]  10000000 2000000
LIST/PREC=12 zte_zero_mean[z=@var,t=@var,e=@var]
