SUBROUTINE SURAND2(KSTEP)

!**** *SURAND2*  - Initialize stochastic physic parameters - part 2

!     Purpose.
!     --------
!           Compute random numbers

!**   Interface.
!     ----------
!        *CALL* *SURAND2

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

!        Implicit arguments :
!        --------------------
!        COMMON STOPH_MIX

!     Method.
!     -------
!        See documentation

!     Externals.
!     ----------
!        None

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

!     Author.
!     -------
!        R Buizza and L Isaksen - ECMWF - 

!     Modifications.
!     --------------
!        Original : 97-11-20
!        M.Hamrud      01-Oct-2003 CY28 Cleaning
!        J.Berner 06-08-11 added cellular automaton backscatter and 
!                          spectral AR backscatter update
!        G. Shutts 09-03-4 spectral backscatter update
!        M. Steinheimer 09-03-05 added option RVP
!        M. Steinheimer 09-10-27 spectral backscatter update (changes to RVP,
!                          changes related to option LSTOPH_SPBS_FAST)
!     ------------------------------------------------------------------

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


USE STOPH_MIX , ONLY : LSTOPH, ADLATSTOPH, ADLONSTOPH, RSTOPHU, RSTOPHV, RSTOPHT, RSTOPHQ, & 
 &  LSTOPH_CASBS, RSTOPHCA, ADLATSTOPH_CA, ADLONSTOPH_CA, MCELL, RWGHT, & 
 &  LSTOPH_SPBS,SPSTREAM, SPG_AMP,ALPHA_STO, NFRSTOPH, LSTOPH_JBCOR, &
 &  SQRTCORR, LSTOPH_UNIFORM, LSTOPH_UNCORR, &
 &  LSTOPH_RVP, NIMRAN, RVP_MULFACT, RVP_MUL,&
 &  LSTOPH_TAPER, TAPER_FACT, &
 &  LSTOPH_INI, ONEMINALPHA_NFRSPBS, NFRSTOPH_SPBS_PAT, &
 &  LSTOPH_SPBS_T,SPTEMP,SPG_AMP_T,ALPHA_STO_T,ONEMINALPHA_NFRSPBS_T, &
 &  RVP_MULFACT_T, RVP_MUL_T, NSMAXSPBS
USE YOMGC    , ONLY : GELAM     , GELAT
USE YOMGEM   , ONLY : NGPTOT
USE RANDOM_NUMBERS_MIX , ONLY : UNIFORM_DISTRIBUTION, GAUSSIAN_DISTRIBUTION

USE YOMRANDOM_STREAMS, ONLY  : YD_RANDOM_STREAM_STOCHPHYS, YD_RANDOM_STREAM_STOCHPHYS_SPBS, &
                             & YD_RANDOM_STREAM_STOCHPHYS_RVP, &
                             & YD_RANDOM_STREAM_STOPH_SPBS_T, YD_RANDOM_STREAM_STOPH_RVP_T

!    ------- more variables for spectral backscatter

USE YOMDIM    ,ONLY : NSMAX, NSPEC2, NSPEC2G, NFLEVL, NUMP, NFLEVG
USE YOMLAP    ,ONLY : NASM0    , MYMS 
USE YOMLUN    ,ONLY : NULOUT !, NULERR
USE YOMMP     ,ONLY : MYLEVS
USE YOMMPG    ,ONLY : NDIM0G ! NDIM0G    : Defines partitioning of global spectral fields among PEs
USE YOE_CUCONVCA, ONLY : LCUCONV_CA


IMPLICIT NONE
INTEGER(KIND=JPIM),INTENT(IN)    :: KSTEP

REAL(KIND=JPRB), ALLOCATABLE :: ZGLPTSU(:,:), ZGLPTSV(:,:), ZGLPTST(:,:),ZGLPTSQ(:,:)
REAL(KIND=JPRB) :: Z, ZCONV, ZEPS, ZLAT, ZLON, ZRAND_NOS_RE, ZRAND_NOS_IM
INTEGER(KIND=JPIM) :: ILATBOX, ILONBOX, JROF, J, IIP, JJP, JGL

