SUBROUTINE SPNORM(KINDPP)

USE PARKIND1  ,ONLY : JPIM     ,JPRB
USE YOMHOOK   ,ONLY : LHOOK,   DR_HOOK

USE YOMDIM   , ONLY : NFLEVL   ,NFLEVG   ,NFTHER   ,&
 & NFD2D    ,NFC2D    ,NFLSUR   ,&
 & NUMP     ,NSPECG   ,NSPEC2
USE YOMSP    , ONLY : SPVOR    ,SPDIV    ,SPHV     ,&
 & SPSP     ,SPOR    ,SPGFL
USE YOMCT0   , ONLY : NSTOP    ,NSPPR    ,NPROC    ,LNHDYN   ,&
 & LREFOUT  ,LREFGEN  ,LELAM  
USE YOMCT3   , ONLY : NSTEP
USE YOMLUN   , ONLY : NULOUT   ,NULREF
USE YOMSPNRM , ONLY : AVNRMDIV
USE YOMMP    , ONLY : MYPROC   ,NPSP
USE YOM_YGFL , ONLY : YGFL     ,YQ       ,YO3
USE YOMDYNA  , ONLY : NPDVAR   ,NVDVAR   ,LRWSDLR

!**** *SPNORM* - Compute norms in spectral space

!     Purpose.
!     --------
!        Compute the norm in spectral space for all levels and
!        variables.

!**   Interface.
!     ----------
!        *CALL* *SPNORM(KINDPP)

!        Explicit arguments :
!        --------------------

!        KINDPP     0  Calculate norms of SPA3/SPA2 arrays
!                   1  Calculate norms of SPA3JB/SPA2JB arrays

!        Implicit arguments :  The spectral arrays of the model.
!        --------------------

!     Method.
!     -------

!     Externals.
!     ----------
!      Calls SPNORMBL, SPNORMBE and PRTSPNO.
!      Called by CNT4 and many other routines.

!     Reference.
!     ----------
!        ECMWF Research Department documentation of the IFS

!     Author.
!     -------
!        Mats Hamrud and Philippe Courtier  *ECMWF*

!     Modifications.
!     --------------
!   Original : 88-02-17
!   MPP Group: 95-10-01 Support for Distributed Memory version
!   L Isaksen: 97-02-02 Merge with message passing version
!   G Mozdzynski: 97-10-01 Support reference output generation
!                               and checking
!   R. El Khatib 99-02-03 Harmonisation with Aladin.
!   A Peuch  : 99-06-28 Ozone
!   R. El Khatib : 03-05-19 Aladin B-level distribution
!   M.Hamrud      01-Oct-2003 CY28 Cleaning
!   L.Isaksen     01-Feb-2005 Make it work for SPA3JB/SPA2JB arrays
!   K.Yessad : Apr 2005 Update the printings for NH model, + bugfix.
!   N. Wedi and K. Yessad (Jan 2008): different dev for NH model and PC scheme
!     ------------------------------------------------------------------

IMPLICIT NONE

INTEGER(KIND=JPIM), INTENT(IN)    :: KINDPP
!     ------------------------------------------------------------------

REAL(KIND=JPRB) :: ZNVOR(NFLEVL,NUMP)
REAL(KIND=JPRB) :: ZMVOR(NFLEVL,NUMP)
REAL(KIND=JPRB), ALLOCATABLE :: ZNVORG(:,:)
REAL(KIND=JPRB), ALLOCATABLE :: ZMVORG(:,:)
REAL(KIND=JPRB) :: ZVORNORM(NFLEVG)

REAL(KIND=JPRB) :: ZNDIV(NFLEVL,NUMP)
REAL(KIND=JPRB) :: ZMDIV(NFLEVL,NUMP)
REAL(KIND=JPRB), ALLOCATABLE :: ZNDIVG(:,:)
REAL(KIND=JPRB), ALLOCATABLE :: ZMDIVG(:,:)
REAL(KIND=JPRB) :: ZDIVNORM(NFLEVG)

REAL(KIND=JPRB) :: ZNKE(NFLEVL,NUMP)
REAL(KIND=JPRB) :: ZMKE(NFLEVL,NUMP)
REAL(KIND=JPRB), ALLOCATABLE :: ZNKEG(:,:)
REAL(KIND=JPRB), ALLOCATABLE :: ZMKEG(:,:)
REAL(KIND=JPRB) :: ZKENORM(NFLEVG)
REAL(KIND=JPRB) :: ZKEMEAN(NFLEVG)

REAL(KIND=JPRB), ALLOCATABLE :: ZNTHE(:,:,:)
REAL(KIND=JPRB), ALLOCATABLE :: ZMTHE(:,:,:)
REAL(KIND=JPRB), ALLOCATABLE :: ZNTHEG(:,:,:)
REAL(KIND=JPRB), ALLOCATABLE :: ZMTHEG(:,:,:)
REAL(KIND=JPRB), ALLOCATABLE :: ZTHENORM(:,:)
REAL(KIND=JPRB), ALLOCATABLE :: ZTHEAVE(:)

REAL(KIND=JPRB), ALLOCATABLE :: ZNGFL(:,:,:)
REAL(KIND=JPRB), ALLOCATABLE :: ZMGFL(:,:,:)
REAL(KIND=JPRB), ALLOCATABLE :: ZNGFLG(:,:,:)
REAL(KIND=JPRB), ALLOCATABLE :: ZMGFLG(:,:,:)
REAL(KIND=JPRB), ALLOCATABLE :: ZGFLNORM(:,:)
REAL(KIND=JPRB), ALLOCATABLE :: ZGFLAVE(:)

REAL(KIND=JPRB) :: ZNSP(1,NUMP)
REAL(KIND=JPRB) :: ZMSP(1,NUMP)
REAL(KIND=JPRB), ALLOCATABLE :: ZNSPG(:)
REAL(KIND=JPRB), ALLOCATABLE :: ZMSPG(:)

REAL(KIND=JPRB) :: ZNSPOR(1,NUMP)
REAL(KIND=JPRB) :: ZMSPOR(1,NUMP)
REAL(KIND=JPRB), ALLOCATABLE :: ZNSPORG(:)
REAL(KIND=JPRB), ALLOCATABLE :: ZMSPORG(:)
REAL(KIND=JPRB) :: ZSPORNORM(1)
REAL(KIND=JPRB) :: ZSPORAVE

REAL(KIND=JPRB), ALLOCATABLE :: ZNTHEDE(:,:,:)
REAL(KIND=JPRB), ALLOCATABLE :: ZMTHEDE(:,:,:)
REAL(KIND=JPRB), ALLOCATABLE :: ZNGFLDE(:,:,:)
REAL(KIND=JPRB), ALLOCATABLE :: ZMGFLDE(:,:,:)
REAL(KIND=JPRB), ALLOCATABLE :: ZNTHEDEG(:,:,:)
REAL(KIND=JPRB), ALLOCATABLE :: ZMTHEDEG(:,:,:)
REAL(KIND=JPRB), ALLOCATABLE :: ZNGFLDEG(:,:,:)
REAL(KIND=JPRB), ALLOCATABLE :: ZMGFLDEG(:,:,:)

