/[lmdze]/trunk/Sources/dyn3d/PPM3d/ppm3d.f
ViewVC logotype

Diff of /trunk/Sources/dyn3d/PPM3d/ppm3d.f

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

trunk/dyn3d/ppm3d.f revision 76 by guez, Fri Nov 15 18:45:49 2013 UTC trunk/Sources/dyn3d/PPM3d/ppm3d.f revision 166 by guez, Wed Jul 29 14:32:55 2015 UTC
# Line 1  Line 1 
1  !  SUBROUTINE ppm3d(igd, q, ps1, ps2, u, v, w, ndt, iord, jord, kord, nc, imr, &
2  ! $Header: /home/cvsroot/LMDZ4/libf/dyn3d/ppm3d.F,v 1.1.1.1 2004/05/19 12:53:07 lmdzadmin Exp $      jnp, j1, nlay, ap, bp, pt, ae, fill, dum, umax)
3  !  
4      ! implicit none
5  cFrom lin@explorer.gsfc.nasa.gov Wed Apr 15 17:44:44 1998  
6  cDate: Wed, 15 Apr 1998 11:37:03 -0400    ! rajout de déclarations
7  cFrom: lin@explorer.gsfc.nasa.gov    ! integer Jmax,kmax,ndt0,nstep,k,j,i,ic,l,js,jn,imh,iad,jad,krd
8  cTo: Frederic.Hourdin@lmd.jussieu.fr    ! integer iu,iiu,j2,jmr,js0,jt
9  cSubject: 3D transport module of the GSFC CTM and GEOS GCM    ! real dtdy,dtdy5,rcap,iml,jn0,imjm,pi,dl,dp
10      ! real dt,cr1,maxdt,ztc,d5,sum1,sum2,ru
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.    ! INPUT:
16      ! =============
17          
18  C ********************************************************************    ! Q(IMR,JNP,NLAY,NC): mixing ratios at current time (t)
19  C    ! NC: total number of constituents
20  C TransPort Core for Goddard Chemistry Transport Model (G-CTM), Goddard    ! IMR: first dimension (E-W); number of Grid intervals in E-W is IMR
21  C Earth Observing System General Circulation Model (GEOS-GCM), and Data    ! JNP: 2nd dimension (N-S); number of Grid intervals in N-S is JNP-1
22  C Assimilation System (GEOS-DAS).    ! NLAY: 3rd dimension (number of layers); vertical index increases from 1
23  C    ! at
24  C ********************************************************************    ! the model top to NLAY near the surface (see fig. below).
25  C    ! It is assumed that 6 <= NLAY <= JNP (for dynamic memory allocation)
26  C Purpose: given horizontal winds on  a hybrid sigma-p surfaces,  
27  C          one call to tpcore updates the 3-D mixing ratio    ! PS1(IMR,JNP): surface pressure at current time (t)
28  C          fields one time step (NDT). [vertical mass flux is computed    ! PS2(IMR,JNP): surface pressure at mid-time-level (t+NDT/2)
29  C          internally consistent with the discretized hydrostatic mass    ! PS2 is replaced by the predicted PS (at t+NDT) on output.
30  C          continuity equation of the C-Grid GEOS-GCM (for IGD=1)].    ! Note: surface pressure can have any unit or can be multiplied by any
31  C    ! const.
32  C Schemes: Multi-dimensional Flux Form Semi-Lagrangian (FFSL) scheme based  
33  C          on the van Leer or PPM.    ! The pressure at layer edges are defined as follows:
34  C          (see Lin and Rood 1996).  
35  C Version 4.5    ! p(i,j,k) = AP(k)*PT  +  BP(k)*PS(i,j)          (1)
36  C Last modified: Dec. 5, 1996  
37  C Major changes from version 4.0: a more general vertical hybrid sigma-    ! Where PT is a constant having the same unit as PS.
38  C pressure coordinate.    ! AP and BP are unitless constants given at layer edges
39  C Subroutines modified: xtp, ytp, fzppm, qckxyz    ! defining the vertical coordinate.
40  C Subroutines deleted: vanz    ! BP(1) = 0., BP(NLAY+1) = 1.
41  C    ! The pressure at the model top is PTOP = AP(1)*PT
42  C Author: Shian-Jiann Lin  
43  C mail address:    ! For pure sigma system set AP(k) = 1 for all k, PT = PTOP,
44  C                 Shian-Jiann Lin*    ! BP(k) = sige(k) (sigma at edges), PS = Psfc - PTOP.
45  C                 Code 910.3, NASA/GSFC, Greenbelt, MD 20771  
46  C                 Phone: 301-286-9540    ! Note: the sigma-P coordinate is a subset of Eq. 1, which in turn
47  C                 E-mail: lin@dao.gsfc.nasa.gov    ! is a subset of the following even more general sigma-P-thelta coord.
48  C    ! currently under development.
49  C *affiliation:    ! p(i,j,k) = (AP(k)*PT + BP(k)*PS(i,j))/(D(k)-C(k)*TE**(-1/kapa))
50  C                 Joint Center for Earth Systems Technology  
51  C                 The University of Maryland Baltimore County    ! /////////////////////////////////
52  C                 NASA - Goddard Space Flight Center    ! / \ ------------- PTOP --------------  AP(1), BP(1)
53  C References:    ! |
54  C    ! delp(1)    |  ........... Q(i,j,1) ............
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.    ! W(1)    \ / ---------------------------------  AP(2), BP(2)
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,    ! W(k-1)   / \ ---------------------------------  AP(k), BP(k)
61  C    1575-1593.    ! |
62  C    ! delp(K)    |  ........... Q(i,j,k) ............
63  C ****6***0*********0*********0*********0*********0*********0**********72    ! |
64  C    ! W(k)    \ / ---------------------------------  AP(k+1), BP(k+1)
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  c      implicit none    ! / \ ---------------------------------  AP(NLAY), BP(NLAY)
69      ! |
70  c     rajout de déclarations    ! delp(NLAY)   |  ........... Q(i,j,NLAY) .........
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    ! W(NLAY)=0  \ / ------------- surface ----------- AP(NLAY+1), BP(NLAY+1)
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    ! U(IMR,JNP,NLAY) & V(IMR,JNP,NLAY):winds (m/s) at mid-time-level (t+NDT/2)
76  C ********************************************************************    ! U and V may need to be polar filtered in advance in some cases.
77  C  
78  C =============    ! IGD:      grid type on which winds are defined.
79  C INPUT:    ! IGD = 0:  A-Grid  [all variables defined at the same point from south
80  C =============    ! pole (j=1) to north pole (j=JNP) ]
81  C  
82  C Q(IMR,JNP,NLAY,NC): mixing ratios at current time (t)    ! IGD = 1  GEOS-GCM C-Grid
83  C NC: total number of constituents    ! [North]
84  C IMR: first dimension (E-W); number of Grid intervals in E-W is IMR  
85  C JNP: 2nd dimension (N-S); number of Grid intervals in N-S is JNP-1    ! V(i,j)
86  C NLAY: 3rd dimension (number 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    ! U(i-1,j)---Q(i,j)---U(i,j) [EAST]
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    ! V(i,j-1)
94  C       const.  
95  C    ! U(i,  1) is defined at South Pole.
96  C The pressure at layer edges are defined as follows:    ! V(i,  1) is half grid north of the South Pole.
97  C    ! V(i,JMR) is half grid south of the North Pole.
98  C        p(i,j,k) = AP(k)*PT  +  BP(k)*PS(i,j)          (1)  
99  C    ! V must be defined at j=1 and j=JMR if IGD=1
100  C Where PT is a constant having the same unit as PS.    ! V at JNP need not be given.
101  C AP and BP are unitless constants given at layer edges  
102  C defining the vertical coordinate.    ! NDT: time step in seconds (need not be constant during the course of
103  C BP(1) = 0., BP(NLAY+1) = 1.    ! the integration). Suggested value: 30 min. for 4x5, 15 min. for 2x2.5
104  C The pressure at the model top is PTOP = AP(1)*PT    ! (Lat-Lon) resolution. Smaller values are recommanded if the model
105  C    ! has a well-resolved stratosphere.
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.    ! J1 defines the size of the polar cap:
108  C    ! South polar cap edge is located at -90 + (j1-1.5)*180/(JNP-1) deg.
109  C Note: the sigma-P coordinate is a subset of Eq. 1, which in turn    ! North polar cap edge is located at  90 - (j1-1.5)*180/(JNP-1) deg.
110  C is a subset of the following even more general sigma-P-thelta coord.    ! There are currently only two choices (j1=2 or 3).
111  C currently under development.    ! IMR must be an even integer if j1 = 2. Recommended value: J1=3.
112  C  p(i,j,k) = (AP(k)*PT + BP(k)*PS(i,j))/(D(k)-C(k)*TE**(-1/kapa))  
113  C    ! IORD, JORD, and KORD are integers controlling various options in E-W,
114  C                  /////////////////////////////////    ! N-S,
115  C              / \ ------------- PTOP --------------  AP(1), BP(1)    ! and vertical transport, respectively. Recommended values for positive
116  C               |    ! definite scalars: IORD=JORD=3, KORD=5. Use KORD=3 for non-
117  C    delp(1)    |  ........... Q(i,j,1) ............      ! positive definite scalars or when linear correlation between constituents
118  C               |    ! is to be maintained.
119  C      W(1)    \ / ---------------------------------  AP(2), BP(2)  
120  C    ! _ORD=
121  C    ! 1: 1st order upstream scheme (too diffusive, not a useful option; it
122  C    ! can be used for debugging purposes; this is THE only known "linear"
123  C     W(k-1)   / \ ---------------------------------  AP(k), BP(k)    ! monotonic advection scheme.).
124  C               |    ! 2: 2nd order van Leer (full monotonicity constraint;
125  C    delp(K)    |  ........... Q(i,j,k) ............    ! see Lin et al 1994, MWR)
126  C               |    ! 3: monotonic PPM* (slightly improved PPM of Collela & Woodward 1984)
127  C      W(k)    \ / ---------------------------------  AP(k+1), BP(k+1)    ! 4: semi-monotonic PPM (same as 3, but overshoots are allowed)
128  C    ! 5: positive-definite PPM (constraint on the subgrid distribution is
129  C    ! only strong enough to prevent generation of negative values;
130  C    ! both overshoots & undershoots are possible).
131  C              / \ ---------------------------------  AP(NLAY), BP(NLAY)    ! 6: un-constrained PPM (nearly diffusion free; slightly faster but
132  C               |    ! positivity not quaranteed. Use this option only when the fields
133  C  delp(NLAY)   |  ........... Q(i,j,NLAY) .........      ! and winds are very smooth).
134  C               |  
135  C   W(NLAY)=0  \ / ------------- surface ----------- AP(NLAY+1), BP(NLAY+1)    ! *PPM: Piece-wise Parabolic Method
136  C                 //////////////////////////////////  
137  C    ! Note that KORD <=2 options are no longer supported. DO not use option 4
138  C U(IMR,JNP,NLAY) & V(IMR,JNP,NLAY):winds (m/s) at mid-time-level (t+NDT/2)    ! or 5.
139  C U and V may need to be polar filtered in advance in some cases.    ! for non-positive definite scalars (such as Ertel Potential Vorticity).
140  C  
141  C IGD:      grid type on which winds are defined.    ! The implicit numerical diffusion decreases as _ORD increases.
142  C IGD = 0:  A-Grid  [all variables defined at the same point from south    ! The last two options (ORDER=5, 6) should only be used when there is
143  C                   pole (j=1) to north pole (j=JNP) ]    ! significant explicit diffusion (such as a turbulence parameterization).
144  C    ! You
145  C IGD = 1  GEOS-GCM C-Grid    ! might get dispersive results otherwise.
146  C                                      [North]    ! No filter of any kind is applied to the constituent fields here.
147  C  
148  C                                       V(i,j)    ! AE: Radius of the sphere (meters).
149  C                                          |    ! Recommended value for the planet earth: 6.371E6
150  C                                          |  
151  C                                          |    ! fill(logical):   flag to do filling for negatives (see note below).
152  C                             U(i-1,j)---Q(i,j)---U(i,j) [EAST]  
153  C                                          |    ! Umax: Estimate (upper limit) of the maximum U-wind speed (m/s).
154  C                                          |    ! (220 m/s is a good value for troposphere model; 280 m/s otherwise)
155  C                                          |  
156  C                                       V(i,j-1)    ! =============
157  C    ! Output
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.    ! Q: mixing ratios at future time (t+NDT) (original values are
161  C    ! over-written)
162  C         V must be defined at j=1 and j=JMR if IGD=1    ! W(NLAY): large-scale vertical mass flux as diagnosed from the hydrostatic
163  C         V at JNP need not be given.    ! relationship. W will have the same unit as PS1 and PS2 (eg, mb).
164  C    ! W must be divided by NDT to get the correct mass-flux unit.
165  C NDT: time step in seconds (need not be constant during the course of    ! The vertical Courant number C = W/delp_UPWIND, where delp_UPWIND
166  C      the integration). Suggested value: 30 min. for 4x5, 15 min. for 2x2.5    ! is the pressure thickness in the "upwind" direction. For example,
167  C      (Lat-Lon) resolution. Smaller values are recommanded if the model    ! C(k) = W(k)/delp(k)   if W(k) > 0;
168  C      has a well-resolved stratosphere.    ! C(k) = W(k)/delp(k+1) if W(k) < 0.
169  C    ! ( W > 0 is downward, ie, toward surface)
170  C J1 defines the size of the polar cap:    ! PS2: predicted PS at t+NDT (original values are over-written)
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).    ! NOTES:
174  C IMR must be an even integer if j1 = 2. Recommended value: J1=3.    ! This forward-in-time upstream-biased transport scheme reduces to
175  C    ! the 2nd order center-in-time center-in-space mass continuity eqn.
176  C IORD, JORD, and KORD are integers controlling various options in E-W, N-S,    ! if Q = 1 (constant fields will remain constant). This also ensures
177  C and vertical transport, respectively. Recommended values for positive    ! that the computed vertical velocity to be identical to GEOS-1 GCM
178  C definite scalars: IORD=JORD=3, KORD=5. Use KORD=3 for non-    ! for on-line transport.
179  C positive definite scalars or when linear correlation between constituents  
180  C is to be maintained.    ! A larger polar cap is used if j1=3 (recommended for C-Grid winds or when
181  C    ! winds are noisy near poles).
182  C  _ORD=  
183  C        1: 1st order upstream scheme (too diffusive, not a useful option; it    ! Flux-Form Semi-Lagrangian transport in the East-West direction is used
184  C           can be used for debugging purposes; this is THE only known "linear"    ! when and where Courant number is greater than one.
185  C           monotonic advection scheme.).  
186  C        2: 2nd order van Leer (full monotonicity constraint;    ! The user needs to change the parameter Jmax or Kmax if the resolution
187  C           see Lin et al 1994, MWR)    ! is greater than 0.5 deg in N-S or 150 layers in the vertical direction.
188  C        3: monotonic PPM* (slightly improved PPM of Collela & Woodward 1984)    ! (this TransPort Core is otherwise resolution independent and can be used
189  C        4: semi-monotonic PPM (same as 3, but overshoots are allowed)    ! as a library routine).
190  C        5: positive-definite PPM (constraint on the subgrid distribution is  
191  C           only strong enough to prevent generation of negative values;    ! PPM is 4th order accurate when grid spacing is uniform (x & y); 3rd
192  C           both overshoots & undershoots are possible).    ! order accurate for non-uniform grid (vertical sigma coord.).
193  C        6: un-constrained PPM (nearly diffusion free; slightly faster but  
194  C           positivity not quaranteed. Use this option only when the fields    ! Time step is limitted only by transport in the meridional direction.
195  C           and winds are very smooth).    ! (the FFSL scheme is not implemented in the meridional direction).
196  C  
197  C *PPM: Piece-wise Parabolic Method    ! Since only 1-D limiters are applied, negative values could
198  C    ! potentially be generated when large time step is used and when the
199  C Note that KORD <=2 options are no longer supported. DO not use option 4 or 5.    ! initial fields contain discontinuities.
200  C for non-positive definite scalars (such as Ertel Potential Vorticity).    ! This does not necessarily imply the integration is unstable.
201  C    ! These negatives are typically very small. A filling algorithm is
202  C The implicit numerical diffusion decreases as _ORD increases.    ! activated if the user set "fill" to be true.
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    ! The van Leer scheme used here is nearly as accurate as the original PPM
205  C might get dispersive results otherwise.    ! due to the use of a 4th order accurate reference slope. The PPM imple-
206  C No filter of any kind is applied to the constituent fields here.    ! mented here is an improvement over the original and is also based on
207  C    ! the 4th order reference slope.
208  C AE: Radius of the sphere (meters).  
209  C     Recommended value for the planet earth: 6.371E6    ! ****6***0*********0*********0*********0*********0*********0**********72
210  C  
211  C fill(logical):   flag to do filling for negatives (see note below).    ! User modifiable parameters
212  C  
213  C Umax: Estimate (upper limit) of the maximum U-wind speed (m/s).    PARAMETER (jmax=361, kmax=150)
214  C (220 m/s is a good value for troposphere model; 280 m/s otherwise)  
215  C    ! ****6***0*********0*********0*********0*********0*********0**********72
216  C =============  
217  C Output    ! Input-Output arrays
218  C =============  
219  C  
220  C Q: mixing ratios at future time (t+NDT) (original values are over-written)    REAL q(imr, jnp, nlay, nc), ps1(imr, jnp), ps2(imr, jnp), &
221  C W(NLAY): large-scale vertical mass flux as diagnosed from the hydrostatic      u(imr, jnp, nlay), v(imr, jnp, nlay), ap(nlay+1), bp(nlay+1), &
222  C          relationship. W will have the same unit as PS1 and PS2 (eg, mb).      w(imr, jnp, nlay), ndt, val(nlay), umax
223  C          W must be divided by NDT to get the correct mass-flux unit.    INTEGER igd, iord, jord, kord, nc, imr, jnp, j1, nlay, ae
224  C          The vertical Courant number C = W/delp_UPWIND, where delp_UPWIND    INTEGER imrd2
225  C          is the pressure thickness in the "upwind" direction. For example,    REAL pt
226  C          C(k) = W(k)/delp(k)   if W(k) > 0;    LOGICAL cross, fill, dum
227  C          C(k) = W(k)/delp(k+1) if W(k) < 0.  
228  C              ( W > 0 is downward, ie, toward surface)    ! Local dynamic arrays
229  C PS2: predicted PS at t+NDT (original values are over-written)  
230  C    REAL crx(imr, jnp), cry(imr, jnp), xmass(imr, jnp), ymass(imr, jnp), &
231  C ********************************************************************      fx1(imr+1), dpi(imr, jnp, nlay), delp1(imr, jnp, nlay), &
232  C NOTES:      wk1(imr, jnp, nlay), pu(imr, jnp), pv(imr, jnp), dc2(imr, jnp), &
233  C This forward-in-time upstream-biased transport scheme reduces to      delp2(imr, jnp, nlay), dq(imr, jnp, nlay, nc), va(imr, jnp), &
234  C the 2nd order center-in-time center-in-space mass continuity eqn.      ua(imr, jnp), qtmp(-imr:2*imr)
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    ! Local static  arrays
237  C for on-line transport.  
238  C    REAL dtdx(jmax), dtdx5(jmax), acosp(jmax), cosp(jmax), cose(jmax), &
239  C A larger polar cap is used if j1=3 (recommended for C-Grid winds or when      dap(kmax), dbk(kmax)
240  C winds are noisy near poles).    DATA ndt0, nstep/0, 0/
241  C    DATA cross/.TRUE./
242  C Flux-Form Semi-Lagrangian transport in the East-West direction is used    SAVE dtdy, dtdy5, rcap, js0, jn0, iml, dtdx, dtdx5, acosp, cosp, cose, dap, &
243  C when and where Courant number is greater than one.      dbk
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.    jmr = jnp - 1
247  C (this TransPort Core is otherwise resolution independent and can be used    imjm = imr*jnp
248  C as a library routine).    j2 = jnp - j1 + 1
249  C    nstep = nstep + 1
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.).    ! *********** Initialization **********************
252  C    IF (nstep==1) THEN
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).      WRITE (6, *) '------------------------------------ '
255  C      WRITE (6, *) 'NASA/GSFC Transport Core Version 4.5'
256  C Since only 1-D limiters are applied, negative values could      WRITE (6, *) '------------------------------------ '
257  C potentially be generated when large time step is used and when the  
258  C initial fields contain discontinuities.      WRITE (6, *) 'IMR=', imr, ' JNP=', jnp, ' NLAY=', nlay, ' j1=', j1
259  C This does not necessarily imply the integration is unstable.      WRITE (6, *) 'NC=', nc, iord, jord, kord, ndt
260  C These negatives are typically very small. A filling algorithm is  
261  C activated if the user set "fill" to be true.      ! controles sur les parametres
262  C      IF (nlay<6) THEN
263  C The van Leer scheme used here is nearly as accurate as the original PPM        WRITE (6, *) 'NLAY must be >= 6'
264  C due to the use of a 4th order accurate reference slope. The PPM imple-        STOP
265  C mented here is an improvement over the original and is also based on      END IF
266  C the 4th order reference slope.      IF (jnp<nlay) THEN
267  C        WRITE (6, *) 'JNP must be >= NLAY'
268  C ****6***0*********0*********0*********0*********0*********0**********72        STOP
269  C      END IF
270  C     User modifiable parameters      imrd2 = mod(imr, 2)
271  C      IF (j1==2 .AND. imrd2/=0) THEN
272        parameter (Jmax = 361, kmax = 150)        WRITE (6, *) 'if j1=2 IMR must be an even integer'
273  C        STOP
274  C ****6***0*********0*********0*********0*********0*********0**********72      END IF
275  C  
276  C Input-Output arrays  
277  C      IF (jmax<jnp .OR. kmax<nlay) THEN
278                WRITE (6, *) 'Jmax or Kmax is too small'
279        real Q(IMR,JNP,NLAY,NC),PS1(IMR,JNP),PS2(IMR,JNP),        STOP
280       &     U(IMR,JNP,NLAY),V(IMR,JNP,NLAY),AP(NLAY+1),      END IF
281       &     BP(NLAY+1),W(IMR,JNP,NLAY),NDT,val(NLAY),Umax  
282        integer IGD,IORD,JORD,KORD,NC,IMR,JNP,j1,NLAY,AE      DO k = 1, nlay
283        integer IMRD2        dap(k) = (ap(k+1)-ap(k))*pt
284        real    PT              dbk(k) = bp(k+1) - bp(k)
285        logical  cross, fill, dum      END DO
286  C  
287  C Local dynamic arrays      pi = 4.*atan(1.)
288  C      dl = 2.*pi/float(imr)
289        real CRX(IMR,JNP),CRY(IMR,JNP),xmass(IMR,JNP),ymass(IMR,JNP),      dp = pi/float(jmr)
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),      IF (igd==0) THEN
292       &     delp2(IMR,JNP,NLAY),DQ(IMR,JNP,NLAY,NC),VA(IMR,JNP),        ! Compute analytic cosine at cell edges
293       &     UA(IMR,JNP),qtmp(-IMR:2*IMR)        CALL cosa(cosp, cose, jnp, pi, dp)
294  C      ELSE
295  C Local static  arrays        ! Define cosine consistent with GEOS-GCM (using dycore2.0 or later)
296  C        CALL cosc(cosp, cose, jnp, pi, dp)
297        real DTDX(Jmax), DTDX5(Jmax), acosp(Jmax),      END IF
298       &     cosp(Jmax), cose(Jmax), DAP(kmax),DBK(Kmax)  
299        data NDT0, NSTEP /0, 0/      DO j = 2, jmr
300        data cross /.true./        acosp(j) = 1./cosp(j)
301        SAVE DTDY, DTDY5, RCAP, JS0, JN0, IML,      END DO
302       &     DTDX, DTDX5, ACOSP, COSP, COSE, DAP,DBK  
303  C      ! Inverse of the Scaled polar cap area.
304                
305        JMR = JNP -1      rcap = dp/(imr*(1.-cos((j1-1.5)*dp)))
306        IMJM  = IMR*JNP      acosp(1) = rcap
307        j2 = JNP - j1 + 1      acosp(jnp) = rcap
308        NSTEP = NSTEP + 1    END IF
309  C  
310  C *********** Initialization **********************    IF (ndt0/=ndt) THEN
311        if(NSTEP.eq.1) then      dt = ndt
312  c      ndt0 = ndt
313        write(6,*) '------------------------------------ '  
314        write(6,*) 'NASA/GSFC Transport Core Version 4.5'      IF (umax<180.) THEN
315        write(6,*) '------------------------------------ '        WRITE (6, *) 'Umax may be too small!'
316  c      END IF
317        WRITE(6,*) 'IMR=',IMR,' JNP=',JNP,' NLAY=',NLAY,' j1=',j1      cr1 = abs(umax*dt)/(dl*ae)
318        WRITE(6,*) 'NC=',NC,IORD,JORD,KORD,NDT      maxdt = dp*ae/abs(umax) + 0.5
319  C      WRITE (6, *) 'Largest time step for max(V)=', umax, ' is ', maxdt
320  C controles sur les parametres      IF (maxdt<abs(ndt)) THEN
321        if(NLAY.LT.6) then        WRITE (6, *) 'Warning!!! NDT maybe too large!'
322          write(6,*) 'NLAY must be >= 6'      END IF
323          stop  
324        endif      IF (cr1>=0.95) THEN
325        if (JNP.LT.NLAY) then        js0 = 0
326           write(6,*) 'JNP must be >= NLAY'        jn0 = 0
327          stop        iml = imr - 2
328        endif        ztc = 0.
329        IMRD2=mod(IMR,2)      ELSE
330        if (j1.eq.2.and.IMRD2.NE.0) then        ztc = acos(cr1)*(180./pi)
331           write(6,*) 'if j1=2 IMR must be an even integer'  
332          stop        js0 = float(jmr)*(90.-ztc)/180. + 2
333        endif        js0 = max(js0, j1+1)
334          iml = min(6*js0/(j1-1)+2, 4*imr/5)
335  C        jn0 = jnp - js0 + 1
336        if(Jmax.lt.JNP .or. Kmax.lt.NLAY) then      END IF
337          write(6,*) 'Jmax or Kmax is too small'  
338          stop  
339        endif      DO j = 2, jmr
340  C        dtdx(j) = dt/(dl*ae*cosp(j))
341        DO k=1,NLAY  
342        DAP(k) = (AP(k+1) - AP(k))*PT        dtdx5(j) = 0.5*dtdx(j)
343        DBK(k) =  BP(k+1) - BP(k)      END DO
344        ENDDO      
345  C  
346        PI = 4. * ATAN(1.)      dtdy = dt/(ae*dp)
347        DL = 2.*PI / float(IMR)      dtdy5 = 0.5*dtdy
348        DP =    PI / float(JMR)  
349  C    END IF
350        if(IGD.eq.0) then  
351  C Compute analytic cosine at cell edges    ! *********** End Initialization **********************
352              call cosa(cosp,cose,JNP,PI,DP)  
353        else    ! delp = pressure thickness: the psudo-density in a hydrostatic system.
354  C Define cosine consistent with GEOS-GCM (using dycore2.0 or later)    DO k = 1, nlay
355              call cosc(cosp,cose,JNP,PI,DP)      DO j = 1, jnp
356        endif        DO i = 1, imr
357  C          delp1(i, j, k) = dap(k) + dbk(k)*ps1(i, j)
358        do 15 J=2,JMR          delp2(i, j, k) = dap(k) + dbk(k)*ps2(i, j)
359  15    acosp(j) = 1. / cosp(j)        END DO
360  C      END DO
361  C Inverse of the Scaled polar cap area.    END DO
362  C  
363        RCAP  = DP / (IMR*(1.-COS((j1-1.5)*DP)))  
364        acosp(1)   = RCAP    IF (j1/=2) THEN
365        acosp(JNP) = RCAP      DO ic = 1, nc
366        endif        DO l = 1, nlay
367  C          DO i = 1, imr
368        if(NDT0 .ne. NDT) then            q(i, 2, l, ic) = q(i, 1, l, ic)
369        DT   = NDT            q(i, jmr, l, ic) = q(i, jnp, l, ic)
370        NDT0 = NDT          END DO
371          END DO
372          if(Umax .lt. 180.) then      END DO
373           write(6,*) 'Umax may be too small!'    END IF
374          endif  
375        CR1  = abs(Umax*DT)/(DL*AE)    ! Compute "tracer density"
376        MaxDT = DP*AE / abs(Umax) + 0.5    DO ic = 1, nc
377        write(6,*)'Largest time step for max(V)=',Umax,' is ',MaxDT      DO k = 1, nlay
378        if(MaxDT .lt. abs(NDT)) then        DO j = 1, jnp
379              write(6,*) 'Warning!!! NDT maybe too large!'          DO i = 1, imr
380        endif            dq(i, j, k, ic) = q(i, j, k, ic)*delp1(i, j, k)
381  C          END DO
382        if(CR1.ge.0.95) then        END DO
383        JS0 = 0      END DO
384        JN0 = 0    END DO
385        IML = IMR-2  
386        ZTC = 0.    DO k = 1, nlay
387        else  
388        ZTC  = acos(CR1) * (180./PI)      IF (igd==0) THEN
389  C        ! Convert winds on A-Grid to Courant number on C-Grid.
390        JS0 = float(JMR)*(90.-ZTC)/180. + 2        CALL a2c(u(1,1,k), v(1,1,k), imr, jmr, j1, j2, crx, cry, dtdx5, dtdy5)
391        JS0 = max(JS0, J1+1)      ELSE
392        IML = min(6*JS0/(J1-1)+2, 4*IMR/5)        ! Convert winds on C-grid to Courant number
393        JN0 = JNP-JS0+1        DO j = j1, j2
394        endif          DO i = 2, imr
395  C                crx(i, j) = dtdx(j)*u(i-1, j, k)
396  C          END DO
397        do J=2,JMR        END DO
398        DTDX(j)  = DT / ( DL*AE*COSP(J) )  
399    
400        DTDX5(j) = 0.5*DTDX(j)        DO j = j1, j2
401        enddo          crx(1, j) = dtdx(j)*u(imr, j, k)
402  C        END DO
403          
404        DTDY  = DT /(AE*DP)        DO i = 1, imr*jmr
405        DTDY5 = 0.5*DTDY          cry(i, 2) = dtdy*v(i, 1, k)
406  C        END DO
407        endif      END IF
408  C  
409  C *********** End Initialization **********************      ! Determine JS and JN
410  C      js = j1
411  C delp = pressure thickness: the psudo-density in a hydrostatic system.      jn = j2
412        do  k=1,NLAY  
413           do  j=1,JNP      DO j = js0, j1 + 1, -1
414              do  i=1,IMR        DO i = 1, imr
415                 delp1(i,j,k)=DAP(k)+DBK(k)*PS1(i,j)          IF (abs(crx(i,j))>1.) THEN
416                 delp2(i,j,k)=DAP(k)+DBK(k)*PS2(i,j)                  js = j
417              enddo            GO TO 2222
418           enddo          END IF
419        enddo        END DO
420                  END DO
421  C  
422        if(j1.ne.2) then  2222 CONTINUE
423        DO 40 IC=1,NC      DO j = jn0, j2 - 1
424        DO 40 L=1,NLAY        DO i = 1, imr
425        DO 40 I=1,IMR          IF (abs(crx(i,j))>1.) THEN
426        Q(I,  2,L,IC) = Q(I,  1,L,IC)            jn = j
427  40    Q(I,JMR,L,IC) = Q(I,JNP,L,IC)            GO TO 2233
428        endif          END IF
429  C        END DO
430  C Compute "tracer density"      END DO
431        DO 550 IC=1,NC  2233 CONTINUE
432        DO 44 k=1,NLAY  
433        DO 44 j=1,JNP      IF (j1/=2) THEN ! Enlarged polar cap.
434        DO 44 i=1,IMR        DO i = 1, imr
435  44    DQ(i,j,k,IC) = Q(i,j,k,IC)*delp1(i,j,k)          dpi(i, 2, k) = 0.
436  550     continue          dpi(i, jmr, k) = 0.
437  C        END DO
438        do 1500 k=1,NLAY      END IF
439  C  
440        if(IGD.eq.0) then      ! ******* Compute horizontal mass fluxes ************
441  C Convert winds on A-Grid to Courant number on C-Grid.  
442        call A2C(U(1,1,k),V(1,1,k),IMR,JMR,j1,j2,CRX,CRY,dtdx5,DTDY5)      ! N-S component
443        else      DO j = j1, j2 + 1
444  C Convert winds on C-grid to Courant number        d5 = 0.5*cose(j)
445        do 45 j=j1,j2        DO i = 1, imr
446        do 45 i=2,IMR          ymass(i, j) = cry(i, j)*d5*(delp2(i,j,k)+delp2(i,j-1,k))
447  45    CRX(i,J) = dtdx(j)*U(i-1,j,k)        END DO
448          END DO
449  C  
450        do 50 j=j1,j2      DO j = j1, j2
451  50    CRX(1,J) = dtdx(j)*U(IMR,j,k)        DO i = 1, imr
452  C          dpi(i, j, k) = (ymass(i,j)-ymass(i,j+1))*acosp(j)
453        do 55 i=1,IMR*JMR        END DO
454  55    CRY(i,2) = DTDY*V(i,1,k)      END DO
455        endif  
456  C          ! Poles
457  C Determine JS and JN      sum1 = ymass(imr, j1)
458        JS = j1      sum2 = ymass(imr, j2+1)
459        JN = j2      DO i = 1, imr - 1
460  C        sum1 = sum1 + ymass(i, j1)
461        do j=JS0,j1+1,-1        sum2 = sum2 + ymass(i, j2+1)
462        do i=1,IMR      END DO
463        if(abs(CRX(i,j)).GT.1.) then  
464              JS = j      sum1 = -sum1*rcap
465              go to 2222      sum2 = sum2*rcap
466        endif      DO i = 1, imr
467        enddo        dpi(i, 1, k) = sum1
468        enddo        dpi(i, jnp, k) = sum2
469  C      END DO
470  2222  continue  
471        do j=JN0,j2-1      ! E-W component
472        do i=1,IMR  
473        if(abs(CRX(i,j)).GT.1.) then      DO j = j1, j2
474              JN = j        DO i = 2, imr
475              go to 2233          pu(i, j) = 0.5*(delp2(i,j,k)+delp2(i-1,j,k))
476        endif        END DO
477        enddo      END DO
478        enddo  
479  2233  continue      DO j = j1, j2
480  C        pu(1, j) = 0.5*(delp2(1,j,k)+delp2(imr,j,k))
481        if(j1.ne.2) then           ! Enlarged polar cap.      END DO
482        do i=1,IMR  
483        DPI(i,  2,k) = 0.      DO j = j1, j2
484        DPI(i,JMR,k) = 0.        DO i = 1, imr
485        enddo          xmass(i, j) = pu(i, j)*crx(i, j)
486        endif        END DO
487  C      END DO
488  C ******* Compute horizontal mass fluxes ************  
489  C      DO j = j1, j2
490  C N-S component        DO i = 1, imr - 1
491        do j=j1,j2+1          dpi(i, j, k) = dpi(i, j, k) + xmass(i, j) - xmass(i+1, j)
492        D5 = 0.5 * COSE(j)        END DO
493        do i=1,IMR      END DO
494        ymass(i,j) = CRY(i,j)*D5*(delp2(i,j,k) + delp2(i,j-1,k))  
495        enddo      DO j = j1, j2
496        enddo        dpi(imr, j, k) = dpi(imr, j, k) + xmass(imr, j) - xmass(1, j)
497  C      END DO
498        do 95 j=j1,j2  
499        DO 95 i=1,IMR      DO j = j1, j2
500  95    DPI(i,j,k) = (ymass(i,j) - ymass(i,j+1)) * acosp(j)        DO i = 1, imr - 1
501  C          ua(i, j) = 0.5*(crx(i,j)+crx(i+1,j))
502  C Poles        END DO
503        sum1 = ymass(IMR,j1  )      END DO
504        sum2 = ymass(IMR,J2+1)  
505        do i=1,IMR-1      DO j = j1, j2
506        sum1 = sum1 + ymass(i,j1  )        ua(imr, j) = 0.5*(crx(imr,j)+crx(1,j))
507        sum2 = sum2 + ymass(i,J2+1)      END DO
508        enddo      ! cccccccccccccccccccccccccccccccccccccccccccccccccccccc
509  C      ! Rajouts pour LMDZ.3.3
510        sum1 = - sum1 * RCAP      ! cccccccccccccccccccccccccccccccccccccccccccccccccccccc
511        sum2 =   sum2 * RCAP      DO i = 1, imr
512        do i=1,IMR        DO j = 1, jnp
513        DPI(i,  1,k) = sum1          va(i, j) = 0.
514        DPI(i,JNP,k) = sum2        END DO
515        enddo      END DO
516  C  
517  C E-W component      DO i = 1, imr*(jmr-1)
518  C        va(i, 2) = 0.5*(cry(i,2)+cry(i,3))
519        do j=j1,j2      END DO
520        do i=2,IMR  
521        PU(i,j) = 0.5 * (delp2(i,j,k) + delp2(i-1,j,k))      IF (j1==2) THEN
522        enddo        imh = imr/2
523        enddo        DO i = 1, imh
524  C          va(i, 1) = 0.5*(cry(i,2)-cry(i+imh,2))
525        do j=j1,j2          va(i+imh, 1) = -va(i, 1)
526        PU(1,j) = 0.5 * (delp2(1,j,k) + delp2(IMR,j,k))          va(i, jnp) = 0.5*(cry(i,jnp)-cry(i+imh,jmr))
527        enddo          va(i+imh, jnp) = -va(i, jnp)
528  C        END DO
529        do 110 j=j1,j2        va(imr, 1) = va(1, 1)
530        DO 110 i=1,IMR        va(imr, jnp) = va(1, jnp)
531  110   xmass(i,j) = PU(i,j)*CRX(i,j)      END IF
532  C  
533        DO 120 j=j1,j2      ! ****6***0*********0*********0*********0*********0*********0**********72
534        DO 120 i=1,IMR-1      DO ic = 1, nc
535  120   DPI(i,j,k) = DPI(i,j,k) + xmass(i,j) - xmass(i+1,j)  
536  C        DO i = 1, imjm
537        DO 130 j=j1,j2          wk1(i, 1, 1) = 0.
538  130   DPI(IMR,j,k) = DPI(IMR,j,k) + xmass(IMR,j) - xmass(1,j)          wk1(i, 1, 2) = 0.
539  C        END DO
540        DO j=j1,j2  
541        do i=1,IMR-1        ! E-W advective cross term
542        UA(i,j) = 0.5 * (CRX(i,j)+CRX(i+1,j))        DO j = j1, j2
543        enddo          IF (j>js .AND. j<jn) GO TO 250
544        enddo  
545  C          DO i = 1, imr
546        DO j=j1,j2            qtmp(i) = q(i, j, k, ic)
547        UA(imr,j) = 0.5 * (CRX(imr,j)+CRX(1,j))          END DO
548        enddo  
549  ccccccccccccccccccccccccccccccccccccccccccccccccccccccc          DO i = -iml, 0
550  c Rajouts pour LMDZ.3.3            qtmp(i) = q(imr+i, j, k, ic)
551  ccccccccccccccccccccccccccccccccccccccccccccccccccccccc            qtmp(imr+1-i) = q(1-i, j, k, ic)
552        do i=1,IMR          END DO
553           do j=1,JNP  
554               VA(i,j)=0.          DO i = 1, imr
555           enddo            iu = ua(i, j)
556        enddo            ru = ua(i, j) - iu
557              iiu = i - iu
558        do i=1,imr*(JMR-1)            IF (ua(i,j)>=0.) THEN
559        VA(i,2) = 0.5*(CRY(i,2)+CRY(i,3))              wk1(i, j, 1) = qtmp(iiu) + ru*(qtmp(iiu-1)-qtmp(iiu))
560        enddo            ELSE
561  C              wk1(i, j, 1) = qtmp(iiu) + ru*(qtmp(iiu)-qtmp(iiu+1))
562        if(j1.eq.2) then            END IF
563          IMH = IMR/2            wk1(i, j, 1) = wk1(i, j, 1) - qtmp(i)
564        do i=1,IMH          END DO
565        VA(i,      1) = 0.5*(CRY(i,2)-CRY(i+IMH,2))  250   END DO
566        VA(i+IMH,  1) = -VA(i,1)  
567        VA(i,    JNP) = 0.5*(CRY(i,JNP)-CRY(i+IMH,JMR))        IF (jn/=0) THEN
568        VA(i+IMH,JNP) = -VA(i,JNP)          DO j = js + 1, jn - 1
569        enddo  
570        VA(IMR,1)=VA(1,1)            DO i = 1, imr
571        VA(IMR,JNP)=VA(1,JNP)              qtmp(i) = q(i, j, k, ic)
572        endif            END DO
573  C  
574  C ****6***0*********0*********0*********0*********0*********0**********72            qtmp(0) = q(imr, j, k, ic)
575        do 1000 IC=1,NC            qtmp(imr+1) = q(1, j, k, ic)
576  C  
577        do i=1,IMJM            DO i = 1, imr
578        wk1(i,1,1) = 0.              iu = i - ua(i, j)
579        wk1(i,1,2) = 0.              wk1(i, j, 1) = ua(i, j)*(qtmp(iu)-qtmp(iu+1))
580        enddo            END DO
581  C          END DO
582  C E-W advective cross term        END IF
583        do 250 j=J1,J2        ! ****6***0*********0*********0*********0*********0*********0**********72
584        if(J.GT.JS  .and. J.LT.JN) GO TO 250        ! Contribution from the N-S advection
585  C        DO i = 1, imr*(j2-j1+1)
586        do i=1,IMR          jt = float(j1) - va(i, j1)
587        qtmp(i) = q(i,j,k,IC)          wk1(i, j1, 2) = va(i, j1)*(q(i,jt,k,ic)-q(i,jt+1,k,ic))
588        enddo        END DO
589  C  
590        do i=-IML,0        DO i = 1, imjm
591        qtmp(i)       = q(IMR+i,j,k,IC)          wk1(i, 1, 1) = q(i, 1, k, ic) + 0.5*wk1(i, 1, 1)
592        qtmp(IMR+1-i) = q(1-i,j,k,IC)          wk1(i, 1, 2) = q(i, 1, k, ic) + 0.5*wk1(i, 1, 2)
593        enddo        END DO
594  C  
595        DO 230 i=1,IMR        IF (cross) THEN
596        iu = UA(i,j)          ! Add cross terms in the vertical direction.
597        ru = UA(i,j) - iu          IF (iord>=2) THEN
598        iiu = i-iu            iad = 2
599        if(UA(i,j).GE.0.) then          ELSE
600        wk1(i,j,1) = qtmp(iiu)+ru*(qtmp(iiu-1)-qtmp(iiu))            iad = 1
601        else          END IF
602        wk1(i,j,1) = qtmp(iiu)+ru*(qtmp(iiu)-qtmp(iiu+1))  
603        endif          IF (jord>=2) THEN
604        wk1(i,j,1) = wk1(i,j,1) - qtmp(i)            jad = 2
605  230   continue          ELSE
606  250   continue            jad = 1
607  C          END IF
608        if(JN.ne.0) then          CALL xadv(imr, jnp, j1, j2, wk1(1,1,2), ua, js, jn, iml, dc2, iad)
609        do j=JS+1,JN-1          CALL yadv(imr, jnp, j1, j2, wk1(1,1,1), va, pv, w, jad)
610  C          DO j = 1, jnp
611        do i=1,IMR            DO i = 1, imr
612        qtmp(i) = q(i,j,k,IC)              q(i, j, k, ic) = q(i, j, k, ic) + dc2(i, j) + pv(i, j)
613        enddo            END DO
614  C          END DO
615        qtmp(0)     = q(IMR,J,k,IC)        END IF
616        qtmp(IMR+1) = q(  1,J,k,IC)  
617  C        CALL xtp(imr, jnp, iml, j1, j2, jn, js, pu, dq(1,1,k,ic), wk1(1,1,2), &
618        do i=1,imr          crx, fx1, xmass, iord)
619        iu = i - UA(i,j)  
620        wk1(i,j,1) = UA(i,j)*(qtmp(iu) - qtmp(iu+1))        CALL ytp(imr, jnp, j1, j2, acosp, rcap, dq(1,1,k,ic), wk1(1,1,1), cry, &
621        enddo          dc2, ymass, wk1(1,1,3), wk1(1,1,4), wk1(1,1,5), wk1(1,1,6), jord)
622        enddo  
623        endif      END DO
624  C ****6***0*********0*********0*********0*********0*********0**********72    END DO
625  C Contribution from the N-S advection  
626        do i=1,imr*(j2-j1+1)    ! ******* Compute vertical mass flux (same unit as PS) ***********
627        JT = float(J1) - VA(i,j1)  
628        wk1(i,j1,2) = VA(i,j1) * (q(i,jt,k,IC) - q(i,jt+1,k,IC))    ! 1st step: compute total column mass CONVERGENCE.
629        enddo  
630  C    DO j = 1, jnp
631        do i=1,IMJM      DO i = 1, imr
632        wk1(i,1,1) = q(i,1,k,IC) + 0.5*wk1(i,1,1)        cry(i, j) = dpi(i, j, 1)
633        wk1(i,1,2) = q(i,1,k,IC) + 0.5*wk1(i,1,2)      END DO
634        enddo    END DO
635  C  
636          if(cross) then    DO k = 2, nlay
637  C Add cross terms in the vertical direction.      DO j = 1, jnp
638          if(IORD .GE. 2) then        DO i = 1, imr
639                  iad = 2          cry(i, j) = cry(i, j) + dpi(i, j, k)
640          else        END DO
641                  iad = 1      END DO
642          endif    END DO
643  C  
644          if(JORD .GE. 2) then    DO j = 1, jnp
645                  jad = 2      DO i = 1, imr
646          else  
647                  jad = 1        ! 2nd step: compute PS2 (PS at n+1) using the hydrostatic assumption.
648          endif        ! Changes (increases) to surface pressure = total column mass
649        call xadv(IMR,JNP,j1,j2,wk1(1,1,2),UA,JS,JN,IML,DC2,iad)        ! convergence
650        call yadv(IMR,JNP,j1,j2,wk1(1,1,1),VA,PV,W,jad)  
651        do j=1,JNP        ps2(i, j) = ps1(i, j) + cry(i, j)
652        do i=1,IMR  
653        q(i,j,k,IC) = q(i,j,k,IC) + DC2(i,j) + PV(i,j)        ! 3rd step: compute vertical mass flux from mass conservation
654        enddo        ! principle.
655        enddo  
656        endif        w(i, j, 1) = dpi(i, j, 1) - dbk(1)*cry(i, j)
657  C        w(i, j, nlay) = 0.
658        call xtp(IMR,JNP,IML,j1,j2,JN,JS,PU,DQ(1,1,k,IC),wk1(1,1,2)      END DO
659       &        ,CRX,fx1,xmass,IORD)    END DO
660    
661        call ytp(IMR,JNP,j1,j2,acosp,RCAP,DQ(1,1,k,IC),wk1(1,1,1),CRY,    DO k = 2, nlay - 1
662       &  DC2,ymass,WK1(1,1,3),wk1(1,1,4),WK1(1,1,5),WK1(1,1,6),JORD)      DO j = 1, jnp
663  C        DO i = 1, imr
664  1000  continue          w(i, j, k) = w(i, j, k-1) + dpi(i, j, k) - dbk(k)*cry(i, j)
665  1500  continue        END DO
666  C      END DO
667  C ******* Compute vertical mass flux (same unit as PS) ***********    END DO
668  C  
669  C 1st step: compute total column mass CONVERGENCE.    DO k = 1, nlay
670  C      DO j = 1, jnp
671        do 320 j=1,JNP        DO i = 1, imr
672        do 320 i=1,IMR          delp2(i, j, k) = dap(k) + dbk(k)*ps2(i, j)
673  320   CRY(i,j) = DPI(i,j,1)        END DO
674  C      END DO
675        do 330 k=2,NLAY    END DO
676        do 330 j=1,JNP  
677        do 330 i=1,IMR    krd = max(3, kord)
678        CRY(i,j)  = CRY(i,j) + DPI(i,j,k)    DO ic = 1, nc
679  330   continue  
680  C      ! ****6***0*********0*********0*********0*********0*********0**********72
681        do 360 j=1,JNP  
682        do 360 i=1,IMR      CALL fzppm(imr, jnp, nlay, j1, dq(1,1,1,ic), w, q(1,1,1,ic), wk1, dpi, &
683  C        dc2, crx, cry, pu, pv, xmass, ymass, delp1, krd)
684  C 2nd step: compute PS2 (PS at n+1) using the hydrostatic assumption.  
685  C Changes (increases) to surface pressure = total column mass convergence  
686  C      IF (fill) CALL qckxyz(dq(1,1,1,ic), dc2, imr, jnp, nlay, j1, j2, cosp, &
687        PS2(i,j)  = PS1(i,j) + CRY(i,j)        acosp, .FALSE., ic, nstep)
688  C  
689  C 3rd step: compute vertical mass flux from mass conservation principle.      ! Recover tracer mixing ratio from "density" using predicted
690  C      ! "air density" (pressure thickness) at time-level n+1
691        W(i,j,1) = DPI(i,j,1) - DBK(1)*CRY(i,j)  
692        W(i,j,NLAY) = 0.      DO k = 1, nlay
693  360   continue        DO j = 1, jnp
694  C          DO i = 1, imr
695        do 370 k=2,NLAY-1            q(i, j, k, ic) = dq(i, j, k, ic)/delp2(i, j, k)
696        do 370 j=1,JNP          END DO
697        do 370 i=1,IMR        END DO
698        W(i,j,k) = W(i,j,k-1) + DPI(i,j,k) - DBK(k)*CRY(i,j)      END DO
699  370   continue  
700  C      IF (j1/=2) THEN
701        DO 380 k=1,NLAY        DO k = 1, nlay
702        DO 380 j=1,JNP          DO i = 1, imr
703        DO 380 i=1,IMR            ! j=1 c'est le pôle Sud, j=JNP c'est le pôle Nord
704        delp2(i,j,k) = DAP(k) + DBK(k)*PS2(i,j)            q(i, 2, k, ic) = q(i, 1, k, ic)
705  380   continue            q(i, jmr, k, ic) = q(i, jmp, k, ic)
706  C          END DO
707          KRD = max(3, KORD)        END DO
708        do 4000 IC=1,NC      END IF
709  C    END DO
710  C****6***0*********0*********0*********0*********0*********0**********72  
711        IF (j1/=2) THEN
712        call FZPPM(IMR,JNP,NLAY,j1,DQ(1,1,1,IC),W,Q(1,1,1,IC),WK1,DPI,      DO k = 1, nlay
713       &           DC2,CRX,CRY,PU,PV,xmass,ymass,delp1,KRD)        DO i = 1, imr
714  C          w(i, 2, k) = w(i, 1, k)
715                w(i, jmr, k) = w(i, jnp, k)
716        if(fill) call qckxyz(DQ(1,1,1,IC),DC2,IMR,JNP,NLAY,j1,j2,        END DO
717       &                     cosp,acosp,.false.,IC,NSTEP)      END DO
718  C    END IF
719  C Recover tracer mixing ratio from "density" using predicted  
720  C "air density" (pressure thickness) at time-level n+1    RETURN
721  C  END SUBROUTINE ppm3d
722        DO k=1,NLAY  
723        DO j=1,JNP  ! ****6***0*********0*********0*********0*********0*********0**********72
       DO i=1,IMR  
             Q(i,j,k,IC) = DQ(i,j,k,IC) / delp2(i,j,k)  
       enddo  
       enddo  
       enddo  
 C      
       if(j1.ne.2) then  
       DO 400 k=1,NLAY  
       DO 400 I=1,IMR  
 c     j=1 c'est le pôle Sud, j=JNP c'est le pôle Nord  
       Q(I,  2,k,IC) = Q(I,  1,k,IC)  
       Q(I,JMR,k,IC) = Q(I,JMP,k,IC)  
 400   CONTINUE  
       endif  
 4000  continue  
 C  
       if(j1.ne.2) then  
       DO 5000 k=1,NLAY  
       DO 5000 i=1,IMR  
       W(i,  2,k) = W(i,  1,k)  
       W(i,JMR,k) = W(i,JNP,k)  
 5000  continue  
       endif  
 C  
       RETURN  
       END  
 C  
 C****6***0*********0*********0*********0*********0*********0**********72  
       subroutine FZPPM(IMR,JNP,NLAY,j1,DQ,WZ,P,DC,DQDT,AR,AL,A6,  
      &                 flux,wk1,wk2,wz2,delp,KORD)  
       parameter ( kmax = 150 )  
       parameter ( R23 = 2./3., R3 = 1./3.)  
       real WZ(IMR,JNP,NLAY),P(IMR,JNP,NLAY),DC(IMR,JNP,NLAY),  
      &     wk1(IMR,*),delp(IMR,JNP,NLAY),DQ(IMR,JNP,NLAY),  
      &     DQDT(IMR,JNP,NLAY)  
 C Assuming JNP >= NLAY  
       real AR(IMR,*),AL(IMR,*),A6(IMR,*),flux(IMR,*),wk2(IMR,*),  
      &     wz2(IMR,*)  
 C  
       JMR = JNP - 1  
       IMJM = IMR*JNP  
       NLAYM1 = NLAY - 1  
 C  
       LMT = KORD - 3  
 C  
 C ****6***0*********0*********0*********0*********0*********0**********72  
 C Compute DC for PPM  
 C ****6***0*********0*********0*********0*********0*********0**********72  
 C  
       do 1000 k=1,NLAYM1  
       do 1000 i=1,IMJM  
       DQDT(i,1,k) = P(i,1,k+1) - P(i,1,k)  
 1000  continue  
 C  
       DO 1220 k=2,NLAYM1  
       DO 1220 I=1,IMJM      
        c0 =  delp(i,1,k) / (delp(i,1,k-1)+delp(i,1,k)+delp(i,1,k+1))  
        c1 = (delp(i,1,k-1)+0.5*delp(i,1,k))/(delp(i,1,k+1)+delp(i,1,k))      
        c2 = (delp(i,1,k+1)+0.5*delp(i,1,k))/(delp(i,1,k-1)+delp(i,1,k))  
       tmp = c0*(c1*DQDT(i,1,k) + c2*DQDT(i,1,k-1))  
       Qmax = max(P(i,1,k-1),P(i,1,k),P(i,1,k+1)) - P(i,1,k)  
       Qmin = P(i,1,k) - min(P(i,1,k-1),P(i,1,k),P(i,1,k+1))  
       DC(i,1,k) = sign(min(abs(tmp),Qmax,Qmin), tmp)    
 1220  CONTINUE  
       
 C      
 C ****6***0*********0*********0*********0*********0*********0**********72  
 C Loop over latitudes  (to save memory)  
 C ****6***0*********0*********0*********0*********0*********0**********72  
 C  
       DO 2000 j=1,JNP  
       if((j.eq.2 .or. j.eq.JMR) .and. j1.ne.2) goto 2000  
 C  
       DO k=1,NLAY  
       DO i=1,IMR  
       wz2(i,k) =   WZ(i,j,k)  
       wk1(i,k) =    P(i,j,k)  
       wk2(i,k) = delp(i,j,k)  
       flux(i,k) = DC(i,j,k)  !this flux is actually the monotone slope  
       enddo  
       enddo  
 C  
 C****6***0*********0*********0*********0*********0*********0**********72  
 C Compute first guesses at cell interfaces  
 C First guesses are required to be continuous.  
 C ****6***0*********0*********0*********0*********0*********0**********72  
 C  
 C three-cell parabolic subgrid distribution at model top  
 C two-cell parabolic with zero gradient subgrid distribution  
 C at the surface.  
 C  
 C First guess top edge value  
       DO 10 i=1,IMR  
 C three-cell PPM  
 C Compute a,b, and c of q = aP**2 + bP + c using cell averages and delp  
       a = 3.*( DQDT(i,j,2) - DQDT(i,j,1)*(wk2(i,2)+wk2(i,3))/  
      &         (wk2(i,1)+wk2(i,2)) ) /  
      &       ( (wk2(i,2)+wk2(i,3))*(wk2(i,1)+wk2(i,2)+wk2(i,3)) )  
       b = 2.*DQDT(i,j,1)/(wk2(i,1)+wk2(i,2)) -  
      &    R23*a*(2.*wk2(i,1)+wk2(i,2))  
       AL(i,1) =  wk1(i,1) - wk2(i,1)*(R3*a*wk2(i,1) + 0.5*b)  
       AL(i,2) =  wk2(i,1)*(a*wk2(i,1) + b) + AL(i,1)  
 C  
 C Check if change sign  
       if(wk1(i,1)*AL(i,1).le.0.) then  
                  AL(i,1) = 0.  
              flux(i,1) = 0.  
         else  
              flux(i,1) =  wk1(i,1) - AL(i,1)  
         endif  
 10    continue  
 C  
 C Bottom  
       DO 15 i=1,IMR  
 C 2-cell PPM with zero gradient right at the surface  
 C  
       fct = DQDT(i,j,NLAYM1)*wk2(i,NLAY)**2 /  
      & ( (wk2(i,NLAY)+wk2(i,NLAYM1))*(2.*wk2(i,NLAY)+wk2(i,NLAYM1)))  
       AR(i,NLAY) = wk1(i,NLAY) + fct  
       AL(i,NLAY) = wk1(i,NLAY) - (fct+fct)  
       if(wk1(i,NLAY)*AR(i,NLAY).le.0.) AR(i,NLAY) = 0.  
       flux(i,NLAY) = AR(i,NLAY) -  wk1(i,NLAY)  
 15    continue  
       
 C  
 C****6***0*********0*********0*********0*********0*********0**********72  
 C 4th order interpolation in the interior.  
 C****6***0*********0*********0*********0*********0*********0**********72  
 C  
       DO 14 k=3,NLAYM1  
       DO 12 i=1,IMR  
       c1 =  DQDT(i,j,k-1)*wk2(i,k-1) / (wk2(i,k-1)+wk2(i,k))  
       c2 =  2. / (wk2(i,k-2)+wk2(i,k-1)+wk2(i,k)+wk2(i,k+1))  
       A1   =  (wk2(i,k-2)+wk2(i,k-1)) / (2.*wk2(i,k-1)+wk2(i,k))  
       A2   =  (wk2(i,k  )+wk2(i,k+1)) / (2.*wk2(i,k)+wk2(i,k-1))  
       AL(i,k) = wk1(i,k-1) + c1 + c2 *  
      &        ( wk2(i,k  )*(c1*(A1 - A2)+A2*flux(i,k-1)) -  
      &          wk2(i,k-1)*A1*flux(i,k)  )  
 12    CONTINUE  
 14    continue  
 C  
       do 20 i=1,IMR*NLAYM1  
       AR(i,1) = AL(i,2)  
 20    continue  
 C  
       do 30 i=1,IMR*NLAY  
       A6(i,1) = 3.*(wk1(i,1)+wk1(i,1) - (AL(i,1)+AR(i,1)))  
 30    continue  
 C  
 C****6***0*********0*********0*********0*********0*********0**********72  
 C Top & Bot always monotonic  
       call lmtppm(flux(1,1),A6(1,1),AR(1,1),AL(1,1),wk1(1,1),IMR,0)  
       call lmtppm(flux(1,NLAY),A6(1,NLAY),AR(1,NLAY),AL(1,NLAY),  
      &            wk1(1,NLAY),IMR,0)  
 C  
 C Interior depending on KORD  
       if(LMT.LE.2)  
      &  call lmtppm(flux(1,2),A6(1,2),AR(1,2),AL(1,2),wk1(1,2),  
      &              IMR*(NLAY-2),LMT)  
 C  
 C****6***0*********0*********0*********0*********0*********0**********72  
 C  
       DO 140 i=1,IMR*NLAYM1  
       IF(wz2(i,1).GT.0.) then  
         CM = wz2(i,1) / wk2(i,1)  
         flux(i,2) = AR(i,1)+0.5*CM*(AL(i,1)-AR(i,1)+A6(i,1)*(1.-R23*CM))  
       else  
         CP= wz2(i,1) / wk2(i,2)          
         flux(i,2) = AL(i,2)+0.5*CP*(AL(i,2)-AR(i,2)-A6(i,2)*(1.+R23*CP))  
       endif  
 140   continue  
 C  
       DO 250 i=1,IMR*NLAYM1  
       flux(i,2) = wz2(i,1) * flux(i,2)  
 250   continue  
 C  
       do 350 i=1,IMR  
       DQ(i,j,   1) = DQ(i,j,   1) - flux(i,   2)  
       DQ(i,j,NLAY) = DQ(i,j,NLAY) + flux(i,NLAY)  
 350   continue  
 C  
       do 360 k=2,NLAYM1  
       do 360 i=1,IMR  
 360   DQ(i,j,k) = DQ(i,j,k) + flux(i,k) - flux(i,k+1)  
 2000  continue  
       return  
       end  
 C  
       subroutine xtp(IMR,JNP,IML,j1,j2,JN,JS,PU,DQ,Q,UC,  
      &               fx1,xmass,IORD)  
       dimension UC(IMR,*),DC(-IML:IMR+IML+1),xmass(IMR,JNP)  
      &    ,fx1(IMR+1),DQ(IMR,JNP),qtmp(-IML:IMR+1+IML)  
       dimension PU(IMR,JNP),Q(IMR,JNP),ISAVE(IMR)  
 C  
       IMP = IMR + 1  
 C  
 C van Leer at high latitudes  
       jvan = max(1,JNP/18)  
       j1vl = j1+jvan  
       j2vl = j2-jvan  
 C  
       do 1310 j=j1,j2  
 C  
       do i=1,IMR  
       qtmp(i) = q(i,j)  
       enddo  
 C  
       if(j.ge.JN .or. j.le.JS) goto 2222  
 C ************* Eulerian **********  
 C  
       qtmp(0)     = q(IMR,J)  
       qtmp(-1)    = q(IMR-1,J)  
       qtmp(IMP)   = q(1,J)  
       qtmp(IMP+1) = q(2,J)  
 C  
       IF(IORD.eq.1 .or. j.eq.j1. or. j.eq.j2) THEN  
       DO 1406 i=1,IMR  
       iu = float(i) - uc(i,j)  
 1406  fx1(i) = qtmp(iu)  
       ELSE  
       call xmist(IMR,IML,Qtmp,DC)  
       DC(0) = DC(IMR)  
 C  
       if(IORD.eq.2 .or. j.le.j1vl .or. j.ge.j2vl) then  
       DO 1408 i=1,IMR  
       iu = float(i) - uc(i,j)  
 1408  fx1(i) = qtmp(iu) + DC(iu)*(sign(1.,uc(i,j))-uc(i,j))  
       else  
       call fxppm(IMR,IML,UC(1,j),Qtmp,DC,fx1,IORD)  
       endif  
 C  
       ENDIF  
 C  
       DO 1506 i=1,IMR  
 1506  fx1(i) = fx1(i)*xmass(i,j)  
 C  
       goto 1309  
 C  
 C ***** Conservative (flux-form) Semi-Lagrangian transport *****  
 C  
 2222  continue  
 C  
       do i=-IML,0  
       qtmp(i)     = q(IMR+i,j)  
       qtmp(IMP-i) = q(1-i,j)  
       enddo  
 C  
       IF(IORD.eq.1 .or. j.eq.j1. or. j.eq.j2) THEN  
       DO 1306 i=1,IMR  
       itmp = INT(uc(i,j))  
       ISAVE(i) = i - itmp  
       iu = i - uc(i,j)  
 1306  fx1(i) = (uc(i,j) - itmp)*qtmp(iu)  
       ELSE  
       call xmist(IMR,IML,Qtmp,DC)  
 C  
       do i=-IML,0  
       DC(i)     = DC(IMR+i)  
       DC(IMP-i) = DC(1-i)  
       enddo  
 C  
       DO 1307 i=1,IMR  
       itmp = INT(uc(i,j))  
       rut  = uc(i,j) - itmp  
       ISAVE(i) = i - itmp  
       iu = i - uc(i,j)  
 1307  fx1(i) = rut*(qtmp(iu) + DC(iu)*(sign(1.,rut) - rut))  
       ENDIF  
 C  
       do 1308 i=1,IMR  
       IF(uc(i,j).GT.1.) then  
 CDIR$ NOVECTOR  
         do ist = ISAVE(i),i-1  
         fx1(i) = fx1(i) + qtmp(ist)  
         enddo  
       elseIF(uc(i,j).LT.-1.) then  
         do ist = i,ISAVE(i)-1  
         fx1(i) = fx1(i) - qtmp(ist)  
         enddo  
 CDIR$ VECTOR  
       endif  
 1308  continue  
       do i=1,IMR  
       fx1(i) = PU(i,j)*fx1(i)  
       enddo  
 C  
 C ***************************************  
 C  
 1309  fx1(IMP) = fx1(1)  
       DO 1215 i=1,IMR  
 1215  DQ(i,j) =  DQ(i,j) + fx1(i)-fx1(i+1)  
 C  
 C ***************************************  
 C  
 1310  continue  
       return  
       end  
 C  
       subroutine fxppm(IMR,IML,UT,P,DC,flux,IORD)  
       parameter ( R3 = 1./3., R23 = 2./3. )  
       DIMENSION UT(*),flux(*),P(-IML:IMR+IML+1),DC(-IML:IMR+IML+1)  
       DIMENSION AR(0:IMR),AL(0:IMR),A6(0:IMR)  
       integer LMT  
 c      logical first  
 c      data first /.true./  
 c      SAVE LMT  
 c      if(first) then  
 C  
 C correction calcul de LMT a chaque passage pour pouvoir choisir  
 c plusieurs schemas PPM pour differents traceurs  
 c      IF (IORD.LE.0) then  
 c            if(IMR.GE.144) then  
 c                  LMT = 0  
 c            elseif(IMR.GE.72) then  
 c                  LMT = 1  
 c            else  
 c                  LMT = 2  
 c            endif  
 c      else  
 c            LMT = IORD - 3  
 c      endif  
 C  
       LMT = IORD - 3  
   
       DO 10 i=1,IMR  
 10    AL(i) = 0.5*(p(i-1)+p(i)) + (DC(i-1) - DC(i))*R3  
 C  
       do 20 i=1,IMR-1  
 20    AR(i) = AL(i+1)  
       AR(IMR) = AL(1)  
 C  
       do 30 i=1,IMR  
 30    A6(i) = 3.*(p(i)+p(i)  - (AL(i)+AR(i)))  
 C  
       if(LMT.LE.2) call lmtppm(DC(1),A6(1),AR(1),AL(1),P(1),IMR,LMT)  
 C  
       AL(0) = AL(IMR)  
       AR(0) = AR(IMR)  
       A6(0) = A6(IMR)  
 C  
       DO i=1,IMR  
       IF(UT(i).GT.0.) then  
       flux(i) = AR(i-1) + 0.5*UT(i)*(AL(i-1) - AR(i-1) +  
      &                 A6(i-1)*(1.-R23*UT(i)) )  
       else  
       flux(i) = AL(i) - 0.5*UT(i)*(AR(i) - AL(i) +  
      &                        A6(i)*(1.+R23*UT(i)))  
       endif  
       enddo  
       return  
       end  
 C  
       subroutine xmist(IMR,IML,P,DC)  
       parameter( R24 = 1./24.)  
       dimension P(-IML:IMR+1+IML),DC(-IML:IMR+1+IML)  
 C  
       do 10  i=1,IMR  
       tmp = R24*(8.*(p(i+1) - p(i-1)) + p(i-2) - p(i+2))  
       Pmax = max(P(i-1), p(i), p(i+1)) - p(i)  
       Pmin = p(i) - min(P(i-1), p(i), p(i+1))  
 10    DC(i) = sign(min(abs(tmp),Pmax,Pmin), tmp)  
       return  
       end  
 C  
       subroutine ytp(IMR,JNP,j1,j2,acosp,RCAP,DQ,P,VC,DC2  
      &              ,ymass,fx,A6,AR,AL,JORD)  
       dimension P(IMR,JNP),VC(IMR,JNP),ymass(IMR,JNP)  
      &       ,DC2(IMR,JNP),DQ(IMR,JNP),acosp(JNP)  
 C Work array  
       DIMENSION fx(IMR,JNP),AR(IMR,JNP),AL(IMR,JNP),A6(IMR,JNP)  
 C  
       JMR = JNP - 1  
       len = IMR*(J2-J1+2)  
 C  
       if(JORD.eq.1) then  
       DO 1000 i=1,len  
       JT = float(J1) - VC(i,J1)  
 1000  fx(i,j1) = p(i,JT)  
       else  
     
       call ymist(IMR,JNP,j1,P,DC2,4)  
 C  
       if(JORD.LE.0 .or. JORD.GE.3) then  
     
       call fyppm(VC,P,DC2,fx,IMR,JNP,j1,j2,A6,AR,AL,JORD)  
       
       else  
       DO 1200 i=1,len  
       JT = float(J1) - VC(i,J1)  
 1200  fx(i,j1) = p(i,JT) + (sign(1.,VC(i,j1))-VC(i,j1))*DC2(i,JT)  
       endif  
       endif  
 C  
       DO 1300 i=1,len  
 1300  fx(i,j1) = fx(i,j1)*ymass(i,j1)  
 C  
       DO 1400 j=j1,j2  
       DO 1400 i=1,IMR  
 1400  DQ(i,j) = DQ(i,j) + (fx(i,j) - fx(i,j+1)) * acosp(j)  
 C  
 C Poles  
       sum1 = fx(IMR,j1  )  
       sum2 = fx(IMR,J2+1)  
       do i=1,IMR-1  
       sum1 = sum1 + fx(i,j1  )  
       sum2 = sum2 + fx(i,J2+1)  
       enddo  
 C  
       sum1 = DQ(1,  1) - sum1 * RCAP  
       sum2 = DQ(1,JNP) + sum2 * RCAP  
       do i=1,IMR  
       DQ(i,  1) = sum1  
       DQ(i,JNP) = sum2  
       enddo  
 C  
       if(j1.ne.2) then  
       do i=1,IMR  
       DQ(i,  2) = sum1  
       DQ(i,JMR) = sum2  
       enddo  
       endif  
 C  
       return  
       end  
 C  
       subroutine  ymist(IMR,JNP,j1,P,DC,ID)  
       parameter ( R24 = 1./24. )  
       dimension P(IMR,JNP),DC(IMR,JNP)  
 C  
       IMH = IMR / 2  
       JMR = JNP - 1  
       IJM3 = IMR*(JMR-3)  
 C  
       IF(ID.EQ.2) THEN  
       do 10 i=1,IMR*(JMR-1)  
       tmp = 0.25*(p(i,3) - p(i,1))  
       Pmax = max(p(i,1),p(i,2),p(i,3)) - p(i,2)  
       Pmin = p(i,2) - min(p(i,1),p(i,2),p(i,3))  
       DC(i,2) = sign(min(abs(tmp),Pmin,Pmax),tmp)  
 10    CONTINUE  
       ELSE  
       do 12 i=1,IMH  
 C J=2  
       tmp = (8.*(p(i,3) - p(i,1)) + p(i+IMH,2) - p(i,4))*R24  
       Pmax = max(p(i,1),p(i,2),p(i,3)) - p(i,2)  
       Pmin = p(i,2) - min(p(i,1),p(i,2),p(i,3))  
       DC(i,2) = sign(min(abs(tmp),Pmin,Pmax),tmp)  
 C J=JMR  
       tmp=(8.*(p(i,JNP)-p(i,JMR-1))+p(i,JMR-2)-p(i+IMH,JMR))*R24  
       Pmax = max(p(i,JMR-1),p(i,JMR),p(i,JNP)) - p(i,JMR)  
       Pmin = p(i,JMR) - min(p(i,JMR-1),p(i,JMR),p(i,JNP))  
       DC(i,JMR) = sign(min(abs(tmp),Pmin,Pmax),tmp)  
 12    CONTINUE  
       do 14 i=IMH+1,IMR  
 C J=2  
       tmp = (8.*(p(i,3) - p(i,1)) + p(i-IMH,2) - p(i,4))*R24  
       Pmax = max(p(i,1),p(i,2),p(i,3)) - p(i,2)  
       Pmin = p(i,2) - min(p(i,1),p(i,2),p(i,3))  
       DC(i,2) = sign(min(abs(tmp),Pmin,Pmax),tmp)  
 C J=JMR  
       tmp=(8.*(p(i,JNP)-p(i,JMR-1))+p(i,JMR-2)-p(i-IMH,JMR))*R24  
       Pmax = max(p(i,JMR-1),p(i,JMR),p(i,JNP)) - p(i,JMR)  
       Pmin = p(i,JMR) - min(p(i,JMR-1),p(i,JMR),p(i,JNP))  
       DC(i,JMR) = sign(min(abs(tmp),Pmin,Pmax),tmp)  
 14    CONTINUE  
 C  
       do 15 i=1,IJM3  
       tmp = (8.*(p(i,4) - p(i,2)) + p(i,1) - p(i,5))*R24  
       Pmax = max(p(i,2),p(i,3),p(i,4)) - p(i,3)  
       Pmin = p(i,3) - min(p(i,2),p(i,3),p(i,4))  
       DC(i,3) = sign(min(abs(tmp),Pmin,Pmax),tmp)  
 15    CONTINUE  
       ENDIF  
 C  
       if(j1.ne.2) then  
       do i=1,IMR  
       DC(i,1) = 0.  
       DC(i,JNP) = 0.  
       enddo  
       else  
 C Determine slopes in polar caps for scalars!  
 C  
       do 13 i=1,IMH  
 C South  
       tmp = 0.25*(p(i,2) - p(i+imh,2))  
       Pmax = max(p(i,2),p(i,1), p(i+imh,2)) - p(i,1)  
       Pmin = p(i,1) - min(p(i,2),p(i,1), p(i+imh,2))  
       DC(i,1)=sign(min(abs(tmp),Pmax,Pmin),tmp)  
 C North.  
       tmp = 0.25*(p(i+imh,JMR) - p(i,JMR))  
       Pmax = max(p(i+imh,JMR),p(i,jnp), p(i,JMR)) - p(i,JNP)  
       Pmin = p(i,JNP) - min(p(i+imh,JMR),p(i,jnp), p(i,JMR))  
       DC(i,JNP) = sign(min(abs(tmp),Pmax,pmin),tmp)  
 13    continue  
 C  
       do 25 i=imh+1,IMR  
       DC(i,  1) =  - DC(i-imh,  1)  
       DC(i,JNP) =  - DC(i-imh,JNP)  
 25    continue  
       endif  
       return  
       end  
 C  
       subroutine fyppm(VC,P,DC,flux,IMR,JNP,j1,j2,A6,AR,AL,JORD)  
       parameter ( R3 = 1./3., R23 = 2./3. )  
       real VC(IMR,*),flux(IMR,*),P(IMR,*),DC(IMR,*)  
 C Local work arrays.  
       real AR(IMR,JNP),AL(IMR,JNP),A6(IMR,JNP)  
       integer LMT  
 c      logical first  
 C      data first /.true./  
 C      SAVE LMT  
 C  
       IMH = IMR / 2  
       JMR = JNP - 1  
       j11 = j1-1  
       IMJM1 = IMR*(J2-J1+2)  
       len   = IMR*(J2-J1+3)  
 C      if(first) then  
 C      IF(JORD.LE.0) then  
 C            if(JMR.GE.90) then  
 C                  LMT = 0  
 C            elseif(JMR.GE.45) then  
 C                  LMT = 1  
 C            else  
 C                  LMT = 2  
 C            endif  
 C      else  
 C            LMT = JORD - 3  
 C      endif  
 C  
 C      first = .false.  
 C      endif  
 C      
 c modifs pour pouvoir choisir plusieurs schemas PPM  
       LMT = JORD - 3        
 C  
       DO 10 i=1,IMR*JMR          
       AL(i,2) = 0.5*(p(i,1)+p(i,2)) + (DC(i,1) - DC(i,2))*R3  
       AR(i,1) = AL(i,2)  
 10    CONTINUE  
 C  
 CPoles:  
 C  
       DO i=1,IMH  
       AL(i,1) = AL(i+IMH,2)  
       AL(i+IMH,1) = AL(i,2)  
 C  
       AR(i,JNP) = AR(i+IMH,JMR)  
       AR(i+IMH,JNP) = AR(i,JMR)  
       ENDDO  
   
 ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc  
 c   Rajout pour LMDZ.3.3  
 cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc  
       AR(IMR,1)=AL(1,1)  
       AR(IMR,JNP)=AL(1,JNP)  
 ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc  
         
             
       do 30 i=1,len  
 30    A6(i,j11) = 3.*(p(i,j11)+p(i,j11)  - (AL(i,j11)+AR(i,j11)))  
 C  
       if(LMT.le.2) call lmtppm(DC(1,j11),A6(1,j11),AR(1,j11)  
      &                       ,AL(1,j11),P(1,j11),len,LMT)  
 C  
       
       DO 140 i=1,IMJM1  
       IF(VC(i,j1).GT.0.) then  
       flux(i,j1) = AR(i,j11) + 0.5*VC(i,j1)*(AL(i,j11) - AR(i,j11) +  
      &                         A6(i,j11)*(1.-R23*VC(i,j1)) )  
       else  
       flux(i,j1) = AL(i,j1) - 0.5*VC(i,j1)*(AR(i,j1) - AL(i,j1) +  
      &                        A6(i,j1)*(1.+R23*VC(i,j1)))  
       endif  
 140   continue  
       return  
       end  
 C  
         subroutine yadv(IMR,JNP,j1,j2,p,VA,ady,wk,IAD)  
         REAL p(IMR,JNP),ady(IMR,JNP),VA(IMR,JNP)  
         REAL WK(IMR,-1:JNP+2)  
 C  
         JMR = JNP-1  
         IMH = IMR/2  
         do j=1,JNP  
         do i=1,IMR  
         wk(i,j) = p(i,j)  
         enddo  
         enddo  
 C Poles:  
         do i=1,IMH  
         wk(i,   -1) = p(i+IMH,3)  
         wk(i+IMH,-1) = p(i,3)  
         wk(i,    0) = p(i+IMH,2)  
         wk(i+IMH,0) = p(i,2)  
         wk(i,JNP+1) = p(i+IMH,JMR)  
         wk(i+IMH,JNP+1) = p(i,JMR)  
         wk(i,JNP+2) = p(i+IMH,JNP-2)  
         wk(i+IMH,JNP+2) = p(i,JNP-2)  
         enddo  
   
       IF(IAD.eq.2) then  
       do j=j1-1,j2+1  
       do i=1,IMR  
       JP = NINT(VA(i,j))        
       rv = JP - VA(i,j)  
       JP = j - JP  
       a1 = 0.5*(wk(i,jp+1)+wk(i,jp-1)) - wk(i,jp)  
       b1 = 0.5*(wk(i,jp+1)-wk(i,jp-1))  
       ady(i,j) = wk(i,jp) + rv*(a1*rv + b1) - wk(i,j)  
       enddo  
       enddo  
   
       ELSEIF(IAD.eq.1) then  
         do j=j1-1,j2+1  
       do i=1,imr  
       JP = float(j)-VA(i,j)  
       ady(i,j) = VA(i,j)*(wk(i,jp)-wk(i,jp+1))  
       enddo  
       enddo  
       ENDIF  
 C  
         if(j1.ne.2) then  
         sum1 = 0.  
         sum2 = 0.  
       do i=1,imr  
       sum1 = sum1 + ady(i,2)  
       sum2 = sum2 + ady(i,JMR)  
       enddo  
         sum1 = sum1 / IMR  
         sum2 = sum2 / IMR  
 C  
       do i=1,imr  
       ady(i,  2) =  sum1  
       ady(i,JMR) =  sum2  
       ady(i,  1) =  sum1  
       ady(i,JNP) =  sum2  
       enddo  
         else  
 C Poles:  
         sum1 = 0.  
         sum2 = 0.  
       do i=1,imr  
       sum1 = sum1 + ady(i,1)  
       sum2 = sum2 + ady(i,JNP)  
       enddo  
         sum1 = sum1 / IMR  
         sum2 = sum2 / IMR  
 C  
       do i=1,imr  
       ady(i,  1) =  sum1  
       ady(i,JNP) =  sum2  
       enddo  
         endif  
 C  
         return  
         end  
 C  
         subroutine xadv(IMR,JNP,j1,j2,p,UA,JS,JN,IML,adx,IAD)  
         REAL p(IMR,JNP),adx(IMR,JNP),qtmp(-IMR:IMR+IMR),UA(IMR,JNP)  
 C  
         JMR = JNP-1  
       do 1309 j=j1,j2  
       if(J.GT.JS  .and. J.LT.JN) GO TO 1309  
 C  
       do i=1,IMR  
       qtmp(i) = p(i,j)  
       enddo  
 C  
       do i=-IML,0  
       qtmp(i)       = p(IMR+i,j)  
       qtmp(IMR+1-i) = p(1-i,j)  
       enddo  
 C  
       IF(IAD.eq.2) THEN  
       DO i=1,IMR  
       IP = NINT(UA(i,j))  
       ru = IP - UA(i,j)  
       IP = i - IP  
       a1 = 0.5*(qtmp(ip+1)+qtmp(ip-1)) - qtmp(ip)  
       b1 = 0.5*(qtmp(ip+1)-qtmp(ip-1))  
       adx(i,j) = qtmp(ip) + ru*(a1*ru + b1)  
       enddo  
       ELSEIF(IAD.eq.1) then  
       DO i=1,IMR  
       iu = UA(i,j)  
       ru = UA(i,j) - iu  
       iiu = i-iu  
       if(UA(i,j).GE.0.) then  
       adx(i,j) = qtmp(iiu)+ru*(qtmp(iiu-1)-qtmp(iiu))  
       else  
       adx(i,j) = qtmp(iiu)+ru*(qtmp(iiu)-qtmp(iiu+1))  
       endif  
       enddo  
       ENDIF  
 C  
       do i=1,IMR  
       adx(i,j) = adx(i,j) - p(i,j)  
       enddo  
 1309  continue  
 C  
 C Eulerian upwind  
 C  
       do j=JS+1,JN-1  
 C  
       do i=1,IMR  
       qtmp(i) = p(i,j)  
       enddo  
 C  
       qtmp(0)     = p(IMR,J)  
       qtmp(IMR+1) = p(1,J)  
 C  
       IF(IAD.eq.2) THEN  
       qtmp(-1)     = p(IMR-1,J)  
       qtmp(IMR+2) = p(2,J)  
       do i=1,imr  
       IP = NINT(UA(i,j))  
       ru = IP - UA(i,j)  
       IP = i - IP  
       a1 = 0.5*(qtmp(ip+1)+qtmp(ip-1)) - qtmp(ip)  
       b1 = 0.5*(qtmp(ip+1)-qtmp(ip-1))  
       adx(i,j) = qtmp(ip)- p(i,j) + ru*(a1*ru + b1)  
       enddo  
       ELSEIF(IAD.eq.1) then  
 C 1st order  
       DO i=1,IMR  
       IP = i - UA(i,j)  
       adx(i,j) = UA(i,j)*(qtmp(ip)-qtmp(ip+1))  
       enddo  
       ENDIF  
       enddo  
 C  
         if(j1.ne.2) then  
       do i=1,IMR  
       adx(i,  2) = 0.  
       adx(i,JMR) = 0.  
       enddo  
         endif  
 C set cross term due to x-adv at the poles to zero.  
       do i=1,IMR  
       adx(i,  1) = 0.  
       adx(i,JNP) = 0.  
       enddo  
         return  
         end  
 C  
       subroutine lmtppm(DC,A6,AR,AL,P,IM,LMT)  
 C  
 C A6 =  CURVATURE OF THE TEST PARABOLA  
 C AR =  RIGHT EDGE VALUE OF THE TEST PARABOLA  
 C AL =  LEFT  EDGE VALUE OF THE TEST PARABOLA  
 C DC =  0.5 * MISMATCH  
 C P  =  CELL-AVERAGED VALUE  
 C IM =  VECTOR LENGTH  
 C  
 C OPTIONS:  
 C  
 C LMT = 0: FULL MONOTONICITY  
 C LMT = 1: SEMI-MONOTONIC CONSTRAINT (NO UNDERSHOOTS)  
 C LMT = 2: POSITIVE-DEFINITE CONSTRAINT  
 C  
       parameter ( R12 = 1./12. )  
       dimension A6(IM),AR(IM),AL(IM),P(IM),DC(IM)  
 C  
       if(LMT.eq.0) then  
 C Full constraint  
       do 100 i=1,IM  
       if(DC(i).eq.0.) then  
             AR(i) = p(i)  
             AL(i) = p(i)  
             A6(i) = 0.  
       else  
       da1  = AR(i) - AL(i)  
       da2  = da1**2  
       A6DA = A6(i)*da1  
       if(A6DA .lt. -da2) then  
             A6(i) = 3.*(AL(i)-p(i))  
             AR(i) = AL(i) - A6(i)  
       elseif(A6DA .gt. da2) then  
             A6(i) = 3.*(AR(i)-p(i))  
             AL(i) = AR(i) - A6(i)  
       endif  
       endif  
 100   continue  
       elseif(LMT.eq.1) then  
 C Semi-monotonic constraint  
       do 150 i=1,IM  
       if(abs(AR(i)-AL(i)) .GE. -A6(i)) go to 150  
       if(p(i).lt.AR(i) .and. p(i).lt.AL(i)) then  
             AR(i) = p(i)  
             AL(i) = p(i)  
             A6(i) = 0.  
       elseif(AR(i) .gt. AL(i)) then  
             A6(i) = 3.*(AL(i)-p(i))  
             AR(i) = AL(i) - A6(i)  
       else  
             A6(i) = 3.*(AR(i)-p(i))  
             AL(i) = AR(i) - A6(i)  
       endif  
 150   continue  
       elseif(LMT.eq.2) then  
       do 250 i=1,IM  
       if(abs(AR(i)-AL(i)) .GE. -A6(i)) go to 250  
       fmin = p(i) + 0.25*(AR(i)-AL(i))**2/A6(i) + A6(i)*R12  
       if(fmin.ge.0.) go to 250  
       if(p(i).lt.AR(i) .and. p(i).lt.AL(i)) then  
             AR(i) = p(i)  
             AL(i) = p(i)  
             A6(i) = 0.  
       elseif(AR(i) .gt. AL(i)) then  
             A6(i) = 3.*(AL(i)-p(i))  
             AR(i) = AL(i) - A6(i)  
       else  
             A6(i) = 3.*(AR(i)-p(i))  
             AL(i) = AR(i) - A6(i)  
       endif  
 250   continue  
       endif  
       return  
       end  
 C  
       subroutine A2C(U,V,IMR,JMR,j1,j2,CRX,CRY,dtdx5,DTDY5)  
       dimension U(IMR,*),V(IMR,*),CRX(IMR,*),CRY(IMR,*),DTDX5(*)  
 C  
       do 35 j=j1,j2  
       do 35 i=2,IMR  
 35    CRX(i,J) = dtdx5(j)*(U(i,j)+U(i-1,j))  
 C  
       do 45 j=j1,j2  
 45    CRX(1,J) = dtdx5(j)*(U(1,j)+U(IMR,j))  
 C  
       do 55 i=1,IMR*JMR  
 55    CRY(i,2) = DTDY5*(V(i,2)+V(i,1))  
       return  
       end  
 C  
       subroutine cosa(cosp,cose,JNP,PI,DP)  
       dimension cosp(*),cose(*)  
       JMR = JNP-1  
       do 55 j=2,JNP  
         ph5  =  -0.5*PI + (FLOAT(J-1)-0.5)*DP  
 55      cose(j) = cos(ph5)  
 C  
       JEQ = (JNP+1) / 2  
       if(JMR .eq. 2*(JMR/2) ) then  
       do j=JNP, JEQ+1, -1  
        cose(j) =  cose(JNP+2-j)  
       enddo  
       else  
 C cell edge at equator.  
        cose(JEQ+1) =  1.  
       do j=JNP, JEQ+2, -1  
        cose(j) =  cose(JNP+2-j)  
        enddo  
       endif  
 C  
       do 66 j=2,JMR  
 66    cosp(j) = 0.5*(cose(j)+cose(j+1))  
       cosp(1) = 0.  
       cosp(JNP) = 0.  
       return  
       end  
 C  
       subroutine cosc(cosp,cose,JNP,PI,DP)  
       dimension cosp(*),cose(*)  
 C  
       phi = -0.5*PI  
       do 55 j=2,JNP-1  
       phi  =  phi + DP  
 55    cosp(j) = cos(phi)  
         cosp(  1) = 0.  
         cosp(JNP) = 0.  
 C  
       do 66 j=2,JNP  
         cose(j) = 0.5*(cosp(j)+cosp(j-1))  
 66    CONTINUE  
 C  
       do 77 j=2,JNP-1  
        cosp(j) = 0.5*(cose(j)+cose(j+1))  
 77    CONTINUE  
       return  
       end  
 C  
       SUBROUTINE qckxyz (Q,qtmp,IMR,JNP,NLAY,j1,j2,cosp,acosp,  
      &                   cross,IC,NSTEP)  
 C  
       parameter( tiny = 1.E-60 )  
       DIMENSION Q(IMR,JNP,NLAY),qtmp(IMR,JNP),cosp(*),acosp(*)  
       logical cross  
 C  
       NLAYM1 = NLAY-1  
       len = IMR*(j2-j1+1)  
       ip = 0  
 C  
 C Top layer  
       L = 1  
         icr = 1  
       call filns(q(1,1,L),IMR,JNP,j1,j2,cosp,acosp,ipy,tiny)  
       if(ipy.eq.0) goto 50  
       call filew(q(1,1,L),qtmp,IMR,JNP,j1,j2,ipx,tiny)  
       if(ipx.eq.0) goto 50  
 C  
       if(cross) then  
       call filcr(q(1,1,L),IMR,JNP,j1,j2,cosp,acosp,icr,tiny)  
       endif  
       if(icr.eq.0) goto 50  
 C  
 C Vertical filling...  
       do i=1,len  
       IF( Q(i,j1,1).LT.0.) THEN  
       ip = ip + 1  
           Q(i,j1,2) = Q(i,j1,2) + Q(i,j1,1)  
           Q(i,j1,1) = 0.  
       endif  
       enddo  
 C  
 50    continue  
       DO 225 L = 2,NLAYM1  
       icr = 1  
 C  
       call filns(q(1,1,L),IMR,JNP,j1,j2,cosp,acosp,ipy,tiny)  
       if(ipy.eq.0) goto 225  
       call filew(q(1,1,L),qtmp,IMR,JNP,j1,j2,ipx,tiny)  
       if(ipx.eq.0) go to 225  
       if(cross) then  
       call filcr(q(1,1,L),IMR,JNP,j1,j2,cosp,acosp,icr,tiny)  
       endif  
       if(icr.eq.0) goto 225  
 C  
       do i=1,len  
       IF( Q(I,j1,L).LT.0.) THEN  
 C  
       ip = ip + 1  
 C From above  
           qup =  Q(I,j1,L-1)  
           qly = -Q(I,j1,L)  
           dup  = min(qly,qup)  
           Q(I,j1,L-1) = qup - dup  
           Q(I,j1,L  ) = dup-qly  
 C Below  
           Q(I,j1,L+1) = Q(I,j1,L+1) + Q(I,j1,L)  
           Q(I,j1,L)   = 0.  
       ENDIF  
       ENDDO  
 225   CONTINUE  
 C  
 C BOTTOM LAYER  
       sum = 0.  
       L = NLAY  
 C  
       call filns(q(1,1,L),IMR,JNP,j1,j2,cosp,acosp,ipy,tiny)  
       if(ipy.eq.0) goto 911  
       call filew(q(1,1,L),qtmp,IMR,JNP,j1,j2,ipx,tiny)  
       if(ipx.eq.0) goto 911  
 C  
       call filcr(q(1,1,L),IMR,JNP,j1,j2,cosp,acosp,icr,tiny)  
       if(icr.eq.0) goto 911  
 C  
       DO  I=1,len  
       IF( Q(I,j1,L).LT.0.) THEN  
       ip = ip + 1  
 c  
 C From above  
 C  
           qup = Q(I,j1,NLAYM1)  
           qly = -Q(I,j1,L)  
           dup = min(qly,qup)  
           Q(I,j1,NLAYM1) = qup - dup  
 C From "below" the surface.  
           sum = sum + qly-dup  
           Q(I,j1,L) = 0.  
        ENDIF  
       ENDDO  
 C  
 911   continue  
 C  
       if(ip.gt.IMR) then  
       write(6,*) 'IC=',IC,' STEP=',NSTEP,  
      &           ' Vertical filling pts=',ip  
       endif  
 C  
       if(sum.gt.1.e-25) then  
       write(6,*) IC,NSTEP,' Mass source from the ground=',sum  
       endif  
       RETURN  
       END  
 C  
       subroutine filcr(q,IMR,JNP,j1,j2,cosp,acosp,icr,tiny)  
       dimension q(IMR,*),cosp(*),acosp(*)  
       icr = 0  
       do 65 j=j1+1,j2-1  
       DO 50 i=1,IMR-1  
       IF(q(i,j).LT.0.) THEN  
       icr =  1  
       dq  = - q(i,j)*cosp(j)  
 C N-E  
       dn = q(i+1,j+1)*cosp(j+1)  
       d0 = max(0.,dn)  
       d1 = min(dq,d0)  
       q(i+1,j+1) = (dn - d1)*acosp(j+1)  
       dq = dq - d1  
 C S-E  
       ds = q(i+1,j-1)*cosp(j-1)  
       d0 = max(0.,ds)  
       d2 = min(dq,d0)  
       q(i+1,j-1) = (ds - d2)*acosp(j-1)  
       q(i,j) = (d2 - dq)*acosp(j) + tiny  
       endif  
 50    continue  
       if(icr.eq.0 .and. q(IMR,j).ge.0.) goto 65  
       DO 55 i=2,IMR  
       IF(q(i,j).LT.0.) THEN  
       icr =  1  
       dq  = - q(i,j)*cosp(j)  
 C N-W  
       dn = q(i-1,j+1)*cosp(j+1)  
       d0 = max(0.,dn)  
       d1 = min(dq,d0)  
       q(i-1,j+1) = (dn - d1)*acosp(j+1)  
       dq = dq - d1  
 C S-W  
       ds = q(i-1,j-1)*cosp(j-1)  
       d0 = max(0.,ds)  
       d2 = min(dq,d0)  
       q(i-1,j-1) = (ds - d2)*acosp(j-1)  
       q(i,j) = (d2 - dq)*acosp(j) + tiny  
       endif  
 55    continue  
 C *****************************************  
 C i=1  
       i=1  
       IF(q(i,j).LT.0.) THEN  
       icr =  1  
       dq  = - q(i,j)*cosp(j)  
 C N-W  
       dn = q(IMR,j+1)*cosp(j+1)  
       d0 = max(0.,dn)  
       d1 = min(dq,d0)  
       q(IMR,j+1) = (dn - d1)*acosp(j+1)  
       dq = dq - d1  
 C S-W  
       ds = q(IMR,j-1)*cosp(j-1)  
       d0 = max(0.,ds)  
       d2 = min(dq,d0)  
       q(IMR,j-1) = (ds - d2)*acosp(j-1)  
       q(i,j) = (d2 - dq)*acosp(j) + tiny  
       endif  
 C *****************************************  
 C i=IMR  
       i=IMR  
       IF(q(i,j).LT.0.) THEN  
       icr =  1  
       dq  = - q(i,j)*cosp(j)  
 C N-E  
       dn = q(1,j+1)*cosp(j+1)  
       d0 = max(0.,dn)  
       d1 = min(dq,d0)  
       q(1,j+1) = (dn - d1)*acosp(j+1)  
       dq = dq - d1  
 C S-E  
       ds = q(1,j-1)*cosp(j-1)  
       d0 = max(0.,ds)  
       d2 = min(dq,d0)  
       q(1,j-1) = (ds - d2)*acosp(j-1)  
       q(i,j) = (d2 - dq)*acosp(j) + tiny  
       endif  
 C *****************************************  
 65    continue  
 C  
       do i=1,IMR  
       if(q(i,j1).lt.0. .or. q(i,j2).lt.0.) then  
       icr = 1  
       goto 80  
       endif  
       enddo  
 C  
 80    continue  
 C  
       if(q(1,1).lt.0. .or. q(1,jnp).lt.0.) then  
       icr = 1  
       endif  
 C  
       return  
       end  
 C  
       subroutine filns(q,IMR,JNP,j1,j2,cosp,acosp,ipy,tiny)  
       dimension q(IMR,*),cosp(*),acosp(*)  
 c      logical first  
 c      data first /.true./  
 c      save cap1  
 C  
 c      if(first) then  
       DP = 4.*ATAN(1.)/float(JNP-1)  
       CAP1 = IMR*(1.-COS((j1-1.5)*DP))/DP  
 c      first = .false.  
 c      endif  
 C  
       ipy = 0  
       do 55 j=j1+1,j2-1  
       DO 55 i=1,IMR  
       IF(q(i,j).LT.0.) THEN  
       ipy =  1  
       dq  = - q(i,j)*cosp(j)  
 C North  
       dn = q(i,j+1)*cosp(j+1)  
       d0 = max(0.,dn)  
       d1 = min(dq,d0)  
       q(i,j+1) = (dn - d1)*acosp(j+1)  
       dq = dq - d1  
 C South  
       ds = q(i,j-1)*cosp(j-1)  
       d0 = max(0.,ds)  
       d2 = min(dq,d0)  
       q(i,j-1) = (ds - d2)*acosp(j-1)  
       q(i,j) = (d2 - dq)*acosp(j) + tiny  
       endif  
 55    continue  
 C  
       do i=1,imr  
       IF(q(i,j1).LT.0.) THEN  
       ipy =  1  
       dq  = - q(i,j1)*cosp(j1)  
 C North  
       dn = q(i,j1+1)*cosp(j1+1)  
       d0 = max(0.,dn)  
       d1 = min(dq,d0)  
       q(i,j1+1) = (dn - d1)*acosp(j1+1)  
       q(i,j1) = (d1 - dq)*acosp(j1) + tiny  
       endif  
       enddo  
 C  
       j = j2  
       do i=1,imr  
       IF(q(i,j).LT.0.) THEN  
       ipy =  1  
       dq  = - q(i,j)*cosp(j)  
 C South  
       ds = q(i,j-1)*cosp(j-1)  
       d0 = max(0.,ds)  
       d2 = min(dq,d0)  
       q(i,j-1) = (ds - d2)*acosp(j-1)  
       q(i,j) = (d2 - dq)*acosp(j) + tiny  
       endif  
       enddo  
 C  
 C Check Poles.  
       if(q(1,1).lt.0.) then  
       dq = q(1,1)*cap1/float(IMR)*acosp(j1)  
       do i=1,imr  
       q(i,1) = 0.  
       q(i,j1) = q(i,j1) + dq  
       if(q(i,j1).lt.0.) ipy = 1  
       enddo  
       endif  
 C  
       if(q(1,JNP).lt.0.) then  
       dq = q(1,JNP)*cap1/float(IMR)*acosp(j2)  
       do i=1,imr  
       q(i,JNP) = 0.  
       q(i,j2) = q(i,j2) + dq  
       if(q(i,j2).lt.0.) ipy = 1  
       enddo  
       endif  
 C  
       return  
       end  
 C  
       subroutine filew(q,qtmp,IMR,JNP,j1,j2,ipx,tiny)  
       dimension q(IMR,*),qtmp(JNP,IMR)  
 C  
       ipx = 0  
 C Copy & swap direction for vectorization.  
       do 25 i=1,imr  
       do 25 j=j1,j2  
 25    qtmp(j,i) = q(i,j)  
 C  
       do 55 i=2,imr-1  
       do 55 j=j1,j2  
       if(qtmp(j,i).lt.0.) then  
       ipx =  1  
 c west  
       d0 = max(0.,qtmp(j,i-1))  
       d1 = min(-qtmp(j,i),d0)  
       qtmp(j,i-1) = qtmp(j,i-1) - d1  
       qtmp(j,i) = qtmp(j,i) + d1  
 c east  
       d0 = max(0.,qtmp(j,i+1))  
       d2 = min(-qtmp(j,i),d0)  
       qtmp(j,i+1) = qtmp(j,i+1) - d2  
       qtmp(j,i) = qtmp(j,i) + d2 + tiny  
       endif  
 55    continue  
 c  
       i=1  
       do 65 j=j1,j2  
       if(qtmp(j,i).lt.0.) then  
       ipx =  1  
 c west  
       d0 = max(0.,qtmp(j,imr))  
       d1 = min(-qtmp(j,i),d0)  
       qtmp(j,imr) = qtmp(j,imr) - d1  
       qtmp(j,i) = qtmp(j,i) + d1  
 c east  
       d0 = max(0.,qtmp(j,i+1))  
       d2 = min(-qtmp(j,i),d0)  
       qtmp(j,i+1) = qtmp(j,i+1) - d2  
 c  
       qtmp(j,i) = qtmp(j,i) + d2 + tiny  
       endif  
 65    continue  
       i=IMR  
       do 75 j=j1,j2  
       if(qtmp(j,i).lt.0.) then  
       ipx =  1  
 c west  
       d0 = max(0.,qtmp(j,i-1))  
       d1 = min(-qtmp(j,i),d0)  
       qtmp(j,i-1) = qtmp(j,i-1) - d1  
       qtmp(j,i) = qtmp(j,i) + d1  
 c east  
       d0 = max(0.,qtmp(j,1))  
       d2 = min(-qtmp(j,i),d0)  
       qtmp(j,1) = qtmp(j,1) - d2  
 c  
       qtmp(j,i) = qtmp(j,i) + d2 + tiny  
       endif  
 75    continue  
 C  
       if(ipx.ne.0) then  
       do 85 j=j1,j2  
       do 85 i=1,imr  
 85    q(i,j) = qtmp(j,i)  
       else  
 C  
 C Poles.  
       if(q(1,1).lt.0. or. q(1,JNP).lt.0.) ipx = 1  
       endif  
       return  
       end  

Legend:
Removed from v.76  
changed lines
  Added in v.166

  ViewVC Help
Powered by ViewVC 1.1.21