!     ----------------variables for spectral backscatter

INTEGER(KIND=JPIM) :: ILEV, IM, IN, JMLOC, JN, IJSE, ILEVG, ILEVGPTR
INTEGER(KIND=JPIM) :: INDSP2G_RE_RAN, INDSP2G_IM_RAN

REAL(KIND=JPRB), ALLOCATABLE :: ZRAND_NOS(:)  ! Either one or NFLEVG global spectral field of random numbers, 
!                                               dependent on LSTOPH_UNCORR

REAL(KIND=JPRB), ALLOCATABLE :: ZRAND_RVP(:,:)  ! Random vertical profile, used if LSTOPH_RVP == .true.
REAL(KIND=JPRB), ALLOCATABLE :: ZRAND_UNI(:)

!     ----------------variables for random vertical profile
REAL(KIND=JPRB)    :: ZPHI, ZABS, ZRT
INTEGER(KIND=JPIM) :: JI
REAL(KIND=JPRB) :: ZMUL
REAL(KIND=JPRB) :: ZFACT
REAL(KIND=JPRB) :: ZFACT0
REAL(KIND=JPRB) :: ZSTDEV
REAL(KIND=JPRB) :: ZHOOK_HANDLE

!     ----------------variables for T-backscatter
REAL(KIND=JPRB), ALLOCATABLE :: ZRAND_NOS_T(:)
REAL(KIND=JPRB), ALLOCATABLE :: ZRAND_RVP_T(:,:)
REAL(KIND=JPRB), ALLOCATABLE :: ZRAND_UNI_T(:)
REAL(KIND=JPRB)    :: ZPHI_T, ZABS_T, ZRT_T
REAL(KIND=JPRB) :: ZMUL_T
REAL(KIND=JPRB) :: ZRAND_NOS_RE_T, ZRAND_NOS_IM_T

#include "updcelaut.intfb.h"

IF (LHOOK) CALL DR_HOOK('SURAND2',0,ZHOOK_HANDLE)
ZCONV = 45._JPRB/ATAN(1.0_JPRB)
ZEPS  = 1000._JPRB*TINY(Z)



IF (LSTOPH .AND. MOD(KSTEP,NFRSTOPH) == 0) THEN

!     --------------------------------------------------
!*    1.  STOCHASTIC DIABATIC TENDENCIES
!     --------------------------------------------------

!     A random number r, 0<=r<1, is generated for each box with
!     dimension ADLONSTOPH,ADLATSTOPH, and then used for all the
!     grid points inside that box.

!*    1.  Generate random numbers for stochastic physics
!     --------------------------------------------------
!     1.1 A random number is generated for each box

ALLOCATE(ZGLPTSU(NINT(360._JPRB/ADLONSTOPH),NINT(180._JPRB/ADLATSTOPH)))
ALLOCATE(ZGLPTSV(NINT(360._JPRB/ADLONSTOPH),NINT(180._JPRB/ADLATSTOPH)))
ALLOCATE(ZGLPTST(NINT(360._JPRB/ADLONSTOPH),NINT(180._JPRB/ADLATSTOPH)))
ALLOCATE(ZGLPTSQ(NINT(360._JPRB/ADLONSTOPH),NINT(180._JPRB/ADLATSTOPH)))

DO J=1,NINT(180._JPRB/ADLATSTOPH)
  CALL UNIFORM_DISTRIBUTION (ZGLPTSU(:,J),YD_RANDOM_STREAM_STOCHPHYS)
  CALL UNIFORM_DISTRIBUTION (ZGLPTSV(:,J),YD_RANDOM_STREAM_STOCHPHYS)
  CALL UNIFORM_DISTRIBUTION (ZGLPTST(:,J),YD_RANDOM_STREAM_STOCHPHYS)
  CALL UNIFORM_DISTRIBUTION (ZGLPTSQ(:,J),YD_RANDOM_STREAM_STOCHPHYS)
ENDDO

!     1.2 A random number is defined for each grid point, so that
!         grid points inside the same box have the same random number

