SUBROUTINE SPA2SPAD 2,1
#if defined (DOC)
*
***s/r SPA2SPAD - Adjoint of the conversion of analysis variables to
* . model state increments
* .
* Purpose
* . To revert from the analysis variables to the model state variables
* . as defined in spectral space
* . IMPORTANT: after a call to SP2SPAD, the fields SPVOR and SPDIV
* . may contain PSI and CHI. This will eventually become
* . the default option
*Author : P. Gauthier *ARMA/AES March 25, 1996
* .
*Revision:
* . P. Gauthier *ARMA/AES August 5, 1996
* . Redefine the balance relationship and reformulate the
* . analysis variable in terms of PSI and CHI instead of
* . vorticity and divergence.
* . S. Pellerin *ARMA/AES Sept 97.
* - Control of the different model state of the 3Dvar
* through COMSTATE, COMSTATEC and COMSTNUM common
* blocks variables (comstate.cdk).
* . M. Buehner November 97
* . Introduce transformation for new definition of control
* . vector that reduces background covariances to the identity
* . matrix (for NANALVAR=3)
* . L. Fillion/M. Buehner 20 jul 98
* . Model's coordinate
* C. Charette *ARMA/AES Nov 1998
* Changed LDIVBAL to LBALDIV
* JM Belanger CMDA/SMC Aug 2000
* . 32 bits conversion
* (MXMA8, replace 2.0 by REAL*8 in SQRT)
* P. Koclas CMDA/SMC Apr 2003
* cnnert call to mxma8 to mxmaop
* M. Buehner *ARMA/SMC October 2004
* - changed damplibg to 3D and to be after balance operators
* Y.J. Rochon ARQX/MSC May 2005
* - Addition of general module to contain application of
* adjoint of balance operators related to species (CH_ABALOPER).
#endif
C
IMPLICIT NONE
#include "pardim.cdk"
#include "comdim.cdk"
#include "comcst.cdk"
#include "comgem.cdk"
#include "comleg.cdk"
#include "comcva.cdk"
#include "comsp.cdk"
#include "comspg.cdk"
#include "comgd0.cdk"
#include "compstat.cdk"
#include "comcorr.cdk"
#include "comcse1.cdk"
#include "comstate.cdk"
INTEGER ILEN
INTEGER JN,JM,JK,ILA
! REAL*8 ZSP(NKSDIM,2,0:NTRUNC),ZSP2(NKSDIM,2,0:NTRUNC),SQ2
! POINTER(PXZSP,ZSP), (PXZSP2,ZSP2)
REAL*8 SQ2
REAL*8 ,ALLOCATABLE,DIMENSION(:,:,:) :: zsp,zsp2
INTEGER ILENGD, IERR, ILON, JLEV, JLON, JLAT, JLA
REAL*8 Z1SA2,ZNORMPSI, ZNORMCHI
! REAL*8 ZGDPSI(NIBEG:NIEND,NFLEV,NJBEG:NJEND)
! S ,ZGDCHI(NIBEG:NIEND,NFLEV,NJBEG:NJEND)
! POINTER (PXGDPSI,ZGDPSI),(PXGDCHI,ZGDCHI)
REAL*8,ALLOCATABLE,DIMENSION(:,:,:) :: ZGDPSI ,ZGDCHI
!
INTEGER :: NTRUNCHF,JN0,INS,JNS,thdid,numthd
INTEGER :: omp_get_thread_num, omp_get_num_threads
real*8 two
*
two = 2.d0
*-------------------------------------------------------------------
C
C 1. Create local arrays for CHI and PSI if needed
C
100 CONTINUE
C
C . 1.1 Case where the analysis variable is X - Xb
C . (SPA2SP = Identity)
C
110 CONTINUE
IF(NANALVAR.EQ.0) THEN
RETURN
END IF
C
C . 1.2 Memory allocation
C
C
IF(NANALVAR.GE.2) THEN
ALLOCATE(ZGDPSI(NIBEG:NIEND,NFLEV,NJBEG:NJEND))
ALLOCATE(ZGDCHI(NIBEG:NIEND,NFLEV,NJBEG:NJEND))
END IF
C
C 2. Previous way of implementing the multivariate analysis
C . (based on the linear balance relationship)
C
200 CONTINUE
IF(NANALVAR.EQ.1) THEN
IF(NCNTVAR.EQ.2.AND.CFGERR.EQ.'G')THEN
CALL PROJIA(.TRUE.)
CALL GDSPA
CALL FGERR('M')
CALL SPGDA
CALL FGERR('O')
END IF
IF(NCNTVAR.EQ.2.AND.CFGERR.EQ.'S')THEN
CALL PROJIA(.TRUE.)
CALL FGERR('M')
END IF
RETURN
END IF
C
C 3. Formulation using PSI and CHI
C
300 CONTINUE
C
C . 3.5 Rederive the vorticity and divergence from PSI and CHI
C
Z1SA2 = 1./(RA*RA)
!$OMP PARALLEL DO
DO JLEV = 1, NFLEV
DO JLA = 1, NLA
SPVOR(JLA,1,JLEV) = SPVOR(JLA,1,JLEV)*Z1SA2*RNNP1(JLA)
SPVOR(JLA,2,JLEV) = SPVOR(JLA,2,JLEV)*Z1SA2*RNNP1(JLA)
SPDIV(JLA,1,JLEV) = SPDIV(JLA,1,JLEV)*Z1SA2*RNNP1(JLA)
SPDIV(JLA,2,JLEV) = SPDIV(JLA,2,JLEV)*Z1SA2*RNNP1(JLA)
END DO
END DO
!$OMP END PARALLEL DO
C
C . 3.4 Spectral transform all fields
C
340 CONTINUE
CALL SPEREE(NKSDIM,SP,GD
S ,NLA,NIBEG,NIEND,NJBEG,NJEND,NKSDIM)
C
C Apply 3D amplification factor
C
DO JLAT = 1, NJ
DO JLEV = 1, NKGDIM
DO JLON = 1, NI
GD(JLON,JLEV,JLAT)=
+ GD(JLON,JLEV,JLAT)*damplibg(JLON,JLEV,JLAT)
END DO
END DO
END DO
C
C . 3.3 Obtain the full geopotential
C
DO JLAT = 1, NJ
ILON = NILON(JLAT)
DO JLEV = 1, NFLEV
DO JLON = 1, ILON
ZGDPSI(JLON,JLEV,JLAT) = UT0(JLON,JLEV,JLAT)
ZGDCHI(JLON,JLEV,JLAT) = VT0(JLON,JLEV,JLAT)
END DO
END DO
END DO
IF(LBALDIV) THEN
CALL ADIVBAL(zgdpsi,zgdchi)
ENDIF
call abmass
(zgdpsi,zgdchi)
C
C . 3.2 Multiply by the background error variances
C
IF(LUSE3DSTD) THEN
DO JLEV = 1, NFLEV
DO JLAT = 1, NJ
ILON = NILON(JLAT)
DO JLON = 1, ILON
UT0(JLON,JLEV,JLAT)=
+ ZGDPSI(JLON,JLEV,JLAT)*RGSIGUU3D(JLON,JLEV,JLAT)
VT0(JLON,JLEV,JLAT)=
+ ZGDCHI(JLON,JLEV,JLAT)*RGSIGVV3D(JLON,JLEV,JLAT)
TT0(JLON,JLEV,JLAT)=
+ TT0(JLON,JLEV,JLAT)*RGSIGTT3D(JLON,JLEV,JLAT)
Q0(JLON,JLEV,JLAT)=
+ Q0(JLON,JLEV,JLAT)*RGSIGQ3D(JLON,JLEV,JLAT)
END DO
END DO
END DO
DO JLAT = 1, NJ
ILON = NILON(JLAT)
DO JLON = 1, ILON
GPS0(JLON,1,JLAT)=
+ GPS0(JLON,1,JLAT)*RGSIGPS3D(JLON,1,JLAT)
END DO
END DO
IF(nsexist(nstg).eq.1) THEN
DO JLAT = 1, NJ
ILON = NILON(JLAT)
DO JLON = 1, ILON
GTG0(JLON,1,JLAT)=
+ GTG0(JLON,1,JLAT)*RGSIGTG3D(JLON,1,JLAT)
END DO
END DO
ENDIF
ELSE
320 CONTINUE
CALL FGERR('M')
!$OMP PARALLEL DO PRIVATE(ILON,ZNORMPSI,ZNORMCHI)
DO JLAT = 1, NJ
ILON = NILON(JLAT)
DO JLEV = 1, NFLEV
ZNORMPSI = RGSIGUU(JLAT,JLEV)
ZNORMCHI = RGSIGVV(JLAT,JLEV)
DO JLON = 1, ILON
UT0(JLON,JLEV,JLAT)
S = ZGDPSI(JLON,JLEV,JLAT)*ZNORMPSI
VT0(JLON,JLEV,JLAT)
S = ZGDCHI(JLON,JLEV,JLAT)*ZNORMCHI
END DO
END DO
END DO
!$OMP END PARALLEL DO
ENDIF
C
C . 3.1 Transform PSI and CHI and the other variables
C . to physical space
C
310 CONTINUE
C
CALL REESPE(NKSDIM,SP,GD
S ,NLA,NIBEG,NIEND,NJBEG,NJEND,NKSDIM)
C
C 3.0 Multiply by CORNS to add in vert corr (scale/rotate)
C
IF(NANALVAR.EQ.3) THEN
NTRUNCHF=NTRUNC/2
SQ2=sqrt(two)
!$OMP PARALLEL PRIVATE(thdid,numthd,JN,JM,JK,ILA,JN0,INS,JNS,zsp,zsp2)
thdid=omp_get_thread_num()
numthd=omp_get_num_threads()
ALLOCATE(zsp(NKSDIM,2,0:NTRUNC))
ALLOCATE(zsp2(NKSDIM,2,0:NTRUNC))
DO JN0 = thdid, NTRUNCHF,numthd
INS=1
IF(JN0 == (NTRUNC-JN0))INS=0
DO 222 JNS=0,INS
JN=(1-JNS)*JN0+JNS*(NTRUNC-JN0)
C
C* Transfer Dx from global to working array
C
DO JM = 0, JN
ILA = NIND(JM) + JN - JM
DO JK = 1, NKSDIM
ZSP(JK,1,JM) = SP(ILA,1,JK)
ZSP(JK,2,JM) = SP(ILA,2,JK)
END DO
END DO
C
C* Compute (CORNS(NKSDIM,NKSDIM,JN)' * ZSP)
C
CALL MXMAOP(CORNS(1,1,JN,1),1,NKSDIM,ZSP(1,1,0),1,NKSDIM
+ ,ZSP2(1,1,0),1,NKSDIM,NKSDIM,NKSDIM,2*(JN+1))
C
C* Transfer from working array to global array
C
ILA = NIND(0) +JN
DO JK = 1, NKSDIM
SP(ILA,1,JK) = ZSP2(JK,1,0)*SQ2
SP(ILA,2,JK) = ZSP2(JK,2,0)*SQ2
END DO
C
DO JM = 1, JN
ILA = NIND(JM) +JN - JM
DO JK = 1, NKSDIM
SP(ILA,1,JK) = ZSP2(JK,1,JM)
SP(ILA,2,JK) = ZSP2(JK,2,JM)
END DO
END DO
C
222 CONTINUE
END DO
DEALLOCATE(zsp)
DEALLOCATE(zsp2)
!$OMP END PARALLEL
C
DO JK=1,NKSDIM
DO ILA=1,NTRUNC+1
SP(ILA,2,JK)=0.0
ENDDO
ENDDO
C
ENDIF
C
C 9. Deallocate local arrays
C
900 CONTINUE
C
C
IF(NANALVAR.GE.2) THEN
DEALLOCATE(ZGDPSI)
DEALLOCATE(ZGDCHI)
END IF
C
RETURN
END