GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: phylmd/hines_gwd.F90 Lines: 0 471 0.0 %
Date: 2023-06-30 12:56:34 Branches: 0 370 0.0 %

Line Branch Exec Source
1
2
! $Id: hines_gwd.F90 3102 2017-12-03 20:27:42Z oboucher $
3
4
SUBROUTINE hines_gwd(nlon, nlev, dtime, paphm1x, papm1x, rlat, tx, ux, vx, &
5
    zustrhi, zvstrhi, d_t_hin, d_u_hin, d_v_hin)
6
7
  ! ########################################################################
8
  ! Parametrization of the momentum flux deposition due to a broad band
9
  ! spectrum of gravity waves, following Hines (1997a,b), as coded by
10
  ! McLANDRESS (1995). Modified by McFARLANE and MANZINI (1995-1997)
11
  ! MAECHAM model stand alone version
12
  ! ########################################################################
13
14
15
  USE dimphy
16
  IMPLICIT NONE
17
18
  include "YOEGWD.h"
19
  include "YOMCST.h"
20
21
  INTEGER nazmth
22
  PARAMETER (nazmth=8)
23
24
  ! INPUT ARGUMENTS.
25
  ! ----- ----------
26
27
  ! - 2D
28
  ! PAPHM1   : HALF LEVEL PRESSURE (T-DT)
29
  ! PAPM1    : FULL LEVEL PRESSURE (T-DT)
30
  ! PTM1     : TEMPERATURE (T-DT)
31
  ! PUM1     : ZONAL WIND (T-DT)
32
  ! PVM1     : MERIDIONAL WIND (T-DT)
33
34
35
  ! REFERENCE.
36
  ! ----------
37
  ! SEE MODEL DOCUMENTATION
38
39
  ! AUTHOR.
40
  ! -------
41
42
  ! N. MCFARLANE   DKRZ-HAMBURG   MAY 1995
43
  ! STAND ALONE E. MANZINI MPI-HAMBURG FEBRUARY 1997
44
45
  ! BASED ON A COMBINATION OF THE OROGRAPHIC SCHEME BY N.MCFARLANE 1987
46
  ! AND THE HINES SCHEME AS CODED BY C. MCLANDRESS 1995.
47
48
49
50
  ! ym      INTEGER KLEVM1
51
52
  REAL paphm1(klon, klev+1), papm1(klon, klev)
53
  REAL ptm1(klon, klev), pum1(klon, klev), pvm1(klon, klev)
54
  REAL prflux(klon)
55
  ! 1
56
  ! 1
57
  ! 1
58
  REAL rlat(klon), coslat(klon)
59
60
  REAL th(klon, klev), utendgw(klon, klev), vtendgw(klon, klev), &
61
    pressg(klon), uhs(klon, klev), vhs(klon, klev), zpr(klon)
62
63
  ! * VERTICAL POSITIONING ARRAYS.
64
65
  REAL sgj(klon, klev), shj(klon, klev), shxkj(klon, klev), dsgj(klon, klev)
66
67
  ! * LOGICAL SWITCHES TO CONTROL ROOF DRAG, ENVELOP GW DRAG AND
68
  ! * HINES' DOPPLER SPREADING EXTROWAVE GW DRAG.
69
  ! * LOZPR IS TRUE FOR ZPR ENHANCEMENT
70
71
72
  ! * WORK ARRAYS.
73
74
  REAL m_alpha(klon, klev, nazmth), v_alpha(klon, klev, nazmth), &
75
    sigma_alpha(klon, klev, nazmth), sigsqh_alpha(klon, klev, nazmth), &
76
    drag_u(klon, klev), drag_v(klon, klev), flux_u(klon, klev), &
77
    flux_v(klon, klev), heat(klon, klev), diffco(klon, klev), &
78
    bvfreq(klon, klev), density(klon, klev), sigma_t(klon, klev), &
79
    visc_mol(klon, klev), alt(klon, klev), sigsqmcw(klon, klev, nazmth), &
80
    sigmatm(klon, klev), ak_alpha(klon, nazmth), k_alpha(klon, nazmth), &
81
    mmin_alpha(klon, nazmth), i_alpha(klon, nazmth), rmswind(klon), &
82
    bvfbot(klon), densbot(klon)
83
  REAL smoothr1(klon, klev), smoothr2(klon, klev)
84
  REAL sigalpmc(klon, klev, nazmth)
85
  REAL f2mod(klon, klev)
86
87
  ! * THES ARE THE INPUT PARAMETERS FOR HINES ROUTINE AND
88
  ! * ARE SPECIFIED IN ROUTINE HINES_SETUP. SINCE THIS IS CALLED
89
  ! * ONLY AT FIRST CALL TO THIS ROUTINE THESE VARIABLES MUST BE SAVED
90
  ! * FOR USE AT SUBSEQUENT CALLS. THIS CAN BE AVOIDED BY CALLING
91
  ! * HINES_SETUP IN MAIN PROGRAM AND PASSING THE PARAMETERS AS
92
  ! * SUBROUTINE ARGUEMENTS.
93
94
95
  REAL rmscon
96
  INTEGER nmessg, iprint, ilrms
97
  INTEGER ifl
98
99
  INTEGER naz, icutoff, nsmax, iheatcal
100
  REAL slope, f1, f2, f3, f5, f6, kstar(klon), alt_cutoff, smco
101
102
  ! PROVIDED AS INPUT
103
104
  INTEGER nlon, nlev
105
106
  REAL dtime
107
  REAL paphm1x(nlon, nlev+1), papm1x(nlon, nlev)
108
  REAL ux(nlon, nlev), vx(nlon, nlev), tx(nlon, nlev)
109
110
  ! VARIABLES FOR OUTPUT
111
112
113
  REAL d_t_hin(nlon, nlev), d_u_hin(nlon, nlev), d_v_hin(nlon, nlev)
114
  REAL zustrhi(nlon), zvstrhi(nlon)
115
116
117
  ! * LOGICAL SWITCHES TO CONTROL PRECIP ENHANCEMENT AND
118
  ! * HINES' DOPPLER SPREADING EXTROWAVE GW DRAG.
119
  ! * LOZPR IS TRUE FOR ZPR ENHANCEMENT
120
121
  LOGICAL lozpr, lorms(klon)
122
123
  ! LOCAL PARAMETERS TO MAKE THINGS WORK (TEMPORARY VARIABLE)
124
125
  REAL rhoh2o, zpcons, rgocp, zlat, dttdsf, ratio, hscal
126
  INTEGER i, j, l, jl, jk, le, lref, lrefp, levbot
127
128
  ! DATA PARAMETERS NEEDED, EXPLAINED LATER
129
130
  REAL v0, vmin, dmpscal, taufac, hmin, apibt, cpart, fcrit
131
  REAL pcrit, pcons
132
  INTEGER iplev, ierror
133
134
135
136
  ! PRINT *,' IT IS STARTED HINES GOING ON...'
137
138
139
140
141
  ! *    COMPUTATIONAL CONSTANTS.
142
  ! ------------- ----------
143
144
145
  d_t_hin(:, :) = 0.
146
147
  rhoh2o = 1000.
148
  zpcons = (1000.*86400.)/rhoh2o
149
  ! ym      KLEVM1=KLEV-1
150
151
152
  DO jl = kidia, kfdia
153
    paphm1(jl, 1) = paphm1x(jl, klev+1)
154
    DO jk = 1, klev
155
      le = klev + 1 - jk
156
      paphm1(jl, jk+1) = paphm1x(jl, le)
157
      papm1(jl, jk) = papm1x(jl, le)
158
      ptm1(jl, jk) = tx(jl, le)
159
      pum1(jl, jk) = ux(jl, le)
160
      pvm1(jl, jk) = vx(jl, le)
161
    END DO
162
  END DO
163
164
  ! Define constants and arrays needed for the ccc/mam gwd scheme
165
  ! *Constants:
166
167
  rgocp = rd/rcpd
168
  lrefp = klev - 1
169
  lref = klev - 2
170
  ! 1
171
  ! 1    *Arrays
172
  ! 1
173
  DO jk = 1, klev
174
    DO jl = kidia, kfdia
175
      shj(jl, jk) = papm1(jl, jk)/paphm1(jl, klev+1)
176
      sgj(jl, jk) = papm1(jl, jk)/paphm1(jl, klev+1)
177
      dsgj(jl, jk) = (paphm1(jl,jk+1)-paphm1(jl,jk))/paphm1(jl, klev+1)
178
      shxkj(jl, jk) = (papm1(jl,jk)/paphm1(jl,klev+1))**rgocp
179
      th(jl, jk) = ptm1(jl, jk)
180
    END DO
181
  END DO
182
183
  ! C
184
  DO jl = kidia, kfdia
185
    pressg(jl) = paphm1(jl, klev+1)
186
  END DO
187
188
189
  DO jl = kidia, kfdia
190
    prflux(jl) = 0.0
191
    zpr(jl) = zpcons*prflux(jl)
192
    zlat = (rlat(jl)/180.)*rpi
193
    coslat(jl) = cos(zlat)
194
  END DO
195
196
  ! /#########################################################################
197
  ! /
198
  ! /
199
200
  ! * AUG. 14/95 - C. MCLANDRESS.
201
  ! * SEP.    95   N. MCFARLANE.
202
203
  ! * THIS ROUTINE CALCULATES THE HORIZONTAL WIND TENDENCIES
204
  ! * DUE TO MCFARLANE'S OROGRAPHIC GW DRAG SCHEME, HINES'
205
  ! * DOPPLER SPREAD SCHEME FOR "EXTROWAVES" AND ADDS ON
206
  ! * ROOF DRAG. IT IS BASED ON THE ROUTINE GWDFLX8.
207
208
  ! * LREFP IS THE INDEX OF THE MODEL LEVEL BELOW THE REFERENCE LEVEL
209
  ! * I/O ARRAYS PASSED FROM MAIN.
210
  ! * (PRESSG = SURFACE PRESSURE)
211
212
213
214
215
  ! * CONSTANTS VALUES DEFINED IN DATA STATEMENT ARE :
216
  ! * VMIN     = MIMINUM WIND IN THE DIRECTION OF REFERENCE LEVEL
217
  ! *            WIND BEFORE WE CONSIDER BREAKING TO HAVE OCCURED.
218
  ! * DMPSCAL  = DAMPING TIME FOR GW DRAG IN SECONDS.
219
  ! * TAUFAC   = 1/(LENGTH SCALE).
220
  ! * HMIN     = MIMINUM ENVELOPE HEIGHT REQUIRED TO PRODUCE GW DRAG.
221
  ! * V0       = VALUE OF WIND THAT APPROXIMATES ZERO.
222
223
224
  DATA vmin/5.0/, v0/1.E-10/, taufac/5.E-6/, hmin/40000./, dmpscal/6.5E+6/, &
225
    apibt/1.5708/, cpart/0.7/, fcrit/1./
226
227
  ! * HINES EXTROWAVE GWD CONSTANTS DEFINED IN DATA STATEMENT ARE:
228
  ! * RMSCON = ROOT MEAN SQUARE GRAVITY WAVE WIND AT LOWEST LEVEL (M/S).
229
  ! * NMESSG  = UNIT NUMBER FOR PRINTED MESSAGES.
230
  ! * IPRINT  = 1 TO DO PRINT OUT SOME HINES ARRAYS.
231
  ! * IFL     = FIRST CALL FLAG TO HINES_SETUP ("SAVE" IT)
232
  ! * PCRIT = CRITICAL VALUE OF ZPR (MM/D)
233
  ! * IPLEV = LEVEL OF APPLICATION OF PRCIT
234
  ! * PCONS = FACTOR OF ZPR ENHANCEMENT
235
236
237
  DATA pcrit/5./, pcons/4.75/
238
239
  iplev = lrefp - 1
240
241
  DATA rmscon/1.00/iprint/2/, nmessg/6/
242
  DATA ifl/0/
243
244
  lozpr = .FALSE.
245
246
  ! -----------------------------------------------------------------------
247
248
249
250
  ! * SET ERROR FLAG
251
252
  ierror = 0
253
254
  ! * SPECIFY VARIOUS PARAMETERS FOR HINES ROUTINE AT VERY FIRST CALL.