CALL GSTATS(1412,0)
!$OMP PARALLEL DO SCHEDULE(STATIC) PRIVATE(JROF,ZLON,ZLAT,ILATBOX,ILONBOX)
DO JROF=1,NGPTOT
  ZLON=GELAM(JROF)*ZCONV
  ZLAT=GELAT(JROF)*ZCONV

  ILATBOX=INT((90._JPRB-ZLAT)/(ADLATSTOPH+ZEPS))+1
  ILONBOX=INT(ZLON/(ADLONSTOPH+ZEPS))+1

  RSTOPHU(JROF)=ZGLPTSU(ILONBOX,ILATBOX)
  RSTOPHV(JROF)=ZGLPTSV(ILONBOX,ILATBOX)
  RSTOPHT(JROF)=ZGLPTST(ILONBOX,ILATBOX)
  RSTOPHQ(JROF)=ZGLPTSQ(ILONBOX,ILATBOX)
ENDDO
!$OMP END PARALLEL DO
CALL GSTATS(1412,1)

DEALLOCATE(ZGLPTSU, ZGLPTSV, ZGLPTST, ZGLPTSQ)

ENDIF


IF (LSTOPH_CASBS .AND. (.NOT. LCUCONV_CA)) THEN

!     ------------------------
!*    2.0 CASBS
!     ------------------------

!     2.1 UPDATE CELLULAR AUTOMATON  
!     -----------------------------------------------

  IIP= NINT(360._JPRB/ADLONSTOPH_CA)
  JJP= NINT(180._JPRB/ADLATSTOPH_CA)

  CALL UPDCELAUT(MCELL,RWGHT,IIP,JJP)

!     2.2 generate smooth pattern from CA (on Gaussian grid)
!     -----------------------------------------------

!$OMP PARALLEL DO SCHEDULE(STATIC) PRIVATE(JROF,ZLON,ZLAT,ILATBOX,ILONBOX)
  DO JROF=1,NGPTOT
     ZLON=GELAM(JROF)*ZCONV
     ZLAT=GELAT(JROF)*ZCONV
     ILATBOX=INT((90._JPRB-ZLAT)/(ADLATSTOPH_CA+ZEPS))+1
     ILONBOX=INT(ZLON/(ADLONSTOPH_CA+ZEPS))+1
     RSTOPHCA(JROF)= RWGHT(ILONBOX,ILATBOX)*COS(GELAT(JROF))
  ENDDO
!$OMP END PARALLEL DO

ENDIF

IF (LSTOPH_SPBS .AND. MOD(KSTEP,NFRSTOPH_SPBS_PAT) == 0) THEN

