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

Annotation of /trunk/dyn3d/ppm3d.f

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.21