255
  ! * (NOTE THAT ARRAY K_ALPHA IS SPECIFIED SO MAKE SURE THAT
256
  ! * IT IS NOT OVERWRITTEN LATER ON).
257
258
  CALL hines_setup(naz, slope, f1, f2, f3, f5, f6, kstar, icutoff, &
259
    alt_cutoff, smco, nsmax, iheatcal, k_alpha, ierror, nmessg, klon, nazmth, &
260
    coslat)
261
  IF (ierror/=0) GO TO 999
262
263
  ! * START GWD CALCULATIONS.
264
265
  lref = lrefp - 1
266
267
268
  DO j = 1, nazmth
269
    DO l = 1, klev
270
      DO i = kidia, klon
271
        sigsqmcw(i, l, j) = 0.
272
      END DO
273
    END DO
274
  END DO
275
276
277
278
  ! * INITIALIZE NECESSARY ARRAYS.
279
280
  DO l = 1, klev
281
    DO i = kidia, kfdia
282
      utendgw(i, l) = 0.
283
      vtendgw(i, l) = 0.
284
285
      uhs(i, l) = 0.
286
      vhs(i, l) = 0.
287
288
    END DO
289
  END DO
290
291
  ! * IF USING HINES SCHEME THEN CALCULATE B V FREQUENCY AT ALL POINTS
292
  ! * AND SMOOTH BVFREQ.
293
294
  DO l = 2, klev
295
    DO i = kidia, kfdia
296
      dttdsf = (th(i,l)/shxkj(i,l)-th(i,l-1)/shxkj(i,l-1))/ &
297
        (shj(i,l)-shj(i,l-1))
298
      dttdsf = min(dttdsf, -5./sgj(i,l))
299
      bvfreq(i, l) = sqrt(-dttdsf*sgj(i,l)*(sgj(i,l)**rgocp)/rd)*rg/ptm1(i, l &
300
        )
301
    END DO
302
  END DO
303
  DO l = 1, klev
304
    DO i = kidia, kfdia
305
      IF (l==1) THEN
306
        bvfreq(i, l) = bvfreq(i, l+1)
307
      END IF
308
      IF (l>1) THEN
309
        ratio = 5.*log(sgj(i,l)/sgj(i,l-1))
310
        bvfreq(i, l) = (bvfreq(i,l-1)+ratio*bvfreq(i,l))/(1.+ratio)
311
      END IF
312
    END DO
313
  END DO
314
315
  ! * CALCULATE GW DRAG DUE TO HINES' EXTROWAVES
316
  ! * SET MOLECULAR VISCOSITY TO A VERY SMALL VALUE.
317
  ! * IF THE MODEL TOP IS GREATER THAN 100 KM THEN THE ACTUAL
318
  ! * VISCOSITY COEFFICIENT COULD BE SPECIFIED HERE.
319
320
  DO l = 1, klev
321
    DO i = kidia, kfdia
322
      visc_mol(i, l) = 1.5E-5
323
      drag_u(i, l) = 0.
324
      drag_v(i, l) = 0.
325
      flux_u(i, l) = 0.
326
      flux_v(i, l) = 0.
327
      heat(i, l) = 0.
328
      diffco(i, l) = 0.
329
    END DO
330
  END DO
331
332
  ! * ALTITUDE AND DENSITY AT BOTTOM.
333
334
  DO i = kidia, kfdia
335
    hscal = rd*ptm1(i, klev)/rg
336
    density(i, klev) = sgj(i, klev)*pressg(i)/(rg*hscal)
337
    alt(i, klev) = 0.
338
  END DO
339
340
  ! * ALTITUDE AND DENSITY AT REMAINING LEVELS.
341
342
  DO l = klev - 1, 1, -1
343
    DO i = kidia, kfdia
344
      hscal = rd*ptm1(i, l)/rg
345
      alt(i, l) = alt(i, l+1) + hscal*dsgj(i, l)/sgj(i, l)
346
      density(i, l) = sgj(i, l)*pressg(i)/(rg*hscal)
347
    END DO
348
  END DO
349
350
351
  ! * INITIALIZE SWITCHES FOR HINES GWD CALCULATION
352
353
  ilrms = 0
354
355
  DO i = kidia, kfdia
356
    lorms(i) = .FALSE.
357
  END DO
358
359
360
  ! * DEFILE BOTTOM LAUNCH LEVEL
361
362
  levbot = iplev
363
364
  ! * BACKGROUND WIND MINUS VALUE AT BOTTOM LAUNCH LEVEL.
365
366
  DO l = 1, levbot
367
    DO i = kidia, kfdia
368
      uhs(i, l) = pum1(i, l) - pum1(i, levbot)
369
      vhs(i, l) = pvm1(i, l) - pvm1(i, levbot)
370
    END DO
371
  END DO
372
373
  ! * SPECIFY ROOT MEAN SQUARE WIND AT BOTTOM LAUNCH LEVEL.
374
375
  DO i = kidia, kfdia
376
    rmswind(i) = rmscon
377
  END DO
378
379
  IF (lozpr) THEN
380
    DO i = kidia, kfdia
381
      IF (zpr(i)>pcrit) THEN
382
        rmswind(i) = rmscon + ((zpr(i)-pcrit)/zpr(i))*pcons
383
      END IF
384
    END DO
385
  END IF
386
387
  DO i = kidia, kfdia
388
    IF (rmswind(i)>0.0) THEN
389
      ilrms = ilrms + 1
390
      lorms(i) = .TRUE.
391
    END IF
392
  END DO
393
394
  ! * CALCULATE GWD (NOTE THAT DIFFUSION COEFFICIENT AND
395
  ! * HEATING RATE ONLY CALCULATED IF IHEATCAL = 1).
396
397
  IF (ilrms>0) THEN
398
399
    CALL hines_extro0(drag_u, drag_v, heat, diffco, flux_u, flux_v, uhs, vhs, &
400
      bvfreq, density, visc_mol, alt, rmswind, k_alpha, m_alpha, v_alpha, &
401
      sigma_alpha, sigsqh_alpha, ak_alpha, mmin_alpha, i_alpha, sigma_t, &
402
      densbot, bvfbot, 1, iheatcal, icutoff, iprint, nsmax, smco, alt_cutoff, &
403
      kstar, slope, f1, f2, f3, f5, f6, naz, sigsqmcw, sigmatm, kidia, klon, &
404
      1, levbot, klon, klev, nazmth, lorms, smoothr1, smoothr2, sigalpmc, &
405
      f2mod)
406
407
    ! * ADD ON HINES' GWD TENDENCIES TO OROGRAPHIC TENDENCIES AND
408
    ! * APPLY HINES' GW DRAG ON (UROW,VROW) WORK ARRAYS.
409
410
    DO l = 1, klev
411
      DO i = kidia, kfdia
412
        utendgw(i, l) = utendgw(i, l) + drag_u(i, l)
413
        vtendgw(i, l) = vtendgw(i, l) + drag_v(i, l)
414
      END DO
415
    END DO
416
417
418
    ! * END OF HINES CALCULATIONS.
419
420
  END IF
421
422
  ! -----------------------------------------------------------------------
423
424
  DO jl = kidia, kfdia
425
    zustrhi(jl) = flux_u(jl, 1)
426
    zvstrhi(jl) = flux_v(jl, 1)
427
    DO jk = 1, klev
428
      le = klev - jk + 1
429
      d_u_hin(jl, jk) = utendgw(jl, le)*dtime
430
      d_v_hin(jl, jk) = vtendgw(jl, le)*dtime
431
    END DO
432
  END DO
433
434
  ! PRINT *,'UTENDGW:',UTENDGW
435
436
  ! PRINT *,' HINES HAS BEEN COMPLETED (LONG ISNT IT...)'
437
438
  RETURN
439
999 CONTINUE
440
441
  ! * IF ERROR DETECTED THEN ABORT.
442
443
  WRITE (nmessg, 6000)
444
  WRITE (nmessg, 6010) ierror
445
6000 FORMAT (/' EXECUTION ABORTED IN GWDOREXV')
446
6010 FORMAT ('     ERROR FLAG =', I4)
447
448
449
  RETURN
450
END SUBROUTINE hines_gwd
451
! /
452
! /
453
454
455
SUBROUTINE hines_extro0(drag_u, drag_v, heat, diffco, flux_u, flux_v, vel_u, &
456
    vel_v, bvfreq, density, visc_mol, alt, rmswind, k_alpha, m_alpha, &
457
    v_alpha, sigma_alpha, sigsqh_alpha, ak_alpha, mmin_alpha, i_alpha, &
458
    sigma_t, densb, bvfb, iorder, iheatcal, icutoff, iprint, nsmax, smco, &
459
    alt_cutoff, kstar, slope, f1, f2, f3, f5, f6, naz, sigsqmcw, sigmatm, &
460
    il1, il2, lev1, lev2, nlons, nlevs, nazmth, lorms, smoothr1, smoothr2, &
461
    sigalpmc, f2mod)
462
463
  IMPLICIT NONE
464
465
  ! Main routine for Hines' "extrowave" gravity wave parameterization based
466
  ! on Hines' Doppler spread theory. This routine calculates zonal
467
  ! and meridional components of gravity wave drag, heating rates
468
  ! and diffusion coefficient on a longitude by altitude grid.
469
  ! No "mythical" lower boundary region calculation is made so it
470
  ! is assumed that lowest level winds are weak (i.e, approximately zero).
471
472
  ! Aug. 13/95 - C. McLandress
473
  ! SEPT. /95  - N.McFarlane
474
475
  ! Modifications:
476
477
  ! Output arguements:
478
479
  ! * DRAG_U = zonal component of gravity wave drag (m/s^2).
480
  ! * DRAG_V = meridional component of gravity wave drag (m/s^2).
481
  ! * HEAT   = gravity wave heating (K/sec).
482
  ! * DIFFCO = diffusion coefficient (m^2/sec)
483
  ! * FLUX_U = zonal component of vertical momentum flux (Pascals)
484
  ! * FLUX_V = meridional component of vertical momentum flux (Pascals)
485
486
  ! Input arguements:
487
488
  ! * VEL_U      = background zonal wind component (m/s).
489
  ! * VEL_V      = background meridional wind component (m/s).
490
  ! * BVFREQ     = background Brunt Vassala frequency (radians/sec).
491
  ! * DENSITY    = background density (kg/m^3)
492
  ! * VISC_MOL   = molecular viscosity (m^2/s)
493
  ! * ALT        = altitude of momentum, density, buoyancy levels (m)
494
  ! *              (NOTE: levels ordered so that ALT(I,1) > ALT(I,2), etc.)
495
  ! * RMSWIND   = root mean square gravity wave wind at lowest level (m/s).
496
  ! * K_ALPHA    = horizontal wavenumber of each azimuth (1/m).
497
  ! * IORDER	   = 1 means vertical levels are indexed from top down
498
  ! *              (i.e., highest level indexed 1 and lowest level NLEVS);
499
  ! *           .NE. 1 highest level is index NLEVS.
500
  ! * IHEATCAL   = 1 to calculate heating rates and diffusion coefficient.
501
  ! * IPRINT     = 1 to print out various arrays.
502
  ! * ICUTOFF    = 1 to exponentially damp GWD, heating and diffusion
503
  ! *              arrays above ALT_CUTOFF; otherwise arrays not modified.
504
  ! * ALT_CUTOFF = altitude in meters above which exponential decay applied.
505
  ! * SMCO       = smoothing factor used to smooth cutoff vertical
506
  ! *              wavenumbers and total rms winds in vertical direction
507
  ! *              before calculating drag or heating
508
  ! *              (SMCO >= 1 ==> 1:SMCO:1 stencil used).
509
  ! * NSMAX      = number of times smoother applied ( >= 1),
510
  ! *            = 0 means no smoothing performed.
511
  ! * KSTAR      = typical gravity wave horizontal wavenumber (1/m).
512
  ! * SLOPE      = slope of incident vertical wavenumber spectrum
513
  ! *              (SLOPE must equal 1., 1.5 or 2.).
514
  ! * F1 to F6   = Hines's fudge factors (F4 not needed since used for
515
  ! *              vertical flux of vertical momentum).
516
  ! * NAZ        = actual number of horizontal azimuths used.
517
  ! * IL1        = first longitudinal index to use (IL1 >= 1).
