GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: dyn3d_common/ppm3d.F Lines: 0 975 0.0 %
Date: 2023-06-30 12:56:34 Branches: 0 634 0.0 %

Line Branch Exec Source
1
!
2
! $Id: ppm3d.F 2197 2015-02-09 07:13:05Z emillour $
3
!
4
5
cFrom lin@explorer.gsfc.nasa.gov Wed Apr 15 17:44:44 1998
6
cDate: Wed, 15 Apr 1998 11:37:03 -0400
7
cFrom: lin@explorer.gsfc.nasa.gov
8
cTo: Frederic.Hourdin@lmd.jussieu.fr
9
cSubject: 3D transport module of the GSFC CTM and GEOS GCM
10
11
12
cThis code is sent to you by S-J Lin, DAO, NASA-GSFC
13
14
cNote: this version is intended for machines like CRAY
15
C-90. No multitasking directives implemented.
16
17
18
C ********************************************************************
19
C
20
C TransPort Core for Goddard Chemistry Transport Model (G-CTM), Goddard
21
C Earth Observing System General Circulation Model (GEOS-GCM), and Data
22
C Assimilation System (GEOS-DAS).
23
C
24
C ********************************************************************
25
C
26
C Purpose: given horizontal winds on  a hybrid sigma-p surfaces,
27
C          one call to tpcore updates the 3-D mixing ratio
28
C          fields one time step (NDT). [vertical mass flux is computed
29
C          internally consistent with the discretized hydrostatic mass
30
C          continuity equation of the C-Grid GEOS-GCM (for IGD=1)].
31
C
32
C Schemes: Multi-dimensional Flux Form Semi-Lagrangian (FFSL) scheme based
33
C          on the van Leer or PPM.
34
C          (see Lin and Rood 1996).
35
C Version 4.5
36
C Last modified: Dec. 5, 1996
37
C Major changes from version 4.0: a more general vertical hybrid sigma-
38
C pressure coordinate.
39
C Subroutines modified: xtp, ytp, fzppm, qckxyz
40
C Subroutines deleted: vanz
41
C
42
C Author: Shian-Jiann Lin
43
C mail address:
44
C                 Shian-Jiann Lin*
45
C                 Code 910.3, NASA/GSFC, Greenbelt, MD 20771
46
C                 Phone: 301-286-9540
47
C                 E-mail: lin@dao.gsfc.nasa.gov
48
C
49
C *affiliation:
50
C                 Joint Center for Earth Systems Technology
51
C                 The University of Maryland Baltimore County
52
C                 NASA - Goddard Space Flight Center
53
C References:
54
C
55
C 1. Lin, S.-J., and R. B. Rood, 1996: Multidimensional flux form semi-
56
C    Lagrangian transport schemes. Mon. Wea. Rev., 124, 2046-2070.
57
C
58
C 2. Lin, S.-J., W. C. Chao, Y. C. Sud, and G. K. Walker, 1994: A class of
59
C    the van Leer-type transport schemes and its applications to the moist-
60
C    ure transport in a General Circulation Model. Mon. Wea. Rev., 122,
61
C    1575-1593.
62
C
63
C ****6***0*********0*********0*********0*********0*********0**********72
64
C
65
      subroutine ppm3d(IGD,Q,PS1,PS2,U,V,W,NDT,IORD,JORD,KORD,NC,IMR,
66
     &                  JNP,j1,NLAY,AP,BP,PT,AE,fill,dum,Umax)
67
68
      implicit none