!     ------------------------
!*    3.0 SPECTRAL BACKSCATTER
!     ------------------------

  IF (.NOT.LSTOPH_JBCOR.AND..NOT.LSTOPH_UNCORR) THEN
    ! Same random number is used for all vertical levels (fully correlated)
    ! RVP-style correlations may be introduced by setting LSTOPH_RVP=.T.
    ALLOCATE(ZRAND_NOS(NSPEC2G))
    IF (LSTOPH_SPBS_T) ALLOCATE(ZRAND_NOS_T(NSPEC2G))
  ELSE
    ! Different random numbers used for each vertical level (uncorrelated)
    ! Jb-style correlations may be introduced by setting LSTOPH_JBCOR=.T.
    ALLOCATE(ZRAND_NOS(NFLEVG*NSPEC2G))
    IF (LSTOPH_SPBS_T) ALLOCATE(ZRAND_NOS_T(NFLEVG*NSPEC2G))
  ENDIF


  !     3.1 UPDATE MARKOV CHAIN OF SPECTRAL WAVENUMBERS
  !     -----------------------------------------------
  IF (LSTOPH_UNIFORM) THEN
    CALL UNIFORM_DISTRIBUTION(ZRAND_NOS,YD_RANDOM_STREAM_STOCHPHYS_SPBS)
    IF (LSTOPH_SPBS_T) CALL UNIFORM_DISTRIBUTION(ZRAND_NOS_T,YD_RANDOM_STREAM_STOPH_SPBS_T)
  ELSE
    CALL GAUSSIAN_DISTRIBUTION(ZRAND_NOS,YD_RANDOM_STREAM_STOCHPHYS_SPBS)
    ! Change standard deviation of Gaussian distribution to be similar to
    ! standard deviation for a uniform distribution (st.dev=sqrt(1/12.))
    ZSTDEV=SQRT(1./12.)
    IF (KSTEP == 0)  &
     & WRITE(NULOUT,*) ' Standard deviation for Gaussian random distribution: ',ZSTDEV
    ZRAND_NOS(:)=ZSTDEV*ZRAND_NOS(:)
    IF (LSTOPH_SPBS_T) THEN
      CALL GAUSSIAN_DISTRIBUTION(ZRAND_NOS_T,YD_RANDOM_STREAM_STOPH_SPBS_T)
      ! Change standard deviation of Gaussian distribution to be similar to
      ! standard deviation for a uniform distribution (st.dev=sqrt(1/12.))
      ZSTDEV=SQRT(1./12.)
      ZRAND_NOS_T(:)=ZSTDEV*ZRAND_NOS_T(:)
    ENDIF
  ENDIF

  !     3.1.1 Random vertical profiles
  !     -----------------------------------------------
  IF (LSTOPH_RVP) THEN
    ALLOCATE(ZRAND_RVP(NFLEVG,NSPEC2))
    ALLOCATE(ZRAND_UNI(NFLEVG*NSPEC2G/2))

    CALL UNIFORM_DISTRIBUTION(ZRAND_UNI,YD_RANDOM_STREAM_STOCHPHYS_RVP)

    IF (LSTOPH_SPBS_T) THEN
      ALLOCATE(ZRAND_RVP_T(NFLEVG,NSPEC2))
      ALLOCATE(ZRAND_UNI_T(NFLEVG*NSPEC2G/2))
      CALL UNIFORM_DISTRIBUTION(ZRAND_UNI_T,YD_RANDOM_STREAM_STOPH_RVP_T)
    ENDIF