518
  ! * IL2        = last longitudinal index to use (IL1 <= IL2 <= NLONS).
519
  ! * LEV1       = index of first level for drag calculation.
520
  ! * LEV2       = index of last level for drag calculation
521
  ! *              (i.e., LEV1 < LEV2 <= NLEVS).
522
  ! * NLONS      = number of longitudes.
523
  ! * NLEVS      = number of vertical levels.
524
  ! * NAZMTH     = azimuthal array dimension (NAZMTH >= NAZ).
525
526
  ! Work arrays.
527
528
  ! * M_ALPHA      = cutoff vertical wavenumber (1/m).
529
  ! * V_ALPHA      = wind component at each azimuth (m/s) and if IHEATCAL=1
530
  ! *                holds vertical derivative of cutoff wavenumber.
531
  ! * SIGMA_ALPHA  = total rms wind in each azimuth (m/s).
532
  ! * SIGSQH_ALPHA = portion of wind variance from waves having wave
533
  ! *                normals in the alpha azimuth (m/s).
534
  ! * SIGMA_T      = total rms horizontal wind (m/s).
535
  ! * AK_ALPHA     = spectral amplitude factor at each azimuth
536
  ! *                (i.e.,{AjKj}) in m^4/s^2.
537
  ! * I_ALPHA      = Hines' integral.
538
  ! * MMIN_ALPHA   = minimum value of cutoff wavenumber.
539
  ! * DENSB        = background density at bottom level.
540
  ! * BVFB         = buoyancy frequency at bottom level and
541
  ! *                work array for ICUTOFF = 1.
542
543
  ! * LORMS       = .TRUE. for drag computation
544
545
  INTEGER naz, nlons, nlevs, nazmth, il1, il2, lev1, lev2
546
  INTEGER icutoff, nsmax, iorder, iheatcal, iprint
547
  REAL kstar(nlons), f1, f2, f3, f5, f6, slope
548
  REAL alt_cutoff, smco
549
  REAL drag_u(nlons, nlevs), drag_v(nlons, nlevs)
550
  REAL heat(nlons, nlevs), diffco(nlons, nlevs)
551
  REAL flux_u(nlons, nlevs), flux_v(nlons, nlevs)
552
  REAL vel_u(nlons, nlevs), vel_v(nlons, nlevs)
553
  REAL bvfreq(nlons, nlevs), density(nlons, nlevs)
554
  REAL visc_mol(nlons, nlevs), alt(nlons, nlevs)
555
  REAL rmswind(nlons), bvfb(nlons), densb(nlons)
556
  REAL sigma_t(nlons, nlevs), sigsqmcw(nlons, nlevs, nazmth)
557
  REAL sigma_alpha(nlons, nlevs, nazmth), sigmatm(nlons, nlevs)
558
  REAL sigsqh_alpha(nlons, nlevs, nazmth)
559
  REAL m_alpha(nlons, nlevs, nazmth), v_alpha(nlons, nlevs, nazmth)
560
  REAL ak_alpha(nlons, nazmth), k_alpha(nlons, nazmth)
561
  REAL mmin_alpha(nlons, nazmth), i_alpha(nlons, nazmth)
562
  REAL smoothr1(nlons, nlevs), smoothr2(nlons, nlevs)
563
  REAL sigalpmc(nlons, nlevs, nazmth)
564
  REAL f2mod(nlons, nlevs)
565
566
  LOGICAL lorms(nlons)
567
568
  ! Internal variables.
569
570
  INTEGER levbot, levtop, i, n, l, lev1p, lev2m
571
  INTEGER ilprt1, ilprt2
572
  ! -----------------------------------------------------------------------
573
574
  ! PRINT *,' IN HINES_EXTRO0'
575
  lev1p = lev1 + 1
576
  lev2m = lev2 - 1
577
578
  ! Index of lowest altitude level (bottom of drag calculation).
579
580
  levbot = lev2
581
  levtop = lev1
582
  IF (iorder/=1) THEN
583
    WRITE (6, 1)
584
1   FORMAT (2X, ' error: IORDER NOT ONE! ')
585
  END IF
586
587
  ! Buoyancy and density at bottom level.
588
589
  DO i = il1, il2
590
    bvfb(i) = bvfreq(i, levbot)
591
    densb(i) = density(i, levbot)
592
  END DO
593
594
  ! initialize some variables
595
596
  DO n = 1, naz
597
    DO l = lev1, lev2
598
      DO i = il1, il2
599
        m_alpha(i, l, n) = 0.0
600
      END DO
601
    END DO
602
  END DO
603
  DO l = lev1, lev2
604
    DO i = il1, il2
605
      sigma_t(i, l) = 0.0
606
    END DO
607
  END DO
608
  DO n = 1, naz
609
    DO i = il1, il2
610
      i_alpha(i, n) = 0.0
611
    END DO
612
  END DO
613
614
  ! Compute azimuthal wind components from zonal and meridional winds.
615
616
  CALL hines_wind(v_alpha, vel_u, vel_v, naz, il1, il2, lev1, lev2, nlons, &
617
    nlevs, nazmth)
618
619
  ! Calculate cutoff vertical wavenumber and velocity variances.
620
621
  CALL hines_wavnum(m_alpha, sigma_alpha, sigsqh_alpha, sigma_t, ak_alpha, &
622
    v_alpha, visc_mol, density, densb, bvfreq, bvfb, rmswind, i_alpha, &
623
    mmin_alpha, kstar, slope, f1, f2, f3, naz, levbot, levtop, il1, il2, &
624
    nlons, nlevs, nazmth, sigsqmcw, sigmatm, lorms, sigalpmc, f2mod)
625
  ! Smooth cutoff wavenumbers and total rms velocity in the vertical
626
  ! direction NSMAX times, using FLUX_U as temporary work array.
627
628
  IF (nsmax>0) THEN
629
    DO n = 1, naz
630
      DO l = lev1, lev2
631
        DO i = il1, il2
632
          smoothr1(i, l) = m_alpha(i, l, n)
633
        END DO
634
      END DO
635
      CALL vert_smooth(smoothr1, smoothr2, smco, nsmax, il1, il2, lev1, lev2, &
636
        nlons, nlevs)
637
      DO l = lev1, lev2
638
        DO i = il1, il2
639
          m_alpha(i, l, n) = smoothr1(i, l)
640
        END DO
641
      END DO
642
    END DO
643
    CALL vert_smooth(sigma_t, smoothr2, smco, nsmax, il1, il2, lev1, lev2, &
644
      nlons, nlevs)
645
  END IF
646
647
  ! Calculate zonal and meridional components of the
648
  ! momentum flux and drag.
649
650
  CALL hines_flux(flux_u, flux_v, drag_u, drag_v, alt, density, densb, &
651
    m_alpha, ak_alpha, k_alpha, slope, naz, il1, il2, lev1, lev2, nlons, &
652
    nlevs, nazmth, lorms)
653
654
  ! Cutoff drag above ALT_CUTOFF, using BVFB as temporary work array.
655
656
  IF (icutoff==1) THEN
657
    CALL hines_exp(drag_u, bvfb, alt, alt_cutoff, iorder, il1, il2, lev1, &
658
      lev2, nlons, nlevs)
659
    CALL hines_exp(drag_v, bvfb, alt, alt_cutoff, iorder, il1, il2, lev1, &
660
      lev2, nlons, nlevs)
661
  END IF
662
663
  ! Print out various arrays for diagnostic purposes.
664
665
  IF (iprint==1) THEN
666
    ilprt1 = 15
667
    ilprt2 = 16
668
    CALL hines_print(flux_u, flux_v, drag_u, drag_v, alt, sigma_t, &
669
      sigma_alpha, v_alpha, m_alpha, 1, 1, 6, ilprt1, ilprt2, lev1, lev2, &
670
      naz, nlons, nlevs, nazmth)
671
  END IF
672
673
  ! If not calculating heating rate and diffusion coefficient then finished.
674
675
  IF (iheatcal/=1) RETURN
676
677
  ! Calculate vertical derivative of cutoff wavenumber (store
678
  ! in array V_ALPHA) using centered differences at interior gridpoints
679
  ! and one-sided differences at first and last levels.
680
681
  DO n = 1, naz
682
    DO l = lev1p, lev2m
683
      DO i = il1, il2
684
        v_alpha(i, l, n) = (m_alpha(i,l+1,n)-m_alpha(i,l-1,n))/ &
685
          (alt(i,l+1)-alt(i,l-1))
686
      END DO
687
    END DO
688
    DO i = il1, il2
689
      v_alpha(i, lev1, n) = (m_alpha(i,lev1p,n)-m_alpha(i,lev1,n))/ &
690
        (alt(i,lev1p)-alt(i,lev1))
691
    END DO
692
    DO i = il1, il2
693
      v_alpha(i, lev2, n) = (m_alpha(i,lev2,n)-m_alpha(i,lev2m,n))/ &
694
        (alt(i,lev2)-alt(i,lev2m))
695
    END DO
696
  END DO
697
698
  ! Heating rate and diffusion coefficient.
699
700
  CALL hines_heat(heat, diffco, m_alpha, v_alpha, ak_alpha, k_alpha, bvfreq, &
701
    density, densb, sigma_t, visc_mol, kstar, slope, f2, f3, f5, f6, naz, &
702
    il1, il2, lev1, lev2, nlons, nlevs, nazmth)
703
704
  ! Finished.
705
706
  RETURN
707
  ! -----------------------------------------------------------------------
708
END SUBROUTINE hines_extro0
709
710
SUBROUTINE hines_wavnum(m_alpha, sigma_alpha, sigsqh_alpha, sigma_t, &
711
    ak_alpha, v_alpha, visc_mol, density, densb, bvfreq, bvfb, rms_wind, &
712
    i_alpha, mmin_alpha, kstar, slope, f1, f2, f3, naz, levbot, levtop, il1, &
713
    il2, nlons, nlevs, nazmth, sigsqmcw, sigmatm, lorms, sigalpmc, f2mod)
714
  IMPLICIT NONE
715
  ! This routine calculates the cutoff vertical wavenumber and velocity
716
  ! variances on a longitude by altitude grid for the Hines' Doppler
717
  ! spread gravity wave drag parameterization scheme.
718
  ! NOTE: (1) only values of four or eight can be used for # azimuths (NAZ).
719
  ! (2) only values of 1.0, 1.5 or 2.0 can be used for slope (SLOPE).
720
721
  ! Aug. 10/95 - C. McLandress
722
723
  ! Output arguements:
724
725
  ! * M_ALPHA      = cutoff wavenumber at each azimuth (1/m).
726
  ! * SIGMA_ALPHA  = total rms wind in each azimuth (m/s).
727
  ! * SIGSQH_ALPHA = portion of wind variance from waves having wave
728
  ! *                normals in the alpha azimuth (m/s).
729
  ! * SIGMA_T      = total rms horizontal wind (m/s).
730
  ! * AK_ALPHA     = spectral amplitude factor at each azimuth
731
  ! *                (i.e.,{AjKj}) in m^4/s^2.
732
733
  ! Input arguements:
734
735
  ! * V_ALPHA  = wind component at each azimuth (m/s).
736
  ! * VISC_MOL = molecular viscosity (m^2/s)
737
  ! * DENSITY  = background density (kg/m^3).
738
  ! * DENSB    = background density at model bottom (kg/m^3).
739
  ! * BVFREQ   = background Brunt Vassala frequency (radians/sec).
740
  ! * BVFB     = background Brunt Vassala frequency at model bottom.
741
  ! * RMS_WIND = root mean square gravity wave wind at lowest level (m/s).
742
  ! * KSTAR    = typical gravity wave horizontal wavenumber (1/m).
743
  ! * SLOPE    = slope of incident vertical wavenumber spectrum
744
  ! *            (SLOPE = 1., 1.5 or 2.).
745
  ! * F1,F2,F3 = Hines's fudge factors.
746
  ! * NAZ      = actual number of horizontal azimuths used (4 or 8).
747
  ! * LEVBOT   = index of lowest vertical level.
748
  ! * LEVTOP   = index of highest vertical level
749
  ! *            (NOTE: if LEVTOP < LEVBOT then level index
750
  ! *             increases from top down).
751
  ! * IL1      = first longitudinal index to use (IL1 >= 1).
