module module_stoch 2 !*********************************************************************** ! ! Purpose: Stochastic kinetic-energy backscatter scheme (SKEB) ! Author : Judith Berner, NCAR (berner@ucar.edu) ! Date : Dec 2010 ! Version: 1.0 ! !*********************************************************************** ! ! The scheme introduces stochastic perturbations to the rotational wind ! components and to the potential temperature field. The stochastic ! perturbations are generated by independent autoregressive processes for ! each wavenumber and results in smooth spatially and temporally correlated patterns. ! Details of the scheme and its performance in a meso-scale WRF-ensemble ! system are available in: ! ! Berner, J., S.-Y. Ha, J. P. Hacker, A. Fournier and C. Snyder 2010: ! Model uncertainty in a mesoscale ensemble prediction system: Stochastic ! versus multi-physics representations, MWR, accepted ! (available through the AMS early online release) ! ! Features: ! Version 1.0: ! Dissipation: Dissipation rates are assumed constant in space and time ! Vertical structure: Supports two options for vertical structure: ! 0) constant ! 1) random phase ! ! Optional namelist parameters: ! stoch_opt - 0) No stochastic parameterization ! - 1) Stochastic kinetic-energy backscatter scheme (SKEB) ! stoch_vertstruc_opt - 0) Constant vertical structure ! - 1) Random phase vertical structure ! tot_backscat_psi - Strength of streamfunction perturbations ! tot_backscat-t - Strength of potential temperature perturbations ! !*********************************************************************** ! ------------------------------------------------------------------ !************** DECLARE FIELDS AND VARIABLES FOR STOCHASTIC BACKSCATTER ! ------------------------------------------------------------------ implicit none public :: SETUP_STOCH, UPDATE_STOCH,do_fftback_along_x,do_fftback_along_y,& SP2GP_prep INTEGER :: LMINFORC, LMAXFORC, KMINFORC, KMAXFORC, & & LMINFORCT, LMAXFORCT, KMINFORCT, KMAXFORCT REAL :: ALPH, TOT_BACKSCAT_PSI, TOT_BACKSCAT_T, REXPONENT ! ----------Fields for spectral transform ----------- INTEGER :: LENSAV INTEGER,ALLOCATABLE:: wavenumber_k(:), wavenumber_l(:),ISEED(:) REAL, ALLOCATABLE :: WSAVE1(:),WSAVE2(:) ! --------- Others ------------------------------------------------- REAL, PARAMETER:: RPI= 3.141592653589793 !4.0*atan(1.0) REAL, PARAMETER:: CP= 1006 ! specific heat of dry air in J/(Kg*K)= m^2/(K* s^2) save !======================================================================= contains !======================================================================= ! ------------------------------------------------------------------ !!******** INITIALIZE STOCHASTIC KINETIC ENERGY BACKSCATTER (SKEB) ***** ! ------------------------------------------------------------------ subroutine SETUP_STOCH( & 1,3 VERTSTRUCC,VERTSTRUCS, & SPT_AMP,SPSTREAM_AMP, & stoch_vertstruc_opt, & itime_step,DX,DY,NENS, & TOT_BACKSCAT_PSI,TOT_BACKSCAT_T, & ids, ide, jds, jde, kds, kde, & ims, ime, jms, jme, kms, kme, & its, ite, jts, jte, kts, kte ) USE module_configure IMPLICIT NONE TYPE (grid_config_rec_type) :: config_flags INTEGER :: IER,IK,IL,I,J INTEGER :: itime_step,stoch_vertstruc_opt INTEGER :: KMAX,LMAX,LENSAV,ILEV INTEGER , INTENT(IN) :: ids, ide, jds, jde, kds, kde, & ims, ime, jms, jme, kms, kme, & its, ite, jts, jte, kts, kte REAL :: DX,DY,RY,RX,RATIO_BACKSCAT,TOT_BACKSCAT_PSI,TOT_BACKSCAT_T REAL :: ZGAMMAN,ZTAU,ZCONSTF0,ZCONSTF0T,ZSIGMA2_EPS, RHOKLMAX,ZREF,RHOKL,EPS REAL, DIMENSION (ims:ime,kms:kme,jms:jme) :: VERTSTRUCC,VERTSTRUCS REAL, DIMENSION (ims:ime,jms:jme) :: SPSTREAM_AMP,SPT_AMP REAL, DIMENSION (ids:ide,jds:jde) :: ZCHI,ZCHIT INTEGER :: how_many, nens LOGICAL :: is_print = .true. LOGICAL , EXTERNAL :: wrf_dm_on_monitor ! --------- SETUP PARAMETERS --------------------------------------- KMAX=(jde-jds)+1 !NLAT LMAX=(ide-ids)+1 !NLON RY= KMAX*DY RX= LMAX*DY LENSAV= 4*(KMAX+LMAX)+INT(LOG(REAL(KMAX))) + INT(LOG(REAL(LMAX))) + 8 ! --------- ALLOCATE FIELDS FOR FFTPACK---------------------------- IF ( ALLOCATED(WSAVE1) ) DEALLOCATE(WSAVE1) IF ( ALLOCATED(WSAVE2) ) DEALLOCATE(WSAVE2) ALLOCATE(WSAVE1(LENSAV),WSAVE2(LENSAV)) IF ( ALLOCATED(WAVENUMBER_K)) DEALLOCATE(WAVENUMBER_K) IF ( ALLOCATED(WAVENUMBER_L)) DEALLOCATE(WAVENUMBER_L) ALLOCATE (wavenumber_k(jds:jde),wavenumber_l(ids:ide)) ! -------- INITIALIZE FFTPACK ROUTINES ----------------------------- call CFFT1I (LMAX, WSAVE1, LENSAV, IER) if(ier.ne. 0) write(*,95) ier call CFFT1I (KMAX, WSAVE2, LENSAV, IER) if(ier.ne. 0) write(*,95) ier 95 format('error in cFFT2I= 'i5) call findindex( wavenumber_k, wavenumber_l, & ids, ide, jds, jde, kds, kde, & ims, ime, jms, jme, kms, kme, & its, ite, jts, jte, kts, kte ) ! ---------- INITIAIZE STOCHASTIC KINETIC ENERGY BACKSCATTER PARAMETERS----------- REXPONENT=-1.83 !produces 2(p+1) kinetic energy spectra % p=-11/6=1.83 => k=-5/3 ! TOT_BACKSCAT_PSI = 2.0 ! TOT_BACKSCAT_T = 4.8E-04 ! 2.E-06/240 KMINFORC=0 KMAXFORC=min0(40,KMAX/2) LMINFORC=KMINFORC LMAXFORC=KMAXFORC KMINFORCT=0 KMAXFORCT=KMAXFORC LMINFORCT=KMINFORCT LMAXFORCT=KMAXFORCT ZTAU = 2.E04/12. ALPH = float(itime_step)/ZTAU ! approximation of 1.-exp(-itime_step/ZTAU) ZSIGMA2_EPS=1./(12.0*ALPH) ! Sanity checks for forcing wavenumber range IF (LMAXFORC>LMAX/2) then LMAXFORC=min0(40,LMAX/2)-1 KMAXFORC=LMAXFORC ENDIF IF (LMAXFORCT>LMAX/2) then LMAXFORCT=min0(40,LMAX/2)-1 KMAXFORCT=LMAXFORCT ENDIF IF ((LMINFORC>LMAXFORC).or.(KMINFORC>KMAXFORC)) then WRITE(*,'('' LMINFORC>LMAXFORC IN SETUP_STOCH.F90'')') STOP ENDIF IF ((KMAXFORC>KMAX/2).or.(LMAXFORC>LMAX/2)) then WRITE(*,'('' KMAXFORC>KMAX/2 IN SETUP_STOCH.F90'')') print*,KMAXFORC,KMAX/2 STOP ENDIF IF ((KMINFORC.ne.LMINFORC).or.(KMAXFORC.ne.LMAXFORC)) then WRITE(*,'('' Forcing is non-homogenious in latitude and longitude'')') WRITE(*,'('' If this is what you want, comment *stop* IN SETUP_STOCH.F90'')') STOP ENDIF ! Output of stochastic settings if (is_print) then WRITE(*,'('' '')') WRITE(*,'('' =============================================='')') WRITE(*,'('' >> Initializing stochastic kinetic-energy backscatter scheme << '')') WRITE(*,'('' Total backscattered energy, TOT_BACKSCAT_PSI '',E12.5)') TOT_BACKSCAT_PSI WRITE(*,'('' Total backscattered temperature, TOT_BACKSCAT_T '',E12.5)') TOT_BACKSCAT_T WRITE(*,'('' Exponent for energy spectra, REXPONENT ='',E12.5)') REXPONENT WRITE(*,'('' Minimal wavenumber of streamfunction forcing, LMINFORC ='',I10)') LMINFORC WRITE(*,'('' Maximal wavenumber of streamfunction forcing, LMAXFORC ='',I10)') LMAXFORC WRITE(*,'('' Minimal wavenumber of streamfunction forcing, KMINFORC ='',I10)') KMINFORC WRITE(*,'('' Maximal wavenumber of streamfunction forcing, KMAXFORC ='',I10)') KMAXFORC WRITE(*,'('' Minimal wavenumber of temperature forcing, LMINFORCT ='',I10)') LMINFORCT WRITE(*,'('' Maximal wavenumber of temperature forcing, LMAXFORCT ='',I10)') LMAXFORCT WRITE(*,'('' stoch_vertstruc_opt '',I10)') stoch_vertstruc_opt WRITE(*,'('' Time step: itime_step='',I10)') itime_step WRITE(*,'('' Decorrelation time of noise, ZTAU ='',E12.5)') ZTAU WRITE(*,'('' Variance of noise, ZSIGMA2_EPS ='',E12.5)') ZSIGMA2_EPS WRITE(*,'('' Autoregressive parameter 1-ALPH ='',E12.5)') 1.-ALPH WRITE(*,'('' =============================================='')') endif ! ---------- INITIALIZE NOISE AMPLITUDES ---------------------------------- ! Amplitudes for streamfunction and temperature perturbations: SPSTREAM_AMP , SPT_AMP ! Unit of SPSTREAM_AMP: sqrt(m^2/s^3 1/s m**2(p+1)) m**-2(p/2) = m^/s^2 * m**[(p+1)-p] = m^2/s^2 m ! First the constants: ZCHI = 0.0 ! Fill lower left quadrant of ZCHI. For this range the indeces IK,IL do IK=KMINFORC,KMAXFORC do IL=LMINFORC,LMAXFORC if ((sqrt(float(IK*IK+IL*IL))).le.(KMAXFORC)) then if ((IK>0).or.(IL>0)) then ZCHI(IL+1,IK+1)=((IK/RY*IK/RY)+(IL/RX*IL/RX))**(REXPONENT/2.) endif endif enddo enddo ZGAMMAN = 0.0 DO IK=KMINFORC,KMAXFORC DO IL=LMINFORC,LMAXFORC if (sqrt(float(IK*IK+IL*IL)).le.KMAXFORC) then if ((IK>0).or.(IL>0)) then ZGAMMAN= ZGAMMAN + ((IK/RY*IK/RY)+(IL/RX*IL/RX))**(REXPONENT+1) endif endif ENDDO ENDDO ZGAMMAN=4.0*ZGAMMAN !account for all quadrants, although only one is Filled ! A value TOT_BACKSCAT_PSI=xx m^2/S^3 means that in each gridbox and on average, ! a dissipation rate of D=TOT_BACKSCAT_PSI m^2/s^3 is backscattered onto the resolved streamfunction ! The resulting units for ZCONSTF0 are sqrt(m^2/(s^3*s)) = m^2/s^2, which is the unit of dpsi/dt ! Note, that the unit of IK has the unit m here. ZCONSTF0=SQRT(ALPH*TOT_BACKSCAT_PSI/(float(itime_step)*ZSIGMA2_EPS*ZGAMMAN))/(2*RPI) ZCHIT = 0.0 ! Fill lower left quadrant of ZCHI. For this range the indeces IK,IL do IK=KMINFORCT,KMAXFORCT do IL=LMINFORCT,LMAXFORCT if ((sqrt(float(IK*IK+IL*IL))).le.(KMAXFORCT)) then if ((IK>0).or.(IL>0)) then ZCHIT(IL+1,IK+1)=((IK/RY*IK/RY)+(IL/RX*IL/RX))**(REXPONENT/2.) endif endif enddo enddo ZGAMMAN = 0.0 DO IK=KMINFORCT,KMAXFORCT DO IL=LMINFORCT,LMAXFORCT if (sqrt(float(IK*IK+IL*IL)).le.KMAXFORC) then if ((IK>0).or.(IL>0)) then ZGAMMAN= ZGAMMAN + ((IK/RY*IK/RY)+(IL/RX*IL/RX))**(REXPONENT+1) endif endif ENDDO ENDDO ZGAMMAN=4.0*ZGAMMAN !account for all quadrants, although only one is Filled ! A value TOT_BACKSCAT_T= xx m^2/S^3 means that in each gridbox and on average, ! a dissipation rate of D=TOT_BACKSCAT_T m^2/s^3 is backscattered onto the resolved temperture pattern ! The resulting units for ZCONSTF0T are m^2/s^3* (K* s^2)/m^2 = K/s , which is the unit of dT/dt ZCONSTF0T=TOT_BACKSCAT_T /cp* SQRT(ALPH/(ZSIGMA2_EPS*ZGAMMAN))/(2*RPI) ! Now the wavenumber-dependent amplitudes ! Note: There are symmetries and anti-symmetries to ensure real-valued back transforms ! Fill lower left quadrant of matrix of noise amplitudes for wavenumbers K=0,KMAX/2 SPSTREAM_AMP=0.0 SPT_AMP=0.0 SPT_AMP=0.0 DO IK=jts,jte DO IL=its,ite if ((IL .le. (LMAX/2+1)) .and. (IK .le. (KMAX/2+1)) ) then SPSTREAM_AMP(IL,IK) = ZCONSTF0 *ZCHI(IL,IK) SPT_AMP(IL,IK) = ZCONSTF0T*ZCHIT(IL,IK) endif ENDDO ENDDO ! Fill other quadrants: ! Upper left quadrant DO IK=jts,jte DO IL=its,ite if ( (IL .gt. (LMAX/2+1)) .and. (IK .le. (KMAX/2+1)) ) then SPSTREAM_AMP(IL,IK) = ZCONSTF0 *ZCHI(LMAX-IL+2,IK) SPT_AMP(IL,IK) = ZCONSTF0T*ZCHIT(LMAX-IL+2,IK) endif ENDDO ENDDO ! Lower right quadrant DO IK=jts,jte DO IL=its,ite if ((IK .gt. (KMAX/2+1)) .and. (IL.le.LMAX/2) ) then SPSTREAM_AMP(IL,IK) = ZCONSTF0 *ZCHI(IL,KMAX-IK+2) SPT_AMP(IL,IK) = ZCONSTF0T*ZCHIT(IL,KMAX-IK+2) endif ENDDO ENDDO ! Upper right quadrant DO IK=jts,jte DO IL=its,ite if ((IK .gt. (KMAX/2+1)) .and. (IL.gt.LMAX/2) ) then SPSTREAM_AMP(IL,IK) = ZCONSTF0 *ZCHI(LMAX-IL+2,KMAX-IK+2) SPT_AMP(IL,IK) = ZCONSTF0T*ZCHIT(LMAX-IL+2,KMAX-IK+2) endif ENDDO ENDDO ! Array for vertical structure if desired IF (stoch_vertstruc_opt>0) then VERTSTRUCC=0.0 VERTSTRUCS=0.0 RHOKLMAX= sqrt(KMAX**2/DY**2 + LMAX**2/DX**2) ZREF=32.0 DO ILEV=kts,kte DO IK=jts,jte DO IL=its,ite if (IL.le.(LMAX/2)) then RHOKL = sqrt((IK+1)**2/DY**2 + (IL+1)**2/DX**2) EPS = ((RHOKLMAX - RHOKL)/ RHOKLMAX) * (ILEV/ZREF) * RPI VERTSTRUCC(IL,ILEV,IK) = cos ( eps* (IL+1) ) VERTSTRUCS(IL,ILEV,IK) = sin ( eps* (IL+1) ) else RHOKL = sqrt((IK+1)**2/DY**2 + (LMAX-IL+2)**2/DX**2) EPS = ((RHOKLMAX - RHOKL)/ RHOKLMAX) * (ILEV/ZREF) * RPI VERTSTRUCC (IL,ILEV,IK) = cos ( eps* (LMAX-IL+2) ) VERTSTRUCS (IL,ILEV,IK) = - sin ( eps* (LMAX-IL+2) ) endif ENDDO ENDDO ENDDO END IF ! Allocate field for seed and set seed for random number generator CALL random_seed(size=how_many) IF ( ALLOCATED(ISEED) ) DEALLOCATE(ISEED) ALLOCATE (ISEED(how_many)) iseed=0 IF ( wrf_dm_on_monitor() ) THEN iseed(1) = 7654321 iseed(2) = 2*(nens*811)+1 call random_seed(put=iseed) ! set random seed on monitor. END IF #ifdef DM_PARALLEL CALL wrf_dm_bcast_integer ( iseed , how_many ) #endif END subroutine SETUP_STOCH ! ------------------------------------------------------------------ !!************** UPDATE STOCHASTIC PATTERN IN WAVENUMBER SPACE********** ! ------------------------------------------------------------------ subroutine UPDATE_STOCH( & 1,4 SPSTREAMFORCS,SPSTREAMFORCC,SPTFORCS,SPTFORCC, & SPT_AMP,SPSTREAM_AMP, & itime,ij, & ids, ide, jds, jde, kds, kde, & ims, ime, jms, jme, kms, kme, & its, ite, jts, jte, kts, kte ) IMPLICIT NONE REAL, DIMENSION( ids:ide,jds:jde) :: ZRANDNOSS1,ZRANDNOSC1,ZRANDNOSS2,ZRANDNOSC2 REAL, DIMENSION (ims:ime,jms:jme) :: SPSTREAMFORCS,SPSTREAMFORCC,SPTFORCS,SPTFORCc,SPSTREAM_AMP,SPT_AMP INTEGER , INTENT(IN) :: ids, ide, jds, jde, kds, kde, & ims, ime, jms, jme, kms, kme, & its, ite, jts, jte, kts, kte REAL :: Z, thresh INTEGER ::IL, IK,LMAX,KMAX,i,itime,ij,llmax,kkmax,how_many LOGICAL :: LGAUSS KMAX=(jde-jds)+1 !NLAT LMAX=(ide-ids)+1 !NATX ! Pick the distribution of the noise ! Random noise uses global indexes to ensure necessary symmetries and anti-symmetries ! of random forcing when run on multiple processors CALL random_seed(size=how_many) call random_seed(put=iseed) LGAUSS=.false. thresh=3.0 ! Set threshold to ensure stability IF (LGAUSS) then DO IK=jds,int(jde/2.0)+2 DO IL=ids,ide do call gauss_noise(z) if (abs(z).le.thresh) exit enddo ZRANDNOSS1(IL,IK)=z do call gauss_noise(z) if (abs(z).le.thresh) exit enddo ZRANDNOSC1(IL,IK)=z do call gauss_noise(z) if (abs(z).le.thresh) exit enddo ZRANDNOSS2(IL,IK)=z do call gauss_noise(z) if (abs(z).le.thresh) exit enddo ZRANDNOSC2(IL,IK)=z ENDDO ENDDO ELSE DO IK=jds,int(jde/2.0)+2 DO IL=ids,ide CALL RANDOM_NUMBER(z) ZRANDNOSS1(IL,IK)=z-0.5 CALL RANDOM_NUMBER(z) ZRANDNOSC1(IL,IK)=z-0.5 CALL RANDOM_NUMBER(z) ZRANDNOSS2(IL,IK)=z-0.5 CALL RANDOM_NUMBER(z) ZRANDNOSC2(IL,IK)=z-0.5 ENDDO ENDDO ENDIF call random_seed(get=iseed) ! Note: There are symmetries and anti-symmetries to ensure real-valued back transforms DO IK=jts,jte if (IK.le.(KMAX/2)) then DO IL=its,ite SPSTREAMFORCC(IL,IK) = (1.-ALPH)*SPSTREAMFORCC(IL,IK) + SPSTREAM_AMP(IL,IK)*(ZRANDNOSC1(IL,IK)) SPSTREAMFORCS(IL,IK) = (1.-ALPH)*SPSTREAMFORCS(IL,IK) + SPSTREAM_AMP(IL,IK)*(ZRANDNOSS1(IL,IK)) SPTFORCC(IL,IK) = (1.-ALPH)*SPTFORCC(IL,IK) + SPT_AMP(IL,IK) *(ZRANDNOSC2(IL,IK)) SPTFORCS(IL,IK) = (1.-ALPH)*SPTFORCS(IL,IK) + SPT_AMP(IL,IK) *(ZRANDNOSS2(IL,IK)) ENDDO endif ENDDO DO IK=jts,jte if (IK.ge.(KMAX/2+1))then DO IL=its,ite if (IL>1) then SPSTREAMFORCC(IL,IK)= (1.-ALPH)* SPSTREAMFORCC(IL,IK) + & SPSTREAM_AMP(IL,IK) * ZRANDNOSC1(LMAX-IL+2,KMAX-IK+2) SPSTREAMFORCS(IL,IK)= -((1.-ALPH)*(-1.0*SPSTREAMFORCS(IL,IK))+ & SPSTREAM_AMP(IL,IK) * ZRANDNOSS1(LMAX-IL+2,KMAX-IK+2)) SPTFORCC(IL,IK)= (1.-ALPH)* SPTFORCC(IL,IK) + & SPT_AMP(IL,IK) * ZRANDNOSC2(LMAX-IL+2,KMAX-IK+2) SPTFORCS(IL,IK)= -((1.-ALPH)*(-1.0*SPTFORCS(IL,IK))+ & SPT_AMP(IL,IK) * ZRANDNOSS2(LMAX-IL+2,KMAX-IK+2)) else SPSTREAMFORCC(1,IK) = (1.-ALPH) * SPSTREAMFORCC(1,IK) + & SPSTREAM_AMP(1,IK) * ZRANDNOSC1(1,KMAX-IK+2) SPSTREAMFORCS(1,IK) = -((1.-ALPH)*(-1.0*SPSTREAMFORCS(1,IK))+ & SPSTREAM_AMP(1,IK) * ZRANDNOSS1(1,KMAX-IK+2)) SPTFORCC(1,IK) = (1.-ALPH) * SPTFORCC(1,IK) + & SPT_AMP(1,IK) * ZRANDNOSC2(1,KMAX-IK+2) SPTFORCS(1,IK) = -((1.-ALPH)*(-1.0*SPTFORCS(1,IK))+ & SPT_AMP(1,IK) * ZRANDNOSS2(1,KMAX-IK+2)) endif ENDDO endif ENDDO END subroutine UPDATE_STOCH ! ------------------------------------------------------------------ !************** ADD STOCHASTIC TENDENCIES TO PHYSICAL TENDENCIES******** ! ------------------------------------------------------------------ SUBROUTINE CALCULATE_STOCH_TEN( & 1 ru_tendf,rv_tendf,t_tendf, & GPUFORC,GPVFORC,GPTFORC, & ru_real,rv_real,rt_real, & mu,mub, & ids, ide, jds, jde, kds, kde, & ims, ime, jms, jme, kms, kme, & its, ite, jts, jte, kts, kte, & dt) IMPLICIT NONE INTEGER , INTENT(IN) :: ids, ide, jds, jde, kds, kde, & ims, ime, jms, jme, kms, kme, & its, ite, jts, jte, kts, kte REAL , DIMENSION(ims:ime , kms:kme, jms:jme),INTENT(INOUT) :: & ru_tendf, rv_tendf, t_tendf, & GPUFORC,GPVFORC,GPTFORC REAL , DIMENSION(ims:ime , kms:kme, jms:jme),INTENT(IN) :: & ru_real,rv_real,rt_real REAL , DIMENSION(ims:ime,jms:jme) , INTENT(IN) :: mu,mub INTEGER :: I,J,K REAL :: dt DO j = jts,MIN(jde-1,jte) DO k = kts,kte-1 DO i = its,ite GPUFORC(i,k,j)= ru_real(i,k,j) ENDDO ENDDO ENDDO DO j = jts,jte DO k = kts,kte-1 DO i = its,MIN(ide-1,ite) GPVFORC(i,k,j)= rv_real(i,k,j) ENDDO ENDDO ENDDO DO j = jts,MIN(jde-1,jte) DO k = kts,kte-1 DO i = its,MIN(ide-1,ite) GPTFORC(i,k,j)= rt_real(i,k,j) ENDDO ENDDO ENDDO END SUBROUTINE CALCULATE_STOCH_TEN ! ------------------------------------------------------------------ SUBROUTINE UPDATE_STOCH_TEN(ru_tendf,rv_tendf,t_tendf, & 1 GPUFORC,GPVFORC,GPTFORC, & mu,mub, & ids, ide, jds, jde, kds, kde, & ims, ime, jms, jme, kms, kme, & its, ite, jts, jte, kts, kte, & dt ) IMPLICIT NONE INTEGER , INTENT(IN) :: ids, ide, jds, jde, kds, kde, & ims, ime, jms, jme, kms, kme, & its, ite, jts, jte, kts, kte REAL , DIMENSION(ims:ime , kms:kme, jms:jme),INTENT(INOUT) :: & ru_tendf, rv_tendf, t_tendf !REAL , DIMENSION(ims:ime , kms:kme, jms:jme),INTENT(IN) :: & REAL , DIMENSION(ims:ime , kms:kme, jms:jme) :: & GPUFORC,GPVFORC,GPTFORC REAL , DIMENSION(ims:ime,jms:jme) , INTENT(IN) :: mu,mub INTEGER :: I,J,K REAL :: dt,xm DO j = jts,MIN(jde-1,jte) DO k = kts,kte-1 DO i = its,ite ru_tendf(i,k,j) = ru_tendf(i,k,j) + GPUFORC(i,k,j) * (mu(i,j)+mub(i,j)) ENDDO ENDDO ENDDO DO j = jts,jte DO i = its,MIN(ide-1,ite) DO k = kts,kte-1 rv_tendf(i,k,j) = rv_tendf(i,k,j) + GPVFORC(i,k,j) * (mu(i,j)+mub(i,j)) ENDDO ENDDO ENDDO DO j = jts,MIN(jde-1,jte) DO k = kts,kte-1 DO i = its,MIN(ide-1,ite) t_tendf(i,k,j) = t_tendf(i,k,j) + GPTFORC(i,k,j) * (mu(i,j)+mub(i,j)) ENDDO ENDDO ENDDO END SUBROUTINE UPDATE_STOCH_TEN ! ------------------------------------------------------------------ !!************** TRANSFORM FROM SPHERICAL HARMONICS TO GRIDPOILT SPACE** ! ------------------------------------------------------------------ subroutine SP2GP_prep( & 1 SPSTREAMFORCS,SPSTREAMFORCC,SPTFORCS,SPTFORCC, & VERTSTRUCC,VERTSTRUCS, & RU_REAL,RV_REAL,RT_REAL, & RU_IMAG,RV_IMAG,RT_IMAG, & dx,dy,stoch_vertstruc_opt, & ids, ide, jds, jde, kds, kde, & ims, ime, jms, jme, kms, kme, & its, ite, jts, jte, kts, kte ) IMPLICIT NONE INTEGER , INTENT(IN) :: ids, ide, jds, jde, kds, kde, & ims, ime, jms, jme, kms, kme, & its, ite, jts, jte, kts, kte REAL, DIMENSION (ims:ime , jms:jme) :: SPSTREAMFORCS,SPSTREAMFORCC,SPTFORCS,SPTFORCC REAL, DIMENSION (ims:ime , kms:kme, jms:jme) :: RU_REAL,RV_REAL,RT_REAL,RU_IMAG,RV_IMAG,RT_IMAG, & VERTSTRUCC,VERTSTRUCS INTEGER :: IK,IL,ILEV,NLAT,NLON,stoch_vertstruc_opt REAL :: dx,dy,RY,RX NLAT=(jde-jds)+1 !KMAX NLON=(ide-ids)+1 !LMAX RY= NLAT*DY RX= NLON*DX DO ILEV=kts,kte if (stoch_vertstruc_opt==0) then DO IL=its,ite DO IK=jts,jte rt_real(IL,ILEV,IK) = SPTFORCC(IL,IK) rt_imag(IL,ILEV,IK) = SPTFORCS(IL,IK) ru_real(IL,ILEV,IK) = 2*RPI/RY* wavenumber_k(IK) * SPSTREAMFORCS(IL,IK) ru_imag(IL,ILEV,IK) =-2*RPI/RY* wavenumber_k(IK) * SPSTREAMFORCC(IL,IK) rv_real(IL,ILEV,IK) =-2*RPI/RX* wavenumber_l(IL) * SPSTREAMFORCS(IL,IK) rv_imag(IL,ILEV,IK) = 2*RPI/RX* wavenumber_l(IL) * SPSTREAMFORCC(IL,IK) ENDDO ENDDO elseif (stoch_vertstruc_opt==1) then DO IL=its,ite DO IK=jts,jte rt_real(IL,ILEV,IK) = SPTFORCC(IL,IK)*VERTSTRUCC(IL,ILEV,IK) - SPTFORCS(IL,IK)*VERTSTRUCS(IL,ILEV,IK) rt_imag(IL,ILEV,IK) = SPTFORCC(IL,IK)*VERTSTRUCS(IL,ILEV,IK) + SPTFORCS(IL,IK)*VERTSTRUCC(IL,ILEV,IK) ru_real(IL,ILEV,IK) = 2*RPI/RY* wavenumber_k(IK) *& (+SPSTREAMFORCC(IL,IK)*VERTSTRUCS(IL,ILEV,IK) + SPSTREAMFORCS(IL,IK)*VERTSTRUCC(IL,ILEV,IK)) ru_imag(IL,ILEV,IK) = 2*RPI/RY* wavenumber_k(IK) *& (-SPSTREAMFORCC(IL,IK)*VERTSTRUCC(IL,ILEV,IK) + SPSTREAMFORCS(IL,IK)*VERTSTRUCS(IL,ILEV,IK)) rv_real(IL,ILEV,IK) = 2*RPI/RX* wavenumber_l(IL) *& (-SPSTREAMFORCC(IL,IK)*VERTSTRUCS(IL,ILEV,IK) - SPSTREAMFORCS(IL,IK)*VERTSTRUCC(IL,ILEV,IK)) rv_imag(IL,ILEV,IK) = 2*RPI/RX* wavenumber_l(IL) *& (+SPSTREAMFORCC(IL,IK)*VERTSTRUCC(IL,ILEV,IK) - SPSTREAMFORCS(IL,IK)*VERTSTRUCS(IL,ILEV,IK)) ENDDO ENDDO endif ENDDO !ILEV END subroutine SP2GP_prep ! ------------------------------------------------------------------ !!************** SUBROUTINE DO_FFTBACK_ALONG_X ! ------------------------------------------------------------------ subroutine do_fftback_along_x(fieldc_U_xxx,fields_U_xxx, & 2,3 fieldc_V_xxx,fields_V_xxx, & fieldc_T_xxx,fields_T_xxx, & ids, ide, jds, jde, kds, kde, & ims, ime, jms, jme, kms, kme, & ips, ipe, jps, jpe, kps, kpe, & imsx,imex,jmsx,jmex,kmsx,kmex, & ipsx,ipex,jpsx,jpex,kpsx,kpex, & imsy,imey,jmsy,jmey,kmsy,kmey, & ipsy,ipey,jpsy,jpey,kpsy,kpey, & k_start , k_end & ) IMPLICIT NONE INTEGER, INTENT(IN) :: ids, ide, jds, jde, kds, kde, & ims, ime, jms, jme, kms, kme, & ips, ipe, jps, jpe, kps, kpe, & imsx,imex,jmsx,jmex,kmsx,kmex, & ipsx,ipex,jpsx,jpex,kpsx,kpex, & imsy,imey,jmsy,jmey,kmsy,kmey, & ipsy,ipey,jpsy,jpey,kpsy,kpey, & k_start , k_end REAL, DIMENSION (imsx:imex, kmsx:kmex, jmsx:jmex) :: fieldc_U_xxx,fields_U_xxx, & fieldc_V_xxx,fields_V_xxx, & fieldc_T_xxx,fields_T_xxx COMPLEX, DIMENSION (ipsx:ipex) :: dummy_complex INTEGER :: IER,LENWRK,KMAX,LMAX,I,J,K REAL, ALLOCATABLE :: WORK(:) CHARACTER (LEN=160) :: mess KMAX=(jde-jds)+1 LMAX=(ide-ids)+1 LENWRK=2*KMAX*LMAX ALLOCATE(WORK(LENWRK)) LENSAV= 4*(KMAX+LMAX)+INT(LOG(REAL(KMAX))) + INT(LOG(REAL(LMAX))) + 8 DO k=kpsx,kpex DO j = jpsx, jpex DO i = ipsx, ipex dummy_complex(i)=cmplx(fieldc_U_xxx(i,k,j),fields_U_xxx(i,k,j)) ENDDO CALL cFFT1B (LMAX, 1 ,dummy_complex,LMAX, WSAVE1, LENSAV, WORK, LENWRK, IER) if (ier.ne.0) then WRITE(mess,FMT='(A)') 'error in cFFT1B in do_fftback_along_x, field U' CALL wrf_debug(0,mess) end if DO i = ipsx, ipex fieldc_U_xxx(i,k,j)=real(dummy_complex(i)) fields_U_xxx(i,k,j)=imag(dummy_complex(i)) END DO END DO END DO DO k=kpsx,kpex DO j = jpsx, jpex DO i = ipsx, ipex dummy_complex(i)=cmplx(fieldc_V_xxx(i,k,j),fields_V_xxx(i,k,j)) ENDDO CALL cFFT1B (LMAX, 1 ,dummy_complex,LMAX, WSAVE1, LENSAV, WORK, LENWRK, IER) if (ier.ne.0) then WRITE(mess,FMT='(A)') 'error in cFFT1B in do_fftback_along_x, field V' CALL wrf_debug(0,mess) end if DO i = ipsx,ipex fieldc_V_xxx(i,k,j)=real(dummy_complex(i)) fields_V_xxx(i,k,j)=imag(dummy_complex(i)) END DO END DO END DO DO k=kpsx,kpex DO j = jpsx, jpex DO i = ipsx, ipex dummy_complex(i)=cmplx(fieldc_T_xxx(i,k,j),fields_T_xxx(i,k,j)) ENDDO CALL cFFT1B (LMAX, 1 ,dummy_complex,LMAX, WSAVE1, LENSAV, WORK, LENWRK, IER) if (ier.ne.0) then WRITE(mess,FMT='(A)') 'error in cFFT1B in do_fftback_along_x, field T' CALL wrf_debug(0,mess) end if DO i = ipsx, ipex fieldc_T_xxx(i,k,j)=real(dummy_complex(i)) fields_T_xxx(i,k,j)=imag(dummy_complex(i)) END DO END DO END DO ! DEALLOCATE(WORK) end subroutine do_fftback_along_x !! ------------------------------------------------------------------ !!!************** SUBROUTINE DO_FFTBACK_ALONG_Y !! ------------------------------------------------------------------ subroutine do_fftback_along_y(fieldc_U_yyy,fields_U_yyy, & 2,3 fieldc_V_yyy,fields_V_yyy, & fieldc_T_yyy,fields_T_yyy, & ids, ide, jds, jde, kds, kde, & ims, ime, jms, jme, kms, kme, & ips, ipe, jps, jpe, kps, kpe, & imsx,imex,jmsx,jmex,kmsx,kmex, & ipsx,ipex,jpsx,jpex,kpsx,kpex, & imsy,imey,jmsy,jmey,kmsy,kmey, & ipsy,ipey,jpsy,jpey,kpsy,kpey, & k_start , k_end & ) IMPLICIT NONE INTEGER :: IER,LENWRK,KMAX,LMAX,I,J,K INTEGER, INTENT(IN) :: ids, ide, jds, jde, kds, kde, & ims, ime, jms, jme, kms, kme, & ips, ipe, jps, jpe, kps, kpe, & imsx,imex,jmsx,jmex,kmsx,kmex, & ipsx,ipex,jpsx,jpex,kpsx,kpex, & imsy,imey,jmsy,jmey,kmsy,kmey, & ipsy,ipey,jpsy,jpey,kpsy,kpey, & k_start , k_end REAL, DIMENSION (imsy:imey, kmsy:kmey, jmsy:jmey) :: fieldc_U_yyy,fields_U_yyy, & fieldc_V_yyy,fields_V_yyy, & fieldc_T_yyy,fields_T_yyy COMPLEX, DIMENSION (jpsy:jpey) :: dummy_complex REAL, ALLOCATABLE :: WORK(:) CHARACTER (LEN=160) :: mess KMAX=(jde-jds)+1 LMAX=(ide-ids)+1 LENWRK=2*KMAX*LMAX ALLOCATE(WORK(LENWRK)) LENSAV= 4*(KMAX+LMAX)+INT(LOG(REAL(KMAX))) + INT(LOG(REAL(LMAX))) + 8 DO k=kpsy,kpey DO i = ipsy, ipey DO j = jpsy,jpey dummy_complex(j)=cmplx(fieldc_U_yyy(i,k,j),fields_U_yyy(i,k,j)) ENDDO CALL cFFT1B (KMAX, 1 ,dummy_complex,KMAX, WSAVE2, LENSAV, WORK, LENWRK, IER) if (ier.ne.0) then WRITE(mess,FMT='(A)') 'error in cFFT1B in do_fftback_along_y, field U' CALL wrf_debug(0,mess) end if DO j = jpsy, jpey fieldc_U_yyy(i,k,j)=real(dummy_complex(j)) fields_U_yyy(i,k,j)=imag(dummy_complex(j)) END DO END DO END DO ! k_start-k_end DO k=kpsy,kpey DO i = ipsy, ipey DO j = jpsy, jpey dummy_complex(j)=cmplx(fieldc_V_yyy(i,k,j),fields_V_yyy(i,k,j)) ENDDO CALL cFFT1B (KMAX, 1 ,dummy_complex,KMAX, WSAVE2, LENSAV, WORK, LENWRK, IER) if (ier.ne.0) then WRITE(mess,FMT='(A)') 'error in cFFT1B in do_fftback_along_y, field V' CALL wrf_debug(0,mess) end if DO j = jpsy, jpey fieldc_V_yyy(i,k,j)=real(dummy_complex(j)) fields_V_yyy(i,k,j)=imag(dummy_complex(j)) END DO END DO END DO ! k_start-k_end DO k=kpsy,kpey DO i = ipsy, ipey DO j = jpsy,jpey dummy_complex(j)=cmplx(fieldc_T_yyy(i,k,j),fields_T_yyy(i,k,j)) ENDDO CALL cFFT1B (KMAX, 1 ,dummy_complex,KMAX, WSAVE2, LENSAV, WORK, LENWRK, IER) if (ier.ne.0) then WRITE(mess,FMT='(A)') 'error in cFFT1B in do_fftback_along_y, field T' CALL wrf_debug(0,mess) end if DO j = jpsy,jpey fieldc_T_yyy(i,k,j)=real(dummy_complex(j)) fields_T_yyy(i,k,j)=imag(dummy_complex(j)) END DO END DO END DO ! k_start-k_end DEALLOCATE(WORK) end subroutine do_fftback_along_y ! ------------------------------------------------------------------ !!************** TRANSFORM FROM GRIDPOILT SPACE TO SPHERICAL HARMONICS ** ! ------------------------------------------------------------------ subroutine findindex( wavenumber_k, wavenumber_L, & 1 ids, ide, jds, jde, kds, kde, & ims, ime, jms, jme, kms, kme, & its, ite, jts, jte, kts, kte ) IMPLICIT NONE INTEGER :: IK,IL,KMAX,LMAX INTEGER, DIMENSION (jds:jde):: wavenumber_k INTEGER, DIMENSION (ids:ide):: wavenumber_l INTEGER , INTENT(IN) :: ids, ide, jds, jde, kds, kde, & ims, ime, jms, jme, kms, kme, & its, ite, jts, jte, kts, kte KMAX=(jde-jds)+1 LMAX=(ide-ids)+1 !map wave numbers K,L to indeces IK, IL DO IK=1,KMAX/2+1 wavenumber_k(IK)=IK-1 ENDDO DO IK=KMAX,KMAX/2+2,-1 wavenumber_k(IK)=IK-KMAX-1 ENDDO DO IL=1,LMAX/2+1 wavenumber_l(IL)=IL-1 ENDDO DO IL=LMAX,LMAX/2+2,-1 wavenumber_l(IL)=IL-LMAX-1 ENDDO END subroutine findindex ! ------------------------------------------------------------------ subroutine gauss_noise(z) 4 real :: z ! output real :: x,y,r, coeff ! INPUT ! [2.1] Get two uniform variate random numbers IL range 0 to 1: do call random_number( x ) call random_number( y ) ! [2.2] Transform to range -1 to 1 and calculate sum of squares: x = 2.0 * x - 1.0 y = 2.0 * y - 1.0 r = x * x + y * y if ( r > 0.0 .and. r < 1.0 ) exit end do ! ! [2.3] Use Box-Muller transformation to get normal deviates: coeff = sqrt( -2.0 * log(r) / r ) z = coeff * x end subroutine gauss_noise ! ------------------------------------------------------------------ end module module_stoch