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