REAL(KIND=JPRB) :: ZNSPDE(1,NUMP)
REAL(KIND=JPRB) :: ZMSPDE(1,NUMP)
REAL(KIND=JPRB), ALLOCATABLE :: ZNSPDEG(:)
REAL(KIND=JPRB), ALLOCATABLE :: ZMSPDEG(:)
REAL(KIND=JPRB), ALLOCATABLE :: ZTMP(:,:)

!     The exact dimension of ZMETxxx could be computed in SUDIM for both arp/ifs and ald.
REAL(KIND=JPRB) :: ZMET1(NSPECG)
REAL(KIND=JPRB) :: ZMETDER(NSPECG)
REAL(KIND=JPRB) :: ZMETKE(NSPECG)

CHARACTER (LEN = 4)   ::  CLVAR
CHARACTER (LEN = 13)  ::  CLNAME
CHARACTER (LEN = 130) ::  CLDUMMY
CHARACTER (LEN = 60)  ::  CLTEXT
CHARACTER (LEN = 18) ::  CLSP
CHARACTER (LEN = 21) ::  CLSPD
CHARACTER (LEN = 21) ::  CLSVD
CHARACTER (LEN = 30) ::  CLNSPD
CHARACTER (LEN = 30) ::  CLNSVD

LOGICAL :: LLCOROG, LLEXIST, LLNWAVE, LLPRTAV, LLPRTLV, LLPRTAL
LOGICAL :: LLSPQ,  LLSPO3

INTEGER(KIND=JPIM) :: IT, IQ, IO3,  ISPD, ISVD, ILEV, ILEVX, ILEVXG,&
 & IOMASTER, INSMAX, JLEV, JVAR, INUMSPFLDS, IFTHER 

REAL(KIND=JPRB) :: ZDDIF, ZDIV1, ZDIVAVE, ZEPS, ZERROR, ZKDIF,&
 & ZKE1, ZKEAVE, ZRDIF, ZSDDIF, ZSDREF, ZSKDIF, &
 & ZSKREF, ZSP, ZSPAVE, ZSPNORM(1), ZSPNORM1, ZSRDIF, &
 & ZSRREF, ZSTDIF, ZSTREF, ZSVDIF, ZSVREF, ZTDIF, &
 & ZTHET, ZGFLQ, ZVDIF, ZVOR1, ZVORAVE  
REAL(KIND=JPRB) :: ZHOOK_HANDLE

!     Orography norms are only calculated once and then saved

SAVE LLCOROG
SAVE ZSPORNORM, ZSPORAVE

!     ------------------------------------------------------------------

#include "abor1.intfb.h"
#include "commspnorm.intfb.h"
#include "ecommspnorm.intfb.h"
#include "espnormave.intfb.h"
#include "prtspno.intfb.h"
#include "spnormave.intfb.h"
#include "spnormbe.intfb.h"
#include "spnormbl.intfb.h"
#include "suemetric.intfb.h"
#include "sumetric.intfb.h"

!     ------------------------------------------------------------------

DATA LLCOROG /.TRUE./

!     ------------------------------------------------------------------

IF (LHOOK) CALL DR_HOOK('SPNORM',0,ZHOOK_HANDLE)

!     ------------------------------------------------------------------

!*       1.    INITIALISATIONS
!              ---------------


!-- this is a temporary hack. The real solution is to write a
!-- proper, flexible version of SPNORM that makes fewer assumptions
!-- about what fields are available -- Mike F.

IF (KINDPP==1) THEN
  CALL ABOR1('SPNORM: No SPNORM for Jb arrays.')
ENDIF

CALL GSTATS(12,0)

!     Determine level of output diagnostics
LLPRTAV=NSPPR >= 0
LLPRTLV=NSPPR >= 1
LLPRTAL=NSPPR >= 2

IF (NSPPR >= 1) WRITE(NULOUT,*)

!     ZNxxx and ZNxxxG are only available if nproc.eq.1.and.nsppr.ge.2
LLNWAVE=NSPPR >= 2.AND.NPROC == 1

!     Orography norms are computed only if nsppr.ge.2
IF (LLPRTAL) THEN
  LLCOROG=.TRUE.
ENDIF

!     Compute metric and zonal truncation
IF (.NOT.LELAM) THEN
  CALL SUMETRIC(INSMAX,ZMET1,ZMETDER,ZMETKE)
ELSE
  CALL SUEMETRIC(INSMAX,ZMET1,ZMETDER,ZMETKE)
ENDIF

!     Compute dimensions
ILEVX=NFLEVL
ILEVXG=NFLEVG

!     Setup processor number for computing global norms & printing
IOMASTER=1


! Check if it is SPA3/SPA2 or SPA3JB/SPA2JB. Number of spectral GFL 
! variables may differ, depending on YQ%LSP, YQ%LSPJB etc. 

INUMSPFLDS=YGFL%NUMSPFLDS
IQ=YQ%MPSP
IO3=YO3%MPSP
LLSPQ=YQ%LSP
LLSPO3=YO3%LSP
IFTHER=NFTHER

! * Position of Temperature, humidity and ozone.
IT=MIN(1,IFTHER)