69
70
c     rajout de d�clarations
71
c      integer Jmax,kmax,ndt0,nstep,k,j,i,ic,l,js,jn,imh,iad,jad,krd
72
c      integer iu,iiu,j2,jmr,js0,jt
73
c      real dtdy,dtdy5,rcap,iml,jn0,imjm,pi,dl,dp
74
c      real dt,cr1,maxdt,ztc,d5,sum1,sum2,ru
75
C
76
C ********************************************************************
77
C
78
C =============
79
C INPUT:
80
C =============
81
C
82
C Q(IMR,JNP,NLAY,NC): mixing ratios at current time (t)
83
C NC: total # of constituents
84
C IMR: first dimension (E-W); # of Grid intervals in E-W is IMR
85
C JNP: 2nd dimension (N-S); # of Grid intervals in N-S is JNP-1
86
C NLAY: 3rd dimension (# of layers); vertical index increases from 1 at
87
C       the model top to NLAY near the surface (see fig. below).
88
C       It is assumed that 6 <= NLAY <= JNP (for dynamic memory allocation)
89
C
90
C PS1(IMR,JNP): surface pressure at current time (t)
91
C PS2(IMR,JNP): surface pressure at mid-time-level (t+NDT/2)
92
C PS2 is replaced by the predicted PS (at t+NDT) on output.
93
C Note: surface pressure can have any unit or can be multiplied by any
94
C       const.
95
C
96
C The pressure at layer edges are defined as follows:
97
C
98
C        p(i,j,k) = AP(k)*PT  +  BP(k)*PS(i,j)          (1)
99
C
100
C Where PT is a constant having the same unit as PS.
101
C AP and BP are unitless constants given at layer edges
102
C defining the vertical coordinate.
103
C BP(1) = 0., BP(NLAY+1) = 1.
104
C The pressure at the model top is PTOP = AP(1)*PT
105
C
106
C For pure sigma system set AP(k) = 1 for all k, PT = PTOP,
107
C BP(k) = sige(k) (sigma at edges), PS = Psfc - PTOP.
108
C
109
C Note: the sigma-P coordinate is a subset of Eq. 1, which in turn
110
C is a subset of the following even more general sigma-P-thelta coord.
111
C currently under development.
112
C  p(i,j,k) = (AP(k)*PT + BP(k)*PS(i,j))/(D(k)-C(k)*TE**(-1/kapa))
113
C
114
C                  /////////////////////////////////
115
C              / \ ------------- PTOP --------------  AP(1), BP(1)
116
C               |
117
C    delp(1)    |  ........... Q(i,j,1) ............
118
C               |
119
C      W(1)    \ / ---------------------------------  AP(2), BP(2)
120
C
121
C
122
C
123
C     W(k-1)   / \ ---------------------------------  AP(k), BP(k)
124
C               |
125
C    delp(K)    |  ........... Q(i,j,k) ............
126
C               |
127
C      W(k)    \ / ---------------------------------  AP(k+1), BP(k+1)
128
C
129
C
130
C
131
C              / \ ---------------------------------  AP(NLAY), BP(NLAY)
132
C               |
133
C  delp(NLAY)   |  ........... Q(i,j,NLAY) .........
134
C               |
135
C   W(NLAY)=0  \ / ------------- surface ----------- AP(NLAY+1), BP(NLAY+1)
136
C                 //////////////////////////////////
137
C
138
C U(IMR,JNP,NLAY) & V(IMR,JNP,NLAY):winds (m/s) at mid-time-level (t+NDT/2)
139
C U and V may need to be polar filtered in advance in some cases.
140
C
141
C IGD:      grid type on which winds are defined.
142
C IGD = 0:  A-Grid  [all variables defined at the same point from south
143
C                   pole (j=1) to north pole (j=JNP) ]
144
C
145
C IGD = 1  GEOS-GCM C-Grid
146
C                                      [North]
147
C
148
C                                       V(i,j)
149
C                                          |
150
C                                          |
151
C                                          |
152
C                             U(i-1,j)---Q(i,j)---U(i,j) [EAST]
153
C                                          |
154
C                                          |
155
C                                          |
156
C                                       V(i,j-1)
157
C
158
C         U(i,  1) is defined at South Pole.
159
C         V(i,  1) is half grid north of the South Pole.
160
C         V(i,JMR) is half grid south of the North Pole.
161
C
162
C         V must be defined at j=1 and j=JMR if IGD=1
163
C         V at JNP need not be given.
164
C
165
C NDT: time step in seconds (need not be constant during the course of
166
C      the integration). Suggested value: 30 min. for 4x5, 15 min. for 2x2.5
167
C      (Lat-Lon) resolution. Smaller values are recommanded if the model
168
C      has a well-resolved stratosphere.
169
C
170
C J1 defines the size of the polar cap:
171
C South polar cap edge is located at -90 + (j1-1.5)*180/(JNP-1) deg.
172
C North polar cap edge is located at  90 - (j1-1.5)*180/(JNP-1) deg.
173
C There are currently only two choices (j1=2 or 3).
174
C IMR must be an even integer if j1 = 2. Recommended value: J1=3.
175
C
176
C IORD, JORD, and KORD are integers controlling various options in E-W, N-S,
177
C and vertical transport, respectively. Recommended values for positive
178
C definite scalars: IORD=JORD=3, KORD=5. Use KORD=3 for non-
179
C positive definite scalars or when linear correlation between constituents
180
C is to be maintained.
181
C
182
C  _ORD=
183
C        1: 1st order upstream scheme (too diffusive, not a useful option; it
184
C           can be used for debugging purposes; this is THE only known "linear"
185
C           monotonic advection scheme.).
186
C        2: 2nd order van Leer (full monotonicity constraint;
187
C           see Lin et al 1994, MWR)
188
C        3: monotonic PPM* (slightly improved PPM of Collela & Woodward 1984)
189
C        4: semi-monotonic PPM (same as 3, but overshoots are allowed)
190
C        5: positive-definite PPM (constraint on the subgrid distribution is
191
C           only strong enough to prevent generation of negative values;
192
C           both overshoots & undershoots are possible).
193
C        6: un-constrained PPM (nearly diffusion free; slightly faster but
194
C           positivity not quaranteed. Use this option only when the fields
195
C           and winds are very smooth).
196
C
197
C *PPM: Piece-wise Parabolic Method
198
C
199
C Note that KORD <=2 options are no longer supported. DO not use option 4 or 5.
200
C for non-positive definite scalars (such as Ertel Potential Vorticity).
201
C
202
C The implicit numerical diffusion decreases as _ORD increases.
203
C The last two options (ORDER=5, 6) should only be used when there is
204
C significant explicit diffusion (such as a turbulence parameterization). You
205
C might get dispersive results otherwise.
206
C No filter of any kind is applied to the constituent fields here.
207
C
208
C AE: Radius of the sphere (meters).
209
C     Recommended value for the planet earth: 6.371E6
210
C
211
C fill(logical):   flag to do filling for negatives (see note below).
212
C
213
C Umax: Estimate (upper limit) of the maximum U-wind speed (m/s).
214
C (220 m/s is a good value for troposphere model; 280 m/s otherwise)
215
C
216
C =============
217
C Output
218
C =============
219
C
220
C Q: mixing ratios at future time (t+NDT) (original values are over-written)
221
C W(NLAY): large-scale vertical mass flux as diagnosed from the hydrostatic
222
C          relationship. W will have the same unit as PS1 and PS2 (eg, mb).
223
C          W must be divided by NDT to get the correct mass-flux unit.
224
C          The vertical Courant number C = W/delp_UPWIND, where delp_UPWIND
225
C          is the pressure thickness in the "upwind" direction. For example,
226
C          C(k) = W(k)/delp(k)   if W(k) > 0;
227
C          C(k) = W(k)/delp(k+1) if W(k) < 0.
228
C              ( W > 0 is downward, ie, toward surface)
229
C PS2: predicted PS at t+NDT (original values are over-written)
230
C
231
C ********************************************************************
232
C NOTES:
233
C This forward-in-time upstream-biased transport scheme reduces to
234
C the 2nd order center-in-time center-in-space mass continuity eqn.
235
C if Q = 1 (constant fields will remain constant). This also ensures
236
C that the computed vertical velocity to be identical to GEOS-1 GCM
237
C for on-line transport.
238
C
239
C A larger polar cap is used if j1=3 (recommended for C-Grid winds or when
240
C winds are noisy near poles).
241
C
242
C Flux-Form Semi-Lagrangian transport in the East-West direction is used
243
C when and where Courant # is greater than one.
244
C
245
C The user needs to change the parameter Jmax or Kmax if the resolution
246
C is greater than 0.5 deg in N-S or 150 layers in the vertical direction.
247
C (this TransPort Core is otherwise resolution independent and can be used
248
C as a library routine).
249
C
250
C PPM is 4th order accurate when grid spacing is uniform (x & y); 3rd
251
C order accurate for non-uniform grid (vertical sigma coord.).
252
C
253
C Time step is limitted only by transport in the meridional direction.
254
C (the FFSL scheme is not implemented in the meridional direction).
255
C
256
C Since only 1-D limiters are applied, negative values could
257
C potentially be generated when large time step is used and when the
258
C initial fields contain discontinuities.
259
C This does not necessarily imply the integration is unstable.
260
C These negatives are typically very small. A filling algorithm is
261
C activated if the user set "fill" to be true.
262
C
263
C The van Leer scheme used here is nearly as accurate as the original PPM
264
C due to the use of a 4th order accurate reference slope. The PPM imple-
265
C mented here is an improvement over the original and is also based on
266
C the 4th order reference slope.
267
C
268
C ****6***0*********0*********0*********0*********0*********0**********72
269
C
270
C     User modifiable parameters
271
C
272
      integer,parameter :: Jmax = 361, kmax = 150
273
C
274
C ****6***0*********0*********0*********0*********0*********0**********72
275
C
276
C Input-Output arrays
277
C
278
279
      real Q(IMR,JNP,NLAY,NC),PS1(IMR,JNP),PS2(IMR,JNP),
280
     &     U(IMR,JNP,NLAY),V(IMR,JNP,NLAY),AP(NLAY+1),
281
     &     BP(NLAY+1),W(IMR,JNP,NLAY),NDT,val(NLAY),Umax
282
      integer IGD,IORD,JORD,KORD,NC,IMR,JNP,j1,NLAY,AE
283
      integer IMRD2
284
      real    PT
285
      logical  cross, fill, dum
286
C
287
C Local dynamic arrays
288
C
289
      real CRX(IMR,JNP),CRY(IMR,JNP),xmass(IMR,JNP),ymass(IMR,JNP),
290
     &     fx1(IMR+1),DPI(IMR,JNP,NLAY),delp1(IMR,JNP,NLAY),
291
     &     WK1(IMR,JNP,NLAY),PU(IMR,JNP),PV(IMR,JNP),DC2(IMR,JNP),
292
     &     delp2(IMR,JNP,NLAY),DQ(IMR,JNP,NLAY,NC),VA(IMR,JNP),
293
     &     UA(IMR,JNP),qtmp(-IMR:2*IMR)
294
C
295
C Local static  arrays
296
C
297
      real DTDX(Jmax), DTDX5(Jmax), acosp(Jmax),
298
     &     cosp(Jmax), cose(Jmax), DAP(kmax),DBK(Kmax)
299
      data NDT0, NSTEP /0, 0/
300
      data cross /.true./
301
      REAL DTDY, DTDY5, RCAP
302
      INTEGER JS0, JN0, IML, JMR, IMJM
303
      SAVE DTDY, DTDY5, RCAP, JS0, JN0, IML,
304
     &     DTDX, DTDX5, ACOSP, COSP, COSE, DAP,DBK
305
C
306
      INTEGER NDT0, NSTEP, j2, k,j,i,ic,l,JS,JN,IMH
307
      INTEGER IU,IIU,JT,iad,jad,krd
308
      REAL r23,r3,PI,DL,DP,DT,CR1,MAXDT,ZTC,D5
309
      REAL sum1,sum2,ru
310
311
      JMR = JNP -1
312
      IMJM  = IMR*JNP
313
      j2 = JNP - j1 + 1
314
      NSTEP = NSTEP + 1
315
C
316
C *********** Initialization **********************
317
      if(NSTEP.eq.1) then
318
c
319
      write(6,*) '------------------------------------ '
320
      write(6,*) 'NASA/GSFC Transport Core Version 4.5'
321
      write(6,*) '------------------------------------ '
322
c
323
      WRITE(6,*) 'IMR=',IMR,' JNP=',JNP,' NLAY=',NLAY,' j1=',j1
324
      WRITE(6,*) 'NC=',NC,IORD,JORD,KORD,NDT
325
C
326
C controles sur les parametres
327
      if(NLAY.LT.6) then
328
        write(6,*) 'NLAY must be >= 6'
329
        stop
330
      endif
331
      if (JNP.LT.NLAY) then
332
         write(6,*) 'JNP must be >= NLAY'
333
        stop
334
      endif
335
      IMRD2=mod(IMR,2)
336
      if (j1.eq.2.and.IMRD2.NE.0) then
337
         write(6,*) 'if j1=2 IMR must be an even integer'
338
        stop
339
      endif
340
341
C
342
      if(Jmax.lt.JNP .or. Kmax.lt.NLAY) then
343
        write(6,*) 'Jmax or Kmax is too small'
344
        stop
345
      endif
346
C
347
      DO k=1,NLAY
348
      DAP(k) = (AP(k+1) - AP(k))*PT
349
      DBK(k) =  BP(k+1) - BP(k)
350
      ENDDO
351
C
352
      PI = 4. * ATAN(1.)
353
      DL = 2.*PI / REAL(IMR)
354
      DP =    PI / REAL(JMR)
355
C
356
      if(IGD.eq.0) then
357
C Compute analytic cosine at cell edges
358
            call cosa(cosp,cose,JNP,PI,DP)
359
      else
360
C Define cosine consistent with GEOS-GCM (using dycore2.0 or later)
361
            call cosc(cosp,cose,JNP,PI,DP)
362
      endif
363
C
364
      do 15 J=2,JMR
365
15    acosp(j) = 1. / cosp(j)
366
C
367
C Inverse of the Scaled polar cap area.
368
C
369
      RCAP  = DP / (IMR*(1.-COS((j1-1.5)*DP)))
370
      acosp(1)   = RCAP
371
      acosp(JNP) = RCAP
372
      endif
373
C
374
      if(NDT0 .ne. NDT) then
375
      DT   = NDT
376
      NDT0 = NDT
377
378
	if(Umax .lt. 180.) then
379
         write(6,*) 'Umax may be too small!'
380
	endif
381
      CR1  = abs(Umax*DT)/(DL*AE)
382
      MaxDT = DP*AE / abs(Umax) + 0.5
383
      write(6,*)'Largest time step for max(V)=',Umax,' is ',MaxDT
384
      if(MaxDT .lt. abs(NDT)) then
385
            write(6,*) 'Warning!!! NDT maybe too large!'
386
      endif
387
C
388
      if(CR1.ge.0.95) then
389
      JS0 = 0
390
      JN0 = 0
391
      IML = IMR-2
392
      ZTC = 0.
393
      else
394
      ZTC  = acos(CR1) * (180./PI)
395
C
396
      JS0 = REAL(JMR)*(90.-ZTC)/180. + 2
397
      JS0 = max(JS0, J1+1)
398
      IML = min(6*JS0/(J1-1)+2, 4*IMR/5)
399
      JN0 = JNP-JS0+1
400
      endif
401
C
402
C
403
      do J=2,JMR
404
      DTDX(j)  = DT / ( DL*AE*COSP(J) )
405
406
c     print*,'dtdx=',dtdx(j)
407
      DTDX5(j) = 0.5*DTDX(j)
408
      enddo
409
C
410
411
      DTDY  = DT /(AE*DP)
412
c      print*,'dtdy=',dtdy
413
      DTDY5 = 0.5*DTDY
414
C
415
c      write(6,*) 'J1=',J1,' J2=', J2
416
      endif
417
C
418
C *********** End Initialization **********************
419
C
420
C delp = pressure thickness: the psudo-density in a hydrostatic system.
421
      do  k=1,NLAY
422
         do  j=1,JNP
423
            do  i=1,IMR
424
               delp1(i,j,k)=DAP(k)+DBK(k)*PS1(i,j)
425
               delp2(i,j,k)=DAP(k)+DBK(k)*PS2(i,j)
426
            enddo
427
         enddo
428
      enddo
429
430
C
431
      if(j1.ne.2) then
432
      DO 40 IC=1,NC
433
      DO 40 L=1,NLAY
434
      DO 40 I=1,IMR
435
      Q(I,  2,L,IC) = Q(I,  1,L,IC)
436
40    Q(I,JMR,L,IC) = Q(I,JNP,L,IC)
437
      endif
438
C
439
C Compute "tracer density"
440
      DO 550 IC=1,NC
441
      DO 44 k=1,NLAY
442
      DO 44 j=1,JNP
443
      DO 44 i=1,IMR
444
44    DQ(i,j,k,IC) = Q(i,j,k,IC)*delp1(i,j,k)
445
550	continue
446
C
447
      do 1500 k=1,NLAY
448
C
449
      if(IGD.eq.0) then
450
C Convert winds on A-Grid to Courant # on C-Grid.
451
      call A2C(U(1,1,k),V(1,1,k),IMR,JMR,j1,j2,CRX,CRY,dtdx5,DTDY5)
452
      else
453
C Convert winds on C-grid to Courant #
454
      do 45 j=j1,j2
455
      do 45 i=2,IMR
456
45    CRX(i,J) = dtdx(j)*U(i-1,j,k)
457
458
C
459
      do 50 j=j1,j2
460
50    CRX(1,J) = dtdx(j)*U(IMR,j,k)
461
C
462
      do 55 i=1,IMR*JMR
463
55    CRY(i,2) = DTDY*V(i,1,k)
464
      endif
465
C
466
C Determine JS and JN
467
      JS = j1
468
      JN = j2
469
C
470
      do j=JS0,j1+1,-1
471
      do i=1,IMR
472
      if(abs(CRX(i,j)).GT.1.) then
473
            JS = j
474
            go to 2222
475
      endif
476
      enddo
477
      enddo
478
C
479
2222  continue
480
      do j=JN0,j2-1
481
      do i=1,IMR
482
      if(abs(CRX(i,j)).GT.1.) then
483
            JN = j
484
            go to 2233
485
      endif
486
      enddo
487
      enddo
488
2233  continue
489
C
490
      if(j1.ne.2) then           ! Enlarged polar cap.
491
      do i=1,IMR
492
      DPI(i,  2,k) = 0.
493
      DPI(i,JMR,k) = 0.
494
      enddo
495
      endif
496
C
497
C ******* Compute horizontal mass fluxes ************
498
C
499
C N-S component
500
      do j=j1,j2+1
501
      D5 = 0.5 * COSE(j)
502
      do i=1,IMR
503
      ymass(i,j) = CRY(i,j)*D5*(delp2(i,j,k) + delp2(i,j-1,k))
504
      enddo
505
      enddo
506
C
507
      do 95 j=j1,j2
508
      DO 95 i=1,IMR
509
95    DPI(i,j,k) = (ymass(i,j) - ymass(i,j+1)) * acosp(j)
510
C
511
C Poles
512
      sum1 = ymass(IMR,j1  )
513
      sum2 = ymass(IMR,J2+1)
514
      do i=1,IMR-1
515
      sum1 = sum1 + ymass(i,j1  )
516
      sum2 = sum2 + ymass(i,J2+1)
517
      enddo
518
C
519
      sum1 = - sum1 * RCAP
520
      sum2 =   sum2 * RCAP
521
      do i=1,IMR
522
      DPI(i,  1,k) = sum1
523
      DPI(i,JNP,k) = sum2
524
      enddo
525
C
526
C E-W component
527
C
528
      do j=j1,j2
529
      do i=2,IMR
530
      PU(i,j) = 0.5 * (delp2(i,j,k) + delp2(i-1,j,k))
531
      enddo
532
      enddo
533
C
534
      do j=j1,j2
535
      PU(1,j) = 0.5 * (delp2(1,j,k) + delp2(IMR,j,k))
536
      enddo
537
C
538
      do 110 j=j1,j2
539
      DO 110 i=1,IMR
540
110   xmass(i,j) = PU(i,j)*CRX(i,j)
541
C
542
      DO 120 j=j1,j2
543
      DO 120 i=1,IMR-1
544
120   DPI(i,j,k) = DPI(i,j,k) + xmass(i,j) - xmass(i+1,j)
545
C
546
      DO 130 j=j1,j2
547
130   DPI(IMR,j,k) = DPI(IMR,j,k) + xmass(IMR,j) - xmass(1,j)
548
C
549
      DO j=j1,j2
550
      do i=1,IMR-1
551
      UA(i,j) = 0.5 * (CRX(i,j)+CRX(i+1,j))
552
      enddo
553
      enddo
554
C
555
      DO j=j1,j2
556
      UA(imr,j) = 0.5 * (CRX(imr,j)+CRX(1,j))
557
      enddo
558
ccccccccccccccccccccccccccccccccccccccccccccccccccccccc
559
c Rajouts pour LMDZ.3.3
560
ccccccccccccccccccccccccccccccccccccccccccccccccccccccc
561
      do i=1,IMR
562
         do j=1,JNP
563
             VA(i,j)=0.
564
         enddo
565
      enddo
566
567
      do i=1,imr*(JMR-1)
568
      VA(i,2) = 0.5*(CRY(i,2)+CRY(i,3))
569
      enddo
570
C
571
      if(j1.eq.2) then
572
	IMH = IMR/2
573
      do i=1,IMH
574
      VA(i,      1) = 0.5*(CRY(i,2)-CRY(i+IMH,2))
575
      VA(i+IMH,  1) = -VA(i,1)
576
      VA(i,    JNP) = 0.5*(CRY(i,JNP)-CRY(i+IMH,JMR))
577
      VA(i+IMH,JNP) = -VA(i,JNP)
578
      enddo
579
      VA(IMR,1)=VA(1,1)
580
      VA(IMR,JNP)=VA(1,JNP)
581
      endif
582
C
583
C ****6***0*********0*********0*********0*********0*********0**********72
584
      do 1000 IC=1,NC
585
C
586
      do i=1,IMJM
587
      wk1(i,1,1) = 0.
588
      wk1(i,1,2) = 0.
589
      enddo
590
C
591
C E-W advective cross term
592
      do 250 j=J1,J2
593
      if(J.GT.JS  .and. J.LT.JN) GO TO 250
594
C
595
      do i=1,IMR
596
      qtmp(i) = q(i,j,k,IC)
597
      enddo
598
C
599
      do i=-IML,0
600
      qtmp(i)       = q(IMR+i,j,k,IC)
601
      qtmp(IMR+1-i) = q(1-i,j,k,IC)
602
      enddo
603
C
604
      DO 230 i=1,IMR
605
      iu = UA(i,j)
606
      ru = UA(i,j) - iu
607
      iiu = i-iu
608
      if(UA(i,j).GE.0.) then
609
      wk1(i,j,1) = qtmp(iiu)+ru*(qtmp(iiu-1)-qtmp(iiu))
610
      else
611
      wk1(i,j,1) = qtmp(iiu)+ru*(qtmp(iiu)-qtmp(iiu+1))
612
      endif
613
      wk1(i,j,1) = wk1(i,j,1) - qtmp(i)
614
230   continue
615
250   continue
616
C
617
      if(JN.ne.0) then
618
      do j=JS+1,JN-1
619
C
620
      do i=1,IMR
621
      qtmp(i) = q(i,j,k,IC)
622
      enddo
623
C
624
      qtmp(0)     = q(IMR,J,k,IC)
625
      qtmp(IMR+1) = q(  1,J,k,IC)
626
C
627
      do i=1,imr
628
      iu = i - UA(i,j)
629
      wk1(i,j,1) = UA(i,j)*(qtmp(iu) - qtmp(iu+1))
630
      enddo
631
      enddo
632
      endif
633
C ****6***0*********0*********0*********0*********0*********0**********72
634
C Contribution from the N-S advection
635
      do i=1,imr*(j2-j1+1)
636
      JT = REAL(J1) - VA(i,j1)
637
      wk1(i,j1,2) = VA(i,j1) * (q(i,jt,k,IC) - q(i,jt+1,k,IC))
638
      enddo
639
C
640
      do i=1,IMJM
641
      wk1(i,1,1) = q(i,1,k,IC) + 0.5*wk1(i,1,1)
642
      wk1(i,1,2) = q(i,1,k,IC) + 0.5*wk1(i,1,2)
643
      enddo
644
C
645
	if(cross) then
646
C Add cross terms in the vertical direction.
647
	if(IORD .GE. 2) then
648
		iad = 2
649
	else
650
		iad = 1
651
	endif
652
C
653
	if(JORD .GE. 2) then
654
		jad = 2
655
	else
656
		jad = 1
657
	endif
658
      call xadv(IMR,JNP,j1,j2,wk1(1,1,2),UA,JS,JN,IML,DC2,iad)
659
      call yadv(IMR,JNP,j1,j2,wk1(1,1,1),VA,PV,W,jad)
660
      do j=1,JNP
661
      do i=1,IMR
662
      q(i,j,k,IC) = q(i,j,k,IC) + DC2(i,j) + PV(i,j)
663
      enddo
664
      enddo
665
      endif
666
C
667
      call xtp(IMR,JNP,IML,j1,j2,JN,JS,PU,DQ(1,1,k,IC),wk1(1,1,2)
668
     &        ,CRX,fx1,xmass,IORD)
669
670
      call ytp(IMR,JNP,j1,j2,acosp,RCAP,DQ(1,1,k,IC),wk1(1,1,1),CRY,
671
     &  DC2,ymass,WK1(1,1,3),wk1(1,1,4),WK1(1,1,5),WK1(1,1,6),JORD)
672
C
673
1000  continue
674
1500  continue
675
C
676
C ******* Compute vertical mass flux (same unit as PS) ***********
677
C
678
C 1st step: compute total column mass CONVERGENCE.
679
C
680
      do 320 j=1,JNP
681
      do 320 i=1,IMR
682
320   CRY(i,j) = DPI(i,j,1)
683
C
684
      do 330 k=2,NLAY
685
      do 330 j=1,JNP
686
      do 330 i=1,IMR
687
      CRY(i,j)  = CRY(i,j) + DPI(i,j,k)
688
330   continue
689
C
690
      do 360 j=1,JNP
691
      do 360 i=1,IMR
692
C
693
C 2nd step: compute PS2 (PS at n+1) using the hydrostatic assumption.
694
C Changes (increases) to surface pressure = total column mass convergence
695
C
696
      PS2(i,j)  = PS1(i,j) + CRY(i,j)
697
C
698
C 3rd step: compute vertical mass flux from mass conservation principle.
699
C
700
      W(i,j,1) = DPI(i,j,1) - DBK(1)*CRY(i,j)
701
      W(i,j,NLAY) = 0.
702
360   continue
703
C
704
      do 370 k=2,NLAY-1
705
      do 370 j=1,JNP
706
      do 370 i=1,IMR
707
      W(i,j,k) = W(i,j,k-1) + DPI(i,j,k) - DBK(k)*CRY(i,j)
708
370   continue
709
C
710
      DO 380 k=1,NLAY
711
      DO 380 j=1,JNP
712
      DO 380 i=1,IMR
713
      delp2(i,j,k) = DAP(k) + DBK(k)*PS2(i,j)
714
380   continue
715
C
716
	KRD = max(3, KORD)
717
      do 4000 IC=1,NC
718
C
719
C****6***0*********0*********0*********0*********0*********0**********72
720
721
      call FZPPM(IMR,JNP,NLAY,j1,DQ(1,1,1,IC),W,Q(1,1,1,IC),WK1,DPI,
722
     &           DC2,CRX,CRY,PU,PV,xmass,ymass,delp1,KRD)
723
C
724
725
      if(fill) call qckxyz(DQ(1,1,1,IC),DC2,IMR,JNP,NLAY,j1,j2,
726
     &                     cosp,acosp,.false.,IC,NSTEP)
727
C
728
C Recover tracer mixing ratio from "density" using predicted
729
C "air density" (pressure thickness) at time-level n+1
730
C
731
      DO k=1,NLAY
732
      DO j=1,JNP
733
      DO i=1,IMR
734
            Q(i,j,k,IC) = DQ(i,j,k,IC) / delp2(i,j,k)
735
c            print*,'i=',i,'j=',j,'k=',k,'Q(i,j,k,IC)=',Q(i,j,k,IC)
736
      enddo
737
      enddo
738
      enddo
739
C
740
      if(j1.ne.2) then
741
      DO 400 k=1,NLAY
742
      DO 400 I=1,IMR
743
c     j=1 c'est le p�le Sud, j=JNP c'est le p�le Nord
744
      Q(I,  2,k,IC) = Q(I,  1,k,IC)
745
      Q(I,JMR,k,IC) = Q(I,JNP,k,IC)
746
400   CONTINUE
747
      endif
748
4000  continue
749
C
750
      if(j1.ne.2) then
751
      DO 5000 k=1,NLAY
752
      DO 5000 i=1,IMR
753
      W(i,  2,k) = W(i,  1,k)
754
      W(i,JMR,k) = W(i,JNP,k)
755
5000  continue
756
      endif
757
C
758
      RETURN
759
      END
760
C
761
C****6***0*********0*********0*********0*********0*********0**********72
762
      subroutine FZPPM(IMR,JNP,NLAY,j1,DQ,WZ,P,DC,DQDT,AR,AL,A6,
763
     &                 flux,wk1,wk2,wz2,delp,KORD)
764
      implicit none
765
      integer,parameter :: kmax = 150
766
      real,parameter :: R23 = 2./3., R3 = 1./3.
767
      integer IMR,JNP,NLAY,J1,KORD
768
      real WZ(IMR,JNP,NLAY),P(IMR,JNP,NLAY),DC(IMR,JNP,NLAY),
769
     &     wk1(IMR,*),delp(IMR,JNP,NLAY),DQ(IMR,JNP,NLAY),
770
     &     DQDT(IMR,JNP,NLAY)
771
C Assuming JNP >= NLAY
772
      real AR(IMR,*),AL(IMR,*),A6(IMR,*),flux(IMR,*),wk2(IMR,*),
773
     &     wz2(IMR,*)
774
      integer JMR,IMJM,NLAYM1,LMT,K,I,J
775
      real c0,c1,c2,tmp,qmax,qmin,a,b,fct,a1,a2,cm,cp
776
C
777
      JMR = JNP - 1
778
      IMJM = IMR*JNP
779
      NLAYM1 = NLAY - 1
780
C
781
      LMT = KORD - 3
782
C
783
C ****6***0*********0*********0*********0*********0*********0**********72
784
C Compute DC for PPM
785
C ****6***0*********0*********0*********0*********0*********0**********72
786
C
787
      do 1000 k=1,NLAYM1
788
      do 1000 i=1,IMJM
789
      DQDT(i,1,k) = P(i,1,k+1) - P(i,1,k)
790
1000  continue
791
C
792
      DO 1220 k=2,NLAYM1
793
      DO 1220 I=1,IMJM
794
       c0 =  delp(i,1,k) / (delp(i,1,k-1)+delp(i,1,k)+delp(i,1,k+1))
795
       c1 = (delp(i,1,k-1)+0.5*delp(i,1,k))/(delp(i,1,k+1)+delp(i,1,k))
796
       c2 = (delp(i,1,k+1)+0.5*delp(i,1,k))/(delp(i,1,k-1)+delp(i,1,k))
797
      tmp = c0*(c1*DQDT(i,1,k) + c2*DQDT(i,1,k-1))
798
      Qmax = max(P(i,1,k-1),P(i,1,k),P(i,1,k+1)) - P(i,1,k)
799
      Qmin = P(i,1,k) - min(P(i,1,k-1),P(i,1,k),P(i,1,k+1))
800
      DC(i,1,k) = sign(min(abs(tmp),Qmax,Qmin), tmp)
801
1220  CONTINUE
802
803
C
804
C ****6***0*********0*********0*********0*********0*********0**********72
805
C Loop over latitudes  (to save memory)
806
C ****6***0*********0*********0*********0*********0*********0**********72
807
C
808
      DO 2000 j=1,JNP
809
      if((j.eq.2 .or. j.eq.JMR) .and. j1.ne.2) goto 2000
810
C
811
      DO k=1,NLAY
812
      DO i=1,IMR
813
      wz2(i,k) =   WZ(i,j,k)
814
      wk1(i,k) =    P(i,j,k)
815
      wk2(i,k) = delp(i,j,k)
816
      flux(i,k) = DC(i,j,k)  !this flux is actually the monotone slope
817
      enddo
818
      enddo
819
C
820
C****6***0*********0*********0*********0*********0*********0**********72
821
C Compute first guesses at cell interfaces
822
C First guesses are required to be continuous.
823
C ****6***0*********0*********0*********0*********0*********0**********72
824
C
825
C three-cell parabolic subgrid distribution at model top
826
C two-cell parabolic with zero gradient subgrid distribution
827
C at the surface.
828
C
829
C First guess top edge value
830
      DO 10 i=1,IMR
831
C three-cell PPM
832
C Compute a,b, and c of q = aP**2 + bP + c using cell averages and delp
833
      a = 3.*( DQDT(i,j,2) - DQDT(i,j,1)*(wk2(i,2)+wk2(i,3))/
834
     &         (wk2(i,1)+wk2(i,2)) ) /
835
     &       ( (wk2(i,2)+wk2(i,3))*(wk2(i,1)+wk2(i,2)+wk2(i,3)) )
836
      b = 2.*DQDT(i,j,1)/(wk2(i,1)+wk2(i,2)) -
837
     &    R23*a*(2.*wk2(i,1)+wk2(i,2))
838
      AL(i,1) =  wk1(i,1) - wk2(i,1)*(R3*a*wk2(i,1) + 0.5*b)
839
      AL(i,2) =  wk2(i,1)*(a*wk2(i,1) + b) + AL(i,1)
840
C
841
C Check if change sign
842
      if(wk1(i,1)*AL(i,1).le.0.) then
843
		 AL(i,1) = 0.
844
             flux(i,1) = 0.
845
	else
846
             flux(i,1) =  wk1(i,1) - AL(i,1)
847
	endif
848
10    continue
849
C
850
C Bottom
851
      DO 15 i=1,IMR
852
C 2-cell PPM with zero gradient right at the surface
853
C
854
      fct = DQDT(i,j,NLAYM1)*wk2(i,NLAY)**2 /
855
     & ( (wk2(i,NLAY)+wk2(i,NLAYM1))*(2.*wk2(i,NLAY)+wk2(i,NLAYM1)))
856
      AR(i,NLAY) = wk1(i,NLAY) + fct
857
      AL(i,NLAY) = wk1(i,NLAY) - (fct+fct)
858
      if(wk1(i,NLAY)*AR(i,NLAY).le.0.) AR(i,NLAY) = 0.
859
      flux(i,NLAY) = AR(i,NLAY) -  wk1(i,NLAY)
860
15    continue
861
862
C
863
C****6***0*********0*********0*********0*********0*********0**********72
864
C 4th order interpolation in the interior.
865
C****6***0*********0*********0*********0*********0*********0**********72
866
C
867
      DO 14 k=3,NLAYM1
868
      DO 12 i=1,IMR
869
      c1 =  DQDT(i,j,k-1)*wk2(i,k-1) / (wk2(i,k-1)+wk2(i,k))
870
      c2 =  2. / (wk2(i,k-2)+wk2(i,k-1)+wk2(i,k)+wk2(i,k+1))
871
      A1   =  (wk2(i,k-2)+wk2(i,k-1)) / (2.*wk2(i,k-1)+wk2(i,k))
872
      A2   =  (wk2(i,k  )+wk2(i,k+1)) / (2.*wk2(i,k)+wk2(i,k-1))
873
      AL(i,k) = wk1(i,k-1) + c1 + c2 *
874
     &        ( wk2(i,k  )*(c1*(A1 - A2)+A2*flux(i,k-1)) -
875
     &          wk2(i,k-1)*A1*flux(i,k)  )
876
C      print *,'AL1',i,k, AL(i,k)
877
12    CONTINUE
878
14    continue
879
C
880
      do 20 i=1,IMR*NLAYM1
881
      AR(i,1) = AL(i,2)
882
C      print *,'AR1',i,AR(i,1)
883
20    continue
884
C
885
      do 30 i=1,IMR*NLAY
886
      A6(i,1) = 3.*(wk1(i,1)+wk1(i,1) - (AL(i,1)+AR(i,1)))
887
C      print *,'A61',i,A6(i,1)
888
30    continue
889
C
890
C****6***0*********0*********0*********0*********0*********0**********72
891
C Top & Bot always monotonic
892
      call lmtppm(flux(1,1),A6(1,1),AR(1,1),AL(1,1),wk1(1,1),IMR,0)
893
      call lmtppm(flux(1,NLAY),A6(1,NLAY),AR(1,NLAY),AL(1,NLAY),
894
     &            wk1(1,NLAY),IMR,0)
895
C
896
C Interior depending on KORD
897
      if(LMT.LE.2)
898
     &  call lmtppm(flux(1,2),A6(1,2),AR(1,2),AL(1,2),wk1(1,2),
899
     &              IMR*(NLAY-2),LMT)
900
C
901
C****6***0*********0*********0*********0*********0*********0**********72
902
C
903
      DO 140 i=1,IMR*NLAYM1
904
      IF(wz2(i,1).GT.0.) then
905
        CM = wz2(i,1) / wk2(i,1)
906
        flux(i,2) = AR(i,1)+0.5*CM*(AL(i,1)-AR(i,1)+A6(i,1)*(1.-R23*CM))
907
      else
908
C        print *,'test2-0',i,j,wz2(i,1),wk2(i,2)
909
        CP= wz2(i,1) / wk2(i,2)
910
C        print *,'testCP',CP
911
        flux(i,2) = AL(i,2)+0.5*CP*(AL(i,2)-AR(i,2)-A6(i,2)*(1.+R23*CP))
912
C        print *,'test2',i, AL(i,2),AR(i,2),A6(i,2),R23
913
      endif
914
140   continue
915
C
916
      DO 250 i=1,IMR*NLAYM1
917
      flux(i,2) = wz2(i,1) * flux(i,2)
918
250   continue
919
C
920
      do 350 i=1,IMR
921
      DQ(i,j,   1) = DQ(i,j,   1) - flux(i,   2)
922
      DQ(i,j,NLAY) = DQ(i,j,NLAY) + flux(i,NLAY)
923
350   continue
924
C
925
      do 360 k=2,NLAYM1
926
      do 360 i=1,IMR
927
360   DQ(i,j,k) = DQ(i,j,k) + flux(i,k) - flux(i,k+1)
928
2000  continue
929
      return
930
      end
931
C
932
      subroutine xtp(IMR,JNP,IML,j1,j2,JN,JS,PU,DQ,Q,UC,
933
     &               fx1,xmass,IORD)
934
      implicit none
935
      integer IMR,JNP,IML,j1,j2,JN,JS,IORD
936
      real PU,DQ,Q,UC,fx1,xmass
937
      real dc,qtmp
938
      integer ISAVE(IMR)
939
      dimension UC(IMR,*),DC(-IML:IMR+IML+1),xmass(IMR,JNP)
940
     &    ,fx1(IMR+1),DQ(IMR,JNP),qtmp(-IML:IMR+1+IML)
941
      dimension PU(IMR,JNP),Q(IMR,JNP)
942
      integer jvan,j1vl,j2vl,j,i,iu,itmp,ist,imp
943
      real rut
944
C
945
      IMP = IMR + 1
946
C
947
C van Leer at high latitudes
948
      jvan = max(1,JNP/18)
949
      j1vl = j1+jvan
950
      j2vl = j2-jvan
951
C
952
      do 1310 j=j1,j2
953
C
954
      do i=1,IMR
955
      qtmp(i) = q(i,j)
956
      enddo
957
C
958
      if(j.ge.JN .or. j.le.JS) goto 2222
959
C ************* Eulerian **********
960
C
961
      qtmp(0)     = q(IMR,J)
962
      qtmp(-1)    = q(IMR-1,J)
963
      qtmp(IMP)   = q(1,J)
964
      qtmp(IMP+1) = q(2,J)
965
C
966
      IF(IORD.eq.1 .or. j.eq.j1. or. j.eq.j2) THEN
967
      DO 1406 i=1,IMR
968
      iu = REAL(i) - uc(i,j)
969
1406  fx1(i) = qtmp(iu)
970
      ELSE
971
      call xmist(IMR,IML,Qtmp,DC)
972
      DC(0) = DC(IMR)
973
C
974
      if(IORD.eq.2 .or. j.le.j1vl .or. j.ge.j2vl) then
975
      DO 1408 i=1,IMR
976
      iu = REAL(i) - uc(i,j)
977
1408  fx1(i) = qtmp(iu) + DC(iu)*(sign(1.,uc(i,j))-uc(i,j))
978
      else
979
      call fxppm(IMR,IML,UC(1,j),Qtmp,DC,fx1,IORD)
980
      endif
981
C
982
      ENDIF
983
C
984
      DO 1506 i=1,IMR
985
1506  fx1(i) = fx1(i)*xmass(i,j)
986
C
987
      goto 1309
988
C
989
C ***** Conservative (flux-form) Semi-Lagrangian transport *****
990
C
991
2222  continue
992
C
993
      do i=-IML,0
994
      qtmp(i)     = q(IMR+i,j)
995
      qtmp(IMP-i) = q(1-i,j)
996
      enddo
997
C
998
      IF(IORD.eq.1 .or. j.eq.j1. or. j.eq.j2) THEN
999
      DO 1306 i=1,IMR
1000
      itmp = INT(uc(i,j))
1001
      ISAVE(i) = i - itmp
1002
      iu = i - uc(i,j)
1003
1306  fx1(i) = (uc(i,j) - itmp)*qtmp(iu)
1004
      ELSE
1005
      call xmist(IMR,IML,Qtmp,DC)
1006
C
1007
      do i=-IML,0
1008
      DC(i)     = DC(IMR+i)
1009
      DC(IMP-i) = DC(1-i)
1010
      enddo
1011
C
1012
      DO 1307 i=1,IMR
1013
      itmp = INT(uc(i,j))
1014
      rut  = uc(i,j) - itmp
1015
      ISAVE(i) = i - itmp
1016
      iu = i - uc(i,j)
1017
1307  fx1(i) = rut*(qtmp(iu) + DC(iu)*(sign(1.,rut) - rut))
1018
      ENDIF
1019
C
1020
      do 1308 i=1,IMR
1021
      IF(uc(i,j).GT.1.) then
1022
CDIR$ NOVECTOR
1023
        do ist = ISAVE(i),i-1
1024
        fx1(i) = fx1(i) + qtmp(ist)
1025
        enddo
1026
      elseIF(uc(i,j).LT.-1.) then
1027
        do ist = i,ISAVE(i)-1
1028
        fx1(i) = fx1(i) - qtmp(ist)
1029
        enddo
1030
CDIR$ VECTOR
1031
      endif
1032
1308  continue
1033
      do i=1,IMR
1034
      fx1(i) = PU(i,j)*fx1(i)
1035
      enddo
1036
C
1037
C ***************************************
1038
C
1039
1309  fx1(IMP) = fx1(1)
1040
      DO 1215 i=1,IMR
1041
1215  DQ(i,j) =  DQ(i,j) + fx1(i)-fx1(i+1)
1042
C
1043
C ***************************************
1044
C
1045
1310  continue
1046
      return
1047
      end
1048
C
1049
      subroutine fxppm(IMR,IML,UT,P,DC,flux,IORD)
1050
      implicit none
1051
      integer IMR,IML,IORD
1052
      real UT,P,DC,flux
1053
      real,parameter ::  R3 = 1./3., R23 = 2./3.
1054
      DIMENSION UT(*),flux(*),P(-IML:IMR+IML+1),DC(-IML:IMR+IML+1)
1055
      REAL :: AR(0:IMR),AL(0:IMR),A6(0:IMR)
1056
      integer LMT,IMP,JLVL,i
1057
c      logical first
1058
c      data first /.true./
1059
c      SAVE LMT
1060
c      if(first) then
1061
C
1062
C correction calcul de LMT a chaque passage pour pouvoir choisir
1063
c plusieurs schemas PPM pour differents traceurs
1064
c      IF (IORD.LE.0) then
1065
c            if(IMR.GE.144) then
1066
c                  LMT = 0
1067
c            elseif(IMR.GE.72) then
1068
c                  LMT = 1
1069
c            else
1070
c                  LMT = 2
1071
c            endif
1072
c      else
1073
c            LMT = IORD - 3
1074
c      endif
1075
C
1076
      LMT = IORD - 3
1077
c      write(6,*) 'PPM option in E-W direction = ', LMT
1078
c      first = .false.
1079
C      endif
1080
C
1081
      DO 10 i=1,IMR
1082
10    AL(i) = 0.5*(p(i-1)+p(i)) + (DC(i-1) - DC(i))*R3
1083
C
1084
      do 20 i=1,IMR-1
1085
20    AR(i) = AL(i+1)
1086
      AR(IMR) = AL(1)
1087
C
1088
      do 30 i=1,IMR
1089
30    A6(i) = 3.*(p(i)+p(i)  - (AL(i)+AR(i)))
1090
C
1091
      if(LMT.LE.2) call lmtppm(DC(1),A6(1),AR(1),AL(1),P(1),IMR,LMT)
1092
C
1093
      AL(0) = AL(IMR)
1094
      AR(0) = AR(IMR)
1095
      A6(0) = A6(IMR)
1096
C
1097
      DO i=1,IMR
1098
      IF(UT(i).GT.0.) then
1099
      flux(i) = AR(i-1) + 0.5*UT(i)*(AL(i-1) - AR(i-1) +
1100
     &                 A6(i-1)*(1.-R23*UT(i)) )
1101
      else
1102
      flux(i) = AL(i) - 0.5*UT(i)*(AR(i) - AL(i) +
1103
     &                        A6(i)*(1.+R23*UT(i)))
1104
      endif
1105
      enddo
1106
      return
1107
      end
1108
C
1109
      subroutine xmist(IMR,IML,P,DC)
1110
      implicit none
1111
      integer IMR,IML
1112
      real,parameter :: R24 = 1./24.
1113
      real :: P(-IML:IMR+1+IML),DC(-IML:IMR+1+IML)
1114
      integer :: i
1115
      real :: tmp,pmax,pmin
1116
C
1117
      do 10  i=1,IMR
1118
      tmp = R24*(8.*(p(i+1) - p(i-1)) + p(i-2) - p(i+2))
1119
      Pmax = max(P(i-1), p(i), p(i+1)) - p(i)
1120
      Pmin = p(i) - min(P(i-1), p(i), p(i+1))
1121
10    DC(i) = sign(min(abs(tmp),Pmax,Pmin), tmp)
1122
      return
1123
      end
1124
C
1125
      subroutine ytp(IMR,JNP,j1,j2,acosp,RCAP,DQ,P,VC,DC2
1126
     &              ,ymass,fx,A6,AR,AL,JORD)
1127
      implicit none
1128
      integer :: IMR,JNP,j1,j2,JORD
1129
      real :: acosp,RCAP,DQ,P,VC,DC2,ymass,fx,A6,AR,AL
1130
      dimension P(IMR,JNP),VC(IMR,JNP),ymass(IMR,JNP)
1131
     &       ,DC2(IMR,JNP),DQ(IMR,JNP),acosp(JNP)
1132
C Work array
1133
      DIMENSION fx(IMR,JNP),AR(IMR,JNP),AL(IMR,JNP),A6(IMR,JNP)
1134
      integer :: JMR,len,i,jt,j
1135
      real :: sum1,sum2
1136
C
1137
      JMR = JNP - 1
1138
      len = IMR*(J2-J1+2)
1139
C
1140
      if(JORD.eq.1) then
1141
      DO 1000 i=1,len
1142
      JT = REAL(J1) - VC(i,J1)
1143
1000  fx(i,j1) = p(i,JT)
1144
      else
1145
1146
      call ymist(IMR,JNP,j1,P,DC2,4)
1147
C
1148
      if(JORD.LE.0 .or. JORD.GE.3) then
1149
1150
      call fyppm(VC,P,DC2,fx,IMR,JNP,j1,j2,A6,AR,AL,JORD)
1151
1152
      else
1153
      DO 1200 i=1,len
1154
      JT = REAL(J1) - VC(i,J1)
1155
1200  fx(i,j1) = p(i,JT) + (sign(1.,VC(i,j1))-VC(i,j1))*DC2(i,JT)
1156
      endif
1157
      endif
1158
C
1159
      DO 1300 i=1,len
1160
1300  fx(i,j1) = fx(i,j1)*ymass(i,j1)
1161
C
1162
      DO 1400 j=j1,j2
1163
      DO 1400 i=1,IMR
1164
1400  DQ(i,j) = DQ(i,j) + (fx(i,j) - fx(i,j+1)) * acosp(j)
1165
C
1166
C Poles
1167
      sum1 = fx(IMR,j1  )
1168
      sum2 = fx(IMR,J2+1)
1169
      do i=1,IMR-1
1170
      sum1 = sum1 + fx(i,j1  )
1171
      sum2 = sum2 + fx(i,J2+1)
1172
      enddo
1173
C
1174
      sum1 = DQ(1,  1) - sum1 * RCAP
1175
      sum2 = DQ(1,JNP) + sum2 * RCAP
1176
      do i=1,IMR
1177
      DQ(i,  1) = sum1
1178
      DQ(i,JNP) = sum2
1179
      enddo
1180
C
1181
      if(j1.ne.2) then
1182
      do i=1,IMR
1183
      DQ(i,  2) = sum1
1184
      DQ(i,JMR) = sum2
1185
      enddo
1186
      endif
1187
C
1188
      return
1189
      end
1190
C
1191
      subroutine  ymist(IMR,JNP,j1,P,DC,ID)
1192
      implicit none
1193
      integer :: IMR,JNP,j1,ID
1194
      real,parameter :: R24 = 1./24.
1195
      real :: P(IMR,JNP),DC(IMR,JNP)
1196
      integer :: iimh,jmr,ijm3,imh,i
1197
      real :: pmax,pmin,tmp
1198
C
1199
      IMH = IMR / 2
1200
      JMR = JNP - 1
1201
      IJM3 = IMR*(JMR-3)
1202
C
1203
      IF(ID.EQ.2) THEN
1204
      do 10 i=1,IMR*(JMR-1)
1205
      tmp = 0.25*(p(i,3) - p(i,1))
1206
      Pmax = max(p(i,1),p(i,2),p(i,3)) - p(i,2)
1207
      Pmin = p(i,2) - min(p(i,1),p(i,2),p(i,3))
1208
      DC(i,2) = sign(min(abs(tmp),Pmin,Pmax),tmp)
1209
10    CONTINUE
1210
      ELSE
1211
      do 12 i=1,IMH
1212
C J=2
1213
      tmp = (8.*(p(i,3) - p(i,1)) + p(i+IMH,2) - p(i,4))*R24
1214
      Pmax = max(p(i,1),p(i,2),p(i,3)) - p(i,2)
1215
      Pmin = p(i,2) - min(p(i,1),p(i,2),p(i,3))
1216
      DC(i,2) = sign(min(abs(tmp),Pmin,Pmax),tmp)
1217
C J=JMR
1218
      tmp=(8.*(p(i,JNP)-p(i,JMR-1))+p(i,JMR-2)-p(i+IMH,JMR))*R24
1219
      Pmax = max(p(i,JMR-1),p(i,JMR),p(i,JNP)) - p(i,JMR)
1220
      Pmin = p(i,JMR) - min(p(i,JMR-1),p(i,JMR),p(i,JNP))
1221
      DC(i,JMR) = sign(min(abs(tmp),Pmin,Pmax),tmp)
1222
12    CONTINUE
1223
      do 14 i=IMH+1,IMR
1224
C J=2
1225
      tmp = (8.*(p(i,3) - p(i,1)) + p(i-IMH,2) - p(i,4))*R24
1226
      Pmax = max(p(i,1),p(i,2),p(i,3)) - p(i,2)
1227
      Pmin = p(i,2) - min(p(i,1),p(i,2),p(i,3))
1228
      DC(i,2) = sign(min(abs(tmp),Pmin,Pmax),tmp)
1229
C J=JMR
1230
      tmp=(8.*(p(i,JNP)-p(i,JMR-1))+p(i,JMR-2)-p(i-IMH,JMR))*R24
1231
      Pmax = max(p(i,JMR-1),p(i,JMR),p(i,JNP)) - p(i,JMR)
1232
      Pmin = p(i,JMR) - min(p(i,JMR-1),p(i,JMR),p(i,JNP))
1233
      DC(i,JMR) = sign(min(abs(tmp),Pmin,Pmax),tmp)
1234
14    CONTINUE
1235
C
1236
      do 15 i=1,IJM3
1237
      tmp = (8.*(p(i,4) - p(i,2)) + p(i,1) - p(i,5))*R24
1238
      Pmax = max(p(i,2),p(i,3),p(i,4)) - p(i,3)
1239
      Pmin = p(i,3) - min(p(i,2),p(i,3),p(i,4))
1240
      DC(i,3) = sign(min(abs(tmp),Pmin,Pmax),tmp)
1241
15    CONTINUE
1242
      ENDIF
1243
C
1244
      if(j1.ne.2) then
1245
      do i=1,IMR
1246
      DC(i,1) = 0.
1247
      DC(i,JNP) = 0.
1248
      enddo
1249
      else
1250
C Determine slopes in polar caps for scalars!
1251
C
1252
      do 13 i=1,IMH
1253
C South
1254
      tmp = 0.25*(p(i,2) - p(i+imh,2))
1255
      Pmax = max(p(i,2),p(i,1), p(i+imh,2)) - p(i,1)
1256
      Pmin = p(i,1) - min(p(i,2),p(i,1), p(i+imh,2))
1257
      DC(i,1)=sign(min(abs(tmp),Pmax,Pmin),tmp)
1258
C North.
1259
      tmp = 0.25*(p(i+imh,JMR) - p(i,JMR))
1260
      Pmax = max(p(i+imh,JMR),p(i,jnp), p(i,JMR)) - p(i,JNP)
1261
      Pmin = p(i,JNP) - min(p(i+imh,JMR),p(i,jnp), p(i,JMR))
1262
      DC(i,JNP) = sign(min(abs(tmp),Pmax,pmin),tmp)
1263
13    continue
1264
C
1265
      do 25 i=imh+1,IMR
1266
      DC(i,  1) =  - DC(i-imh,  1)
1267
      DC(i,JNP) =  - DC(i-imh,JNP)
1268
25    continue
1269
      endif
1270
      return
1271
      end
1272
C
1273
      subroutine fyppm(VC,P,DC,flux,IMR,JNP,j1,j2,A6,AR,AL,JORD)
1274
      implicit none
1275
      integer IMR,JNP,j1,j2,JORD
1276
      real,parameter :: R3 = 1./3., R23 = 2./3.
1277
      real VC(IMR,*),flux(IMR,*),P(IMR,*),DC(IMR,*)
1278
C Local work arrays.
1279
      real AR(IMR,JNP),AL(IMR,JNP),A6(IMR,JNP)
1280
      integer LMT,i
1281
      integer IMH,JMR,j11,IMJM1,len
1282
c      logical first
1283
C      data first /.true./
1284
C      SAVE LMT
1285
C
1286
      IMH = IMR / 2
1287
      JMR = JNP - 1
1288
      j11 = j1-1
1289
      IMJM1 = IMR*(J2-J1+2)
1290
      len   = IMR*(J2-J1+3)
1291
C      if(first) then
1292
C      IF(JORD.LE.0) then
1293
C            if(JMR.GE.90) then
1294
C                  LMT = 0
1295
C            elseif(JMR.GE.45) then
1296
C                  LMT = 1
1297
C            else
1298
C                  LMT = 2
1299
C            endif
1300
C      else
1301
C            LMT = JORD - 3
1302
C      endif
1303
C
1304
C      first = .false.
1305
C      endif
1306
C
1307
c modifs pour pouvoir choisir plusieurs schemas PPM
1308
      LMT = JORD - 3
1309
C
1310
      DO 10 i=1,IMR*JMR
1311
      AL(i,2) = 0.5*(p(i,1)+p(i,2)) + (DC(i,1) - DC(i,2))*R3
1312
      AR(i,1) = AL(i,2)
1313
10    CONTINUE
1314
C
1315
CPoles:
1316
C
1317
      DO i=1,IMH
1318
      AL(i,1) = AL(i+IMH,2)
1319
      AL(i+IMH,1) = AL(i,2)
1320
C
1321
      AR(i,JNP) = AR(i+IMH,JMR)
1322
      AR(i+IMH,JNP) = AR(i,JMR)
1323
      ENDDO
1324
1325
ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
1326
c   Rajout pour LMDZ.3.3
1327
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
1328
      AR(IMR,1)=AL(1,1)
1329
      AR(IMR,JNP)=AL(1,JNP)
1330
ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
1331
1332
1333
      do 30 i=1,len
1334
30    A6(i,j11) = 3.*(p(i,j11)+p(i,j11)  - (AL(i,j11)+AR(i,j11)))
1335
C
1336
      if(LMT.le.2) call lmtppm(DC(1,j11),A6(1,j11),AR(1,j11)
1337
     &                       ,AL(1,j11),P(1,j11),len,LMT)
1338
C
1339
1340
      DO 140 i=1,IMJM1
1341
      IF(VC(i,j1).GT.0.) then
1342
      flux(i,j1) = AR(i,j11) + 0.5*VC(i,j1)*(AL(i,j11) - AR(i,j11) +
1343
     &                         A6(i,j11)*(1.-R23*VC(i,j1)) )
1344
      else
1345
      flux(i,j1) = AL(i,j1) - 0.5*VC(i,j1)*(AR(i,j1) - AL(i,j1) +
1346
     &                        A6(i,j1)*(1.+R23*VC(i,j1)))
1347
      endif
1348
140   continue
1349
      return
1350
      end
1351
C
1352
	subroutine yadv(IMR,JNP,j1,j2,p,VA,ady,wk,IAD)
1353
        implicit none
1354
        integer IMR,JNP,j1,j2,IAD
1355
	REAL p(IMR,JNP),ady(IMR,JNP),VA(IMR,JNP)
1356
        REAL WK(IMR,-1:JNP+2)
1357
        INTEGER JMR,IMH,i,j,jp
1358
        REAL rv,a1,b1,sum1,sum2
1359
C
1360
	JMR = JNP-1
1361
	IMH = IMR/2
1362
	do j=1,JNP
1363
	do i=1,IMR
1364
	wk(i,j) = p(i,j)
1365
	enddo
1366
	enddo
1367
C Poles:
1368
	do i=1,IMH
1369
	wk(i,   -1) = p(i+IMH,3)
1370
	wk(i+IMH,-1) = p(i,3)
1371
	wk(i,    0) = p(i+IMH,2)
1372
	wk(i+IMH,0) = p(i,2)
1373
	wk(i,JNP+1) = p(i+IMH,JMR)
1374
	wk(i+IMH,JNP+1) = p(i,JMR)
1375
	wk(i,JNP+2) = p(i+IMH,JNP-2)
1376
	wk(i+IMH,JNP+2) = p(i,JNP-2)
1377
	enddo
1378
c        write(*,*) 'toto 1'
1379
C --------------------------------
1380
      IF(IAD.eq.2) then
1381
      do j=j1-1,j2+1
1382
      do i=1,IMR
1383
c      write(*,*) 'avt NINT','i=',i,'j=',j
1384
      JP = NINT(VA(i,j))
1385
      rv = JP - VA(i,j)
1386
c      write(*,*) 'VA=',VA(i,j), 'JP1=',JP,'rv=',rv
1387
      JP = j - JP
1388
c      write(*,*) 'JP2=',JP
1389
      a1 = 0.5*(wk(i,jp+1)+wk(i,jp-1)) - wk(i,jp)
1390
      b1 = 0.5*(wk(i,jp+1)-wk(i,jp-1))
1391
c      write(*,*) 'a1=',a1,'b1=',b1
1392
      ady(i,j) = wk(i,jp) + rv*(a1*rv + b1) - wk(i,j)
1393
      enddo
1394
      enddo
1395
c      write(*,*) 'toto 2'
1396
C
1397
      ELSEIF(IAD.eq.1) then
1398
	do j=j1-1,j2+1
1399
      do i=1,imr
1400
      JP = REAL(j)-VA(i,j)
1401
      ady(i,j) = VA(i,j)*(wk(i,jp)-wk(i,jp+1))
1402
      enddo
1403
      enddo
1404
      ENDIF
1405
C
1406
	if(j1.ne.2) then
1407
	sum1 = 0.
1408
	sum2 = 0.
1409
      do i=1,imr
1410
      sum1 = sum1 + ady(i,2)
1411
      sum2 = sum2 + ady(i,JMR)
1412
      enddo
1413
	sum1 = sum1 / IMR
1414
	sum2 = sum2 / IMR
1415
C
1416
      do i=1,imr
1417
      ady(i,  2) =  sum1
1418
      ady(i,JMR) =  sum2
1419
      ady(i,  1) =  sum1
1420
      ady(i,JNP) =  sum2
1421
      enddo
1422
	else
1423
C Poles:
1424
	sum1 = 0.
1425
	sum2 = 0.
1426
      do i=1,imr
1427
      sum1 = sum1 + ady(i,1)
1428
      sum2 = sum2 + ady(i,JNP)
1429
      enddo
1430
	sum1 = sum1 / IMR
1431
	sum2 = sum2 / IMR
1432
C
1433
      do i=1,imr
1434
      ady(i,  1) =  sum1
1435
      ady(i,JNP) =  sum2
1436
      enddo
1437
	endif
1438
C
1439
	return
1440
	end
1441
C
1442
	subroutine xadv(IMR,JNP,j1,j2,p,UA,JS,JN,IML,adx,IAD)
1443
        implicit none
1444
        INTEGER IMR,JNP,j1,j2,JS,JN,IML,IAD
1445
	REAL p(IMR,JNP),adx(IMR,JNP),qtmp(-IMR:IMR+IMR),UA(IMR,JNP)
1446
        INTEGER JMR,j,i,ip,iu,iiu
1447
        REAL ru,a1,b1
1448
C
1449
	JMR = JNP-1
1450
      do 1309 j=j1,j2
1451
      if(J.GT.JS  .and. J.LT.JN) GO TO 1309
1452
C
1453
      do i=1,IMR
1454
      qtmp(i) = p(i,j)
1455
      enddo
1456
C
1457
      do i=-IML,0
1458
      qtmp(i)       = p(IMR+i,j)
1459
      qtmp(IMR+1-i) = p(1-i,j)
1460
      enddo
1461
C
1462
      IF(IAD.eq.2) THEN
1463
      DO i=1,IMR
1464
      IP = NINT(UA(i,j))
1465
      ru = IP - UA(i,j)
1466
      IP = i - IP
1467
      a1 = 0.5*(qtmp(ip+1)+qtmp(ip-1)) - qtmp(ip)
1468
      b1 = 0.5*(qtmp(ip+1)-qtmp(ip-1))
1469
      adx(i,j) = qtmp(ip) + ru*(a1*ru + b1)
1470
      enddo
1471
      ELSEIF(IAD.eq.1) then
1472
      DO i=1,IMR
1473
      iu = UA(i,j)
1474
      ru = UA(i,j) - iu
1475
      iiu = i-iu
1476
      if(UA(i,j).GE.0.) then
1477
      adx(i,j) = qtmp(iiu)+ru*(qtmp(iiu-1)-qtmp(iiu))
1478
      else
1479
      adx(i,j) = qtmp(iiu)+ru*(qtmp(iiu)-qtmp(iiu+1))
1480
      endif
1481
      enddo
1482
      ENDIF
1483
C
1484
      do i=1,IMR
1485
      adx(i,j) = adx(i,j) - p(i,j)
1486
      enddo
1487
1309  continue
1488
C
1489
C Eulerian upwind
1490
C
1491
      do j=JS+1,JN-1
1492
C
1493
      do i=1,IMR
1494
      qtmp(i) = p(i,j)
1495
      enddo
1496
C
1497
      qtmp(0)     = p(IMR,J)
1498
      qtmp(IMR+1) = p(1,J)
1499
C
1500
      IF(IAD.eq.2) THEN
1501
      qtmp(-1)     = p(IMR-1,J)
1502
      qtmp(IMR+2) = p(2,J)
1503
      do i=1,imr
1504
      IP = NINT(UA(i,j))
1505
      ru = IP - UA(i,j)
1506
      IP = i - IP
1507
      a1 = 0.5*(qtmp(ip+1)+qtmp(ip-1)) - qtmp(ip)
1508
      b1 = 0.5*(qtmp(ip+1)-qtmp(ip-1))
1509
      adx(i,j) = qtmp(ip)- p(i,j) + ru*(a1*ru + b1)
1510
      enddo
1511
      ELSEIF(IAD.eq.1) then
1512
C 1st order
1513
      DO i=1,IMR
1514
      IP = i - UA(i,j)
1515
      adx(i,j) = UA(i,j)*(qtmp(ip)-qtmp(ip+1))
1516
      enddo
1517
      ENDIF
1518
      enddo
1519
C
1520
	if(j1.ne.2) then
1521
      do i=1,IMR
1522
      adx(i,  2) = 0.
1523
      adx(i,JMR) = 0.
1524
      enddo
1525
	endif
1526
C set cross term due to x-adv at the poles to zero.
1527
      do i=1,IMR
1528
      adx(i,  1) = 0.
1529
      adx(i,JNP) = 0.
1530
      enddo
1531
	return
1532
	end
1533
C
1534
      subroutine lmtppm(DC,A6,AR,AL,P,IM,LMT)
1535
      implicit none
1536
C
1537
C A6 =  CURVATURE OF THE TEST PARABOLA
1538
C AR =  RIGHT EDGE VALUE OF THE TEST PARABOLA
1539
C AL =  LEFT  EDGE VALUE OF THE TEST PARABOLA
1540
C DC =  0.5 * MISMATCH
1541
C P  =  CELL-AVERAGED VALUE
1542
C IM =  VECTOR LENGTH
1543
C
1544
C OPTIONS:
1545
C
1546
C LMT = 0: FULL MONOTONICITY
1547
C LMT = 1: SEMI-MONOTONIC CONSTRAINT (NO UNDERSHOOTS)
1548
C LMT = 2: POSITIVE-DEFINITE CONSTRAINT
1549
C
1550
      real,parameter :: R12 = 1./12.
1551
      real :: A6(IM),AR(IM),AL(IM),P(IM),DC(IM)
1552
      integer :: IM,LMT
1553
      INTEGER i
1554
      REAL da1,da2,a6da,fmin
1555
C
1556
      if(LMT.eq.0) then
1557
C Full constraint
1558
      do 100 i=1,IM
1559
      if(DC(i).eq.0.) then
1560
            AR(i) = p(i)
1561
            AL(i) = p(i)
1562
            A6(i) = 0.
1563
      else
1564
      da1  = AR(i) - AL(i)
1565
      da2  = da1**2
1566
      A6DA = A6(i)*da1
1567
      if(A6DA .lt. -da2) then
1568
            A6(i) = 3.*(AL(i)-p(i))
1569
            AR(i) = AL(i) - A6(i)
1570
      elseif(A6DA .gt. da2) then
1571
            A6(i) = 3.*(AR(i)-p(i))
1572
            AL(i) = AR(i) - A6(i)
1573
      endif
1574
      endif
1575
100   continue
1576
      elseif(LMT.eq.1) then
1577
C Semi-monotonic constraint
1578
      do 150 i=1,IM
1579
      if(abs(AR(i)-AL(i)) .GE. -A6(i)) go to 150
1580
      if(p(i).lt.AR(i) .and. p(i).lt.AL(i)) then
1581
            AR(i) = p(i)
1582
            AL(i) = p(i)
1583
            A6(i) = 0.
1584
      elseif(AR(i) .gt. AL(i)) then
1585
            A6(i) = 3.*(AL(i)-p(i))
1586
            AR(i) = AL(i) - A6(i)
1587
      else
1588
            A6(i) = 3.*(AR(i)-p(i))
1589
            AL(i) = AR(i) - A6(i)
1590
      endif
1591
150   continue
1592
      elseif(LMT.eq.2) then
1593
      do 250 i=1,IM
1594
      if(abs(AR(i)-AL(i)) .GE. -A6(i)) go to 250
1595
      fmin = p(i) + 0.25*(AR(i)-AL(i))**2/A6(i) + A6(i)*R12
1596
      if(fmin.ge.0.) go to 250
1597
      if(p(i).lt.AR(i) .and. p(i).lt.AL(i)) then
1598
            AR(i) = p(i)
1599
            AL(i) = p(i)
1600
            A6(i) = 0.
1601
      elseif(AR(i) .gt. AL(i)) then
1602
            A6(i) = 3.*(AL(i)-p(i))
1603
            AR(i) = AL(i) - A6(i)
1604
      else
1605
            A6(i) = 3.*(AR(i)-p(i))
1606
            AL(i) = AR(i) - A6(i)
1607
      endif
1608
250   continue
1609
      endif
1610
      return
1611
      end
1612
C
1613
      subroutine A2C(U,V,IMR,JMR,j1,j2,CRX,CRY,dtdx5,DTDY5)
1614
      implicit none
1615
      integer IMR,JMR,j1,j2
1616
      real :: U(IMR,*),V(IMR,*),CRX(IMR,*),CRY(IMR,*),DTDX5(*),DTDY5
1617
      integer i,j
1618
C
1619
      do 35 j=j1,j2
1620
      do 35 i=2,IMR
1621
35    CRX(i,J) = dtdx5(j)*(U(i,j)+U(i-1,j))
1622
C
1623
      do 45 j=j1,j2
1624
45    CRX(1,J) = dtdx5(j)*(U(1,j)+U(IMR,j))
1625
C
1626
      do 55 i=1,IMR*JMR
1627
55    CRY(i,2) = DTDY5*(V(i,2)+V(i,1))
1628
      return
1629
      end
1630
C
1631
      subroutine cosa(cosp,cose,JNP,PI,DP)
1632
      implicit none
1633
      integer JNP
1634
      real :: cosp(*),cose(*),PI,DP
1635
      integer JMR,j,jeq
1636
      real ph5
1637
      JMR = JNP-1
1638
      do 55 j=2,JNP
1639
        ph5  =  -0.5*PI + (REAL(J-1)-0.5)*DP
1640
55      cose(j) = cos(ph5)
1641
C
1642
      JEQ = (JNP+1) / 2
1643
      if(JMR .eq. 2*(JMR/2) ) then
1644
      do j=JNP, JEQ+1, -1
1645
       cose(j) =  cose(JNP+2-j)
1646
      enddo
1647
      else
1648
C cell edge at equator.
1649
       cose(JEQ+1) =  1.
1650
      do j=JNP, JEQ+2, -1
1651
       cose(j) =  cose(JNP+2-j)
1652
       enddo
1653
      endif
1654
C
1655
      do 66 j=2,JMR
1656
66    cosp(j) = 0.5*(cose(j)+cose(j+1))
1657
      cosp(1) = 0.
1658
      cosp(JNP) = 0.
1659
      return
1660
      end
1661
C
1662
      subroutine cosc(cosp,cose,JNP,PI,DP)
1663
      implicit none
1664
      integer JNP
1665
      real :: cosp(*),cose(*),PI,DP
1666
      real phi
1667
      integer j
1668
C
1669
      phi = -0.5*PI
1670
      do 55 j=2,JNP-1
1671
      phi  =  phi + DP
1672
55    cosp(j) = cos(phi)
1673
        cosp(  1) = 0.
1674
        cosp(JNP) = 0.
1675
C
1676
      do 66 j=2,JNP
1677
        cose(j) = 0.5*(cosp(j)+cosp(j-1))
1678
66    CONTINUE
1679
C
1680
      do 77 j=2,JNP-1
1681
       cosp(j) = 0.5*(cose(j)+cose(j+1))
1682
77    CONTINUE
1683
      return
1684
      end
1685
C
1686
      SUBROUTINE qckxyz (Q,qtmp,IMR,JNP,NLAY,j1,j2,cosp,acosp,
1687
     &                   cross,IC,NSTEP)
1688
C
1689
      real,parameter :: tiny = 1.E-60
1690
      INTEGER :: IMR,JNP,NLAY,j1,j2,IC,NSTEP
1691
      REAL :: Q(IMR,JNP,NLAY),qtmp(IMR,JNP),cosp(*),acosp(*)
1692
      logical cross
1693
      INTEGER :: NLAYM1,len,ip,L,icr,ipy,ipx,i
1694
      real :: qup,qly,dup,sum
1695
C
1696
      NLAYM1 = NLAY-1
1697
      len = IMR*(j2-j1+1)
1698
      ip = 0
1699
C
1700
C Top layer
1701
      L = 1
1702
	icr = 1
1703
      call filns(q(1,1,L),IMR,JNP,j1,j2,cosp,acosp,ipy,tiny)
1704
      if(ipy.eq.0) goto 50
1705
      call filew(q(1,1,L),qtmp,IMR,JNP,j1,j2,ipx,tiny)
1706
      if(ipx.eq.0) goto 50
1707
C
1708
      if(cross) then
1709
      call filcr(q(1,1,L),IMR,JNP,j1,j2,cosp,acosp,icr,tiny)
1710
      endif
1711
      if(icr.eq.0) goto 50
1712
C
1713
C Vertical filling...
1714
      do i=1,len
1715
      IF( Q(i,j1,1).LT.0.) THEN
1716
      ip = ip + 1
1717
          Q(i,j1,2) = Q(i,j1,2) + Q(i,j1,1)
1718
          Q(i,j1,1) = 0.
1719
      endif
1720
      enddo
1721
C
1722
50    continue
1723
      DO 225 L = 2,NLAYM1
1724
      icr = 1
1725
C
1726
      call filns(q(1,1,L),IMR,JNP,j1,j2,cosp,acosp,ipy,tiny)
1727
      if(ipy.eq.0) goto 225
1728
      call filew(q(1,1,L),qtmp,IMR,JNP,j1,j2,ipx,tiny)
1729
      if(ipx.eq.0) go to 225
1730
      if(cross) then
1731
      call filcr(q(1,1,L),IMR,JNP,j1,j2,cosp,acosp,icr,tiny)
1732
      endif
1733
      if(icr.eq.0) goto 225
1734
C
1735
      do i=1,len
1736
      IF( Q(I,j1,L).LT.0.) THEN
1737
C
1738
      ip = ip + 1
1739
C From above
1740
          qup =  Q(I,j1,L-1)
1741
          qly = -Q(I,j1,L)
1742
          dup  = min(qly,qup)
1743
          Q(I,j1,L-1) = qup - dup
1744
          Q(I,j1,L  ) = dup-qly
1745
C Below
1746
          Q(I,j1,L+1) = Q(I,j1,L+1) + Q(I,j1,L)
1747
          Q(I,j1,L)   = 0.
1748
      ENDIF
1749
      ENDDO
1750
225   CONTINUE
1751
C
1752
C BOTTOM LAYER
1753
      sum = 0.
1754
      L = NLAY
1755
C
1756
      call filns(q(1,1,L),IMR,JNP,j1,j2,cosp,acosp,ipy,tiny)
1757
      if(ipy.eq.0) goto 911
1758
      call filew(q(1,1,L),qtmp,IMR,JNP,j1,j2,ipx,tiny)
1759
      if(ipx.eq.0) goto 911
1760
C
1761
      call filcr(q(1,1,L),IMR,JNP,j1,j2,cosp,acosp,icr,tiny)
1762
      if(icr.eq.0) goto 911
1763
C
1764
      DO  I=1,len
1765
      IF( Q(I,j1,L).LT.0.) THEN
1766
      ip = ip + 1
1767
c
1768
C From above
1769
C
1770
          qup = Q(I,j1,NLAYM1)
1771
          qly = -Q(I,j1,L)
1772
          dup = min(qly,qup)
1773
          Q(I,j1,NLAYM1) = qup - dup
1774
C From "below" the surface.
1775
          sum = sum + qly-dup
1776
          Q(I,j1,L) = 0.
1777
       ENDIF
1778
      ENDDO
1779
C
1780
911   continue
1781
C
1782
      if(ip.gt.IMR) then
1783
      write(6,*) 'IC=',IC,' STEP=',NSTEP,
1784
     &           ' Vertical filling pts=',ip
1785
      endif
1786
C
1787
      if(sum.gt.1.e-25) then
1788
      write(6,*) IC,NSTEP,' Mass source from the ground=',sum
1789
      endif
1790
      RETURN
1791
      END
1792
C
1793
      subroutine filcr(q,IMR,JNP,j1,j2,cosp,acosp,icr,tiny)
1794
      implicit none
1795
      integer :: IMR,JNP,j1,j2,icr
1796
      real :: q(IMR,*),cosp(*),acosp(*),tiny
1797
      integer :: i,j
1798
      real :: dq,dn,d0,d1,ds,d2
1799
      icr = 0
1800
      do 65 j=j1+1,j2-1
1801
      DO 50 i=1,IMR-1
1802
      IF(q(i,j).LT.0.) THEN
1803
      icr =  1
1804
      dq  = - q(i,j)*cosp(j)
1805
C N-E
1806
      dn = q(i+1,j+1)*cosp(j+1)
1807
      d0 = max(0.,dn)
1808
      d1 = min(dq,d0)
1809
      q(i+1,j+1) = (dn - d1)*acosp(j+1)
1810
      dq = dq - d1
1811
C S-E
1812
      ds = q(i+1,j-1)*cosp(j-1)
1813
      d0 = max(0.,ds)
1814
      d2 = min(dq,d0)
1815
      q(i+1,j-1) = (ds - d2)*acosp(j-1)
1816
      q(i,j) = (d2 - dq)*acosp(j) + tiny
1817
      endif
1818
50    continue
1819
      if(icr.eq.0 .and. q(IMR,j).ge.0.) goto 65
1820
      DO 55 i=2,IMR
1821
      IF(q(i,j).LT.0.) THEN
1822
      icr =  1
1823
      dq  = - q(i,j)*cosp(j)
1824
C N-W
1825
      dn = q(i-1,j+1)*cosp(j+1)
1826
      d0 = max(0.,dn)
1827
      d1 = min(dq,d0)
1828
      q(i-1,j+1) = (dn - d1)*acosp(j+1)
1829
      dq = dq - d1
1830
C S-W
1831
      ds = q(i-1,j-1)*cosp(j-1)
1832
      d0 = max(0.,ds)
1833
      d2 = min(dq,d0)
1834
      q(i-1,j-1) = (ds - d2)*acosp(j-1)
1835
      q(i,j) = (d2 - dq)*acosp(j) + tiny
1836
      endif
1837
55    continue
1838
C *****************************************
1839
C i=1
1840
      i=1
1841
      IF(q(i,j).LT.0.) THEN
1842
      icr =  1
1843
      dq  = - q(i,j)*cosp(j)
1844
C N-W
1845
      dn = q(IMR,j+1)*cosp(j+1)
1846
      d0 = max(0.,dn)
1847
      d1 = min(dq,d0)
1848
      q(IMR,j+1) = (dn - d1)*acosp(j+1)
1849
      dq = dq - d1
1850
C S-W
1851
      ds = q(IMR,j-1)*cosp(j-1)
1852
      d0 = max(0.,ds)
1853
      d2 = min(dq,d0)
1854
      q(IMR,j-1) = (ds - d2)*acosp(j-1)
1855
      q(i,j) = (d2 - dq)*acosp(j) + tiny
1856
      endif
1857
C *****************************************
1858
C i=IMR
1859
      i=IMR
1860
      IF(q(i,j).LT.0.) THEN
1861
      icr =  1
1862
      dq  = - q(i,j)*cosp(j)
1863
C N-E
1864
      dn = q(1,j+1)*cosp(j+1)
1865
      d0 = max(0.,dn)
1866
      d1 = min(dq,d0)
1867
      q(1,j+1) = (dn - d1)*acosp(j+1)
1868
      dq = dq - d1
1869
C S-E
1870
      ds = q(1,j-1)*cosp(j-1)
1871
      d0 = max(0.,ds)
1872
      d2 = min(dq,d0)
1873
      q(1,j-1) = (ds - d2)*acosp(j-1)
1874
      q(i,j) = (d2 - dq)*acosp(j) + tiny
1875
      endif
1876
C *****************************************
1877
65    continue
1878
C
1879
      do i=1,IMR
1880
      if(q(i,j1).lt.0. .or. q(i,j2).lt.0.) then
1881
      icr = 1
1882
      goto 80
1883
      endif
1884
      enddo
1885
C
1886
80    continue
1887
C
1888
      if(q(1,1).lt.0. .or. q(1,jnp).lt.0.) then
1889
      icr = 1
1890
      endif
1891
C
1892
      return
1893
      end
1894
C
1895
      subroutine filns(q,IMR,JNP,j1,j2,cosp,acosp,ipy,tiny)
1896
      implicit none
1897
      integer :: IMR,JNP,j1,j2,ipy
1898
      real :: q(IMR,*),cosp(*),acosp(*),tiny
1899
      real :: DP,CAP1,dq,dn,d0,d1,ds,d2
1900
      INTEGER :: i,j
1901
c      logical first
1902
c      data first /.true./
1903
c      save cap1
1904
C
1905
c      if(first) then
1906
      DP = 4.*ATAN(1.)/REAL(JNP-1)
1907
      CAP1 = IMR*(1.-COS((j1-1.5)*DP))/DP
1908
c      first = .false.
1909
c      endif
1910
C
1911
      ipy = 0
1912
      do 55 j=j1+1,j2-1
1913
      DO 55 i=1,IMR
1914
      IF(q(i,j).LT.0.) THEN
1915
      ipy =  1
1916
      dq  = - q(i,j)*cosp(j)
1917
C North
1918
      dn = q(i,j+1)*cosp(j+1)
1919
      d0 = max(0.,dn)
1920
      d1 = min(dq,d0)
1921
      q(i,j+1) = (dn - d1)*acosp(j+1)
1922
      dq = dq - d1
1923
C South
1924
      ds = q(i,j-1)*cosp(j-1)
1925
      d0 = max(0.,ds)
1926
      d2 = min(dq,d0)
1927
      q(i,j-1) = (ds - d2)*acosp(j-1)
1928
      q(i,j) = (d2 - dq)*acosp(j) + tiny
1929
      endif
1930
55    continue
1931
C
1932
      do i=1,imr
1933
      IF(q(i,j1).LT.0.) THEN
1934
      ipy =  1
1935
      dq  = - q(i,j1)*cosp(j1)
1936
C North
1937
      dn = q(i,j1+1)*cosp(j1+1)
1938
      d0 = max(0.,dn)
1939
      d1 = min(dq,d0)
1940
      q(i,j1+1) = (dn - d1)*acosp(j1+1)
1941
      q(i,j1) = (d1 - dq)*acosp(j1) + tiny
1942
      endif
1943
      enddo
1944
C
1945
      j = j2
1946
      do i=1,imr
1947
      IF(q(i,j).LT.0.) THEN
1948
      ipy =  1
1949
      dq  = - q(i,j)*cosp(j)
1950
C South
1951
      ds = q(i,j-1)*cosp(j-1)
1952
      d0 = max(0.,ds)
1953
      d2 = min(dq,d0)
1954
      q(i,j-1) = (ds - d2)*acosp(j-1)
1955
      q(i,j) = (d2 - dq)*acosp(j) + tiny
1956
      endif
1957
      enddo
1958
C
1959
C Check Poles.
1960
      if(q(1,1).lt.0.) then
1961
      dq = q(1,1)*cap1/REAL(IMR)*acosp(j1)
1962
      do i=1,imr
1963
      q(i,1) = 0.
1964
      q(i,j1) = q(i,j1) + dq
1965
      if(q(i,j1).lt.0.) ipy = 1
1966
      enddo
1967
      endif
1968
C
1969
      if(q(1,JNP).lt.0.) then
1970
      dq = q(1,JNP)*cap1/REAL(IMR)*acosp(j2)
1971
      do i=1,imr
1972
      q(i,JNP) = 0.
1973
      q(i,j2) = q(i,j2) + dq
1974
      if(q(i,j2).lt.0.) ipy = 1
1975
      enddo
1976
      endif
1977
C
1978
      return
1979
      end
1980
C
1981
      subroutine filew(q,qtmp,IMR,JNP,j1,j2,ipx,tiny)
1982
      implicit none
1983
      integer :: IMR,JNP,j1,j2,ipx
1984
      real :: q(IMR,*),qtmp(JNP,IMR),tiny
1985
      integer :: i,j
1986
      real :: d0,d1,d2
1987
C
1988
      ipx = 0
1989
C Copy & swap direction for vectorization.
1990
      do 25 i=1,imr
1991
      do 25 j=j1,j2
1992
25    qtmp(j,i) = q(i,j)
1993
C
1994
      do 55 i=2,imr-1
1995
      do 55 j=j1,j2
1996
      if(qtmp(j,i).lt.0.) then
1997
      ipx =  1
1998
c west
1999
      d0 = max(0.,qtmp(j,i-1))
2000
      d1 = min(-qtmp(j,i),d0)
2001
      qtmp(j,i-1) = qtmp(j,i-1) - d1
2002
      qtmp(j,i) = qtmp(j,i) + d1
2003
c east
2004
      d0 = max(0.,qtmp(j,i+1))
2005
      d2 = min(-qtmp(j,i),d0)
2006
      qtmp(j,i+1) = qtmp(j,i+1) - d2
2007
      qtmp(j,i) = qtmp(j,i) + d2 + tiny
2008
      endif
2009
55    continue
2010
c
2011
      i=1
2012
      do 65 j=j1,j2
2013
      if(qtmp(j,i).lt.0.) then
2014
      ipx =  1
2015
c west
2016
      d0 = max(0.,qtmp(j,imr))
2017
      d1 = min(-qtmp(j,i),d0)
2018
      qtmp(j,imr) = qtmp(j,imr) - d1
2019
      qtmp(j,i) = qtmp(j,i) + d1
2020
c east
2021
      d0 = max(0.,qtmp(j,i+1))
2022
      d2 = min(-qtmp(j,i),d0)
2023
      qtmp(j,i+1) = qtmp(j,i+1) - d2
2024
c
2025
      qtmp(j,i) = qtmp(j,i) + d2 + tiny
2026
      endif
2027
65    continue
2028
      i=IMR
2029
      do 75 j=j1,j2
2030
      if(qtmp(j,i).lt.0.) then
2031
      ipx =  1
2032
c west
2033
      d0 = max(0.,qtmp(j,i-1))
2034
      d1 = min(-qtmp(j,i),d0)
2035
      qtmp(j,i-1) = qtmp(j,i-1) - d1
2036
      qtmp(j,i) = qtmp(j,i) + d1
2037
c east
2038
      d0 = max(0.,qtmp(j,1))
2039
      d2 = min(-qtmp(j,i),d0)
2040
      qtmp(j,1) = qtmp(j,1) - d2
2041
c
2042
      qtmp(j,i) = qtmp(j,i) + d2 + tiny
2043
      endif
2044
75    continue
2045
C
2046
      if(ipx.ne.0) then
2047
      do 85 j=j1,j2
2048
      do 85 i=1,imr
2049
85    q(i,j) = qtmp(j,i)
2050
      else
2051
C
2052
C Poles.
2053
      if(q(1,1).lt.0. or. q(1,JNP).lt.0.) ipx = 1
2054
      endif
2055
      return
2056
      end
2057
C
2058
      subroutine zflip(q,im,km,nc)
2059
      implicit none
2060
C This routine flip the array q (in the vertical).
2061
      integer :: im,km,nc
2062
      real q(im,km,nc)
2063
C local dynamic array
2064
      real qtmp(im,km)
2065
      integer IC,k,i
2066
C
2067
      do 4000 IC = 1, nc
2068
C
2069
      do 1000 k=1,km
2070
      do 1000 i=1,im
2071
      qtmp(i,k) = q(i,km+1-k,IC)
2072
1000  continue
2073
C
2074
      do 2000 i=1,im*km
2075
2000  q(i,1,IC) = qtmp(i,1)
2076
4000  continue
2077
      return
2078
      end