752
  ! * IL2      = last longitudinal index to use (IL1 <= IL2 <= NLONS).
753
  ! * NLONS    = number of longitudes.
754
  ! * NLEVS    = number of vertical levels.
755
  ! * NAZMTH   = azimuthal array dimension (NAZMTH >= NAZ).
756
757
  ! * LORMS       = .TRUE. for drag computation
758
759
  ! Input work arrays:
760
761
  ! * I_ALPHA    = Hines' integral at a single level.
762
  ! * MMIN_ALPHA = minimum value of cutoff wavenumber.
763
764
  INTEGER naz, levbot, levtop, il1, il2, nlons, nlevs, nazmth
765
  REAL slope, kstar(nlons), f1, f2, f3, f2mfac
766
  REAL m_alpha(nlons, nlevs, nazmth)
767
  REAL sigma_alpha(nlons, nlevs, nazmth)
768
  REAL sigalpmc(nlons, nlevs, nazmth)
769
  REAL sigsqh_alpha(nlons, nlevs, nazmth)
770
  REAL sigsqmcw(nlons, nlevs, nazmth)
771
  REAL sigma_t(nlons, nlevs)
772
  REAL sigmatm(nlons, nlevs)
773
  REAL ak_alpha(nlons, nazmth)
774
  REAL v_alpha(nlons, nlevs, nazmth)
775
  REAL visc_mol(nlons, nlevs)
776
  REAL f2mod(nlons, nlevs)
777
  REAL density(nlons, nlevs), densb(nlons)
778
  REAL bvfreq(nlons, nlevs), bvfb(nlons), rms_wind(nlons)
779
  REAL i_alpha(nlons, nazmth), mmin_alpha(nlons, nazmth)
780
781
  LOGICAL lorms(nlons)
782
783
  ! Internal variables.
784
785
  INTEGER i, l, n, lstart, lend, lincr, lbelow
786
  REAL m_sub_m_turb, m_sub_m_mol, m_trial
787
  REAL visc, visc_min, azfac, sp1
788
789
  ! c      REAL  N_OVER_M(1000), SIGFAC(1000)
790
791
  REAL n_over_m(nlons), sigfac(nlons)
792
  DATA visc_min/1.E-10/
793
  ! -----------------------------------------------------------------------
794
795
796
  ! PRINT *,'IN HINES_WAVNUM'
797
  sp1 = slope + 1.
798
799
  ! Indices of levels to process.
800
801
  IF (levbot>levtop) THEN
802
    lstart = levbot - 1
803
    lend = levtop
804
    lincr = -1
805
  ELSE
806
    WRITE (6, 1)
807
1   FORMAT (2X, ' error: IORDER NOT ONE! ')
808
  END IF
809
810
  ! Use horizontal isotropy to calculate azimuthal variances at bottom level.
811
812
  azfac = 1./real(naz)
813
  DO n = 1, naz
814
    DO i = il1, il2
815
      sigsqh_alpha(i, levbot, n) = azfac*rms_wind(i)**2
816
    END DO
817
  END DO
818
819
  ! Velocity variances at bottom level.
820
821
  CALL hines_sigma(sigma_t, sigma_alpha, sigsqh_alpha, naz, levbot, il1, il2, &
822
    nlons, nlevs, nazmth)
823
824
  CALL hines_sigma(sigmatm, sigalpmc, sigsqmcw, naz, levbot, il1, il2, nlons, &
825
    nlevs, nazmth)
826
827
  ! Calculate cutoff wavenumber and spectral amplitude factor
828
  ! at bottom level where it is assumed that background winds vanish
829
  ! and also initialize minimum value of cutoff wavnumber.
830
831
  DO n = 1, naz
832
    DO i = il1, il2
833
      IF (lorms(i)) THEN
834
        m_alpha(i, levbot, n) = bvfb(i)/(f1*sigma_alpha(i,levbot,n)+f2* &
835
          sigma_t(i,levbot))
836
        ak_alpha(i, n) = sigsqh_alpha(i, levbot, n)/ &
837
          (m_alpha(i,levbot,n)**sp1/sp1)
838
        mmin_alpha(i, n) = m_alpha(i, levbot, n)
839
      END IF
840
    END DO
841
  END DO
842
843
  ! Calculate quantities from the bottom upwards,
844
  ! starting one level above bottom.
845
846
  DO l = lstart, lend, lincr
847
848
    ! Level beneath present level.
849
850
    lbelow = l - lincr
851
852
    ! Calculate N/m_M where m_M is maximum permissible value of the vertical
853
    ! wavenumber (i.e., m > m_M are obliterated) and N is buoyancy frequency.
854
    ! m_M is taken as the smaller of the instability-induced
855
    ! wavenumber (M_SUB_M_TURB) and that imposed by molecular viscosity
856
    ! (M_SUB_M_MOL). Since variance at this level is not yet known
857
    ! use value at level below.
858
859
    DO i = il1, il2
860
      IF (lorms(i)) THEN
861
862
        f2mfac = sigmatm(i, lbelow)**2
863
        f2mod(i, lbelow) = 1. + 2.*f2mfac/(f2mfac+sigma_t(i,lbelow)**2)
864
865
        visc = amax1(visc_mol(i,l), visc_min)
866
        m_sub_m_turb = bvfreq(i, l)/(f2*f2mod(i,lbelow)*sigma_t(i,lbelow))
867
        m_sub_m_mol = (bvfreq(i,l)*kstar(i)/visc)**0.33333333/f3
868
        IF (m_sub_m_turb<m_sub_m_mol) THEN
869
          n_over_m(i) = f2*f2mod(i, lbelow)*sigma_t(i, lbelow)
870
        ELSE
871
          n_over_m(i) = bvfreq(i, l)/m_sub_m_mol
872
        END IF
873
      END IF
874
    END DO
875
876
    ! Calculate cutoff wavenumber at this level.
877
878
    DO n = 1, naz
879
      DO i = il1, il2
880
        IF (lorms(i)) THEN
881
882
          ! Calculate trial value (since variance at this level is not yet
883
          ! known
884
          ! use value at level below). If trial value is negative or if it
885
          ! exceeds
886
          ! minimum value (not permitted) then set it to minimum value.
887
888
          m_trial = bvfb(i)/(f1*(sigma_alpha(i,lbelow,n)+sigalpmc(i,lbelow, &
889
            n))+n_over_m(i)+v_alpha(i,l,n))
890
          IF (m_trial<=0. .OR. m_trial>mmin_alpha(i,n)) THEN
891
            m_trial = mmin_alpha(i, n)
892
          END IF
893
          m_alpha(i, l, n) = m_trial
894
895
          ! Reset minimum value of cutoff wavenumber if necessary.
896
897
          IF (m_alpha(i,l,n)<mmin_alpha(i,n)) THEN
898
            mmin_alpha(i, n) = m_alpha(i, l, n)
899
          END IF
900
901
        END IF
902
      END DO
903
    END DO
904
905
    ! Calculate the Hines integral at this level.
906
907
    CALL hines_intgrl(i_alpha, v_alpha, m_alpha, bvfb, slope, naz, l, il1, &
908
      il2, nlons, nlevs, nazmth, lorms)
909
910
911
    ! Calculate the velocity variances at this level.
912
913
    DO i = il1, il2
914
      sigfac(i) = densb(i)/density(i, l)*bvfreq(i, l)/bvfb(i)
915
    END DO
916
    DO n = 1, naz
917
      DO i = il1, il2
918
        sigsqh_alpha(i, l, n) = sigfac(i)*ak_alpha(i, n)*i_alpha(i, n)
919
      END DO
920
    END DO
921
    CALL hines_sigma(sigma_t, sigma_alpha, sigsqh_alpha, naz, l, il1, il2, &
922
      nlons, nlevs, nazmth)
923
924
    CALL hines_sigma(sigmatm, sigalpmc, sigsqmcw, naz, l, il1, il2, nlons, &
925
      nlevs, nazmth)
926
927
    ! End of level loop.
928
929
  END DO
930
931
  RETURN
932
  ! -----------------------------------------------------------------------
933
END SUBROUTINE hines_wavnum
934
935
SUBROUTINE hines_wind(v_alpha, vel_u, vel_v, naz, il1, il2, lev1, lev2, &
936
    nlons, nlevs, nazmth)
937
    IMPLICIT NONE
938
  ! This routine calculates the azimuthal horizontal background wind
939
  ! components
940
  ! on a longitude by altitude grid for the case of 4 or 8 azimuths for
941
  ! the Hines' Doppler spread GWD parameterization scheme.
942
943
  ! Aug. 7/95 - C. McLandress
944
945
  ! Output arguement:
946
947
  ! * V_ALPHA   = background wind component at each azimuth (m/s).
948
  ! *             (note: first azimuth is in eastward direction
949
  ! *              and rotate in counterclockwise direction.)
950
951
  ! Input arguements:
952
953
  ! * VEL_U     = background zonal wind component (m/s).
954
  ! * VEL_V     = background meridional wind component (m/s).
955
  ! * NAZ       = actual number of horizontal azimuths used (must be 4 or 8).
956
  ! * IL1       = first longitudinal index to use (IL1 >= 1).
957
  ! * IL2       = last longitudinal index to use (IL1 <= IL2 <= NLONS).
958
  ! * LEV1      = first altitude level to use (LEV1 >=1).
959
  ! * LEV2      = last altitude level to use (LEV1 < LEV2 <= NLEVS).
960
  ! * NLONS     = number of longitudes.
961
  ! * NLEVS     = number of vertical levels.
962
  ! * NAZMTH    = azimuthal array dimension (NAZMTH >= NAZ).
963
964
  ! Constants in DATA statements.
965
966
  ! * COS45 = cosine of 45 degrees.
967
  ! * UMIN  = minimum allowable value for zonal or meridional
968
  ! *         wind component (m/s).
969
970
  ! Subroutine arguements.
971
972
  INTEGER naz, il1, il2, lev1, lev2
973
  INTEGER nlons, nlevs, nazmth
974
  REAL v_alpha(nlons, nlevs, nazmth)
975
  REAL vel_u(nlons, nlevs), vel_v(nlons, nlevs)
976
977
  ! Internal variables.
978
979
  INTEGER i, l
980
  REAL u, v, cos45, umin
981
982
  DATA cos45/0.7071068/
983
  DATA umin/0.001/
984
  ! -----------------------------------------------------------------------
985
986
  ! Case with 4 azimuths.
987
988
989
  ! PRINT *,'IN HINES_WIND'
990
  IF (naz==4) THEN
991
    DO l = lev1, lev2
992
      DO i = il1, il2
993
        u = vel_u(i, l)
994
        v = vel_v(i, l)
995
        IF (abs(u)<umin) u = umin
996
        IF (abs(v)<umin) v = umin
997
        v_alpha(i, l, 1) = u
998
        v_alpha(i, l, 2) = v
999
        v_alpha(i, l, 3) = -u
1000
        v_alpha(i, l, 4) = -v
1001
      END DO
1002
    END DO
1003
  END IF
1004
1005
  ! Case with 8 azimuths.
1006
1007
  IF (naz==8) THEN
1008
    DO l = lev1, lev2
1009
      DO i = il1, il2
1010
        u = vel_u(i, l)
1011
        v = vel_v(i, l)
1012
        IF (abs(u)<umin) u = umin
1013
        IF (abs(v)<umin) v = umin
1014
        v_alpha(i, l, 1) = u
1015
        v_alpha(i, l, 2) = cos45*(v+u)
1016
        v_alpha(i, l, 3) = v
1017
        v_alpha(i, l, 4) = cos45*(v-u)
1018
        v_alpha(i, l, 5) = -u
1019
        v_alpha(i, l, 6) = -v_alpha(i, l, 2)
1020
        v_alpha(i, l, 7) = -v
1021
        v_alpha(i, l, 8) = -v_alpha(i, l, 4)
1022
      END DO
1023
    END DO
1024
  END IF
1025
1026
  RETURN
1027
  ! -----------------------------------------------------------------------
1028
END SUBROUTINE hines_wind
1029
1030
SUBROUTINE hines_flux(flux_u, flux_v, drag_u, drag_v, alt, density, densb, &
1031
    m_alpha, ak_alpha, k_alpha, slope, naz, il1, il2, lev1, lev2, nlons, &
1032
    nlevs, nazmth, lorms)