!     Allocate global arrays
ALLOCATE(ZNVORG(NFLEVG,0:INSMAX))
ALLOCATE(ZMVORG(NFLEVG,0:INSMAX))
ALLOCATE(ZNDIVG(NFLEVG,0:INSMAX))
ALLOCATE(ZMDIVG(NFLEVG,0:INSMAX))
ALLOCATE(ZNTHE(NFLEVL,NUMP,IFTHER))
ALLOCATE(ZMTHE(NFLEVL,NUMP,IFTHER))
ALLOCATE(ZNKEG(NFLEVG,0:INSMAX))
ALLOCATE(ZMKEG(NFLEVG,0:INSMAX))
ALLOCATE(ZNTHEG(NFLEVG,0:INSMAX,IFTHER))
ALLOCATE(ZMTHEG(NFLEVG,0:INSMAX,IFTHER))
ALLOCATE(ZNGFLG(NFLEVG,0:INSMAX,INUMSPFLDS))
ALLOCATE(ZMGFLG(NFLEVG,0:INSMAX,INUMSPFLDS))
ALLOCATE(ZNGFL(NFLEVL,NUMP,INUMSPFLDS))
ALLOCATE(ZMGFL(NFLEVL,NUMP,INUMSPFLDS))
ALLOCATE(ZGFLNORM(NFLEVG,INUMSPFLDS))
ALLOCATE(ZGFLAVE(INUMSPFLDS))
ALLOCATE(ZNSPG(0:INSMAX))
ALLOCATE(ZMSPG(0:INSMAX))
ALLOCATE(ZNSPORG(0:INSMAX))
ALLOCATE(ZMSPORG(0:INSMAX))
ALLOCATE(ZNTHEDEG(NFLEVG,0:INSMAX,IFTHER))
ALLOCATE(ZNGFLDEG(NFLEVG,0:INSMAX,INUMSPFLDS)) 
ALLOCATE(ZMTHEDEG(NFLEVG,0:INSMAX,IFTHER))
ALLOCATE(ZMGFLDEG(NFLEVG,0:INSMAX,INUMSPFLDS)) 
ALLOCATE(ZNSPDEG(0:INSMAX))
ALLOCATE(ZMSPDEG(0:INSMAX))
ALLOCATE(ZNGFLDE(NFLEVL,NUMP,INUMSPFLDS))
ALLOCATE(ZMGFLDE(NFLEVL,NUMP,INUMSPFLDS))
ALLOCATE(ZTHENORM(NFLEVG,IFTHER))
ALLOCATE(ZTHEAVE(IFTHER))
ALLOCATE (ZNTHEDE(NFLEVL,NUMP,IFTHER))
ALLOCATE (ZMTHEDE(NFLEVL,NUMP,IFTHER))
!     ------------------------------------------------------------------

!*       2.    COMPUTE SPECTRUMS.
!              ------------------

!*       2.1  COMPUTE NORMS OF BASIC FIELDS

CALL SPNORMBL(SPVOR,ZNVOR,ZMVOR,ILEVX,ZMET1,NFLEVL,NFLSUR,LLNWAVE)
CALL SPNORMBL(SPDIV,ZNDIV,ZMDIV,ILEVX,ZMET1,NFLEVL,NFLSUR,LLNWAVE)
CALL SPNORMBE(SPVOR,SPDIV,ZNKE,ZMKE,ILEVX,ZMETKE,NFLEVL,NFLSUR,LLNWAVE)

DO JVAR=1,IFTHER
  CALL SPNORMBL(SPHV(:,:,JVAR),ZNTHE(:,:,JVAR),ZMTHE(:,:,JVAR),&
   & ILEVX,ZMET1,NFLEVL,NFLSUR,LLNWAVE)  
  IF(LLPRTAL) THEN
    CALL SPNORMBL(SPHV(:,:,JVAR),ZNTHEDE(:,:,JVAR),&
     & ZMTHEDE(:,:,JVAR),ILEVX,ZMETDER,NFLEVL,NFLSUR,LLNWAVE)  
  ENDIF
ENDDO

DO JVAR=1,INUMSPFLDS
  CALL SPNORMBL(SPGFL(:,:,JVAR),ZNGFL(:,:,JVAR),ZMGFL(:,:,JVAR),&
   & ILEVX,ZMET1,NFLEVL,NFLSUR,LLNWAVE)  
  IF(LLPRTAL) THEN
    CALL SPNORMBL(SPGFL(:,:,JVAR),ZNGFLDE(:,:,JVAR),         &
     & ZMGFLDE(:,:,JVAR),ILEVX,ZMETDER,NFLEVL,NFLSUR,LLNWAVE)  
  ENDIF
ENDDO

ALLOCATE(ZTMP(1,NSPEC2))
IF(NFD2D > 0.AND.NPSP == 1)THEN
  ZTMP(1,:)=SPSP(:)
  CALL SPNORMBL(ZTMP,ZNSP,ZMSP,1,ZMET1,1,1,LLNWAVE)
  IF(LLPRTAL) THEN
    ZTMP(1,:)=SPSP(:)
    CALL SPNORMBL(ZTMP,ZNSPDE,ZMSPDE,1,ZMETDER,1,1,LLNWAVE)
  ENDIF
ENDIF

IF(NFC2D > 0.AND.NPSP == 1.AND.LLCOROG)THEN
  ZTMP(1,:)=SPOR(:)
  CALL SPNORMBL(ZTMP,ZNSPOR,ZMSPOR,1,ZMET1,1,1,LLNWAVE)
ENDIF

DEALLOCATE(ZTMP)

!     ------------------------------------------------------------------

!*       3.    GATHER ALL LOCAL CONTRIBUTIONS ON 1 PE (MESSAGE PASSING)
!              --------------------------------------------------------

CALL GSTATS(12,2)
CALL GSTATS(56,0)
CALL COMMSPNORM(LLPRTAL,LLCOROG,INSMAX,IOMASTER,&
 & IFTHER,INUMSPFLDS,&
 & ZNVOR  ,ZNVORG  ,ZMVOR  ,ZMVORG,&
 & ZNDIV  ,ZNDIVG  ,ZMDIV  ,ZMDIVG,&
 & ZNKE   ,ZNKEG   ,ZMKE   ,ZMKEG,&
 & ZNTHE  ,ZNTHEG  ,ZMTHE  ,ZMTHEG,&
 & ZNGFL  ,ZNGFLG  ,ZMGFL  ,ZMGFLG,&
 & ZNSP   ,ZNSPG   ,ZMSP   ,ZMSPG,&
 & ZNSPOR ,ZNSPORG ,ZMSPOR ,ZMSPORG,&
 & ZNTHEDE,ZNTHEDEG,ZMTHEDE,ZMTHEDEG,&
 & ZNGFLDE,ZNGFLDEG,ZMGFLDE,ZMGFLDEG,  &
 & ZNSPDE ,ZNSPDEG ,ZMSPDE ,ZMSPDEG)  
CALL GSTATS(56,1)
CALL GSTATS(12,3)

IF (LELAM) THEN
  CALL ECOMMSPNORM(IOMASTER,ZKEMEAN)
ENDIF

!     ------------------------------------------------------------------

!*       4.    Print out spectral norms on PE1
!              -------------------------------

