1 | MODULE tropopause_m |
---|
2 | |
---|
3 | IMPLICIT NONE; PRIVATE |
---|
4 | PUBLIC dyn_tropopause |
---|
5 | |
---|
6 | CONTAINS |
---|
7 | |
---|
8 | !------------------------------------------------------------------------------- |
---|
9 | |
---|
10 | FUNCTION dyn_tropopause(t, ts, paprs, pplay, rot, itrop, thet0, pvor0) |
---|
11 | |
---|
12 | !------------------------------------------------------------------------------- |
---|
13 | USE lmdz_assert, ONLY: assert |
---|
14 | USE lmdz_assert_eq, ONLY: assert_eq |
---|
15 | USE dimphy, ONLY: klon, klev |
---|
16 | USE lmdz_geometry, ONLY: latitude_deg, longitude_deg |
---|
17 | USE lmdz_vertical_layers, ONLY: aps, bps, preff |
---|
18 | USE lmdz_cppkeys_wrapper, ONLY: CPPKEY_REPROBUS |
---|
19 | USE lmdz_reprobus_wrappers, ONLY: itroprep |
---|
20 | USE lmdz_yomcst |
---|
21 | |
---|
22 | !------------------------------------------------------------------------------- |
---|
23 | ! Arguments: |
---|
24 | REAL :: dyn_tropopause(klon) !--- Pressure at tropopause |
---|
25 | REAL, INTENT(IN) :: t(:, :) !--- Cells-centers temperature |
---|
26 | REAL, INTENT(IN) :: ts(:) !--- Surface temperature |
---|
27 | REAL, INTENT(IN) :: paprs(:, :) !--- Cells-edges pressure |
---|
28 | REAL, INTENT(IN) :: pplay(:, :) !--- Cells-centers pressure |
---|
29 | REAL, INTENT(IN) :: rot(:, :) !--- Cells-centers relative vorticity |
---|
30 | INTEGER, INTENT(OUT), OPTIONAL :: itrop(klon) !--- Last tropospheric layer idx |
---|
31 | REAL, INTENT(IN), OPTIONAL :: thet0, pvor0 |
---|
32 | !------------------------------------------------------------------------------- |
---|
33 | ! Local variables: |
---|
34 | REAL, PARAMETER :: DynPTrMin = 8.E+3 !--- Thresholds for minimum and maximum |
---|
35 | REAL, PARAMETER :: DynPTrMax = 4.E+4 ! dynamical tropopause pressure (Pa). |
---|
36 | CHARACTER(LEN = 80) :: sub |
---|
37 | INTEGER :: i, k, kb, kt, kp, ib, ie, nw |
---|
38 | REAL :: al, th0, pv0 |
---|
39 | REAL, DIMENSION(klon, klev) :: tpot_cen, tpot_edg, pvor_cen |
---|
40 | REAL, PARAMETER :: sg0 = 0.75 !--- Start level for PV=cte search loop |
---|
41 | INTEGER, PARAMETER :: nadj = 3 !--- Adjacent levs nb for thresholds detection |
---|
42 | REAL, PARAMETER :: w(5) = [0.1, 0.25, 0.3, 0.25, 0.1] !--- Vertical smoothing |
---|
43 | INTEGER, SAVE :: k0 |
---|
44 | LOGICAL, SAVE :: first = .TRUE. |
---|
45 | !$OMP THREADPRIVATE(k0,first) |
---|
46 | !------------------------------------------------------------------------------- |
---|
47 | sub = 'dyn_tropopause' |
---|
48 | CALL assert(SIZE(t, 1)==klon, TRIM(sub) // " t klon") |
---|
49 | CALL assert(SIZE(t, 2)==klev, TRIM(sub) // " t klev") |
---|
50 | CALL assert(SIZE(ts, 1)==klon, TRIM(sub) // " ts klon") |
---|
51 | CALL assert(SHAPE(paprs)==[klon, klev + 1], TRIM(sub) // " paprs shape") |
---|
52 | CALL assert(SHAPE(pplay)==[klon, klev ], TRIM(sub) // " pplay shape") |
---|
53 | CALL assert(SHAPE(rot) ==[klon, klev ], TRIM(sub) // " rot shape") |
---|
54 | |
---|
55 | !--- DEFAULT THRESHOLDS |
---|
56 | th0 = 380.; IF(PRESENT(thet0)) th0 = thet0 !--- In kelvins |
---|
57 | pv0 = 2.; IF(PRESENT(pvor0)) pv0 = pvor0 !--- In PVU |
---|
58 | IF(first) THEN |
---|
59 | DO k0 = 1, klev; IF(aps(k0) / preff + bps(k0)<sg0) EXIT; |
---|
60 | END DO; first = .FALSE. |
---|
61 | END IF |
---|
62 | |
---|
63 | !--- POTENTIAL TEMPERATURE AT CELLS CENTERS AND INTERFACES |
---|
64 | DO i = 1, klon |
---|
65 | tpot_cen(i, 1) = t(i, 1) * (preff / pplay(i, 1))**RKAPPA |
---|
66 | tpot_edg(i, 1) = ts(i) * (preff / paprs(i, 1))**RKAPPA |
---|
67 | DO k = 2, klev |
---|
68 | al = LOG(pplay(i, k - 1) / paprs(i, k)) / LOG(pplay(i, k - 1) / pplay(i, k)) |
---|
69 | tpot_cen(i, k) = t(i, k) * (preff / pplay(i, k))**RKAPPA |
---|
70 | tpot_edg(i, k) = (t(i, k - 1) + al * (t(i, k) - t(i, k - 1))) * (preff / paprs(i, k))**RKAPPA |
---|
71 | !--- FORCE QUANTITIES TO BE GROWING |
---|
72 | IF(tpot_edg(i, k)<tpot_edg(i, k - 1)) tpot_edg(i, k) = tpot_edg(i, k - 1) + 1.E-5 |
---|
73 | IF(tpot_cen(i, k)<tpot_cen(i, k - 1)) tpot_cen(i, k) = tpot_cen(i, k - 1) + 1.E-5 |
---|
74 | END DO |
---|
75 | !--- VERTICAL SMOOTHING |
---|
76 | tpot_cen(i, :) = smooth(tpot_cen(i, :), w) |
---|
77 | tpot_edg(i, :) = smooth(tpot_edg(i, :), w) |
---|
78 | END DO |
---|
79 | |
---|
80 | !--- ERTEL POTENTIAL VORTICITY AT CELLS CENTERS (except in top layer) |
---|
81 | DO i = 1, klon |
---|
82 | DO k = 1, klev - 1 |
---|
83 | pvor_cen(i, k) = -1.E6 * RG * (rot(i, k) + 2. * ROMEGA * SIN(latitude_deg(i) * RPI / 180.))& |
---|
84 | * (tpot_edg(i, k + 1) - tpot_edg(i, k)) / (paprs(i, k + 1) - paprs(i, k)) |
---|
85 | END DO |
---|
86 | !--- VERTICAL SMOOTHING |
---|
87 | pvor_cen(i, 1:klev - 1) = smooth(pvor_cen(i, 1:klev - 1), w) |
---|
88 | END DO |
---|
89 | |
---|
90 | !--- LOCATE TROPOPAUSE: LOWEST POINT BETWEEN THETA=380K AND PV=2PVU SURFACES. |
---|
91 | DO i = 1, klon |
---|
92 | !--- UPPER TROPOPAUSE: |PV|=2PVU POINT STARTING FROM TOP |
---|
93 | DO kt = klev - 1, 1, -1; IF(ALL(ABS(pvor_cen(i, kt - nadj:kt))<=pv0)) EXIT; |
---|
94 | END DO |
---|
95 | !--- LOWER TROPOPAUSE: |PV|=2PVU POINT STARTING FROM BOTTOM |
---|
96 | DO kb = k0, klev - 1; IF(ALL(ABS(pvor_cen(i, kb:kb + nadj))> pv0)) EXIT; |
---|
97 | END DO; kb = kb - 1 |
---|
98 | !--- ISO-THETA POINT: THETA=380K STARTING FROM TOP |
---|
99 | DO kp = klev - 1, 1, -1; IF(ALL(ABS(tpot_cen(i, kp - nadj:kp))<=th0)) EXIT; |
---|
100 | END DO |
---|
101 | !--- CHOOSE BETWEEN LOWER AND UPPER TROPOPAUSE |
---|
102 | IF(2 * COUNT(ABS(pvor_cen(i, kb:kt))>pv0)>kt - kb + 1) kt = kb |
---|
103 | !--- PV-DEFINED TROPOPAUSE |
---|
104 | al = (ABS(pvor_cen(i, kt + 1)) - pv0) / ABS(pvor_cen(i, kt + 1) - pvor_cen(i, kt)) |
---|
105 | dyn_tropopause(i) = pplay(i, kt + 1) * (pplay(i, kt) / pplay(i, kt + 1))**al |
---|
106 | !--- THETA=380K IN THE TROPICAL REGION |
---|
107 | al = (tpot_cen(i, kp + 1) - th0) / (tpot_cen(i, kp + 1) - tpot_cen(i, kp)) |
---|
108 | dyn_tropopause(i) = MAX(pplay(i, kp + 1) * (pplay(i, kp) / pplay(i, kp + 1))**al, & |
---|
109 | dyn_tropopause(i)) |
---|
110 | !--- UNREALISTIC VALUES DETECTION |
---|
111 | IF(dyn_tropopause(i)<DynPTrMin.OR.dyn_tropopause(i)>DynPTrMax) THEN |
---|
112 | dyn_tropopause(i) = MIN(MAX(dyn_tropopause(i), DynPTrMax), DynPTrMin) |
---|
113 | DO kt = 1, klev - 1; IF(pplay(i, kt + 1)>dyn_tropopause(i)) EXIT; |
---|
114 | END DO; kp = kt |
---|
115 | END IF |
---|
116 | IF (CPPKEY_REPROBUS) THEN |
---|
117 | itroprep(i) = MAX(kt, kp) |
---|
118 | END IF |
---|
119 | !--- LAST TROPOSPHERIC LAYER INDEX NEEDED |
---|
120 | IF(PRESENT(itrop)) itrop(i) = MAX(kt, kp) |
---|
121 | END DO |
---|
122 | |
---|
123 | END FUNCTION dyn_tropopause |
---|
124 | |
---|
125 | |
---|
126 | !------------------------------------------------------------------------------- |
---|
127 | |
---|
128 | FUNCTION smooth(v, w) |
---|
129 | |
---|
130 | !------------------------------------------------------------------------------- |
---|
131 | ! Arguments: |
---|
132 | REAL, INTENT(IN) :: v(:), w(:) |
---|
133 | REAL, DIMENSION(SIZE(v)) :: smooth |
---|
134 | !------------------------------------------------------------------------------- |
---|
135 | ! Local variables: |
---|
136 | INTEGER :: nv, nw, k, kb, ke, lb, le |
---|
137 | !------------------------------------------------------------------------------- |
---|
138 | nv = SIZE(v); nw = (SIZE(w) - 1) / 2 |
---|
139 | DO k = 1, nv |
---|
140 | kb = MAX(k - nw, 1); lb = MAX(2 + nw - k, 1) |
---|
141 | ke = MIN(k + nw, nv); le = MIN(1 + nw + nv - k, 1 + 2 * nw) |
---|
142 | smooth(k) = SUM(v(kb:ke) * w(lb:le)) / SUM(w(lb:le)) |
---|
143 | END DO |
---|
144 | |
---|
145 | END FUNCTION smooth |
---|
146 | |
---|
147 | !------------------------------------------------------------------------------- |
---|
148 | |
---|
149 | END MODULE tropopause_m |
---|