1033
    IMPLICIT NONE
1034
  ! Calculate zonal and meridional components of the vertical flux
1035
  ! of horizontal momentum and corresponding wave drag (force per unit mass)
1036
  ! on a longitude by altitude grid for the Hines' Doppler spread
1037
  ! GWD parameterization scheme.
1038
  ! NOTE: only 4 or 8 azimuths can be used.
1039
1040
  ! Aug. 6/95 - C. McLandress
1041
1042
  ! Output arguements:
1043
1044
  ! * FLUX_U = zonal component of vertical momentum flux (Pascals)
1045
  ! * FLUX_V = meridional component of vertical momentum flux (Pascals)
1046
  ! * DRAG_U = zonal component of drag (m/s^2).
1047
  ! * DRAG_V = meridional component of drag (m/s^2).
1048
1049
  ! Input arguements:
1050
1051
  ! * ALT       = altitudes (m).
1052
  ! * DENSITY   = background density (kg/m^3).
1053
  ! * DENSB     = background density at bottom level (kg/m^3).
1054
  ! * M_ALPHA   = cutoff vertical wavenumber (1/m).
1055
  ! * AK_ALPHA  = spectral amplitude factor (i.e., {AjKj} in m^4/s^2).
1056
  ! * K_ALPHA   = horizontal wavenumber (1/m).
1057
  ! * SLOPE     = slope of incident vertical wavenumber spectrum.
1058
  ! * NAZ       = actual number of horizontal azimuths used (must be 4 or 8).
1059
  ! * IL1       = first longitudinal index to use (IL1 >= 1).
1060
  ! * IL2       = last longitudinal index to use (IL1 <= IL2 <= NLONS).
1061
  ! * LEV1      = first altitude level to use (LEV1 >=1).
1062
  ! * LEV2      = last altitude level to use (LEV1 < LEV2 <= NLEVS).
1063
  ! * NLONS     = number of longitudes.
1064
  ! * NLEVS     = number of vertical levels.
1065
  ! * NAZMTH    = azimuthal array dimension (NAZMTH >= NAZ).
1066
1067
  ! * LORMS       = .TRUE. for drag computation
1068
1069
  ! Constant in DATA statement.
1070
1071
  ! * COS45 = cosine of 45 degrees.
1072
1073
  ! Subroutine arguements.
1074
1075
  INTEGER naz, il1, il2, lev1, lev2
1076
  INTEGER nlons, nlevs, nazmth
1077
  REAL slope
1078
  REAL flux_u(nlons, nlevs), flux_v(nlons, nlevs)
1079
  REAL drag_u(nlons, nlevs), drag_v(nlons, nlevs)
1080
  REAL alt(nlons, nlevs), density(nlons, nlevs), densb(nlons)
1081
  REAL m_alpha(nlons, nlevs, nazmth)
1082
  REAL ak_alpha(nlons, nazmth), k_alpha(nlons, nazmth)
1083
1084
  LOGICAL lorms(nlons)
1085
1086
  ! Internal variables.
1087
1088
  INTEGER i, l, lev1p, lev2m, lev2p
1089
  REAL cos45, prod2, prod4, prod6, prod8, dendz, dendz2
1090
  DATA cos45/0.7071068/
1091
  ! -----------------------------------------------------------------------
1092
1093
  lev1p = lev1 + 1
1094
  lev2m = lev2 - 1
1095
  lev2p = lev2 + 1
1096
1097
  ! Sum over azimuths for case where SLOPE = 1.
1098
1099
  IF (slope==1.) THEN
1100
1101
    ! Case with 4 azimuths.
1102
1103
    IF (naz==4) THEN
1104
      DO l = lev1, lev2
1105
        DO i = il1, il2
1106
          flux_u(i, l) = ak_alpha(i, 1)*k_alpha(i, 1)*m_alpha(i, l, 1) - &
1107
            ak_alpha(i, 3)*k_alpha(i, 3)*m_alpha(i, l, 3)
1108
          flux_v(i, l) = ak_alpha(i, 2)*k_alpha(i, 2)*m_alpha(i, l, 2) - &
1109
            ak_alpha(i, 4)*k_alpha(i, 4)*m_alpha(i, l, 4)
1110
        END DO
1111
      END DO
1112
    END IF
1113
1114
    ! Case with 8 azimuths.
1115
1116
    IF (naz==8) THEN
1117
      DO l = lev1, lev2
1118
        DO i = il1, il2
1119
          prod2 = ak_alpha(i, 2)*k_alpha(i, 2)*m_alpha(i, l, 2)
1120
          prod4 = ak_alpha(i, 4)*k_alpha(i, 4)*m_alpha(i, l, 4)
1121
          prod6 = ak_alpha(i, 6)*k_alpha(i, 6)*m_alpha(i, l, 6)
1122
          prod8 = ak_alpha(i, 8)*k_alpha(i, 8)*m_alpha(i, l, 8)
1123
          flux_u(i, l) = ak_alpha(i, 1)*k_alpha(i, 1)*m_alpha(i, l, 1) - &
1124
            ak_alpha(i, 5)*k_alpha(i, 5)*m_alpha(i, l, 5) + &
1125
            cos45*(prod2-prod4-prod6+prod8)
1126
          flux_v(i, l) = ak_alpha(i, 3)*k_alpha(i, 3)*m_alpha(i, l, 3) - &
1127
            ak_alpha(i, 7)*k_alpha(i, 7)*m_alpha(i, l, 7) + &
1128
            cos45*(prod2+prod4-prod6-prod8)
1129
        END DO
1130
      END DO
1131
    END IF
1132
1133
  END IF
1134
1135
  ! Sum over azimuths for case where SLOPE not equal to 1.
1136
1137
  IF (slope/=1.) THEN
1138
1139
    ! Case with 4 azimuths.
1140
1141
    IF (naz==4) THEN
1142
      DO l = lev1, lev2
1143
        DO i = il1, il2
1144
          flux_u(i, l) = ak_alpha(i, 1)*k_alpha(i, 1)* &
1145
            m_alpha(i, l, 1)**slope - ak_alpha(i, 3)*k_alpha(i, 3)*m_alpha(i, &
1146
            l, 3)**slope
1147
          flux_v(i, l) = ak_alpha(i, 2)*k_alpha(i, 2)* &
1148
            m_alpha(i, l, 2)**slope - ak_alpha(i, 4)*k_alpha(i, 4)*m_alpha(i, &
1149
            l, 4)**slope
1150
        END DO
1151
      END DO
1152
    END IF
1153
1154
    ! Case with 8 azimuths.
1155
1156
    IF (naz==8) THEN
1157
      DO l = lev1, lev2
1158
        DO i = il1, il2
1159
          prod2 = ak_alpha(i, 2)*k_alpha(i, 2)*m_alpha(i, l, 2)**slope
1160
          prod4 = ak_alpha(i, 4)*k_alpha(i, 4)*m_alpha(i, l, 4)**slope
1161
          prod6 = ak_alpha(i, 6)*k_alpha(i, 6)*m_alpha(i, l, 6)**slope
1162
          prod8 = ak_alpha(i, 8)*k_alpha(i, 8)*m_alpha(i, l, 8)**slope
1163
          flux_u(i, l) = ak_alpha(i, 1)*k_alpha(i, 1)* &
1164
            m_alpha(i, l, 1)**slope - ak_alpha(i, 5)*k_alpha(i, 5)*m_alpha(i, &
1165
            l, 5)**slope + cos45*(prod2-prod4-prod6+prod8)
1166
          flux_v(i, l) = ak_alpha(i, 3)*k_alpha(i, 3)* &
1167
            m_alpha(i, l, 3)**slope - ak_alpha(i, 7)*k_alpha(i, 7)*m_alpha(i, &
1168
            l, 7)**slope + cos45*(prod2+prod4-prod6-prod8)
1169
        END DO
1170
      END DO
1171
    END IF
1172
1173
  END IF
1174
1175
  ! Calculate flux from sum.
1176
1177
  DO l = lev1, lev2
1178
    DO i = il1, il2
1179
      flux_u(i, l) = flux_u(i, l)*densb(i)/slope
1180
      flux_v(i, l) = flux_v(i, l)*densb(i)/slope
1181
    END DO
1182
  END DO
1183
1184
  ! Calculate drag at intermediate levels using centered differences
1185
1186
  DO l = lev1p, lev2m
1187
    DO i = il1, il2
1188
      IF (lorms(i)) THEN
1189
        ! cc       DENDZ2 = DENSITY(I,L) * ( ALT(I,L+1) - ALT(I,L-1) )
1190
        dendz2 = density(i, l)*(alt(i,l-1)-alt(i,l))
1191
        ! cc       DRAG_U(I,L) = - ( FLUX_U(I,L+1) - FLUX_U(I,L-1) ) / DENDZ2
1192
        drag_u(i, l) = -(flux_u(i,l-1)-flux_u(i,l))/dendz2
1193
        ! cc       DRAG_V(I,L) = - ( FLUX_V(I,L+1) - FLUX_V(I,L-1) ) / DENDZ2
1194
        drag_v(i, l) = -(flux_v(i,l-1)-flux_v(i,l))/dendz2
1195
1196
      END IF
1197
    END DO
1198
  END DO
1199
1200
  ! Drag at first and last levels using one-side differences.
1201
1202
  DO i = il1, il2
1203
    IF (lorms(i)) THEN
1204
      dendz = density(i, lev1)*(alt(i,lev1)-alt(i,lev1p))
1205
      drag_u(i, lev1) = flux_u(i, lev1)/dendz
1206
      drag_v(i, lev1) = flux_v(i, lev1)/dendz
1207
    END IF
1208
  END DO
1209
  DO i = il1, il2
1210
    IF (lorms(i)) THEN
1211
      dendz = density(i, lev2)*(alt(i,lev2m)-alt(i,lev2))
1212
      drag_u(i, lev2) = -(flux_u(i,lev2m)-flux_u(i,lev2))/dendz
1213
      drag_v(i, lev2) = -(flux_v(i,lev2m)-flux_v(i,lev2))/dendz
1214
    END IF
1215
  END DO
1216
  IF (nlevs>lev2) THEN
1217
    DO i = il1, il2
1218
      IF (lorms(i)) THEN
1219
        dendz = density(i, lev2p)*(alt(i,lev2)-alt(i,lev2p))
1220
        drag_u(i, lev2p) = -flux_u(i, lev2)/dendz
1221
        drag_v(i, lev2p) = -flux_v(i, lev2)/dendz
1222
      END IF
1223
    END DO
1224
  END IF
1225
1226
  RETURN
1227
  ! -----------------------------------------------------------------------
1228
END SUBROUTINE hines_flux
1229
1230
SUBROUTINE hines_heat(heat, diffco, m_alpha, dmdz_alpha, ak_alpha, k_alpha, &
1231
    bvfreq, density, densb, sigma_t, visc_mol, kstar, slope, f2, f3, f5, f6, &
1232
    naz, il1, il2, lev1, lev2, nlons, nlevs, nazmth)
1233
  IMPLICIT NONE
1234
  ! This routine calculates the gravity wave induced heating and
1235
  ! diffusion coefficient on a longitude by altitude grid for
1236
  ! the Hines' Doppler spread gravity wave drag parameterization scheme.
1237
1238
  ! Aug. 6/95 - C. McLandress
1239
1240
  ! Output arguements:
1241
1242
  ! * HEAT   = gravity wave heating (K/sec).
1243
  ! * DIFFCO = diffusion coefficient (m^2/sec)
1244
1245
  ! Input arguements:
1246
1247
  ! * M_ALPHA     = cutoff vertical wavenumber (1/m).
1248
  ! * DMDZ_ALPHA  = vertical derivative of cutoff wavenumber.
1249
  ! * AK_ALPHA    = spectral amplitude factor of each azimuth
1250
  ! (i.e., {AjKj} in m^4/s^2).
1251
  ! * K_ALPHA     = horizontal wavenumber of each azimuth (1/m).
1252
  ! * BVFREQ      = background Brunt Vassala frequency (rad/sec).
1253
  ! * DENSITY     = background density (kg/m^3).
1254
  ! * DENSB       = background density at bottom level (kg/m^3).