IF (MYPROC == IOMASTER) THEN

  CALL SPNORMAVE(INSMAX,ZMVORG,NFLEVG,ILEVXG,.FALSE.,ZVORNORM,ZVORAVE)
  CALL SPNORMAVE(INSMAX,ZMDIVG,NFLEVG,ILEVXG,.FALSE.,ZDIVNORM,ZDIVAVE)
  CALL SPNORMAVE(INSMAX,ZMKEG,NFLEVG,ILEVXG,.TRUE.,ZKENORM,ZKEAVE)
  IF (LELAM) THEN
    CALL ESPNORMAVE(NFLEVG,ZKENORM,ZKEMEAN,ZKEAVE)
  ENDIF

  DO JVAR=1,IFTHER
    CALL SPNORMAVE(INSMAX,ZMTHEG(1,0,JVAR),NFLEVG,ILEVXG,.FALSE.,&
     & ZTHENORM(1,JVAR),ZTHEAVE(JVAR))  
  ENDDO

  DO JVAR=1,INUMSPFLDS
    CALL SPNORMAVE(INSMAX,ZMGFLG(1,0,JVAR),NFLEVG,ILEVXG,.FALSE.,&
     & ZGFLNORM(1,JVAR),ZGFLAVE(JVAR))  
  ENDDO

  IF(NFD2D > 0)THEN
    CALL SPNORMAVE(INSMAX,ZMSPG,1,1,.FALSE.,ZSPNORM,ZSPAVE)
  ELSE
    ZSPNORM=-.9999999_JPRB
    ZSPAVE =-.9999999_JPRB
  ENDIF

  IF(LLCOROG)THEN
    IF(NFC2D > 0)THEN
      CALL SPNORMAVE(INSMAX,ZMSPORG,1,1,.FALSE.,ZSPORNORM,ZSPORAVE)
    ELSE
      ZSPORNORM=-.9999999_JPRB
      ZSPORAVE =-.9999999_JPRB
    ENDIF
  ENDIF

!*       4.4  STORE AWAY COMPUTED AVERAGE NORMS FOR USE IN OPDIS

  AVNRMDIV=ZDIVAVE

!     ------------------------------------------------------------------

!*       5.    Print Global Averages.
!              ----------------------

  IF(LLPRTAV) THEN

    CLTEXT='SPECTRAL NORMS - '

    IF (LRWSDLR) THEN
      CLSP='   LOG(PRESIMS)   '
    ELSE
      CLSP='   LOG(PREHYDS)   '
    ENDIF
    IF (LLCOROG) THEN
      WRITE(NULOUT,'(1X,A,2(1X,A,1X,E21.15))') TRIM(CLTEXT), &
       & CLSP,ZSPNORM,'    OROGRAPHY     ',ZSPORNORM  
    ELSE
      WRITE(NULOUT,'(1(1X,2A,1X,E21.15))') TRIM(CLTEXT),CLSP,ZSPNORM  
    ENDIF

    IF(IFTHER > 0 .AND. INUMSPFLDS>=2 .AND. LLSPQ .AND. LLSPO3) THEN
      WRITE(NULOUT,'(1X,A,6(1X,A21))') 'LEV'&
       & ,'    VORTICITY        ', '    DIVERGENCE       '&
       & ,'   TEMPERATURE       ', '    HUMIDITY         '&
       & ,'   OZONE             ', '    KINETIC ENERGY   '  
      WRITE(NULOUT,'(1X,A,6(1X,E21.15))')&
       & 'AVE',ZVORAVE,ZDIVAVE &
       & ,ZTHEAVE(IT),ZGFLAVE(IQ),ZGFLAVE(IO3),ZKEAVE  
    ELSEIF(IFTHER > 0 .AND. INUMSPFLDS>0 .AND. LLSPQ .AND. (.NOT.LLSPO3)) THEN
      WRITE(NULOUT,'(1X,A,5(1X,A21))') 'LEV'&
       & ,'    VORTICITY        ', '    DIVERGENCE       '&
       & ,'   TEMPERATURE       ', '    HUMIDITY         '&
       & ,'   KINETIC ENERGY    '  
      WRITE(NULOUT,'(1X,A,5(1X,E21.15))')&
       & 'AVE',ZVORAVE,ZDIVAVE &
       & ,ZTHEAVE(IT),ZGFLAVE(IQ),ZKEAVE  
    ELSEIF (IFTHER > 0 .AND. (.NOT.LLSPQ) .AND. (.NOT.LLSPO3)) THEN
      WRITE(NULOUT,'(1X,A,4(1X,A21))') 'LEV'&
       & ,'    VORTICITY        ', '    DIVERGENCE       '&
       & ,'   TEMPERATURE       ', '   KINETIC ENERGY    '  
      WRITE(NULOUT,'(1X,A,4(1X,E21.15))')&
       & 'AVE',ZVORAVE,ZDIVAVE &
       & ,ZTHEAVE(IT),ZKEAVE  
    ELSE
      WRITE(NULOUT,'(1X,A,3(1X,A21))') 'LEV'&
       & ,'    VORTICITY        ', '    DIVERGENCE       '&
       & ,'   KINETIC ENERGY    '  
      WRITE(NULOUT,'(1X,A,4(1X,E21.15))')'AVE',ZVORAVE,ZDIVAVE,ZKEAVE
    ENDIF

  ENDIF

  IF(LLPRTLV) THEN
    DO JLEV=1,ILEVXG
      IF (IFTHER > 0 .AND. INUMSPFLDS>0 .AND. LLSPQ .AND. LLSPO3) THEN
        WRITE(NULOUT,'(1X,I3,6(1X,E21.15))')JLEV &
         & ,ZVORNORM(JLEV),ZDIVNORM(JLEV),ZTHENORM(JLEV,IT)&
         & ,ZGFLNORM(JLEV,IQ),ZGFLNORM(JLEV,IO3),ZKENORM(JLEV)  
      ELSEIF (IFTHER > 0 .AND. INUMSPFLDS>0 .AND. LLSPQ) THEN
        WRITE(NULOUT,'(1X,I3,5(1X,E21.15))')JLEV &
         & ,ZVORNORM(JLEV),ZDIVNORM(JLEV)&
         & ,ZTHENORM(JLEV,IT),ZGFLNORM(JLEV,IQ),ZKENORM(JLEV)  
      ELSEIF(IFTHER > 0 .AND. (.NOT.LLSPQ) .AND. (.NOT.LLSPO3))THEN
        WRITE(NULOUT,'(1X,I3,4(1X,E21.15))')JLEV &
         & ,ZVORNORM(JLEV),ZDIVNORM(JLEV),ZTHENORM(JLEV,IT),ZKENORM(JLEV)  
      ELSEIF(IFTHER == 0) THEN
        WRITE(NULOUT,'(1X,I3,3(1X,E21.15))')JLEV &
         & ,ZVORNORM(JLEV),ZDIVNORM(JLEV),ZKENORM(JLEV)  
      ENDIF
    ENDDO
  ENDIF

  IF(LNHDYN) THEN

    ISPD=MIN(2,IFTHER)
    ISVD=MIN(3,IFTHER)
    IF (NPDVAR == 2 .AND. (.NOT.LRWSDLR)) THEN
      CLSPD='  LOG(PRE/PREHYD)    '
    ELSEIF (NPDVAR == 2 .AND. LRWSDLR) THEN
      CLSPD='  LOG(PRE/PRESIM)    '
    ELSEIF (NPDVAR == 3) THEN
      CLSPD='  PHI - B PHIS       '
    ELSEIF (NPDVAR == 4) THEN
      CLSPD='  PHI                '
    ENDIF

    IF (NVDVAR == 3) THEN
      CLSVD='  VERT  DIVERGENCE   '
    ELSEIF (NVDVAR == 4) THEN
      CLSVD='  d4 = VERT DIV + X  '
    ELSEIF (NVDVAR == 5) THEN
      CLSVD='  gw - B gw_s        '
    ELSEIF (NVDVAR == 6) THEN
      CLSVD='  gw                 '
    ENDIF

    IF(LLPRTAV) THEN
      WRITE(NULOUT,'(3(1X,A))') 'LEV',CLSPD,CLSVD
      WRITE(NULOUT,'(1X,A,2(1X,E21.15))')'AVE',ZTHEAVE(ISPD),ZTHEAVE(ISVD)
    ENDIF
    IF(LLPRTLV) THEN
      DO JLEV=1,ILEVXG
        WRITE(NULOUT,'(1X,I3,2(1X,E21.15))')JLEV &
         & ,ZTHENORM(JLEV,ISPD),ZTHENORM(JLEV,ISVD)  
      ENDDO
    ENDIF

  ENDIF