!$OMP  PARALLEL DO SCHEDULE(STATIC) & 
!$OMP& PRIVATE(JMLOC,IM,JN,IJSE,INDSP2G_RE_RAN,INDSP2G_IM_RAN,ZMUL,ZMUL_T,ZRAND_NOS_RE,ZRAND_NOS_IM,ZPHI,ZPHI_T)&
!$OMP& PRIVATE(ZABS,ZABS_T,JI,ZRT,ZRT_T,ILEVGPTR,ZRAND_NOS_RE_T,ZRAND_NOS_IM_T)
    DO JMLOC=1,NUMP !Number of spectral waves handled by this processor
      IM=MYMS(JMLOC) !actual wave numbers handled by this processor (confiremd: goes from 1-NSMAX)
      DO JN=IM,NSMAXSPBS
        IJSE=NASM0(IM)+2*(JN-IM)                 ! NASM0(0:NSMAX)  : address in a spectral array of (m, n=m)

        INDSP2G_RE_RAN = NIMRAN(IM)+(JN-IM)*2    ! index of real part in a sorted global spectral array of (m, n=m)
        INDSP2G_IM_RAN = NIMRAN(IM)+(JN-IM)*2+1  ! index of imaginary part in a sorted global spectral array of (m, n=m)

        !wavenumber dependent random number scaling
        ZMUL=RVP_MULFACT(JN)

        ZRAND_NOS_RE=ZRAND_NOS(INDSP2G_RE_RAN)
        ZRAND_NOS_IM=ZRAND_NOS(INDSP2G_IM_RAN)

        IF (LSTOPH_UNIFORM) THEN
          ZRAND_NOS_RE=ZRAND_NOS_RE-0.5
          ZRAND_NOS_IM=ZRAND_NOS_IM-0.5
        ENDIF

        IF (ZRAND_NOS_IM == 0._JPRB .AND. ZRAND_NOS_RE == 0._JPRB) THEN
           ZPHI=0._JPRB
        ELSE
           ZPHI=ATAN2(ZRAND_NOS_IM,ZRAND_NOS_RE)
        ENDIF
        ZABS=(ZRAND_NOS_RE**2+ZRAND_NOS_IM**2)**0.5

        ZRAND_RVP(1,IJSE)  =ZRAND_NOS_RE
        ZRAND_RVP(1,IJSE+1)=ZRAND_NOS_IM

        IF (LSTOPH_SPBS_T) THEN
          ZMUL_T=RVP_MULFACT_T(JN)

          ZRAND_NOS_RE_T=ZRAND_NOS_T(INDSP2G_RE_RAN)
          ZRAND_NOS_IM_T=ZRAND_NOS_T(INDSP2G_IM_RAN)

          IF (LSTOPH_UNIFORM) THEN
            ZRAND_NOS_RE_T=ZRAND_NOS_RE_T-0.5
            ZRAND_NOS_IM_T=ZRAND_NOS_IM_T-0.5
          ENDIF

          IF (ZRAND_NOS_IM_T == 0._JPRB .AND. ZRAND_NOS_RE_T == 0._JPRB) THEN
            ZPHI_T=0._JPRB
          ELSE
            ZPHI_T=ATAN2(ZRAND_NOS_IM_T,ZRAND_NOS_RE_T)
          ENDIF
          ZABS_T=(ZRAND_NOS_RE_T**2+ZRAND_NOS_IM_T**2)**0.5

          ZRAND_RVP_T(1,IJSE)  =ZRAND_NOS_RE_T
          ZRAND_RVP_T(1,IJSE+1)=ZRAND_NOS_IM_T
        ENDIF


        DO JI=2,NFLEVG
          ILEVGPTR=(JI-1)*NSPEC2G
          ZRT=ZRAND_UNI((ILEVGPTR+INDSP2G_IM_RAN)/2)

          IF ( ZRT > 1.0E-250_JPRB ) THEN   !to avoid infinit LOG(0) -> there are for sure better ways to do that
             ZRT=ZRT-0.5
             ZRT=SIGN(1._JPRB,ZRT)*LOG(1-2*ABS(ZRT))
          ELSE
              ZRT=0.
          ENDIF

         !scale random number and calculate new phase
          ZPHI=ZPHI+ZMUL*RVP_MUL(JI)*ZRT

          ZRAND_RVP(JI,IJSE)=ZABS*COS(ZPHI)
          ZRAND_RVP(JI,IJSE+1)=ZABS*SIN(ZPHI)

          IF (LSTOPH_SPBS_T) THEN
            ZRT_T=ZRAND_UNI_T((ILEVGPTR+INDSP2G_IM_RAN)/2)

            IF ( ZRT_T > 1.0E-250_JPRB ) THEN   !to avoid infinit LOG(0) -> there are for sure better ways to do that
              ZRT_T=ZRT_T-0.5
              ZRT_T=SIGN(1._JPRB,ZRT_T)*LOG(1-2*ABS(ZRT_T))
            ELSE
              ZRT_T=0.
            ENDIF

           !scale random number and calculate new phase
            ZPHI_T=ZPHI_T+ZMUL_T*RVP_MUL_T(JI)*ZRT_T

            ZRAND_RVP_T(JI,IJSE)=ZABS_T*COS(ZPHI_T)
            ZRAND_RVP_T(JI,IJSE+1)=ZABS_T*SIN(ZPHI_T)
          ENDIF
        ENDDO
      ENDDO
    ENDDO
!$OMP END PARALLEL DO
  ENDIF