1255
  ! * SIGMA_T     = total rms horizontal wind (m/s).
1256
  ! * VISC_MOL    = molecular viscosity (m^2/s).
1257
  ! * KSTAR       = typical gravity wave horizontal wavenumber (1/m).
1258
  ! * SLOPE       = slope of incident vertical wavenumber spectrum.
1259
  ! * F2,F3,F5,F6 = Hines's fudge factors.
1260
  ! * NAZ         = actual number of horizontal azimuths used.
1261
  ! * IL1         = first longitudinal index to use (IL1 >= 1).
1262
  ! * IL2         = last longitudinal index to use (IL1 <= IL2 <= NLONS).
1263
  ! * LEV1        = first altitude level to use (LEV1 >=1).
1264
  ! * LEV2        = last altitude level to use (LEV1 < LEV2 <= NLEVS).
1265
  ! * NLONS       = number of longitudes.
1266
  ! * NLEVS       = number of vertical levels.
1267
  ! * NAZMTH      = azimuthal array dimension (NAZMTH >= NAZ).
1268
1269
  INTEGER naz, il1, il2, lev1, lev2, nlons, nlevs, nazmth
1270
  REAL kstar(nlons), slope, f2, f3, f5, f6
1271
  REAL heat(nlons, nlevs), diffco(nlons, nlevs)
1272
  REAL m_alpha(nlons, nlevs, nazmth), dmdz_alpha(nlons, nlevs, nazmth)
1273
  REAL ak_alpha(nlons, nazmth), k_alpha(nlons, nazmth)
1274
  REAL bvfreq(nlons, nlevs), density(nlons, nlevs), densb(nlons)
1275
  REAL sigma_t(nlons, nlevs), visc_mol(nlons, nlevs)
1276
1277
  ! Internal variables.
1278
1279
  INTEGER i, l, n
1280
  REAL m_sub_m_turb, m_sub_m_mol, m_sub_m, heatng
1281
  REAL visc, visc_min, cpgas, sm1
1282
1283
  ! specific heat at constant pressure
1284
1285
  DATA cpgas/1004./
1286
1287
  ! minimum permissible viscosity
1288
1289
  DATA visc_min/1.E-10/
1290
  ! -----------------------------------------------------------------------
1291
1292
  ! Initialize heating array.
1293
1294
  DO l = 1, nlevs
1295
    DO i = 1, nlons
1296
      heat(i, l) = 0.
1297
    END DO
1298
  END DO
1299
1300
  ! Perform sum over azimuths for case where SLOPE = 1.
1301
1302
  IF (slope==1.) THEN
1303
    DO n = 1, naz
1304
      DO l = lev1, lev2
1305
        DO i = il1, il2
1306
          heat(i, l) = heat(i, l) + ak_alpha(i, n)*k_alpha(i, n)*dmdz_alpha(i &
1307
            , l, n)
1308
        END DO
1309
      END DO
1310
    END DO
1311
  END IF
1312
1313
  ! Perform sum over azimuths for case where SLOPE not 1.
1314
1315
  IF (slope/=1.) THEN
1316
    sm1 = slope - 1.
1317
    DO n = 1, naz
1318
      DO l = lev1, lev2
1319
        DO i = il1, il2
1320
          heat(i, l) = heat(i, l) + ak_alpha(i, n)*k_alpha(i, n)*m_alpha(i, l &
1321
            , n)**sm1*dmdz_alpha(i, l, n)
1322
        END DO
1323
      END DO
1324
    END DO
1325
  END IF
1326
1327
  ! Heating and diffusion.
1328
1329
  DO l = lev1, lev2
1330
    DO i = il1, il2
1331
1332
      ! Maximum permissible value of cutoff wavenumber is the smaller
1333
      ! of the instability-induced wavenumber (M_SUB_M_TURB) and
1334
      ! that imposed by molecular viscosity (M_SUB_M_MOL).
1335
1336
      visc = amax1(visc_mol(i,l), visc_min)
1337
      m_sub_m_turb = bvfreq(i, l)/(f2*sigma_t(i,l))
1338
      m_sub_m_mol = (bvfreq(i,l)*kstar(i)/visc)**0.33333333/f3
1339
      m_sub_m = amin1(m_sub_m_turb, m_sub_m_mol)
1340
1341
      heatng = -heat(i, l)*f5*bvfreq(i, l)/m_sub_m*densb(i)/density(i, l)
1342
      diffco(i, l) = f6*heatng**0.33333333/m_sub_m**1.33333333
1343
      heat(i, l) = heatng/cpgas
1344
1345
    END DO
1346
  END DO
1347
1348
  RETURN
1349
  ! -----------------------------------------------------------------------
1350
END SUBROUTINE hines_heat
1351
1352
SUBROUTINE hines_sigma(sigma_t, sigma_alpha, sigsqh_alpha, naz, lev, il1, &
1353
    il2, nlons, nlevs, nazmth)
1354
  IMPLICIT NONE
1355
  ! This routine calculates the total rms and azimuthal rms horizontal
1356
  ! velocities at a given level on a longitude by altitude grid for
1357
  ! the Hines' Doppler spread GWD parameterization scheme.
1358
  ! NOTE: only four or eight azimuths can be used.
1359
1360
  ! Aug. 7/95 - C. McLandress
1361
1362
  ! Output arguements:
1363
1364
  ! * SIGMA_T      = total rms horizontal wind (m/s).
1365
  ! * SIGMA_ALPHA  = total rms wind in each azimuth (m/s).
1366
1367
  ! Input arguements:
1368
1369
  ! * SIGSQH_ALPHA = portion of wind variance from waves having wave
1370
  ! *                normals in the alpha azimuth (m/s).
1371
  ! * NAZ       = actual number of horizontal azimuths used (must be 4 or 8).
1372
  ! * LEV       = altitude level to process.
1373
  ! * IL1       = first longitudinal index to use (IL1 >= 1).
1374
  ! * IL2       = last longitudinal index to use (IL1 <= IL2 <= NLONS).
1375
  ! * NLONS     = number of longitudes.
1376
  ! * NLEVS     = number of vertical levels.
1377
  ! * NAZMTH    = azimuthal array dimension (NAZMTH >= NAZ).
1378
1379
  ! Subroutine arguements.
1380
1381
  INTEGER lev, naz, il1, il2
1382
  INTEGER nlons, nlevs, nazmth
1383
  REAL sigma_t(nlons, nlevs)
1384
  REAL sigma_alpha(nlons, nlevs, nazmth)
1385
  REAL sigsqh_alpha(nlons, nlevs, nazmth)
1386
1387
  ! Internal variables.
1388
1389
  INTEGER i, n
1390
  REAL sum_even, sum_odd
1391
  ! -----------------------------------------------------------------------
1392
1393
  ! Calculate azimuthal rms velocity for the 4 azimuth case.
1394
1395
  IF (naz==4) THEN
1396
    DO i = il1, il2
1397
      sigma_alpha(i, lev, 1) = sqrt(sigsqh_alpha(i,lev,1)+sigsqh_alpha(i,lev, &
1398
        3))
1399
      sigma_alpha(i, lev, 2) = sqrt(sigsqh_alpha(i,lev,2)+sigsqh_alpha(i,lev, &
1400
        4))
1401
      sigma_alpha(i, lev, 3) = sigma_alpha(i, lev, 1)
1402
      sigma_alpha(i, lev, 4) = sigma_alpha(i, lev, 2)
1403
    END DO
1404
  END IF
1405
1406
  ! Calculate azimuthal rms velocity for the 8 azimuth case.
1407
1408
  IF (naz==8) THEN
1409
    DO i = il1, il2
1410
      sum_odd = (sigsqh_alpha(i,lev,1)+sigsqh_alpha(i,lev,3)+ &
1411
        sigsqh_alpha(i,lev,5)+sigsqh_alpha(i,lev,7))/2.
1412
      sum_even = (sigsqh_alpha(i,lev,2)+sigsqh_alpha(i,lev,4)+ &
1413
        sigsqh_alpha(i,lev,6)+sigsqh_alpha(i,lev,8))/2.
1414
      sigma_alpha(i, lev, 1) = sqrt(sigsqh_alpha(i,lev,1)+sigsqh_alpha(i,lev, &
1415
        5)+sum_even)
1416
      sigma_alpha(i, lev, 2) = sqrt(sigsqh_alpha(i,lev,2)+sigsqh_alpha(i,lev, &
1417
        6)+sum_odd)
1418
      sigma_alpha(i, lev, 3) = sqrt(sigsqh_alpha(i,lev,3)+sigsqh_alpha(i,lev, &
1419
        7)+sum_even)
1420
      sigma_alpha(i, lev, 4) = sqrt(sigsqh_alpha(i,lev,4)+sigsqh_alpha(i,lev, &
1421
        8)+sum_odd)
1422
      sigma_alpha(i, lev, 5) = sigma_alpha(i, lev, 1)
1423
      sigma_alpha(i, lev, 6) = sigma_alpha(i, lev, 2)
1424
      sigma_alpha(i, lev, 7) = sigma_alpha(i, lev, 3)
1425
      sigma_alpha(i, lev, 8) = sigma_alpha(i, lev, 4)
1426
    END DO
1427
  END IF
1428
1429
  ! Calculate total rms velocity.
1430
1431
  DO i = il1, il2
1432
    sigma_t(i, lev) = 0.
1433
  END DO
1434
  DO n = 1, naz
1435
    DO i = il1, il2
1436
      sigma_t(i, lev) = sigma_t(i, lev) + sigsqh_alpha(i, lev, n)
1437
    END DO
1438
  END DO
1439
  DO i = il1, il2
1440
    sigma_t(i, lev) = sqrt(sigma_t(i,lev))
1441
  END DO
1442
1443
  RETURN
1444
  ! -----------------------------------------------------------------------
1445
END SUBROUTINE hines_sigma
1446
1447
SUBROUTINE hines_intgrl(i_alpha, v_alpha, m_alpha, bvfb, slope, naz, lev, &
1448
    il1, il2, nlons, nlevs, nazmth, lorms)
1449
  IMPLICIT NONE
1450
  ! This routine calculates the vertical wavenumber integral
1451
  ! for a single vertical level at each azimuth on a longitude grid
1452
  ! for the Hines' Doppler spread GWD parameterization scheme.
1453
  ! NOTE: (1) only spectral slopes of 1, 1.5 or 2 are permitted.
1454
  ! (2) the integral is written in terms of the product QM
1455
  ! which by construction is always less than 1. Series
1456
  ! solutions are used for small |QM| and analytical solutions
1457
  ! for remaining values.
1458
1459
  ! Aug. 8/95 - C. McLandress
1460
1461
  ! Output arguement:
1462
1463
  ! * I_ALPHA = Hines' integral.
1464
1465
  ! Input arguements:
1466
1467
  ! * V_ALPHA = azimuthal wind component (m/s).
1468
  ! * M_ALPHA = azimuthal cutoff vertical wavenumber (1/m).
1469
  ! * BVFB    = background Brunt Vassala frequency at model bottom.
1470
  ! * SLOPE   = slope of initial vertical wavenumber spectrum
1471
  ! *           (must use SLOPE = 1., 1.5 or 2.)
1472
  ! * NAZ     = actual number of horizontal azimuths used.
1473
  ! * LEV     = altitude level to process.
1474
  ! * IL1     = first longitudinal index to use (IL1 >= 1).
1475
  ! * IL2     = last longitudinal index to use (IL1 <= IL2 <= NLONS).
1476
  ! * NLONS   = number of longitudes.
1477
  ! * NLEVS   = number of vertical levels.
1478
  ! * NAZMTH  = azimuthal array dimension (NAZMTH >= NAZ).
1479
1480
  ! * LORMS       = .TRUE. for drag computation
1481
1482
  ! Constants in DATA statements:
1483
1484
  ! * QMIN = minimum value of Q_ALPHA (avoids indeterminant form of integral)
1485
  ! * QM_MIN = minimum value of Q_ALPHA * M_ALPHA (used to avoid numerical
1486
  ! *          problems).
1487
1488
  INTEGER lev, naz, il1, il2, nlons, nlevs, nazmth
1489
  REAL i_alpha(nlons, nazmth)
1490
  REAL v_alpha(nlons, nlevs, nazmth)
