source: LMDZ6/branches/Amaury_dev/libf/dyn3d_common/ppm3d.f90 @ 5106

Last change on this file since 5106 was 5106, checked in by abarral, 2 months ago

Turn coefils.h into lmdz_coefils.f90
Put filtreg.F90 inside lmdz_filtreg.F90
Turn mod_filtreg_p.F90 into lmdz_filtreg_p.F90
Delete obsolete parafilt.h*
(lint) remove spaces between routine name and args

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