!$OMP  PARALLEL DO SCHEDULE(STATIC) &
!$OMP& PRIVATE(ILEV,ILEVG,ILEVGPTR,JMLOC,IM,JN,IJSE) &
!$OMP& PRIVATE(ZRAND_NOS_RE,ZRAND_NOS_IM,JGL,INDSP2G_RE_RAN,INDSP2G_IM_RAN) &
!$OMP& PRIVATE(ZFACT,ZFACT0)&
!$OMP& PRIVATE(ZRAND_NOS_RE_T,ZRAND_NOS_IM_T)
  DO ILEV=1,NFLEVL
    ILEVG=MYLEVS(ILEV)   ! To assure perturbations are reproducible if NFLEVL is changed
    ILEVGPTR=(ILEVG-1)*NSPEC2G

    ZFACT=1._JPRB
    IF (LSTOPH_TAPER) THEN
       ZFACT=TAPER_FACT(ILEVG)
    ENDIF

    DO JMLOC=1,NUMP !Number of spectral waves handled by this processor
      IM=MYMS(JMLOC) !actual wave numbers handled by this processor (confiremd: goes from 1-NSMAX)
      DO JN=IM,NSMAXSPBS
        IJSE=NASM0(IM)+2*(JN-IM) ! NASM0(0:NSMAX)  : address in a spectral array of (m, n=m)

        INDSP2G_RE_RAN = NIMRAN(IM)+(JN-IM)*2    ! index of real part in a sorted global spectral array of (m, n=m)
        INDSP2G_IM_RAN = NIMRAN(IM)+(JN-IM)*2+1  ! index of imaginary part in a sorted global spectral array of (m, n=m)

        ZRAND_NOS_RE=0.0
        ZRAND_NOS_IM=0.0
        IF (LSTOPH_SPBS_T) THEN
          ZRAND_NOS_RE_T=0.0
          ZRAND_NOS_IM_T=0.0
        ENDIF

        IF (LSTOPH_UNCORR) THEN
          ZRAND_NOS_RE=ZRAND_NOS(ILEVGPTR+INDSP2G_RE_RAN)
          ZRAND_NOS_IM=ZRAND_NOS(ILEVGPTR+INDSP2G_IM_RAN)
          IF (LSTOPH_SPBS_T) THEN
            ZRAND_NOS_RE_T=ZRAND_NOS_T(ILEVGPTR+INDSP2G_RE_RAN)
            ZRAND_NOS_IM_T=ZRAND_NOS_T(ILEVGPTR+INDSP2G_IM_RAN)
          ENDIF
        ELSEIF (LSTOPH_JBCOR) THEN
          DO JGL=1,ILEVG
            ZRAND_NOS_RE=ZRAND_NOS_RE+ZRAND_NOS((JGL-1)*NSPEC2G+INDSP2G_RE_RAN)* &
               & SQRTCORR(JGL,ILEVG)

            ZRAND_NOS_IM=ZRAND_NOS_IM+ZRAND_NOS((JGL-1)*NSPEC2G+INDSP2G_IM_RAN)* &
               & SQRTCORR(JGL,ILEVG)
          ENDDO
          IF (LSTOPH_SPBS_T) THEN
            DO JGL=1,ILEVG
              ZRAND_NOS_RE_T=ZRAND_NOS_RE_T+ZRAND_NOS_T((JGL-1)*NSPEC2G+INDSP2G_RE_RAN)* &
                & SQRTCORR(JGL,ILEVG)

              ZRAND_NOS_IM_T=ZRAND_NOS_IM_T+ZRAND_NOS_T((JGL-1)*NSPEC2G+INDSP2G_IM_RAN)* &
                & SQRTCORR(JGL,ILEVG)
            ENDDO
          ENDIF
        ELSEIF (LSTOPH_RVP) THEN
            ZRAND_NOS_RE=ZRAND_RVP(ILEVG,IJSE)
            ZRAND_NOS_IM=ZRAND_RVP(ILEVG,IJSE+1)
            IF (LSTOPH_SPBS_T) THEN
              ZRAND_NOS_RE_T=ZRAND_RVP_T(ILEVG,IJSE)
              ZRAND_NOS_IM_T=ZRAND_RVP_T(ILEVG,IJSE+1)
            ENDIF
        ELSE
            ZRAND_NOS_RE=ZRAND_NOS(INDSP2G_RE_RAN)
            ZRAND_NOS_IM=ZRAND_NOS(INDSP2G_IM_RAN)
            IF (LSTOPH_SPBS_T) THEN
              ZRAND_NOS_RE_T=ZRAND_NOS_T(INDSP2G_RE_RAN)
              ZRAND_NOS_IM_T=ZRAND_NOS_T(INDSP2G_IM_RAN)
            ENDIF
        ENDIF
        IF (LSTOPH_UNIFORM.and.(.not.LSTOPH_RVP)) THEN  
          ! it has to be verified if using LSTOPH_JBCOR is "compatible" with using LSTOPH_UNIFORM 
          ! i.e. if the current implementation is doing what is expected for both set to true
          ZRAND_NOS_RE=ZRAND_NOS_RE-0.5
          ZRAND_NOS_IM=ZRAND_NOS_IM-0.5
          IF (LSTOPH_SPBS_T) THEN
            ZRAND_NOS_RE_T=ZRAND_NOS_RE_T-0.5
            ZRAND_NOS_IM_T=ZRAND_NOS_IM_T-0.5
          ENDIF
        ENDIF

        IF (KSTEP == 0 .AND. LSTOPH_INI) THEN
         !
         !initialization of Markov Chain
         !
           !WRITE(NULOUT,*) ' Initializing Markov Chain '
           ZFACT0=1._JPRB / SQRT( 1._JPRB -(1._JPRB-ALPHA_STO(JN))**(2*NFRSTOPH_SPBS_PAT) )
           ZRAND_NOS_RE=ZFACT0*ZRAND_NOS_RE
           ZRAND_NOS_IM=ZFACT0*ZRAND_NOS_IM
           IF (LSTOPH_SPBS_T) THEN
             ZFACT0=1._JPRB / SQRT( 1._JPRB -(1._JPRB-ALPHA_STO_T(JN))**(2*NFRSTOPH_SPBS_PAT) )
             ZRAND_NOS_RE_T=ZFACT0*ZRAND_NOS_RE_T
             ZRAND_NOS_IM_T=ZFACT0*ZRAND_NOS_IM_T
           ENDIF
        ENDIF

        SPSTREAM(ILEV,IJSE)  = (ONEMINALPHA_NFRSPBS(JN)*SPSTREAM(ILEV,IJSE)  + &
          &                    SPG_AMP(JN)*ZRAND_NOS_RE)*ZFACT
        SPSTREAM(ILEV,IJSE+1)= (ONEMINALPHA_NFRSPBS(JN)*SPSTREAM(ILEV,IJSE+1) + &
          &                    SPG_AMP(JN)*ZRAND_NOS_IM)*ZFACT

        IF (LSTOPH_SPBS_T) THEN
          SPTEMP(ILEV,IJSE)  = (ONEMINALPHA_NFRSPBS_T(JN)*SPTEMP(ILEV,IJSE)  + &
          &                    SPG_AMP_T(JN)*ZRAND_NOS_RE_T)*ZFACT
          SPTEMP(ILEV,IJSE+1)= (ONEMINALPHA_NFRSPBS_T(JN)*SPTEMP(ILEV,IJSE+1) + &
          &                    SPG_AMP_T(JN)*ZRAND_NOS_IM_T)*ZFACT
        ENDIF

        IF (IM==0) THEN
          SPSTREAM(ILEV,IJSE+1)=0 ! set imginary part of M=0 to zero
          IF (LSTOPH_SPBS_T) SPTEMP(ILEV,IJSE+1)=0
        ENDIF
      ENDDO
    ENDDO
  ENDDO
!$OMP END PARALLEL DO

  DEALLOCATE(ZRAND_NOS)
  IF (LSTOPH_RVP) THEN
    DEALLOCATE(ZRAND_RVP)
    DEALLOCATE(ZRAND_UNI)
  ENDIF

  IF (LSTOPH_SPBS_T) THEN
    DEALLOCATE(ZRAND_NOS_T)
    IF (LSTOPH_RVP) THEN
      DEALLOCATE(ZRAND_RVP_T)
      DEALLOCATE(ZRAND_UNI_T)
    ENDIF
  ENDIF

  LSTOPH_INI=.FALSE.    !set to false to avoid multiple initialization
                        !(surand2 is called more than once for KSTEP == 0)

ENDIF


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