!     ------------------------------------------------------------------

!*       6.    Generate reference output
!              -------------------------

  ! Remark K.Y.: for this part and also for part 7,
  !  we assume that the comparison index "ZERROR"
  !  is computed exactly in the same manner for both
  !  non-hydrostatic and hydrostatic models.
  !  Of course, if the model is non-hydrostatic,
  !  the errors on NH variables will contaminate the
  !  "hydrostatic" variables, so it is not necessary
  !  to take account of the non-hydrostatic variables
  !  in the calculation of ZERROR.

  IF( LREFGEN .AND. NSTEP == NSTOP )THEN
    IF( INSMAX < 1000 )THEN
      WRITE(CLNAME,'("ref_",I3.3,"_",I4.4)') INSMAX, NSTOP
    ELSE
      WRITE(CLNAME,'("ref_",I4.4,"_",I4.4)') INSMAX, NSTOP
    ENDIF
    OPEN(NULREF,FILE=CLNAME)
    IF (LRWSDLR) THEN
      CLSP='   LOG(PRESIMS)   '
    ELSE
      CLSP='   LOG(PREHYDS)   '
    ENDIF
    WRITE(NULREF,'(1(1X,2A,1X,E21.15))') TRIM(CLTEXT),CLSP,ZSPNORM  
    IF (IFTHER > 0 .AND. INUMSPFLDS>0 .AND. LLSPQ) THEN
      WRITE(NULREF,'(6(1X,A))') 'LEV'&
       & ,'    VORTICITY        ', '    DIVERGENCE       '&
       & ,'   TEMPERATURE       ', '    HUMIDITY         '&
       & ,'   KINETIC ENERGY    '  
      WRITE(NULREF,'(1X,A,5(1X,E21.15))')&
       & 'AVE',ZVORAVE,ZDIVAVE,ZTHEAVE(IT),ZGFLAVE(IQ),ZKEAVE  
    ELSEIF(IFTHER > 0 .AND. (.NOT.LLSPQ))THEN
      WRITE(NULREF,'(5(1X,A))') 'LEV'&
       & ,'    VORTICITY        '&
       & ,'    DIVERGENCE       '&
       & ,'   TEMPERATURE       '&
       & ,'   KINETIC ENERGY    '  
      WRITE(NULREF,'(1X,A,4(1X,E21.15))')&
       & 'AVE',ZVORAVE,ZDIVAVE,ZTHEAVE(IT),ZKEAVE  
    ELSE
      WRITE(NULREF,'(5(1X,A))') 'LEV'&
       & ,'    VORTICITY        '&
       & ,'    DIVERGENCE       '&
       & ,'   KINETIC ENERGY    '  
      WRITE(NULREF,'(1X,A,3(1X,E21.15))')&
       & 'AVE',ZVORAVE,ZDIVAVE,ZKEAVE  
    ENDIF
    DO JLEV=1,ILEVXG
      IF (IFTHER > 0 .AND. INUMSPFLDS>0 .AND. LLSPQ) THEN
        WRITE(NULREF,'(1X,I3,5(1X,E21.15))')JLEV &
         & ,ZVORNORM(JLEV),ZDIVNORM(JLEV)&
         & ,ZTHENORM(JLEV,IT),ZGFLNORM(JLEV,IQ),ZKENORM(JLEV)  
      ELSEIF(IFTHER > 0 .AND. (.NOT.LLSPQ))THEN
        WRITE(NULREF,'(1X,I3,4(1X,E21.15))')JLEV &
         & ,ZVORNORM(JLEV),ZDIVNORM(JLEV)&
         & ,ZTHENORM(JLEV,IT),ZKENORM(JLEV)  
      ELSE
        WRITE(NULREF,'(1X,I3,3(1X,E21.15))')JLEV &
         & ,ZVORNORM(JLEV),ZDIVNORM(JLEV)&
         & ,ZKENORM(JLEV)  
      ENDIF
    ENDDO
    CLOSE(NULREF)
  ENDIF

!     ------------------------------------------------------------------

!*       7.    Compare norms against reference output
!              --------------------------------------

  IF( LREFOUT .AND. NSTEP == NSTOP )THEN
    IF( INSMAX < 1000 )THEN
      WRITE(CLNAME,'("ref_",I3.3,"_",I4.4)') INSMAX, NSTOP
    ELSE
      WRITE(CLNAME,'("ref_",I4.4,"_",I4.4)') INSMAX, NSTOP
    ENDIF
    INQUIRE(FILE=CLNAME,EXIST=LLEXIST)
    IF( LLEXIST )THEN

      OPEN(NULREF,FILE=CLNAME,ACTION='READ')

!  Surface Pressure

      READ(NULREF,'(1X,A35,1X,E21.15)') CLDUMMY,ZSPNORM1
      ZSP=ZSPNORM(1)-ZSPNORM1
      ZERROR=ZSP/ZSPNORM1
      ZERROR=SQRT(ZERROR*ZERROR)*100._JPRB

!  Skip over header and AVE line

      READ(NULREF,'(A)') CLDUMMY
      READ(NULREF,'(A)') CLDUMMY
      ZEPS=1.E-20_JPRB
      ZSKDIF=0.0_JPRB
      ZSKREF=0.0_JPRB
      ZSVDIF=0.0_JPRB
      ZSVREF=0.0_JPRB
      ZSDDIF=0.0_JPRB
      ZSDREF=0.0_JPRB
      ZSTDIF=0.0_JPRB
      ZSTREF=0.0_JPRB
      ZSRDIF=0.0_JPRB
      ZSRREF=0.0_JPRB

