source: trunk/LMDZ.MARS/libf/phymars/nonoro_gwd_ran_mod.F90 @ 2173

Last change on this file since 2173 was 2173, checked in by emillour, 5 years ago

Mars GCM:
Update non orographic GW routine so that key parameter RUWMAX is read in
from callphys.def
EM

File size: 22.1 KB
Line 
1MODULE nonoro_gwd_ran_mod
2
3IMPLICIT NONE
4
5CONTAINS
6
7      SUBROUTINE NONORO_GWD_RAN(NLON,NLEV,DTIME, pp,  &
8                  zmax_therm, pt, pu, pv, pdt, pdu, pdv, &
9                  zustr,zvstr,d_t, d_u, d_v)
10
11    !--------------------------------------------------------------------------------
12    ! Parametrization of the momentum flux deposition due to a discrete
13    ! number of gravity waves.
14    ! F. Lott
15    ! Version 14, Gaussian distribution of the source
16    ! LMDz model online version     
17    ! ADAPTED FOR VENUS /  F. LOTT + S. LEBONNOIS
18    ! Version adapted on 03/04/2013:
19    !      - input flux compensated in the deepest layers
20    !                           
21    ! ADAPTED FOR MARS     G.GILLI     02/2016
22    !        Revision with F.Forget    06/2016  Variable EP-flux according to
23    !                                            PBL variation (max velocity thermals)
24    !---------------------------------------------------------------------------------
25
26      use dimphy, only: klon, klev
27!      use moyzon_mod, only: plevmoy
28      use comcstfi_h, only: g, pi, cpp, r
29!      use comgeomfi_h, only: latitude
30      USE ioipsl_getin_p_mod, ONLY : getin_p
31      implicit none
32
33      include "dimensions.h"
34      include "paramet.h"
35      include "yoegwd.h"
36
37    ! 0. DECLARATIONS:
38
39    ! 0.1 INPUTS
40    INTEGER, intent(in):: NLON, NLEV
41    REAL, intent(in):: DTIME ! Time step of the Physics
42    REAL, intent(in):: zmax_therm(NLON) ! altitude of max velocity thermals (m)
43    REAL, intent(in):: pp(NLON,NLEV)   ! Pressure at full levels
44    REAL, intent(in):: pt(NLON,NLEV)   ! Temp at full levels
45    REAL, intent(in):: pu(NLON,NLEV),pv(NLON,NLEV) ! Hor winds at full levels
46    REAL,INTENT(in) :: pdt(nlon,nlev) ! tendency on temperature
47    REAL,INTENT(in) :: pdu(nlon,nlev) ! tendency on zonal wind
48    REAL,INTENT(in) :: pdv(nlon,nlev) ! tendency on meridional wind
49
50    ! 0.2 OUTPUTS
51    REAL, intent(out):: zustr(NLON), zvstr(NLON) ! Surface Stresses
52    REAL, intent(inout):: d_t(NLON, NLEV)        ! Tendency on Temp.
53
54
55    REAL, intent(inout):: d_u(NLON, NLEV), d_v(NLON, NLEV)
56    ! Tendencies on winds
57
58    ! O.3 INTERNAL ARRAYS
59    REAL :: TT(NLON, NLEV)   ! Temp at full levels
60
61    REAL :: UU(NLON, NLEV) , VV(NLON, NLEV)
62    ! Hor winds at full levels
63
64    INTEGER II, LL
65
66    ! 0.3.0 TIME SCALE OF THE LIFE CYCLE OF THE WAVES PARAMETERIZED
67
68    REAL DELTAT
69   
70    ! 0.3.1 GRAVITY-WAVES SPECIFICATIONS
71
72!!  NO= values of C, NW= total of GW
73    INTEGER, PARAMETER:: NK = 2, NP = 2, NO = 2, NW = NK * NP * NO
74    !Online output: change NO
75!    INTEGER, PARAMETER:: NK = 1, NP = 2, NO = 11, NW = NK * NP * NO
76    INTEGER JK, JP, JO, JW
77    REAL KMIN, KMAX ! Min and Max horizontal wavenumbers
78    REAL CMIN, CMAX ! Min and Max absolute ph. vel.
79    REAL CPHA ! absolute PHASE VELOCITY frequency
80    REAL ZK(NW, KLON) ! Horizontal wavenumber amplitude
81    REAL ZP(NW)       ! Horizontal wavenumber angle       
82    REAL ZO(NW, KLON) ! Absolute frequency      !
83
84    ! Waves Intr. freq. at the 1/2 lev surrounding the full level
85    REAL ZOM(NW, KLON), ZOP(NW, KLON)
86
87    ! Wave EP-fluxes at the 2 semi levels surrounding the full level
88    REAL WWM(NW, KLON), WWP(NW, KLON)
89    ! Fluxes X and Y for each waves at 1/2 Levels
90    REAL RUWP(NW, KLON), RVWP(NW, KLON)
91    REAL RUW(KLON, KLEV + 1) ! Flux x at semi levels
92    REAL RVW(KLON, KLEV + 1) ! Flux y at semi levels
93
94    REAL RUW0(NW, KLON) ! Fluxes at launching level
95    REAL,SAVE :: RUWMAX         ! Max value
96    INTEGER LAUNCH      ! Launching altitude
97    REAL XLAUNCH        ! Control the launching altitude
98        REAL ZMAXTH_TOP     ! Top of convective layer (approx.)
99
100   ! 0.3.2 PARAMETERS OF WAVES DISSIPATIONS
101
102    REAL SAT  ! saturation parameter
103    REAL RDISS, ZOISEC ! COEFF DE DISSIPATION, SECURITY FOR INTRINSIC FREQ
104
105    ! 0.3.3 BACKGROUND FLOW AT 1/2 LEVELS AND VERTICAL COORDINATE
106
107    REAL H0bis(KLON, KLEV) ! Characteristic Height of the atmosphere
108    REAL H0 ! Characteristic Height of the atmosphere
109    REAL PR, TR ! Reference Pressure and Temperature
110
111    REAL ZH(KLON, KLEV + 1) ! Log-pressure altitude (constant H0)
112    REAL ZHbis(KLON, KLEV + 1) ! Log-pressure altitude (varying H)
113
114    REAL UH(KLON, KLEV + 1), VH(KLON, KLEV + 1) ! Winds at 1/2 levels
115    REAL PH(KLON, KLEV + 1) ! Pressure at 1/2 levels
116    REAL PSEC ! Security to avoid division by 0 pressure
117    REAL BV(KLON, KLEV + 1) ! Brunt Vaisala freq. (BVF) at 1/2 levels
118    REAL BVSEC ! Security to avoid negative BVF
119
120! COSMETICS TO DIAGNOSE EACH WAVES CONTRIBUTION.
121    logical,save :: output=.false.
122 ! CAUTION ! IF output is .true. THEN change NO to 10 at least !
123    character*14 outform
124    character*2  str2
125    integer      ieq
126
127! ON CONSERVE LA MEMOIRE un certain temps AVEC UN SAVE
128    real,save,allocatable :: d_u_sav(:,:),d_v_sav(:,:)
129    LOGICAL,SAVE :: firstcall = .true.
130
131!      REAL ALEAS
132!      EXTERNAL ALEAS
133
134   !-----------------------------------------------------------------
135    !  1. INITIALISATIONS
136
137      IF (firstcall) THEN
138        write(*,*) "nonoro_gwd_ran: FLott non-oro GW scheme is active!"
139        allocate(d_u_sav(NLON,NLEV),d_v_sav(NLON,NLEV))
140        d_u_sav(:,:) = 0.
141        d_v_sav(:,:) = 0.
142        RUWMAX=1.E-4
143        CALL getin_p("nonoro_gwd_RUWMAX",RUWMAX)
144        write(*,*) "nonoro_gwd_ran: RUWMAX=",RUWMAX
145        firstcall=.false.
146      ENDIF
147
148    ! Compute current values of temperature and winds
149    tt(:,:)=pt(:,:)+dtime*pdt(:,:)
150    uu(:,:)=pu(:,:)+dtime*pdu(:,:)
151    vv(:,:)=pv(:,:)+dtime*pdv(:,:)
152   
153    !    1.1 Basic parameter
154
155    !  PARAMETERS CORRESPONDING TO V3:
156!     RUWMAX  = 1.e-4      ! best-case for MCS comparison
157!      RUWMAX = 5.e-6
158!     RUWMAX  = 1.e-3 
159
160!     SAT    = 0.25       ! Saturation parameter: Sc in (12)       
161      SAT    = 1.         ! GG: This is the bestcase value for MCS comparison,
162!                         ! but runs for 1 full MY in the thermosphere are instables.                 
163!!!   TESTS                   
164!      SAT    = 0.85
165!
166!   RDISS  = 40         ! Diffusion parameter     
167    RDISS  =  1
168!    RDISS = 0.5
169
170    DELTAT=24.*3600.    ! Time scale of the waves (first introduced in 9b)
171!    DELTAT=DTIME
172
173    KMIN = 2.E-5        ! Min horizontal wavenumber
174    KMAX = 7.E-4        ! Max horizontal wavenumber
175
176    !Online output: one value only
177    if (output) then
178      KMIN = 6.3E-5
179      KMAX = 6.3E-5
180    endif
181    CMIN = 1.           ! Min phase velocity
182!    CMAX = 10.          ! Max phase speed velocity
183    CMAX = 30.       
184!    CMAX = 60.
185    XLAUNCH=0.4         ! Parameter that control launching altitude P/Ps
186!!! TEST: launching GW near the ground
187!    XLAUNCH =0.8
188
189! MARS above typical convective cell at 250 Pa
190    PR = 250.           ! Reference pressure  [Pa]   !
191    TR = 220.           ! Reference Temperature [K]  !
192
193    ZMAXTH_TOP  = 8000. ! Reference max altitude of convective layer [m]
194         
195    H0 = r * TR / g   ! Characteristic vertical scale height
196
197    BVSEC  = 1.E-5      ! Security to avoid negative BVF 
198    PSEC   = 1.E-6      ! Security to avoid division by 0 pressure
199    ZOISEC = 1.E-6      ! Security FOR 0 INTRINSIC FREQ
200
201    IF(DELTAT.LT.DTIME)THEN
202       PRINT *,'GWD RANDO: DELTAT LT DTIME!'
203       STOP
204    ENDIF
205
206
207    IF (NLEV < NW) THEN
208       PRINT *, 'YOU WILL HAVE PROBLEM WITH RANDOM NUMBERS'
209       PRINT *, 'FLOTT GWD STOP'
210       STOP 1
211    ENDIF
212
213    !  2. EVALUATION OF THE BACKGROUND FLOW AT SEMI-LEVELS
214    !-------------------------------------------------------------
215
216    !Online output
217    if (output) OPEN(11,file="impact-gwno.dat")
218
219    ! Pressure and Inv of pressure, Temperature / at 1/2 level
220    DO LL = 2, KLEV
221       PH(:, LL) = EXP((LOG(PP(:, LL)) + LOG(PP(:, LL - 1))) / 2.)
222    end DO
223
224    PH(:, KLEV + 1) = 0.
225    PH(:, 1) = 2. * PP(:, 1) - PH(:, 2)
226
227    ! Launching altitude
228
229    DO LL = 1, NLEV
230       IF (PH(NLON / 2, LL) / PH(NLON / 2, 1) > XLAUNCH) LAUNCH = LL
231!       IF (plevmoy(LL) / plevmoy(1) > XLAUNCH) LAUNCH = LL   ! on venus
232    ENDDO
233 
234    if (output) print*, " WE ARE IN FLOTT GW SCHEME "
235   
236    !print*, "launch=",LAUNCH
237    !print*,"launch p =",PH(NLON/2, LAUNCH)
238
239    ! Log pressure vert. coordinate
240    DO LL = 1, KLEV + 1
241       ZH(:, LL) = H0 * LOG(PR / (PH(:, LL) + PSEC))
242     !  print*,'ZH at each level',LL, ZH(NLON/2, LL)
243    end DO
244
245    if (output) then
246    ! altitude above surface
247       ZHbis(:,1) = 0.   
248       DO LL = 2, KLEV + 1
249          H0bis(:, LL-1) = r * TT(:, LL-1) / g
250          ZHbis(:, LL) = ZHbis(:, LL-1) &
251           + H0bis(:, LL-1)*(PH(:, LL-1)-PH(:,LL))/PP(:, LL-1)
252       end DO
253    endif
254
255    ! Winds and BV frequency
256    DO LL = 2, KLEV
257       UH(:, LL) = 0.5 * (UU(:, LL) + UU(:, LL - 1)) ! Zonal wind
258       VH(:, LL) = 0.5 * (VV(:, LL) + VV(:, LL - 1)) ! Meridional wind
259       ! GG test       
260       !print*, 'TT, UH, VH, ZH at launch', TT(NLON/2,LAUNCH), UH(NLON/2,LAUNCH),VH(NLON/2, LAUNCH), ZH(NLON/2,LAUNCH) 
261       ! BVSEC: BV Frequency
262       BV(:, LL) = 0.5 * (TT(:, LL) + TT(:, LL - 1)) &
263            * r**2 / cpp / H0**2 + (TT(:, LL) &
264            - TT(:, LL - 1)) / (ZH(:, LL) - ZH(:, LL - 1)) * r / H0
265       BV(:,LL) =SQRT(MAX(BVSEC,BV(:,LL)))
266    end DO
267       !GG test
268       !print*, 'BV freq in flott_gwnoro:',LAUNCH,  BV(NLON/2, LAUNCH) 
269
270    BV(:, 1) = BV(:, 2)
271    UH(:, 1) = 0.
272    VH(:, 1) = 0.
273    BV(:, KLEV + 1) = BV(:, KLEV)
274    UH(:, KLEV + 1) = UU(:, KLEV)
275    VH(:, KLEV + 1) = VV(:, KLEV)
276
277
278    ! 3. WAVES CHARACTERISTICS CHOSEN RANDOMLY
279    !-------------------------------------------
280
281    ! The mod function of here a weird arguments
282    ! are used to produce the waves characteristics
283    ! in a stochastic way
284
285!! A REVOIR:
286!! - utilisation de MOD ou bien de aleas ?
287!! - distribution gaussienne des CPHA ? (avec signe ZP qui est ajuste apres)
288
289    JW = 0
290    DO JP = 1, NP
291       DO JK = 1, NK
292          DO JO = 1, NO
293             JW = JW + 1
294             !  Angle
295             ZP(JW) = 2. * pi * REAL(JP - 1) / REAL(NP)
296             DO II = 1, KLON
297                ! Horizontal wavenumber amplitude
298!                ZK(JW, II) = KMIN + (KMAX - KMIN) * MOD(TT(II, JW) * 100., 1.)
299                ZK(JW, II) = KMIN + (KMAX - KMIN) * ALEAS(0.)
300                ! Horizontal phase speed
301!                CPHA = CMIN + (CMAX - CMIN) * MOD(TT(II, JW)**2, 1.)
302                CPHA = CMIN + (CMAX - CMIN) * ALEAS(0.)
303       !Online output: linear
304                if (output) CPHA = CMIN + (CMAX - CMIN) * (JO-1)/(NO-1)
305                ! Intrinsic frequency
306                ZO(JW, II) = CPHA * ZK(JW, II)
307                ! Intrinsic frequency  is imposed
308                    ZO(JW, II) = ZO(JW, II)      &
309                  + ZK(JW, II) * COS(ZP(JW)) * UH(II, LAUNCH) &
310                  + ZK(JW, II) * SIN(ZP(JW)) * VH(II, LAUNCH)
311                ! Momentum flux at launch lev
312!!
313!!! CHANGE on MARS GCM: variable EP-FLUX according to:
314!     TEST1:   PBL diurnal variation
315!!
316!                 RUW0(JW, II) = MAX(RUWMAX / 100.,  &
317!                               zmax_therm(II)/ZMAXTH_TOP * RUWMAX)
318         
319!!! BELOW: previous version from Flott original version
320                RUW0(JW, II) = RUWMAX &
321                     * ALEAS(0.)     ! &
322!!! The factor cos**8:Limit the fluxes to tropical regions
323!                    * COS(pi/180.*latitude(II))**8
324       !Online output: fixed to max
325                if (output) RUW0(JW, II) = RUWMAX
326             ENDDO
327          end DO
328       end DO
329    end DO
330
331    ! 4. COMPUTE THE FLUXES
332    !--------------------------
333
334    !  4.1  Vertical velocity at launching altitude to ensure
335    !       the correct value to the imposed fluxes.
336    !
337    DO JW = 1, NW
338
339       ! Evaluate intrinsic frequency at launching altitude:
340       ZOP(JW, :) = ZO(JW, :) &
341            - ZK(JW, :) * COS(ZP(JW)) * UH(:, LAUNCH) &
342            - ZK(JW, :) * SIN(ZP(JW)) * VH(:, LAUNCH)
343       ! Vertical velocity at launch level, value to ensure the imposed
344       ! mom flux:
345       WWP(JW, :) = SQRT(ABS(ZOP(JW, :)) / MAX(BV(:, LAUNCH),BVSEC) &
346            * RUW0(JW,:))
347       RUWP(JW, :) = COS(ZP(JW)) * SIGN(1., ZOP(JW, :)) * RUW0(JW, :)
348       RVWP(JW, :) = SIN(ZP(JW)) * SIGN(1., ZOP(JW, :)) * RUW0(JW, :)
349
350    end DO
351
352    !!!  EARTH VERSION  !!!!
353    !  4.2 Uniform values below the launching altitude
354
355    DO LL = 1, LAUNCH
356       RUW(:, LL) = 0
357       RVW(:, LL) = 0
358       DO JW = 1, NW
359          RUW(:, LL) = RUW(:, LL) + RUWP(JW, :)
360          RVW(:, LL) = RVW(:, LL) + RVWP(JW, :)
361       end DO
362    end DO
363
364    !!!  VENUS VERSION  !!!!
365    !  4.2 Initial flux at launching altitude
366
367    !RUW(:, LAUNCH) = 0
368    !RVW(:, LAUNCH) = 0
369    !DO JW = 1, NW
370    !   RUW(:, LAUNCH) = RUW(:, LAUNCH) + RUWP(JW, :)
371    !   RVW(:, LAUNCH) = RVW(:, LAUNCH) + RVWP(JW, :)
372    !end DO
373
374    !  4.3 Loop over altitudes, with passage from one level to the
375    !      next done by i) conserving the EP flux, ii) dissipating
376    !      a little, iii) testing critical levels, and vi) testing
377    !      the breaking.
378
379    !Online output
380    if (output) then
381        ieq=nlon/2+1
382        write(str2,'(i2)') NW+2
383        outform="("//str2//"(E12.4,1X))"
384        WRITE(11,outform) ZH(IEQ, 1) / 1000., ZHbis(IEQ, 1) / 1000., &
385               (ZO(JW, IEQ)/ZK(JW, IEQ)*COS(ZP(JW)), JW = 1, NW)
386    endif
387
388    DO LL = LAUNCH, KLEV - 1
389
390
391       !  W(KB)ARNING: ALL THE PHYSICS IS HERE (PASSAGE FROM ONE LEVEL
392       ! TO THE NEXT)
393       DO JW = 1, NW
394          ZOM(JW, :) = ZOP(JW, :)
395          WWM(JW, :) = WWP(JW, :)
396          ! Intrinsic Frequency
397          ZOP(JW, :) = ZO(JW, :) - ZK(JW, :) * COS(ZP(JW)) * UH(:, LL + 1) &
398               - ZK(JW, :) * SIN(ZP(JW)) * VH(:, LL + 1)
399
400          WWP(JW, :) = MIN( &
401       ! No breaking (Eq.6)
402               WWM(JW, :) &
403               * SQRT(BV(:, LL ) / BV(:, LL+1) &
404               * ABS(ZOP(JW, :)) / MAX(ABS(ZOM(JW, :)), ZOISEC)) &
405      ! Dissipation (Eq. 8):
406               * EXP(- RDISS * PR / (PH(:, LL + 1) + PH(:, LL)) &
407               * ((BV(:, LL + 1) + BV(:, LL)) / 2.)**3 &
408               / MAX(ABS(ZOP(JW, :) + ZOM(JW, :)) / 2., ZOISEC)**4 &
409               * ZK(JW, :)**3 * (ZH(:, LL + 1) - ZH(:, LL))), &
410       ! Critical levels (forced to zero if intrinsic frequency changes sign)
411               MAX(0., SIGN(1., ZOP(JW, :) * ZOM(JW, :))) &
412       ! Saturation (Eq. 12)
413               * ABS(ZOP(JW, :))**3 /BV(:, LL+1) &
414               * EXP(-ZH(:, LL + 1)/H0) * SAT**2*KMIN**2/ZK(JW, :)**4) 
415       end DO
416
417       ! END OF W(KB)ARNING
418       ! Evaluate EP-flux from Eq. 7 and
419       ! Give the right orientation to the stress
420       DO JW = 1, NW
421          RUWP(JW, :) = ZOP(JW, :)/MAX(ABS(ZOP(JW, :)), ZOISEC)**2 &
422               *BV(:,LL+1)&
423               * COS(ZP(JW)) *  WWP(JW, :)**2
424          RVWP(JW, :) = ZOP(JW, :)/MAX(ABS(ZOP(JW, :)), ZOISEC)**2 &
425               *BV(:,LL+1)&
426               * SIN(ZP(JW)) *  WWP(JW, :)**2
427       end DO
428 
429       !
430       RUW(:, LL + 1) = 0.
431       RVW(:, LL + 1) = 0.
432
433       DO JW = 1, NW
434          RUW(:, LL + 1) = RUW(:, LL + 1) + RUWP(JW, :)
435          RVW(:, LL + 1) = RVW(:, LL + 1) + RVWP(JW, :)
436       end DO
437       !Online output
438       if (output) then
439         do JW=1,NW
440            if(RUWP(JW, IEQ).gt.0.) then
441              RUWP(JW, IEQ) = max(RUWP(JW, IEQ), 1.e-99)
442            else
443              RUWP(JW, IEQ) = min(RUWP(JW, IEQ), -1.e-99)
444            endif
445         enddo
446                   WRITE(11,outform) ZH(IEQ, LL+1) / 1000., &
447                                  ZHbis(IEQ, LL+1) / 1000., &
448                                  (RUWP(JW, IEQ), JW = 1, NW)
449       endif
450
451    end DO
452
453    ! 5 CALCUL DES TENDANCES:
454    !------------------------
455
456    ! 5.1 Rectification des flux au sommet et dans les basses couches:
457
458    RUW(:, KLEV + 1) = 0.
459    RVW(:, KLEV + 1) = 0.
460    RUW(:, 1) = RUW(:, LAUNCH)
461    RVW(:, 1) = RVW(:, LAUNCH)
462    DO LL = 2, LAUNCH
463       RUW(:, LL) = RUW(:, LL - 1) + (RUW(:, LAUNCH + 1) - RUW(:, 1)) * &
464            (PH(:, LL) - PH(:, LL - 1)) / (PH(:, LAUNCH + 1) - PH(:, 1))
465       RVW(:, LL) = RVW(:, LL - 1) + (RVW(:, LAUNCH + 1) - RVW(:, 1)) * &
466            (PH(:, LL) - PH(:, LL - 1)) / (PH(:, LAUNCH + 1) - PH(:, 1))
467    end DO
468
469    ! AR-1 RECURSIVE FORMULA (13) IN VERSION 4
470    DO LL = 1, KLEV
471       d_u(:, LL) = G * (RUW(:, LL + 1) - RUW(:, LL)) &
472            / (PH(:, LL + 1) - PH(:, LL)) * DTIME
473       d_v(:, LL) = G * (RVW(:, LL + 1) - RVW(:, LL)) &
474            / (PH(:, LL + 1) - PH(:, LL)) * DTIME
475    ENDDO
476    d_t(:,:) = 0.
477    ! ON CONSERVE LA MEMOIRE un certain temps AVEC UN SAVE
478    d_u(:,:) = DTIME/DELTAT/REAL(NW) * d_u(:,:) + (1.-DTIME/DELTAT) * d_u_sav(:,:)
479    d_v(:,:) = DTIME/DELTAT/REAL(NW) * d_v(:,:) + (1.-DTIME/DELTAT) * d_v_sav(:,:)
480    d_u_sav(:,:) = d_u(:,:)
481    d_v_sav(:,:) = d_v(:,:)
482
483    ! Cosmetic: evaluation of the cumulated stress
484
485    ZUSTR(:) = 0.
486    ZVSTR(:) = 0.
487    DO LL = 1, KLEV
488       ZUSTR(:) = ZUSTR(:) + D_U(:, LL) / g * (PH(:, LL + 1) - PH(:, LL))
489       ZVSTR(:) = ZVSTR(:) + D_V(:, LL) / g * (PH(:, LL + 1) - PH(:, LL))
490    ENDDO
491
492  END SUBROUTINE NONORO_GWD_RAN
493
494!===================================================================
495!===================================================================
496!===================================================================
497!===================================================================
498
499  REAL FUNCTION ALEAS (R)
500  IMPLICIT NONE
501!***BEGIN PROLOGUE  ALEAS
502!***PURPOSE  Generate a uniformly distributed random number.
503!***LIBRARY   SLATEC (FNLIB)
504!***CATEGORY  L6A21
505!***TYPE      SINGLE PRECISION (ALEAS-S)
506!***KEYWORDS  FNLIB, ALEAS NUMBER, SPECIAL FUNCTIONS, UNIFORM
507!***AUTHOR  Fullerton, W., (LANL)
508!***DESCRIPTION
509!
510!      This pseudo-random number generator is portable among a wide
511! variety of computers.  RAND(R) undoubtedly is not as good as many
512! readily available installation dependent versions, and so this
513! routine is not recommended for widespread usage.  Its redeeming
514! feature is that the exact same random numbers (to within final round-
515! off error) can be generated from machine to machine.  Thus, programs
516! that make use of random numbers can be easily transported to and
517! checked in a new environment.
518!
519!      The random numbers are generated by the linear congruential
520! method described, e.g., by Knuth in Seminumerical Methods (p.9),
521! Addison-Wesley, 1969.  Given the I-th number of a pseudo-random
522! sequence, the I+1 -st number is generated from
523!             X(I+1) = (A*X(I) + C) MOD M,
524! where here M = 2**22 = 4194304, C = 1731 and several suitable values
525! of the multiplier A are discussed below.  Both the multiplier A and
526! random number X are represented in double precision as two 11-bit
527! words.  The constants are chosen so that the period is the maximum
528! possible, 4194304.
529!
530!      In order that the same numbers be generated from machine to
531! machine, it is necessary that 23-bit integers be reducible modulo
532! 2**11 exactly, that 23-bit integers be added exactly, and that 11-bit
533! integers be multiplied exactly.  Furthermore, if the restart option
534! is used (where R is between 0 and 1), then the product R*2**22 =
535! R*4194304 must be correct to the nearest integer.
536!
537!      The first four random numbers should be .0004127026,
538! .6750836372, .1614754200, and .9086198807.  The tenth random number
539! is .5527787209, and the hundredth is .3600893021 .  The thousandth
540! number should be .2176990509 .
541!
542!      In order to generate several effectively independent sequences
543! with the same generator, it is necessary to know the random number
544! for several widely spaced calls.  The I-th random number times 2**22,
545! where I=K*P/8 and P is the period of the sequence (P = 2**22), is
546! still of the form L*P/8.  In particular we find the I-th random
547! number multiplied by 2**22 is given by
548! I   =  0  1*P/8  2*P/8  3*P/8  4*P/8  5*P/8  6*P/8  7*P/8  8*P/8
549! RAND=  0  5*P/8  2*P/8  7*P/8  4*P/8  1*P/8  6*P/8  3*P/8  0
550! Thus the 4*P/8 = 2097152 random number is 2097152/2**22.
551!
552!      Several multipliers have been subjected to the spectral test
553! (see Knuth, p. 82).  Four suitable multipliers roughly in order of
554! goodness according to the spectral test are
555!    3146757 = 1536*2048 + 1029 = 2**21 + 2**20 + 2**10 + 5
556!    2098181 = 1024*2048 + 1029 = 2**21 + 2**10 + 5
557!    3146245 = 1536*2048 +  517 = 2**21 + 2**20 + 2**9 + 5
558!    2776669 = 1355*2048 + 1629 = 5**9 + 7**7 + 1
559!
560!      In the table below LOG10(NU(I)) gives roughly the number of
561! random decimal digits in the random numbers considered I at a time.
562! C is the primary measure of goodness.  In both cases bigger is better.
563!
564!                   LOG10 NU(I)              C(I)
565!       A       I=2  I=3  I=4  I=5    I=2  I=3  I=4  I=5
566!
567!    3146757    3.3  2.0  1.6  1.3    3.1  1.3  4.6  2.6
568!    2098181    3.3  2.0  1.6  1.2    3.2  1.3  4.6  1.7
569!    3146245    3.3  2.2  1.5  1.1    3.2  4.2  1.1  0.4
570!    2776669    3.3  2.1  1.6  1.3    2.5  2.0  1.9  2.6
571!   Best
572!    Possible   3.3  2.3  1.7  1.4    3.6  5.9  9.7  14.9
573!
574!             Input Argument --
575! R      If R=0., the next random number of the sequence is generated.
576!        If R .LT. 0., the last generated number will be returned for
577!          possible use in a restart procedure.
578!        If R .GT. 0., the sequence of random numbers will start with
579!          the seed R mod 1.  This seed is also returned as the value of
580!          RAND provided the arithmetic is done exactly.
581!
582!             Output Value --
583! RAND   a pseudo-random number between 0. and 1.
584!
585!***REFERENCES  (NONE)
586!***ROUTINES CALLED  (NONE)
587!***REVISION HISTORY  (YYMMDD)
588!   770401  DATE WRITTEN
589!   890531  Changed all specific intrinsics to generic.  (WRB)
590!   890531  REVISION DATE from Version 3.2
591!   891214  Prologue converted to Version 4.0 format.  (BAB)
592!***END PROLOGUE  RAND
593      INTEGER IA1, IA0, IA1MA0, IC, IX1, IX0
594      SAVE IA1, IA0, IA1MA0, IC, IX1, IX0
595      DATA IA1, IA0, IA1MA0 /1536, 1029, 507/
596      DATA IC /1731/
597      DATA IX1, IX0 /0, 0/
598      REAL R
599      INTEGER IY0,IY1
600!***FIRST EXECUTABLE STATEMENT  RAND
601!
602!           A*X = 2**22*IA1*IX1 + 2**11*(IA1*IX1 + (IA1-IA0)*(IX0-IX1)
603!                   + IA0*IX0) + IA0*IX0
604!
605      IF (R.EQ.0.) THEN
606       IY0 = IA0*IX0
607       IY1 = IA1*IX1 + IA1MA0*(IX0-IX1) + IY0
608       IY0 = IY0 + IC
609       IX0 = MOD (IY0, 2048)
610       IY1 = IY1 + (IY0-IX0)/2048
611       IX1 = MOD (IY1, 2048)
612      ENDIF
613
614      IF (R.GT.0.) THEN
615       IX1 = MOD(R,1.)*4194304. + 0.5
616       IX0 = MOD (IX1, 2048)
617       IX1 = (IX1-IX0)/2048
618      ENDIF
619
620      ALEAS = IX1*2048 + IX0
621      ALEAS = ALEAS / 4194304.
622      RETURN
623
624      END FUNCTION ALEAS
625
626END MODULE nonoro_gwd_ran_mod
Note: See TracBrowser for help on using the repository browser.