source: LMDZ5/trunk/libf/phylmd/stratosphere_mask.F90 @ 2744

Last change on this file since 2744 was 2715, checked in by oboucher, 8 years ago

Fixing a small glitch in my StratAer? module
p_tropopause was used but not defined...
now it is diagnosed but not used !

File size: 7.4 KB
Line 
1SUBROUTINE stratosphere_mask(t_seri, pplay, xlat)
2
3!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
4!
5! determination of tropopause height and temperature from gridded temperature data
6!
7! reference: Reichler, T., M. Dameris, and R. Sausen (2003):
8! modified: 6/28/06 tjr
9! adapted to LMDZ by C. Kleinschmitt (2016-02-15)
10!
11! input:    temp(nlon,nlat,nlev)    3D-temperature field
12!       ps(nlon,nlat)       2D-surface pressure field
13!       zs(nlon,nlat)       2D-surface height
14!       nlon            grid points in x
15!       nlat            grid points in y
16!       pfull(nlon,nlat,nlev)   full pressure levels in Pa
17!       plimu           upper limit for tropopause pressure
18!       pliml           lower limit for tropopause pressure
19!       gamma           tropopause criterion, e.g. -0.002 K/m
20!
21! output:   tp(nlon, nlat)      tropopause pressure in Pa, -999. if undefined
22!           ttp(nlon, nlat)     tropopause temperature in K, -999. if undefined
23!           ztp(nlon, nlat)     tropopause height in m, -999. if undefined
24!       tperr           # of undetermined values
25!
26!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
27
28USE dimphy
29USE phys_local_var_mod, ONLY: stratomask
30#ifdef CPP_StratAer
31USE phys_local_var_mod, ONLY: p_tropopause
32#endif
33
34IMPLICIT NONE
35
36REAL,DIMENSION(klon,klev),INTENT(IN)   :: t_seri  ! Temperature
37REAL,DIMENSION(klon,klev),INTENT(IN)   :: pplay   ! pression pour le mileu de chaque couche (en Pa)
38REAL,DIMENSION(klon),INTENT(IN)        :: xlat    ! latitudes pour chaque point
39
40REAL, PARAMETER                        :: plimu=45000.
41REAL, PARAMETER                        :: pliml=7500.
42REAL, PARAMETER                        :: gamma=-0.002
43LOGICAL, PARAMETER                     :: dofill=.true.
44REAL,DIMENSION(klon)                   :: tp, ttp, ztp
45REAL,DIMENSION(klev)                   :: t, p
46INTEGER                                :: tperr, i, k, invert, ifil
47REAL                                   :: ptrp, ttrp, ztrp, psrf, zsrf, pi
48
49pi     = 4.*ATAN(1.)
50
51tperr = 0
52DO i=1,klon
53  DO k=1,klev
54    t(k)=t_seri(i,klev+1-k)
55    p(k)=pplay(i,klev+1-k)
56  ENDDO
57  psrf=pplay(i,1)
58  zsrf=0.0
59  call twmo(klev, t, p, psrf, zsrf, plimu, pliml, gamma, ptrp, ttrp, ztrp)
60  tp(i)=ptrp
61  ttp(i)=ttrp
62  ztp(i)=ztrp
63  IF (ptrp.lt.0.0) THEN
64    tperr = tperr+1
65  ENDIF
66ENDDO
67
68! fill holes
69IF (dofill) THEN
70  ifil=0
71  DO i=1,klon
72  IF (tp(i).lt.-990.) THEN
73    !set missing values to very simple profile (neighbour averaging too expensive in LMDZ)
74    tp(i)=50000.-20000.*cos(xlat(i)/360.*2.*pi)
75    ifil=ifil+1
76  ENDIF
77  ENDDO
78!
79  IF (ifil.ne.tperr) THEN
80    CALL abort_physic('stratosphere_mask', 'inconsistency',1)
81  ENDIF
82ENDIF
83!
84DO i=1, klon
85DO k=1, klev
86  IF (pplay(i,k).LT.tp(i)) THEN
87    stratomask(i,k)=1.0
88  ELSE
89    stratomask(i,k)=0.0
90  ENDIF
91ENDDO
92ENDDO
93
94!--this is only diagnosedd in the case of StratAer
95!--but it could be useful to LMDz
96#ifdef CPP_StratAer
97p_tropopause(:)=tp(:)
98#endif
99
100IF (ifil.gt.0) THEN
101  print *,'Tropopause: number of undetermined values =', ifil
102ENDIF
103
104RETURN
105END SUBROUTINE stratosphere_mask
106
107!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
108! twmo
109!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
110
111subroutine twmo(level, t, p, ps, zs, plimu, pliml, gamma, ptrp, ttrp, ztrp)
112
113implicit none
114
115include "YOMCST.h"
116
117integer,intent(in)              :: level
118real,intent(in),dimension(level):: t, p
119real,intent(in)                 :: plimu, pliml, gamma, ps, zs
120real,intent(out)                :: ptrp, ttrp, ztrp
121
122real,parameter                  :: deltaz = 2000.0
123
124real     :: faktor
125real     :: pmk, pm, a, b, tm, dtdp, dtdz, dlnp, tdlnp
126real     :: ag, bg, ptph, ttph, a0, b0
127real     :: pm0, tm0, pmk0, dtdz0
128real     :: p2km, asum, aquer
129real     :: pmk2, pm2, a2, b2, tm2, dtdp2, dtdz2
130integer  :: icount, jj, j
131
132ptrp=-999.0             
133ttrp=-999.0                 
134ztrp=-999.0                 
135
136faktor = -RG/R
137
138do j=level,2,-1
139
140   ! dt/dz
141   pmk= 0.5 * (p(j-1)**rkappa+p(j)**rkappa)        ! p**k at half level
142   pm = pmk**(1./rkappa)                    ! p at half level
143   a = (t(j-1)-t(j))/(p(j-1)**rkappa-p(j)**rkappa)    ! dT/dp^k
144   b = t(j)-(a*p(j)**rkappa)
145   tm = a * pmk + b                    ! T at half level         
146   dtdp = a * rkappa * pm**(rkappa-1.) ! dT/dp at half level
147   dtdz = faktor*dtdp*pm/tm            ! dT/dz at half level
148
149   ! dt/dz valid?
150   if (j.eq.level)     go to 999                 ! no, start level, initialize first
151   if (dtdz.le.gamma)  go to 999                 ! no, dt/dz < -2 K/km
152   if (dtdz0.gt.gamma) go to 999                 ! no, dt/dz below > -2 K/km
153   if (pm.gt.plimu)    go to 999                 ! no, pm too low
154
155   ! dtdz is valid, calculate tropopause pressure ptph
156   ag = (dtdz-dtdz0) / (pmk-pmk0)     
157   bg = dtdz0 - (ag * pmk0)         
158   ptph = exp(log((gamma-bg)/ag)/rkappa)
159
160   ! calculate temperature at this ptph assuming linear gamma
161   ! interpolation
162   ttph = tm0
163   ttph = ttph - (bg * log(pm0)  + ag * (pm0**rkappa) /rkappa) / faktor*t(j)
164   ttph = ttph + (bg * log(ptph) + ag * (ptph**rkappa)/rkappa) / faktor*t(j)
165
166   if (ptph.lt.pliml) go to 999
167   if (ptph.gt.plimu) go to 999     
168
169   ! 2nd test: dtdz above 2 km must not exceed gamma
170   p2km = ptph + deltaz*(pm/tm)*faktor      ! p at ptph + 2km
171   asum = 0.0                               ! dtdz above
172   icount = 0                               ! number of levels above
173
174   ! test until apm < p2km
175   do jj=j,2,-1
176
177       pmk2 = .5 * (p(jj-1)**rkappa+p(jj)**rkappa)    ! p mean ^kappa
178       pm2 = pmk2**(1/rkappa)                      ! p mean
179       if(pm2.gt.ptph) go to 110                ! doesn't happen
180       if(pm2.lt.p2km) go to 888                ! ptropo is valid
181
182       a2 = (t(jj-1)-t(jj))                     ! a
183       a2 = a2/(p(jj-1)**rkappa-p(jj)**rkappa)
184       b2 = t(jj)-(a2*p(jj)**rkappa)               ! b
185       tm2 = a2 * pmk2 + b2                     ! T mean
186       dtdp2 = a2 * rkappa * (pm2**(rkappa-1))        ! dt/dp
187       dtdz2 = faktor*dtdp2*pm2/tm2
188       asum = asum+dtdz2
189       icount = icount+1
190       aquer = asum/float(icount)               ! dt/dz mean
191   
192       ! discard ptropo ?
193        if (aquer.le.gamma) go to 999           ! dt/dz above < gamma
194
195110 continue
196    enddo                   ! test next level
197
198888 continue                    ! ptph is valid
199    ptrp = ptph
200    ttrp = ttph
201
202! now calculate height of tropopause by integrating hypsometric equation
203! from ps to ptrp
204! linearly interpolate in p (results are identical to p^kappa)
205
206jj = LEVEL                                       ! bottom
207do while ((P(jj).gt.PS) .or. (T(jj).lt.100))     ! T must be valid too
208  jj=jj-1
209enddo
210
211DLNP = log(PS/P(jj))                             ! from surface pressure
212TM = T(jj)                                       ! take TM of lowest level (better: extrapolate)
213TDLNP = TM*DLNP
214
215do while ( (JJ.ge.2) .and. (PTRP.lt.P(jj-1)) )
216  DLNP = log(P(jj)/P(jj-1))
217  TM = 0.5 * (T(jj) + T(jj-1))
218  TDLNP = TDLNP + TM*DLNP
219  JJ=JJ-1
220enddo
221
222DLNP = log(P(jj)/PTRP)                           ! up to tropopause pressure
223TM = 0.5 * (T(jj) + TTRP)                        ! use TTRP to get TM of this level
224TDLNP = TDLNP + TM*DLNP
225
226ZTRP = ZS + TDLNP*R/RG
227
228if (ZTRP .lt. 0) then
229  print*,ZTRP
230  print*,PS
231  print*,P
232  print*,T
233  print*,ZS
234  stop
235endif
236
237return
238
239999 continue                    ! continue search at next higher level
240    tm0 = tm
241    pm0 = pm
242    pmk0 = pmk
243    dtdz0  = dtdz
244    a0 = a
245    b0 = b
246
247enddo
248
249! no tropopouse found
250return
251end subroutine twmo
Note: See TracBrowser for help on using the repository browser.