source: LMDZ6/trunk/libf/phylmd/stratosphere_mask.f90

Last change on this file was 5274, checked in by abarral, 47 minutes ago

Replace yomcst.h by existing module

  • Property svn:keywords set to Id
File size: 9.5 KB
Line 
1!
2! $Id: stratosphere_mask.f90 5274 2024-10-25 13:41:23Z abarral $
3!
4SUBROUTINE stratosphere_mask(missing_val, pphis, t_seri, pplay, xlat)
5
6!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
7!
8! determination of tropopause height and temperature from gridded temperature data
9!
10! reference: Reichler, T., M. Dameris, and R. Sausen (GRL, 10.1029/2003GL018240, 2003)
11! modified: 6/28/06 tjr
12! adapted to LMDZ by C. Kleinschmitt (2016-02-15)
13! committed to LMDz by O. Boucher (2016) with a mistake
14! mistake corrected by O. Boucher (2017-12-11)
15!
16! input:  temp(nlon,nlat,nlev)  3D-temperature field
17!         ps(nlon,nlat)         2D-surface pressure field
18!         zs(nlon,nlat)         2D-surface height
19!         nlon                  grid points in x
20!         nlat                  grid points in y
21!         pfull(nlon,nlat,nlev) full pressure levels in Pa
22!         plimu                 upper limit for tropopause pressure
23!         pliml                 lower limit for tropopause pressure
24!         gamma                 tropopause criterion, e.g. -0.002 K/m
25!
26! output: p_tropopause(klon)    tropopause pressure in Pa with missing values
27!         t_tropopause(klon)    tropopause temperature in K with missing values
28!         z_tropopause(klon)    tropopause height in m with missing values
29!         stratomask            stratospheric mask withtout missing values
30!         ifil                  # of undetermined values
31!
32!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
33
34USE dimphy
35USE phys_local_var_mod, ONLY: stratomask
36USE phys_local_var_mod, ONLY: p_tropopause, z_tropopause, t_tropopause
37USE print_control_mod, ONLY: lunout, prt_level
38
39USE yomcst_mod_h, ONLY: RPI, RCLUM, RHPLA, RKBOL, RNAVO                   &
40          , RDAY, REA, REPSM, RSIYEA, RSIDAY, ROMEGA                  &
41          , R_ecc, R_peri, R_incl                                      &
42          , RA, RG, R1SA                                         &
43          , RSIGMA                                                     &
44          , R, RMD, RMV, RD, RV, RCPD                    &
45          , RMO3, RMCO2, RMC, RMCH4, RMN2O, RMCFC11, RMCFC12        &
46          , RCPV, RCVD, RCVV, RKAPPA, RETV, eps_w                    &
47          , RCW, RCS                                                 &
48          , RLVTT, RLSTT, RLMLT, RTT, RATM                           &
49          , RESTT, RALPW, RBETW, RGAMW, RALPS, RBETS, RGAMS            &
50          , RALPD, RBETD, RGAMD
51IMPLICIT NONE
52
53
54
55REAL, INTENT(IN)                       :: missing_val ! missing value, also XIOS
56REAL,DIMENSION(klon),INTENT(IN)        :: pphis   ! Geopotentiel de surface
57REAL,DIMENSION(klon,klev),INTENT(IN)   :: t_seri  ! Temperature
58REAL,DIMENSION(klon,klev),INTENT(IN)   :: pplay   ! pression pour le mileu de chaque couche (en Pa)
59REAL,DIMENSION(klon),INTENT(IN)        :: xlat    ! latitudes pour chaque point
60
61REAL, PARAMETER                        :: plimu=45000.
62REAL, PARAMETER                        :: pliml=7500.
63REAL, PARAMETER                        :: gamma=-0.002
64LOGICAL, PARAMETER                     :: dofill=.true.
65REAL,DIMENSION(klon)                   :: tp
66REAL,DIMENSION(klev)                   :: t, p
67INTEGER                                :: i, k, ifil
68REAL                                   :: ptrp, ttrp, ztrp, psrf, zsrf, pi
69
70pi     = 4.*ATAN(1.)
71
72!--computing tropopause
73DO i=1,klon
74  DO k=1,klev
75    t(k)=t_seri(i,klev+1-k)
76    p(k)=pplay(i,klev+1-k)
77  ENDDO
78  psrf=pplay(i,1)
79  zsrf=pphis(i)/RG           !--altitude de la surface
80  call twmo(missing_val, klev, t, p, psrf, zsrf, plimu, pliml, gamma, ptrp, ttrp, ztrp)
81  tp(i)=ptrp
82  p_tropopause(i)=ptrp
83  z_tropopause(i)=ztrp
84  t_tropopause(i)=ttrp
85ENDDO
86
87!--filling holes in tp but not in p_tropopause
88IF (dofill) THEN
89  ifil=0
90  DO i=1,klon
91  IF (ABS(tp(i)/missing_val-1.0).LT.0.01) THEN
92    !set missing values to very simple profile (neighbour averaging too expensive in LMDZ)
93    tp(i)=50000.-20000.*cos(xlat(i)/360.*2.*pi)
94    ifil=ifil+1
95  ENDIF
96  ENDDO
97!
98ENDIF
99!
100DO i=1, klon
101DO k=1, klev
102  IF (pplay(i,k).LT.tp(i)) THEN
103    stratomask(i,k)=1.0
104  ELSE
105    stratomask(i,k)=0.0
106  ENDIF
107ENDDO
108ENDDO
109
110IF (ifil.GT.0 .AND. prt_level >5) THEN
111  write(lunout,*)'Tropopause: number of undetermined values =', ifil
112ENDIF
113
114RETURN
115END SUBROUTINE stratosphere_mask
116
117!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
118! twmo
119!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
120
121subroutine twmo(missing_val, level, t, p, ps, zs, plimu, pliml, gamma, ptrp, ttrp, ztrp)
122
123! reference: Reichler, T., M. Dameris, and R. Sausen (GRL, 10.1029/2003GL018240, 2003)
124
125USE yomcst_mod_h, ONLY: RPI, RCLUM, RHPLA, RKBOL, RNAVO                   &
126          , RDAY, REA, REPSM, RSIYEA, RSIDAY, ROMEGA                  &
127          , R_ecc, R_peri, R_incl                                      &
128          , RA, RG, R1SA                                         &
129          , RSIGMA                                                     &
130          , R, RMD, RMV, RD, RV, RCPD                    &
131          , RMO3, RMCO2, RMC, RMCH4, RMN2O, RMCFC11, RMCFC12        &
132          , RCPV, RCVD, RCVV, RKAPPA, RETV, eps_w                    &
133          , RCW, RCS                                                 &
134          , RLVTT, RLSTT, RLMLT, RTT, RATM                           &
135          , RESTT, RALPW, RBETW, RGAMW, RALPS, RBETS, RGAMS            &
136          , RALPD, RBETD, RGAMD
137implicit none
138
139
140
141integer,intent(in)              :: level
142real,intent(in)                 :: missing_val
143real,intent(in),dimension(level):: t, p
144real,intent(in)                 :: plimu, pliml, gamma, ps, zs
145real,intent(out)                :: ptrp, ttrp, ztrp
146
147real,parameter                  :: deltaz = 2000.0
148
149real     :: faktor
150real     :: pmk, pm, a, b, tm, dtdp, dtdz, dlnp, tdlnp
151real     :: ag, bg, ptph, ttph, a0, b0
152real     :: pm0, tm0, pmk0, dtdz0
153real     :: p2km, asum, aquer
154real     :: pmk2, pm2, a2, b2, tm2, dtdp2, dtdz2
155integer  :: icount, jj, j
156
157ptrp=missing_val
158ttrp=missing_val
159ztrp=missing_val
160
161faktor = -RG/RD
162
163do j=level,2,-1
164
165   ! dt/dz
166   pmk= 0.5 * (p(j-1)**rkappa+p(j)**rkappa)        ! p**k at half level
167   pm = pmk**(1./rkappa)                    ! p at half level
168   a = (t(j-1)-t(j))/(p(j-1)**rkappa-p(j)**rkappa)    ! dT/dp^k
169   b = t(j)-(a*p(j)**rkappa)
170   tm = a * pmk + b                    ! T at half level         
171   dtdp = a * rkappa * pm**(rkappa-1.) ! dT/dp at half level
172   dtdz = faktor*dtdp*pm/tm            ! dT/dz at half level
173
174   ! dt/dz valid?
175   if (j.eq.level)     go to 999                 ! no, start level, initialize first
176   if (dtdz.le.gamma)  go to 999                 ! no, dt/dz < -2 K/km
177   if (dtdz0.gt.gamma) go to 999                 ! no, dt/dz below > -2 K/km
178   if (pm.gt.plimu)    go to 999                 ! no, pm too low
179
180   ! dtdz is valid, calculate tropopause pressure ptph
181   ag = (dtdz-dtdz0) / (pmk-pmk0)     
182   bg = dtdz0 - (ag * pmk0)         
183   ptph = exp(log((gamma-bg)/ag)/rkappa)
184
185   ! calculate temperature at this ptph assuming linear gamma
186   ! interpolation
187   ttph = tm0
188   ttph = ttph - (bg * log(pm0)  + ag * (pm0**rkappa) /rkappa) / faktor*t(j)
189   ttph = ttph + (bg * log(ptph) + ag * (ptph**rkappa)/rkappa) / faktor*t(j)
190
191   if (ptph.lt.pliml) go to 999
192   if (ptph.gt.plimu) go to 999     
193
194   ! 2nd test: dtdz above 2 km must not exceed gamma
195   p2km = ptph + deltaz*(pm/tm)*faktor      ! p at ptph + 2km
196   asum = 0.0                               ! dtdz above
197   icount = 0                               ! number of levels above
198
199   ! test until apm < p2km
200   do jj=j,2,-1
201
202       pmk2 = .5 * (p(jj-1)**rkappa+p(jj)**rkappa)    ! p mean ^kappa
203       pm2 = pmk2**(1/rkappa)                      ! p mean
204       if(pm2.gt.ptph) go to 110                ! doesn't happen
205       if(pm2.lt.p2km) go to 888                ! ptropo is valid
206
207       a2 = (t(jj-1)-t(jj))                     ! a
208       a2 = a2/(p(jj-1)**rkappa-p(jj)**rkappa)
209       b2 = t(jj)-(a2*p(jj)**rkappa)               ! b
210       tm2 = a2 * pmk2 + b2                     ! T mean
211       dtdp2 = a2 * rkappa * (pm2**(rkappa-1))        ! dt/dp
212       dtdz2 = faktor*dtdp2*pm2/tm2
213       asum = asum+dtdz2
214       icount = icount+1
215       aquer = asum/float(icount)               ! dt/dz mean
216   
217       ! discard ptropo ?
218        if (aquer.le.gamma) go to 999           ! dt/dz above < gamma
219
220110 continue
221    enddo                   ! test next level
222
223888 continue                    ! ptph is valid
224    ptrp = ptph
225    ttrp = ttph
226
227! now calculate height of tropopause by integrating hypsometric equation
228! from ps to ptrp
229! linearly interpolate in p (results are identical to p^kappa)
230
231jj = LEVEL                                       ! bottom
232do while ((P(jj).gt.PS) .or. (T(jj).lt.100))     ! T must be valid too
233  jj=jj-1
234enddo
235
236DLNP = log(PS/P(jj))                             ! from surface pressure
237TM = T(jj)                                       ! take TM of lowest level (better: extrapolate)
238TDLNP = TM*DLNP
239
240do while ( (JJ.ge.2) .and. (PTRP.lt.P(jj-1)) )
241  DLNP = log(P(jj)/P(jj-1))
242  TM = 0.5 * (T(jj) + T(jj-1))
243  TDLNP = TDLNP + TM*DLNP
244  JJ=JJ-1
245enddo
246
247DLNP = log(P(jj)/PTRP)                           ! up to tropopause pressure
248TM = 0.5 * (T(jj) + TTRP)                        ! use TTRP to get TM of this level
249TDLNP = TDLNP + TM*DLNP
250
251ZTRP = ZS + TDLNP*RD/RG
252
253!!if (ZTRP .lt. 0) then
254!!  print*,'ZTRP=',ZTRP
255!!  print*,'PS=',PS
256!!  print*,'P=',P
257!!  print*,'T=',T
258!!  print*,'ZS=',ZS
259!!  stop
260!!endif
261
262return
263
264999 continue                    ! continue search at next higher level
265    tm0 = tm
266    pm0 = pm
267    pmk0 = pmk
268    dtdz0  = dtdz
269    a0 = a
270    b0 = b
271
272enddo
273
274! no tropopouse found
275return
276end subroutine twmo
Note: See TracBrowser for help on using the repository browser.