!  Loop over levels

      DO JLEV=1,ILEVXG
        IF (IFTHER > 0 .AND. INUMSPFLDS>0 .AND. LLSPQ) THEN
          READ(NULREF,'(1X,I3,5(1X,E21.15))')ILEV,ZVOR1,ZDIV1,ZTHET,ZGFLQ,ZKE1
        ELSEIF(IFTHER > 0 .AND. (.NOT.LLSPQ))THEN
          READ(NULREF,'(1X,I3,4(1X,E21.15))')ILEV,ZVOR1,ZDIV1,ZTHET,ZKE1
        ELSE
          READ(NULREF,'(1X,I3,3(1X,E21.15))')ILEV,ZVOR1,ZDIV1,ZKE1
        ENDIF
        IF( ILEV /= JLEV )THEN
          WRITE(NULOUT,'(" SPNORM: PROBLEM IN READING REFERENCE ",&
           & "LEVELS,ILEV=",I3," JLEV=",I3)')ILEV,JLEV  
          CALL ABOR1('SPNORM: LREFOUT LEVEL PROBLEM")')
        ENDIF
        
!  Vorticity

        ZVDIF=ZVORNORM(JLEV)-ZVOR1
        ZSVDIF=ZSVDIF+SQRT(ZVDIF*ZVDIF)
        ZSVREF=ZSVREF+SQRT(ZVOR1*ZVOR1)
        IF( ZSVDIF > 0.0_JPRB )THEN
          ZERROR=MAX(ZERROR,ZSVDIF/(ZSVREF+ZEPS)*100._JPRB)
        ENDIF

!  Divergence

        ZDDIF=ZDIVNORM(JLEV)-ZDIV1
        ZSDDIF=ZSDDIF+SQRT(ZDDIF*ZDDIF)
        ZSDREF=ZSDREF+SQRT(ZDIV1*ZDIV1)
        IF( ZSDDIF > 0.0_JPRB )THEN
          ZERROR=MAX(ZERROR,ZSDDIF/(ZSDREF+ZEPS)*100._JPRB)
        ENDIF

!  Temperature

        IF(IFTHER > 0)THEN
          ZTDIF=ZTHENORM(JLEV,IT)-ZTHET
          ZSTDIF=ZSTDIF+SQRT(ZTDIF*ZTDIF)
          ZSTREF=ZSTREF+SQRT(ZTHET*ZTHET)
          IF( ZSTDIF > 0.0_JPRB )THEN
            ZERROR=MAX(ZERROR,ZSTDIF/(ZSTREF+ZEPS)*100._JPRB)
          ENDIF
        ENDIF

!  Humidity

        IF(LLSPQ)THEN
          ZRDIF=ZGFLNORM(JLEV,IQ)-ZGFLQ
          ZSRDIF=ZSRDIF+SQRT(ZRDIF*ZRDIF)
          ZSRREF=ZSRREF+SQRT(ZGFLQ*ZGFLQ)
          IF( ZSRDIF > 0.0_JPRB )THEN
            ZERROR=MAX(ZERROR,ZSRDIF/(ZSRREF+ZEPS)*100._JPRB)
          ENDIF
        ENDIF

!  Kinetic Energy

        ZKDIF=ZKENORM(JLEV)-ZKE1
        ZSKDIF=ZSKDIF+SQRT(ZKDIF*ZKDIF)
        ZSKREF=ZSKREF+SQRT(ZKE1*ZKE1)
        IF( ZSKDIF > 0.0_JPRB )THEN
          ZERROR=MAX(ZERROR,ZSKDIF/(ZSKREF+ZEPS)*100._JPRB)
        ENDIF
      ENDDO

      CLOSE(NULREF)

!  Display results of error calculation

      IF( INSMAX < 1000 )THEN
        WRITE(CLNAME,'("res_",I3.3,"_",I4.4)') INSMAX, NSTOP
      ELSE
        WRITE(CLNAME,'("res_",I4.4,"_",I4.4)') INSMAX, NSTOP
      ENDIF
      OPEN(NULREF,FILE=CLNAME)
      WRITE(NULREF,'(" ")')
      WRITE(NULREF,'(" ")')
      WRITE(NULREF,'(" ")')
      WRITE(NULREF,'(15X,"Results of ERROR calculation")')
      WRITE(NULREF,'(" ")')
      WRITE(NULREF,'(" ")')
      WRITE(NULREF,'(" ")')
      WRITE(NULREF,'(" The error calculated from the results"," shows")')
      IF( ZERROR > 1.0_JPRB )THEN
        WRITE(NULREF,'(" that the calculations are NOT correct")')
      ELSE
        WRITE(NULREF,'(" that the calculations are correct")')
      ENDIF
      WRITE(NULREF,'(" ")')
      WRITE(NULREF,'(" The maximum error is = ",F15.5," %")')ZERROR
      WRITE(NULREF,'(" ")')
      CLOSE(NULREF)
    ENDIF
  ENDIF

!     ------------------------------------------------------------------