1491
  REAL m_alpha(nlons, nlevs, nazmth)
1492
  REAL bvfb(nlons), slope
1493
1494
  LOGICAL lorms(nlons)
1495
1496
  ! Internal variables.
1497
1498
  INTEGER i, n
1499
  REAL q_alpha, qm, sqrtqm, q_min, qm_min
1500
1501
  DATA q_min/1.0/, qm_min/0.01/
1502
  ! -----------------------------------------------------------------------
1503
1504
  ! For integer value SLOPE = 1.
1505
1506
  IF (slope==1.) THEN
1507
1508
    DO n = 1, naz
1509
      DO i = il1, il2
1510
        IF (lorms(i)) THEN
1511
1512
          q_alpha = v_alpha(i, lev, n)/bvfb(i)
1513
          qm = q_alpha*m_alpha(i, lev, n)
1514
1515
          ! If |QM| is small then use first 4 terms series of Taylor series
1516
          ! expansion of integral in order to avoid indeterminate form of
1517
          ! integral,
1518
          ! otherwise use analytical form of integral.
1519
1520
          IF (abs(q_alpha)<q_min .OR. abs(qm)<qm_min) THEN
1521
            IF (q_alpha==0.) THEN
1522
              i_alpha(i, n) = m_alpha(i, lev, n)**2/2.
1523
            ELSE
1524
              i_alpha(i, n) = (qm**2/2.+qm**3/3.+qm**4/4.+qm**5/5.)/ &
1525
                q_alpha**2
1526
            END IF
1527
          ELSE
1528
            i_alpha(i, n) = -(alog(1.-qm)+qm)/q_alpha**2
1529
          END IF
1530
1531
        END IF
1532
      END DO
1533
    END DO
1534
1535
  END IF
1536
1537
  ! For integer value SLOPE = 2.
1538
1539
  IF (slope==2.) THEN
1540
1541
    DO n = 1, naz
1542
      DO i = il1, il2
1543
        IF (lorms(i)) THEN
1544
1545
          q_alpha = v_alpha(i, lev, n)/bvfb(i)
1546
          qm = q_alpha*m_alpha(i, lev, n)
1547
1548
          ! If |QM| is small then use first 4 terms series of Taylor series
1549
          ! expansion of integral in order to avoid indeterminate form of
1550
          ! integral,
1551
          ! otherwise use analytical form of integral.
1552
1553
          IF (abs(q_alpha)<q_min .OR. abs(qm)<qm_min) THEN
1554
            IF (q_alpha==0.) THEN
1555
              i_alpha(i, n) = m_alpha(i, lev, n)**3/3.
1556
            ELSE
1557
              i_alpha(i, n) = (qm**3/3.+qm**4/4.+qm**5/5.+qm**6/6.)/ &
1558
                q_alpha**3
1559
            END IF
1560
          ELSE
1561
            i_alpha(i, n) = -(alog(1.-qm)+qm+qm**2/2.)/q_alpha**3
1562
          END IF
1563
1564
        END IF
1565
      END DO
1566
    END DO
1567
1568
  END IF
1569
1570
  ! For real value SLOPE = 1.5
1571
1572
  IF (slope==1.5) THEN
1573
1574
    DO n = 1, naz
1575
      DO i = il1, il2
1576
        IF (lorms(i)) THEN
1577
1578
          q_alpha = v_alpha(i, lev, n)/bvfb(i)
1579
          qm = q_alpha*m_alpha(i, lev, n)
1580
1581
          ! If |QM| is small then use first 4 terms series of Taylor series
1582
          ! expansion of integral in order to avoid indeterminate form of
1583
          ! integral,
1584
          ! otherwise use analytical form of integral.
1585
1586
          IF (abs(q_alpha)<q_min .OR. abs(qm)<qm_min) THEN
1587
            IF (q_alpha==0.) THEN
1588
              i_alpha(i, n) = m_alpha(i, lev, n)**2.5/2.5
1589
            ELSE
1590
              i_alpha(i, n) = (qm/2.5+qm**2/3.5+qm**3/4.5+qm**4/5.5)* &
1591
                m_alpha(i, lev, n)**1.5/q_alpha
1592
            END IF
1593
          ELSE
1594
            qm = abs(qm)
1595
            sqrtqm = sqrt(qm)
1596
            IF (q_alpha>=0.) THEN
1597
              i_alpha(i, n) = (alog((1.+sqrtqm)/(1.-sqrtqm))-2.*sqrtqm*(1.+qm &
1598
                /3.))/q_alpha**2.5
1599
            ELSE
1600
              i_alpha(i, n) = 2.*(atan(sqrtqm)+sqrtqm*(qm/3.-1.))/ &
1601
                abs(q_alpha)**2.5
1602
            END IF
1603
          END IF
1604
1605
        END IF
1606
      END DO
1607
    END DO
1608
1609
  END IF
1610
1611
  ! If integral is negative (which in principal should not happen) then
1612
  ! print a message and some info since execution will abort when calculating
1613
  ! the variances.
1614
1615
  ! DO 80 N = 1,NAZ
1616
  ! DO 70 I = IL1,IL2
1617
  ! IF (I_ALPHA(I,N).LT.0.)  THEN
1618
  ! WRITE (6,*)
1619
  ! WRITE (6,*) '******************************'
1620
  ! WRITE (6,*) 'Hines integral I_ALPHA < 0 '
1621
  ! WRITE (6,*) '  longitude I=',I
1622
  ! WRITE (6,*) '  azimuth   N=',N
1623
  ! WRITE (6,*) '  level   LEV=',LEV
1624
  ! WRITE (6,*) '  I_ALPHA =',I_ALPHA(I,N)
1625
  ! WRITE (6,*) '  V_ALPHA =',V_ALPHA(I,LEV,N)
1626
  ! WRITE (6,*) '  M_ALPHA =',M_ALPHA(I,LEV,N)
1627
  ! WRITE (6,*) '  Q_ALPHA =',V_ALPHA(I,LEV,N) / BVFB(I)
1628
  ! WRITE (6,*) '  QM      =',V_ALPHA(I,LEV,N) / BVFB(I)
1629
  ! ^                                * M_ALPHA(I,LEV,N)
1630
  ! WRITE (6,*) '******************************'
1631
  ! END IF
1632
  ! 70     CONTINUE
1633
  ! 80   CONTINUE
1634
1635
  RETURN
1636
  ! -----------------------------------------------------------------------
1637
END SUBROUTINE hines_intgrl
1638
1639
SUBROUTINE hines_setup(naz, slope, f1, f2, f3, f5, f6, kstar, icutoff, &
1640
    alt_cutoff, smco, nsmax, iheatcal, k_alpha, ierror, nmessg, nlons, &
1641
    nazmth, coslat)
1642
  IMPLICIT NONE
1643
  ! This routine specifies various parameters needed for the
1644
  ! the Hines' Doppler spread gravity wave drag parameterization scheme.
1645
1646
  ! Aug. 8/95 - C. McLandress
1647
1648
  ! Output arguements:
1649
1650
  ! * NAZ        = actual number of horizontal azimuths used
1651
  ! *              (code set up presently for only NAZ = 4 or 8).
1652
  ! * SLOPE      = slope of incident vertical wavenumber spectrum
1653
  ! *              (code set up presently for SLOPE 1., 1.5 or 2.).
1654
  ! * F1         = "fudge factor" used in calculation of trial value of
1655
  ! *              azimuthal cutoff wavenumber M_ALPHA (1.2 <= F1 <= 1.9).
1656
  ! * F2         = "fudge factor" used in calculation of maximum
1657
  ! *              permissible instabiliy-induced cutoff wavenumber
1658
  ! *              M_SUB_M_TURB (0.1 <= F2 <= 1.4).
1659
  ! * F3         = "fudge factor" used in calculation of maximum
1660
  ! *              permissible molecular viscosity-induced cutoff wavenumber
1661
  ! *              M_SUB_M_MOL (0.1 <= F2 <= 1.4).
1662
  ! * F5         = "fudge factor" used in calculation of heating rate
1663
  ! *              (1 <= F5 <= 3).
1664
  ! * F6         = "fudge factor" used in calculation of turbulent
1665
  ! *              diffusivity coefficient.
1666
  ! * KSTAR      = typical gravity wave horizontal wavenumber (1/m)
1667
  ! *              used in calculation of M_SUB_M_TURB.
1668
  ! * ICUTOFF    = 1 to exponentially damp off GWD, heating and diffusion
1669
  ! *              arrays above ALT_CUTOFF; otherwise arrays not modified.
1670
  ! * ALT_CUTOFF = altitude in meters above which exponential decay applied.
1671
  ! * SMCO       = smoother used to smooth cutoff vertical wavenumbers
1672
  ! *              and total rms winds before calculating drag or heating.
1673
  ! *              (==> a 1:SMCO:1 stencil used; SMCO >= 1.).
1674
  ! * NSMAX      = number of times smoother applied ( >= 1),
1675
  ! *            = 0 means no smoothing performed.
1676
  ! * IHEATCAL   = 1 to calculate heating rates and diffusion coefficient.
1677
  ! *            = 0 means only drag and flux calculated.
1678
  ! * K_ALPHA    = horizontal wavenumber of each azimuth (1/m) which
1679
  ! *              is set here to KSTAR.
1680
  ! * IERROR     = error flag.
1681
  ! *            = 0 no errors.
1682
  ! *            = 10 ==> NAZ > NAZMTH
1683
  ! *            = 20 ==> invalid number of azimuths (NAZ must be 4 or 8).
1684
  ! *            = 30 ==> invalid slope (SLOPE must be 1., 1.5 or 2.).
1685
  ! *            = 40 ==> invalid smoother (SMCO must be >= 1.)
1686
1687
  ! Input arguements:
1688
1689
  ! * NMESSG  = output unit number where messages to be printed.
1690
  ! * NLONS   = number of longitudes.
1691
  ! * NAZMTH  = azimuthal array dimension (NAZMTH >= NAZ).
1692
1693
  INTEGER naz, nlons, nazmth, iheatcal, icutoff
1694
  INTEGER nmessg, nsmax, ierror
1695
  REAL kstar(nlons), slope, f1, f2, f3, f5, f6, alt_cutoff, smco
1696
  REAL k_alpha(nlons, nazmth), coslat(nlons)
1697
  REAL ksmin, ksmax
1698
1699
  ! Internal variables.
1700
1701
  INTEGER i, n
1702
  ! -----------------------------------------------------------------------
1703
1704
  ! Specify constants.
1705
1706
  naz = 8
1707
  slope = 1.
1708
  f1 = 1.5
1709
  f2 = 0.3
1710
  f3 = 1.0
1711
  f5 = 3.0
1712
  f6 = 1.0
1713
  ksmin = 1.E-5
1714
  ksmax = 1.E-4
1715
  DO i = 1, nlons
1716
    kstar(i) = ksmin/(coslat(i)+(ksmin/ksmax))
1717
  END DO
1718
  icutoff = 1
1719
  alt_cutoff = 105.E3
1720
  smco = 2.0
1721
  ! SMCO       = 1.0
1722
  nsmax = 5
1723
  ! NSMAX      = 2
1724
  iheatcal = 0
1725
1726
  ! Print information to output file.
1727
1728
  ! WRITE (NMESSG,6000)
1729
  ! 6000 FORMAT (/' Subroutine HINES_SETUP:')
1730
  ! WRITE (NMESSG,*)  '  SLOPE = ', SLOPE
1731
  ! WRITE (NMESSG,*)  '  NAZ = ', NAZ
1732
  ! WRITE (NMESSG,*)  '  F1,F2,F3  = ', F1, F2, F3
1733
  ! WRITE (NMESSG,*)  '  F5,F6     = ', F5, F6
1734
  ! WRITE (NMESSG,*)  '  KSTAR     = ', KSTAR
1735
  ! >           ,'  COSLAT     = ', COSLAT
1736
  ! IF (ICUTOFF .EQ. 1)  THEN
1737
  ! WRITE (NMESSG,*) '  Drag exponentially damped above ',
1738
  ! &                       ALT_CUTOFF/1.E3
1739
  ! END IF
1740
  ! IF (NSMAX.LT.1 )  THEN
1741
  ! WRITE (NMESSG,*) '  No smoothing of cutoff wavenumbers, etc'
