source: trunk/LMDZ.VENUS/libf/phyvenus/flott_gwd_ran.F90 @ 1665

Last change on this file since 1665 was 1621, checked in by emillour, 9 years ago

Further work on full dynamics/physics separation.

LMDZ.COMMON:

  • added phy_common/vertical_layers_mod.F90 to store information on vertical grid. This is where routines in the physics should get the information.
  • The contents of vertical_layers_mod intialized via dynphy_lonlat/inigeomphy_mod.F90.

LMDZ.MARS:

  • physics now completely decoupled from dynamics; the physics package may now be compiled as a library (-libphy option of makelmdz_fcm).
  • created an "ini_tracer_mod" routine in module "tracer_mod" for a cleaner initialization of the later.
  • removed some purely dynamics-related outputs (etot0, zoom parameters, etc.) from diagfi.nc and stats.nc outputs as these informations are not available in the physics.

LMDZ.GENERIC:

  • physics now completely decoupled from dynamics; the physics package may now be compiled as a library (-libphy option of makelmdz_fcm).
  • added nqtot to tracer_h.F90.
  • removed some purely dynamics-related outputs (etot0, zoom parameters, etc.) from diagfi.nc and stats.nc outputs as these informations are not available in the physics.

LMDZ.VENUS:

  • physics now completely decoupled from dynamics; the physics package may now be compiled as a library (-libphy option of makelmdz_fcm).
  • added infotrac_phy.F90 to store information on tracers in the physics. Initialized via iniphysiq.
  • added cpdet_phy_mod.F90 to store t2tpot etc. functions to be used in the physics. Initialized via iniphysiq. IMPORTANT: there are some hard-coded constants! These should match what is in cpdet_mod.F90 in the dynamics.
  • got rid of references to moyzon_mod module within the physics. The required variables (tmoy, plevmoy) are passed to the physics as arguments to physiq.

LMDZ.TITAN:

  • added infotrac_phy.F90 to store information on tracers in the physics. Initialized via iniphysiq.
  • added cpdet_phy_mod.F90 to store t2tpot etc. functions to be used in the physics.
  • Extra work required to completely decouple physics and dynamics: moyzon_mod should be cleaned up and information passed from dynamics to physics as as arguments. Likewise moyzon_ch and moyzon_mu should not be queried from logic_mod (which is in the dynamics).

EM

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