!*       8.    Print spectrums at total wave number N.
!              ---------------------------------------

  IF (LLNWAVE) THEN
    WRITE(NULOUT,'('' SPECTRUM (TOTAL WAVE NUMBER N)  '')')

    WRITE(NULOUT,'('' KINETIC ENERGY SPECTRUM '')')
    CLVAR='NKE '
    CALL PRTSPNO(NULOUT,NFLEVG,ILEVXG,INSMAX,CLVAR,ZNKEG)

    WRITE(NULOUT,'('' VORTICITY      SPECTRUM '')')
    CLVAR='NVOR'
    CALL PRTSPNO(NULOUT,NFLEVG,ILEVXG,INSMAX,CLVAR,ZNVORG)

    WRITE(NULOUT,'('' DIVERGENCE     SPECTRUM '')')
    CLVAR='NDIV'
    CALL PRTSPNO(NULOUT,NFLEVG,ILEVXG,INSMAX,CLVAR,ZNDIVG)

    IF(IFTHER > 0)THEN

      WRITE(NULOUT,'('' TEMPERATURE    SPECTRUM '')')
      CLVAR='NT  '
      CALL PRTSPNO(NULOUT,NFLEVG,ILEVXG,INSMAX,CLVAR,ZNTHEG(1,0,IT))

      IF (LNHDYN) THEN

        IF (NPDVAR == 2 .AND. (.NOT.LRWSDLR)) THEN
          CLNSPD=' LOG(PRE/PREHYD) SPECTRUM     '
        ELSEIF (NPDVAR == 2 .AND. LRWSDLR) THEN
          CLNSPD=' LOG(PRE/PRESIM) SPECTRUM     '
        ELSEIF (NPDVAR == 3) THEN
          CLNSPD=' PHI-B*PHIS SPECTRUM '
        ELSEIF (NPDVAR == 4) THEN
          CLNSPD=' PHI SPECTRUM     '
        ENDIF
        WRITE(NULOUT,'(A)') CLNSPD
        CLVAR='NSPD'
        CALL PRTSPNO(NULOUT,NFLEVG,ILEVXG,INSMAX,CLVAR,ZNTHEG(1,0,ISPD))

        IF (NVDVAR == 3) THEN
          CLNSVD=' VERT DIVERGENCE SPECTRUM     '
        ELSEIF (NVDVAR == 4) THEN
          CLNSVD=' (d4 = VERT DIV + X) SPECTRUM '
        ELSEIF (NVDVAR == 5) THEN
          CLNSVD=' (gw - B*gw_s) SPECTRUM       '
        ELSEIF (NVDVAR == 6) THEN
          CLNSVD=' (gw) SPECTRUM                '
        ENDIF
        WRITE(NULOUT,'(A)') CLNSVD
        CLVAR='NSVD'
        CALL PRTSPNO(NULOUT,NFLEVG,ILEVXG,INSMAX,CLVAR,ZNTHEG(1,0,ISVD))

      ENDIF

    ENDIF

    IF(LLSPQ)THEN
      WRITE(NULOUT,'('' HUMIDITY       SPECTRUM '')')
      CLVAR='NQ  '
      CALL PRTSPNO(NULOUT,NFLEVG,ILEVXG,INSMAX,CLVAR,ZNGFLG(1,0,IQ))
    ENDIF

    IF (LRWSDLR) THEN
      WRITE(NULOUT,'('' LOG(PRESIMS) SPECTRUM '')')
    ELSE
      WRITE(NULOUT,'('' LOG(PREHYDS) SPECTRUM '')')
    ENDIF
    CLVAR='NSP '
    CALL PRTSPNO(NULOUT,1,1,INSMAX,CLVAR,ZNSPG)

    WRITE(NULOUT,'('' OROGRAPHY SPECTRUM '')')
    CLVAR='NORO'
    CALL PRTSPNO(NULOUT,1,1,INSMAX,CLVAR,ZNSPORG)

  ENDIF

!     ------------------------------------------------------------------

!*       9.    Print spectrums at zonal wave number M.
!              ---------------------------------------

  IF(LLPRTAL) THEN
    WRITE(NULOUT,'('' SPECTRUM (ZONAL WAVE NUMBER M)  '')')

    WRITE(NULOUT,'('' KINETIC ENERGY SPECTRUM '')')
    CLVAR='MKE '
    CALL PRTSPNO(NULOUT,NFLEVG,ILEVXG,INSMAX,CLVAR,ZMKEG)

    WRITE(NULOUT,'('' VORTICITY      SPECTRUM '')')
    CLVAR='MVOR'
    CALL PRTSPNO(NULOUT,NFLEVG,ILEVXG,INSMAX,CLVAR,ZMVORG)

    WRITE(NULOUT,'('' DIVERGENCE     SPECTRUM '')')
    CLVAR='MDIV'
    CALL PRTSPNO(NULOUT,NFLEVG,ILEVXG,INSMAX,CLVAR,ZMDIVG)

    IF(IFTHER > 0)THEN

      WRITE(NULOUT,'('' TEMPERATURE    SPECTRUM '')')
      CLVAR='MT  '
      CALL PRTSPNO(NULOUT,NFLEVG,ILEVXG,INSMAX,CLVAR,ZMTHEG(1,0,IT))

      IF (LNHDYN) THEN

        IF (NPDVAR == 2 .AND. (.NOT.LRWSDLR)) THEN
          CLNSPD=' LOG(PRE/PREHYD) SPECTRUM     '
        ELSEIF (NPDVAR == 2 .AND. LRWSDLR) THEN
          CLNSPD=' LOG(PRE/PRESIM) SPECTRUM     '
        ELSEIF (NPDVAR == 3) THEN
          CLNSPD=' PHI-B*PHIS SPECTRUM '
        ELSEIF (NPDVAR == 4) THEN
          CLNSPD=' PHI SPECTRUM     '
        ENDIF
        WRITE(NULOUT,'(A)') CLNSPD
        CLVAR='MSPD'
        CALL PRTSPNO(NULOUT,NFLEVG,ILEVXG,INSMAX,CLVAR,ZMTHEG(1,0,ISPD))

        IF (NVDVAR == 3) THEN
          CLNSVD=' VERT DIVERGENCE SPECTRUM     '
        ELSEIF (NVDVAR == 4) THEN
          CLNSVD=' (d4 = VERT DIV + X) SPECTRUM '
        ELSEIF (NVDVAR == 5) THEN
          CLNSVD=' (gw - B*gw_s) SPECTRUM       '
        ELSEIF (NVDVAR == 6) THEN
          CLNSVD=' (gw) SPECTRUM                '
        ENDIF
        WRITE(NULOUT,'(A)') CLNSVD
        CLVAR='MSVD'
        CALL PRTSPNO(NULOUT,NFLEVG,ILEVXG,INSMAX,CLVAR,ZMTHEG(1,0,ISVD))

      ENDIF

    ENDIF

    IF(LLSPQ)THEN
      WRITE(NULOUT,'('' HUMIDITY       SPECTRUM '')')
      CLVAR='MQ  '
      CALL PRTSPNO(NULOUT,NFLEVG,ILEVXG,INSMAX,CLVAR,ZMGFLG(1,0,IQ))
    ENDIF

    IF (LRWSDLR) THEN
      WRITE(NULOUT,'('' LOG(PRESIMS) SPECTRUM '')')
    ELSE
      WRITE(NULOUT,'('' LOG(PREHYDS) SPECTRUM '')')
    ENDIF
    CLVAR='MSP '
    CALL PRTSPNO(NULOUT,1,1,INSMAX,CLVAR,ZMSPG)

    WRITE(NULOUT,'('' OROGRAPHY SPECTRUM '')')
    CLVAR='MORO'
    CALL PRTSPNO(NULOUT,1,1,INSMAX,CLVAR,ZMSPORG)

  ENDIF

!     ------------------------------------------------------------------

!*      10.1   Compute norms of derivatives in spectral space.
!              -----------------------------------------------

  IF(LLPRTAL) THEN
    DO JVAR=1,IFTHER
      CALL SPNORMAVE(INSMAX,ZMTHEDEG(1,0,JVAR),NFLEVG,ILEVXG,&
       & .FALSE.,ZTHENORM(1,JVAR),ZTHEAVE(JVAR))  
    ENDDO
    DO JVAR=1,INUMSPFLDS
      CALL SPNORMAVE(INSMAX,ZMGFLDEG(1,0,JVAR),NFLEVG,ILEVXG,&
       & .FALSE.,ZGFLNORM(1,JVAR),ZGFLAVE(JVAR))  
    ENDDO

    IF(NFD2D > 0)THEN
      CALL SPNORMAVE(INSMAX,ZMSPDEG,1,1,.FALSE.,ZSPNORM,ZSPAVE)
    ELSE
      ZSPNORM=-.9999999_JPRB
      ZSPAVE =-.9999999_JPRB
    ENDIF
  ENDIF