1742
  ! ELSE
1743
  ! WRITE (NMESSG,*) '  Cutoff wavenumbers and sig_t smoothed:'
1744
  ! WRITE (NMESSG,*) '    SMCO  =', SMCO
1745
  ! WRITE (NMESSG,*) '    NSMAX =', NSMAX
1746
  ! END IF
1747
1748
  ! Check that things are setup correctly and log error if not
1749
1750
  ierror = 0
1751
  IF (naz>nazmth) ierror = 10
1752
  IF (naz/=4 .AND. naz/=8) ierror = 20
1753
  IF (slope/=1. .AND. slope/=1.5 .AND. slope/=2.) ierror = 30
1754
  IF (smco<1.) ierror = 40
1755
1756
  ! Use single value for azimuthal-dependent horizontal wavenumber.
1757
1758
  DO n = 1, naz
1759
    DO i = 1, nlons
1760
      k_alpha(i, n) = kstar(i)
1761
    END DO
1762
  END DO
1763
1764
  RETURN
1765
  ! -----------------------------------------------------------------------
1766
END SUBROUTINE hines_setup
1767
1768
SUBROUTINE hines_print(flux_u, flux_v, drag_u, drag_v, alt, sigma_t, &
1769
    sigma_alpha, v_alpha, m_alpha, iu_print, iv_print, nmessg, ilprt1, &
1770
    ilprt2, levprt1, levprt2, naz, nlons, nlevs, nazmth)
1771
  IMPLICIT NONE
1772
  ! Print out altitude profiles of various quantities from
1773
  ! Hines' Doppler spread gravity wave drag parameterization scheme.
1774
  ! (NOTE: only for NAZ = 4 or 8).
1775
1776
  ! Aug. 8/95 - C. McLandress
1777
1778
  ! Input arguements:
1779
1780
  ! * IU_PRINT = 1 to print out values in east-west direction.
1781
  ! * IV_PRINT = 1 to print out values in north-south direction.
1782
  ! * NMESSG   = unit number for printed output.
1783
  ! * ILPRT1   = first longitudinal index to print.
1784
  ! * ILPRT2   = last longitudinal index to print.
1785
  ! * LEVPRT1  = first altitude level to print.
1786
  ! * LEVPRT2  = last altitude level to print.
1787
1788
  INTEGER naz, ilprt1, ilprt2, levprt1, levprt2
1789
  INTEGER nlons, nlevs, nazmth
1790
  INTEGER iu_print, iv_print, nmessg
1791
  REAL flux_u(nlons, nlevs), flux_v(nlons, nlevs)
1792
  REAL drag_u(nlons, nlevs), drag_v(nlons, nlevs)
1793
  REAL alt(nlons, nlevs), sigma_t(nlons, nlevs)
1794
  REAL sigma_alpha(nlons, nlevs, nazmth)
1795
  REAL v_alpha(nlons, nlevs, nazmth), m_alpha(nlons, nlevs, nazmth)
1796
1797
  ! Internal variables.
1798
1799
  INTEGER n_east, n_west, n_north, n_south
1800
  INTEGER i, l
1801
  ! -----------------------------------------------------------------------
1802
1803
  ! Azimuthal indices of cardinal directions.
1804
1805
  n_east = 1
1806
  IF (naz==4) THEN
1807
    n_west = 3
1808
    n_north = 2
1809
    n_south = 4
1810
  ELSE IF (naz==8) THEN
1811
    n_west = 5
1812
    n_north = 3
1813
    n_south = 7
1814
  END IF
1815
1816
  ! Print out values for range of longitudes.
1817
1818
  DO i = ilprt1, ilprt2
1819
1820
    ! Print east-west wind, sigmas, cutoff wavenumbers, flux and drag.
1821
1822
    IF (iu_print==1) THEN
1823
      WRITE (nmessg, *)
1824
      WRITE (nmessg, 6001) i
1825
      WRITE (nmessg, 6005)
1826
6001  FORMAT ('Hines GW (east-west) at longitude I =', I3)
1827
6005  FORMAT (15X, ' U ', 2X, 'sig_E', 2X, 'sig_T', 3X, 'm_E', 4X, 'm_W', 4X, &
1828
        'fluxU', 5X, 'gwdU')
1829
      DO l = levprt1, levprt2
1830
        WRITE (nmessg, 6701) alt(i, l)/1.E3, v_alpha(i, l, n_east), &
1831
          sigma_alpha(i, l, n_east), sigma_t(i, l), &
1832
          m_alpha(i, l, n_east)*1.E3, m_alpha(i, l, n_west)*1.E3, &
1833
          flux_u(i, l)*1.E5, drag_u(i, l)*24.*3600.
1834
      END DO
1835
6701  FORMAT (' z=', F7.2, 1X, 3F7.1, 2F7.3, F9.4, F9.3)
1836
    END IF
1837
1838
    ! Print north-south winds, sigmas, cutoff wavenumbers, flux and drag.
1839
1840
    IF (iv_print==1) THEN
1841
      WRITE (nmessg, *)
1842
      WRITE (nmessg, 6002) i
1843
6002  FORMAT ('Hines GW (north-south) at longitude I =', I3)
1844
      WRITE (nmessg, 6006)
1845
6006  FORMAT (15X, ' V ', 2X, 'sig_N', 2X, 'sig_T', 3X, 'm_N', 4X, 'm_S', 4X, &
1846
        'fluxV', 5X, 'gwdV')
1847
      DO l = levprt1, levprt2
1848
        WRITE (nmessg, 6701) alt(i, l)/1.E3, v_alpha(i, l, n_north), &
1849
          sigma_alpha(i, l, n_north), sigma_t(i, l), &
1850
          m_alpha(i, l, n_north)*1.E3, m_alpha(i, l, n_south)*1.E3, &
1851
          flux_v(i, l)*1.E5, drag_v(i, l)*24.*3600.
1852
      END DO
1853
    END IF
1854
1855
  END DO
1856
1857
  RETURN
1858
  ! -----------------------------------------------------------------------
1859
END SUBROUTINE hines_print
1860
1861
SUBROUTINE hines_exp(data, data_zmax, alt, alt_exp, iorder, il1, il2, lev1, &
1862
    lev2, nlons, nlevs)
1863
  IMPLICIT NONE
1864
  ! This routine exponentially damps a longitude by altitude array
1865
  ! of data above a specified altitude.
1866
1867
  ! Aug. 13/95 - C. McLandress
1868
1869
  ! Output arguements:
1870
1871
  ! * DATA = modified data array.
1872
1873
  ! Input arguements:
1874
1875
  ! * DATA    = original data array.
1876
  ! * ALT     = altitudes.
1877
  ! * ALT_EXP = altitude above which exponential decay applied.
1878
  ! * IORDER	= 1 means vertical levels are indexed from top down
1879
  ! *           (i.e., highest level indexed 1 and lowest level NLEVS);
1880
  ! *           .NE. 1 highest level is index NLEVS.
1881
  ! * IL1     = first longitudinal index to use (IL1 >= 1).
1882
  ! * IL2     = last longitudinal index to use (IL1 <= IL2 <= NLONS).
1883
  ! * LEV1    = first altitude level to use (LEV1 >=1).
1884
  ! * LEV2    = last altitude level to use (LEV1 < LEV2 <= NLEVS).
1885
  ! * NLONS   = number of longitudes.
1886
  ! * NLEVS   = number of vertical
1887
1888
  ! Input work arrays:
1889
1890
  ! * DATA_ZMAX = data values just above altitude ALT_EXP.
1891
1892
  INTEGER iorder, il1, il2, lev1, lev2, nlons, nlevs
1893
  REAL alt_exp
1894
  REAL data(nlons, nlevs), data_zmax(nlons), alt(nlons, nlevs)
1895
1896
  ! Internal variables.
1897
1898
  INTEGER levbot, levtop, lincr, i, l
1899
  REAL hscale
1900
  DATA hscale/5.E3/
1901
  ! -----------------------------------------------------------------------
1902
1903
  ! Index of lowest altitude level (bottom of drag calculation).
1904
1905
  levbot = lev2
1906
  levtop = lev1
1907
  lincr = 1
1908
  IF (iorder/=1) THEN
1909
    levbot = lev1
1910
    levtop = lev2
1911
    lincr = -1
1912
  END IF
1913
1914
  ! Data values at first level above ALT_EXP.
1915
1916
  DO i = il1, il2
1917
    DO l = levtop, levbot, lincr
1918
      IF (alt(i,l)>=alt_exp) THEN
1919
        data_zmax(i) = data(i, l)
1920
      END IF
1921
    END DO
1922
  END DO
1923
1924
  ! Exponentially damp field above ALT_EXP to model top at L=1.
1925
1926
  DO l = 1, lev2
1927
    DO i = il1, il2
1928
      IF (alt(i,l)>=alt_exp) THEN
1929
        data(i, l) = data_zmax(i)*exp((alt_exp-alt(i,l))/hscale)
1930
      END IF
1931
    END DO
1932
  END DO
1933
1934
  RETURN
1935
  ! -----------------------------------------------------------------------
1936
END SUBROUTINE hines_exp
1937
1938
SUBROUTINE vert_smooth(data, work, coeff, nsmooth, il1, il2, lev1, lev2, &
1939
    nlons, nlevs)
1940
  IMPLICIT NONE
1941
  ! Smooth a longitude by altitude array in the vertical over a
1942
  ! specified number of levels using a three point smoother.
1943
1944
  ! NOTE: input array DATA is modified on output!
1945
1946
  ! Aug. 3/95 - C. McLandress
1947
1948
  ! Output arguement:
1949
1950
  ! * DATA    = smoothed array (on output).
1951
1952
  ! Input arguements:
1953
1954
  ! * DATA    = unsmoothed array of data (on input).
1955
  ! * WORK    = work array of same dimension as DATA.
1956
  ! * COEFF   = smoothing coefficient for a 1:COEFF:1 stencil.
1957
  ! *           (e.g., COEFF = 2 will result in a smoother which
1958
  ! *           weights the level L gridpoint by two and the two
1959
  ! *           adjecent levels (L+1 and L-1) by one).
1960
  ! * NSMOOTH = number of times to smooth in vertical.
1961
  ! *           (e.g., NSMOOTH=1 means smoothed only once,
1962
  ! *           NSMOOTH=2 means smoothing repeated twice, etc.)
1963
  ! * IL1     = first longitudinal index to use (IL1 >= 1).
1964
  ! * IL2     = last longitudinal index to use (IL1 <= IL2 <= NLONS).
1965
  ! * LEV1    = first altitude level to use (LEV1 >=1).
1966
  ! * LEV2    = last altitude level to use (LEV1 < LEV2 <= NLEVS).
1967
  ! * NLONS   = number of longitudes.
1968
  ! * NLEVS   = number of vertical levels.
1969
1970
  ! Subroutine arguements.
1971
1972
  INTEGER nsmooth, il1, il2, lev1, lev2, nlons, nlevs
1973
  REAL coeff
1974
  REAL data(nlons, nlevs), work(nlons, nlevs)
1975
1976
  ! Internal variables.
1977
1978
  INTEGER i, l, ns, lev1p, lev2m
1979
  REAL sum_wts
1980
  ! -----------------------------------------------------------------------
1981
1982
  ! Calculate sum of weights.
1983
1984
  sum_wts = coeff + 2.
1985
1986
  lev1p = lev1 + 1
1987
  lev2m = lev2 - 1
1988
1989
  ! Smooth NSMOOTH times
1990
1991
  DO ns = 1, nsmooth
1992
1993
    ! Copy data into work array.
1994
1995
    DO l = lev1, lev2
1996
      DO i = il1, il2
1997
        work(i, l) = data(i, l)
1998
      END DO
1999
    END DO
2000
2001
    ! Smooth array WORK in vertical direction and put into DATA.
2002
2003
    DO l = lev1p, lev2m
2004
      DO i = il1, il2
2005
        data(i, l) = (work(i,l+1)+coeff*work(i,l)+work(i,l-1))/sum_wts
2006
      END DO
2007
    END DO
2008
2009
  END DO
2010
2011
  RETURN
2012
  ! -----------------------------------------------------------------------
2013
END SUBROUTINE vert_smooth
2014
2015
2016
2017
2018
2019