!*      10.2   Print averages of derivatives
!              -----------------------------

  IF(LLPRTAL) THEN

    WRITE(NULOUT,'(A)')' *** NORMS OF DERIVATIVES IN SPECTRAL SPACE ***'

    IF (LRWSDLR) THEN
      CLSP='   LOG(PRESIMS)   '
    ELSE
      CLSP='   LOG(PREHYDS)   '
    ENDIF

    IF (IFTHER > 0 .AND. INUMSPFLDS>0 .AND. LLSPQ) THEN
      WRITE(NULOUT,'(4(1X,A))') 'LEV','    TEMPERATURE     '&
       & ,'     HUMIDITY       ',CLSP
      WRITE(NULOUT,'(1X,A,3(1X,E21.15))') 'AVE',ZTHEAVE(IT)&
       & ,ZGFLAVE(IQ),ZSPNORM  
      DO JLEV=1,ILEVXG
        WRITE(NULOUT,'(1X,I3,2(1X,E21.15))')JLEV,ZTHENORM(JLEV,IT)&
         & ,ZGFLNORM(JLEV,IQ)  
      ENDDO
    ELSEIF (IFTHER > 0 .AND. (.NOT.LLSPQ)) THEN
      WRITE(NULOUT,'(4(1X,A))') 'LEV','    TEMPERATURE     ',CLSP
      WRITE(NULOUT,'(1X,A,2(1X,E21.15))') 'AVE',ZTHEAVE(IT)&
       & ,ZSPNORM  
      DO JLEV=1,ILEVXG
        WRITE(NULOUT,'(1X,I3,(1X,E21.15))')JLEV,ZTHENORM(JLEV,IT)
      ENDDO
    ELSE
      WRITE(NULOUT,'(1X,A)') CLSP 
      WRITE(NULOUT,'(1X,A,1X,E21.15)') 'AVE',ZSPNORM
    ENDIF

    IF (LNHDYN) THEN
      WRITE(NULOUT,'(3(1X,A))') 'LEV',CLSPD,CLSVD
      WRITE(NULOUT,'(1X,A,2(1X,E21.15))') 'AVE',ZTHEAVE(ISPD),ZTHEAVE(ISVD)
      DO JLEV=1,ILEVXG
        WRITE(NULOUT,'(1X,I3,2(1X,E21.15))')JLEV,ZTHENORM(JLEV,ISPD)&
         & ,ZTHENORM(JLEV,ISVD)
      ENDDO
    ENDIF

  ENDIF

ENDIF

IF (LLCOROG) THEN
  CALL FLUSH(NULOUT)
ENDIF
LLCOROG=.FALSE.
CALL GSTATS(12,1)

!     ------------------------------------------------------------------

!*      11.    Deallocations.
!              --------------

IF(ALLOCATED(ZNVORG))   DEALLOCATE(ZNVORG)
IF(ALLOCATED(ZMVORG))   DEALLOCATE(ZMVORG)
IF(ALLOCATED(ZNDIVG))   DEALLOCATE(ZNDIVG)
IF(ALLOCATED(ZMDIVG))   DEALLOCATE(ZMDIVG)
IF(ALLOCATED(ZNKEG))    DEALLOCATE(ZNKEG)
IF(ALLOCATED(ZMKEG))    DEALLOCATE(ZMKEG)
IF(ALLOCATED(ZNTHEG))   DEALLOCATE(ZNTHEG)
IF(ALLOCATED(ZMTHEG))   DEALLOCATE(ZMTHEG)
IF(ALLOCATED(ZNGFLG))   DEALLOCATE(ZNGFLG)
IF(ALLOCATED(ZMGFLG))   DEALLOCATE(ZMGFLG)
IF(ALLOCATED(ZNSPG))    DEALLOCATE(ZNSPG)
IF(ALLOCATED(ZMSPG))    DEALLOCATE(ZMSPG)
IF(ALLOCATED(ZNSPORG))  DEALLOCATE(ZNSPORG)
IF(ALLOCATED(ZMSPORG))  DEALLOCATE(ZMSPORG)
IF(ALLOCATED(ZNTHEDEG)) DEALLOCATE(ZNTHEDEG)
IF(ALLOCATED(ZMTHEDEG)) DEALLOCATE(ZMTHEDEG)
IF(ALLOCATED(ZNGFLDEG)) DEALLOCATE(ZNGFLDEG)
IF(ALLOCATED(ZMGFLDEG)) DEALLOCATE(ZMGFLDEG)
IF(ALLOCATED(ZNSPDEG))  DEALLOCATE(ZNSPDEG)
IF(ALLOCATED(ZMSPDEG))  DEALLOCATE(ZMSPDEG)
IF(ALLOCATED(ZNGFLG))   DEALLOCATE(ZNGFLG)
IF(ALLOCATED(ZMGFLG))   DEALLOCATE(ZMGFLG)
IF(ALLOCATED(ZNGFL))    DEALLOCATE(ZNGFL)
IF(ALLOCATED(ZMGFL))    DEALLOCATE(ZMGFL)
IF(ALLOCATED(ZGFLNORM)) DEALLOCATE(ZGFLNORM)
IF(ALLOCATED(ZGFLAVE))  DEALLOCATE(ZGFLAVE)
IF(ALLOCATED(ZNGFLDEG)) DEALLOCATE(ZNGFLDEG)
IF(ALLOCATED(ZMGFLDEG)) DEALLOCATE(ZMGFLDEG)
IF(ALLOCATED(ZNGFLDE))  DEALLOCATE(ZNGFLDE)
IF(ALLOCATED(ZMGFLDE))  DEALLOCATE(ZMGFLDE)
IF(ALLOCATED(ZNTHE))    DEALLOCATE(ZNTHE)
IF(ALLOCATED(ZMTHE))    DEALLOCATE(ZMTHE)
IF(ALLOCATED(ZTHENORM)) DEALLOCATE(ZTHENORM)
IF(ALLOCATED(ZTHEAVE))  DEALLOCATE(ZTHEAVE)
IF(ALLOCATED(ZNTHEDE))  DEALLOCATE(ZNTHEDE)
IF(ALLOCATED(ZMTHEDE))  DEALLOCATE(ZMTHEDE)

IF (NSPPR >= 1) WRITE(NULOUT,*)

CALL FLUSH(NULOUT)

!     ------------------------------------------------------------------

IF (LHOOK) CALL DR_HOOK('SPNORM',1,ZHOOK_HANDLE)
END SUBROUTINE SPNORM
