/[lmdze]/trunk/Sources/phylmd/coefkz.f
ViewVC logotype

Contents of /trunk/Sources/phylmd/coefkz.f

Parent Directory Parent Directory | Revision Log Revision Log


Revision 248 - (show annotations)
Fri Jan 5 16:40:13 2018 UTC (6 years, 4 months ago) by guez
File size: 7317 byte(s)
Move the call to clcdrag up from coefkz to clmain (folllowing
LMDZ). As both clcdrag and coefkz need zgeop, also move the
computation of zgeop from coefkz to clmain.

1 module coefkz_m
2
3 IMPLICIT none
4
5 contains
6
7 SUBROUTINE coefkz(nsrf, paprs, pplay, ksta, ksta_ter, ts, u, v, t, q, &
8 zgeop, coefm, coefh)
9
10 ! Authors: F. Hourdin, M. Forichon, Z. X. Li (LMD/CNRS)
11 ! Date: September 22nd, 1993
12
13 ! Objet : calculer les coefficients d'échange turbulent dans
14 ! l'atmosphère.
15
16 USE conf_phys_m, ONLY: iflag_pbl
17 USE dimphy, ONLY: klev
18 USE fcttre, ONLY: foede, foeew
19 USE indicesol, ONLY: is_oce
20 USE suphec_m, ONLY: rcpd, rd, retv, rg, rkappa, rlstt, rlvtt, rtt
21 USE yoethf_m, ONLY: r2es, r5ies, r5les, rvtmp2
22
23 integer, intent(in):: nsrf ! indicateur de la nature du sol
24
25 REAL, intent(in):: paprs(:, :) ! (knon, klev + 1)
26 ! pression a chaque intercouche (en Pa)
27
28 real, intent(in):: pplay(:, :) ! (knon, klev)
29 ! pression au milieu de chaque couche (en Pa)
30
31 REAL, intent(in):: ksta, ksta_ter
32 REAL, intent(in):: ts(:) ! (knon) temperature du sol (en Kelvin)
33 REAL, intent(in):: u(:, :), v(:, :) ! (knon, klev) wind
34 REAL, intent(in):: t(:, :) ! (knon, klev) temperature (K)
35 real, intent(in):: q(:, :) ! (knon, klev) vapeur d'eau (kg/kg)
36 REAL, intent(in):: zgeop(:, :) ! (knon, klev)
37 REAL, intent(out):: coefm(:, 2:) ! (knon, 2:klev) coefficient, vitesse
38
39 real, intent(out):: coefh(:, 2:) ! (knon, 2:klev)
40 ! coefficient, chaleur et humidité
41
42 ! Local:
43
44 INTEGER knon ! nombre de points a traiter
45
46 INTEGER itop(size(ts)) ! (knon)
47 ! numero de couche du sommet de la couche limite
48
49 ! Quelques constantes et options:
50
51 REAL, PARAMETER:: cepdu2 =0.1**2
52 REAL, PARAMETER:: CKAP = 0.4
53 REAL, PARAMETER:: cb = 5.
54 REAL, PARAMETER:: cc = 5.
55 REAL, PARAMETER:: cd = 5.
56 REAL, PARAMETER:: clam = 160.
57 REAL, PARAMETER:: ratqs = 0.05 ! largeur de distribution de vapeur d'eau
58
59 LOGICAL, PARAMETER:: richum = .TRUE.
60 ! utilise le nombre de Richardson humide
61
62 REAL, PARAMETER:: ric = 0.4 ! nombre de Richardson critique
63 REAL, PARAMETER:: prandtl = 0.4
64
65 REAL kstable ! diffusion minimale (situation stable)
66 REAL, PARAMETER:: mixlen = 35. ! constante contrôlant longueur de mélange
67 INTEGER, PARAMETER:: isommet = klev ! sommet de la couche limite
68
69 LOGICAL, PARAMETER:: tvirtu = .TRUE.
70 ! calculer Ri d'une maniere plus performante
71
72 LOGICAL, PARAMETER:: opt_ec = .FALSE.
73 ! formule du Centre Europeen dans l'atmosphere
74
75 INTEGER i, k
76 REAL zmgeom(size(ts))
77 REAL ri(size(ts))
78 REAL l2(size(ts))
79 REAL zdphi, zdu2, ztvd, ztvu, cdn
80 REAL scf
81 REAL zt, zq, zcvm5, zcor, zqs, zfr, zdqs
82 logical zdelta
83 REAL z2geomf, zalh2, alm2, zscfh, scfm
84 REAL gamt(2:klev) ! contre-gradient pour la chaleur sensible: Kelvin/metre
85
86 !--------------------------------------------------------------------
87
88 knon = size(ts)
89
90 ! Prescrire la valeur de contre-gradient
91 if (iflag_pbl.eq.1) then
92 DO k = 3, klev
93 gamt(k) = - 1E-3
94 ENDDO
95 gamt(2) = - 2.5E-3
96 else
97 DO k = 2, klev
98 gamt(k) = 0.0
99 ENDDO
100 ENDIF
101
102 IF (nsrf .NE. is_oce ) THEN
103 kstable = ksta_ter
104 ELSE
105 kstable = ksta
106 ENDIF
107
108 ! Calculer les coefficients turbulents dans l'atmosphere
109
110 itop = isommet
111
112 loop_vertical: DO k = 2, isommet
113 loop_horiz: DO i = 1, knon
114 zdu2 = MAX(cepdu2, (u(i, k) - u(i, k - 1))**2 &
115 + (v(i, k) - v(i, k - 1))**2)
116 zmgeom(i) = zgeop(i, k) - zgeop(i, k - 1)
117 zdphi = zmgeom(i) / 2.0
118 zt = (t(i, k) + t(i, k - 1)) * 0.5
119 zq = (q(i, k) + q(i, k - 1)) * 0.5
120
121 ! calculer Qs et dQs/dT:
122
123 zdelta = RTT >=zt
124 zcvm5 = merge(R5IES * RLSTT, R5LES * RLVTT, zdelta) / RCPD &
125 / (1. + RVTMP2 * zq)
126 zqs = R2ES * FOEEW(zt, zdelta) / pplay(i, k)
127 zqs = MIN(0.5, zqs)
128 zcor = 1./(1. - RETV * zqs)
129 zqs = zqs * zcor
130 zdqs = FOEDE(zt, zdelta, zcvm5, zqs, zcor)
131
132 ! calculer la fraction nuageuse (processus humide):
133
134 zfr = (zq + ratqs * zq - zqs) / (2.0 * ratqs * zq)
135 zfr = MAX(0.0, MIN(1.0, zfr))
136 IF (.NOT.richum) zfr = 0.0
137
138 ! calculer le nombre de Richardson:
139
140 IF (tvirtu) THEN
141 ztvd = (t(i, k) &
142 + zdphi/RCPD/(1. + RVTMP2 * zq) &
143 * ((1. - zfr) + zfr * (1. + RLVTT * zqs/RD/zt)/(1. + zdqs) ) &
144 ) * (1. + RETV * q(i, k))
145 ztvu = (t(i, k - 1) &
146 - zdphi/RCPD/(1. + RVTMP2 * zq) &
147 * ((1. - zfr) + zfr * (1. + RLVTT * zqs/RD/zt)/(1. + zdqs) ) &
148 ) * (1. + RETV * q(i, k - 1))
149 ri(i) = zmgeom(i) * (ztvd - ztvu)/(zdu2 * 0.5 * (ztvd + ztvu))
150 ri(i) = ri(i) &
151 + zmgeom(i) * zmgeom(i)/RG * gamt(k) &
152 * (paprs(i, k)/101325.0)**RKAPPA &
153 /(zdu2 * 0.5 * (ztvd + ztvu))
154 ELSE
155 ! calcul de Ridchardson compatible LMD5
156 ri(i) = (RCPD * (t(i, k) - t(i, k - 1)) &
157 - RD * 0.5 * (t(i, k) + t(i, k - 1))/paprs(i, k) &
158 * (pplay(i, k) - pplay(i, k - 1)) &
159 ) * zmgeom(i)/(zdu2 * 0.5 * RCPD * (t(i, k - 1) + t(i, k)))
160 ri(i) = ri(i) + &
161 zmgeom(i) * zmgeom(i) * gamt(k)/RG &
162 * (paprs(i, k)/101325.0)**RKAPPA &
163 /(zdu2 * 0.5 * (t(i, k - 1) + t(i, k)))
164 ENDIF
165
166 ! finalement, les coefficients d'echange sont obtenus:
167
168 cdn = SQRT(zdu2) / zmgeom(i) * RG
169
170 IF (opt_ec) THEN
171 z2geomf = zgeop(i, k - 1) + zgeop(i, k)
172 alm2 = (0.5 * ckap/RG * z2geomf &
173 /(1. + 0.5 * ckap/rg/clam * z2geomf))**2
174 zalh2 = (0.5 * ckap/rg * z2geomf &
175 /(1. + 0.5 * ckap/RG/(clam * SQRT(1.5 * cd)) * z2geomf))**2
176 IF (ri(i) < 0.) THEN
177 ! situation instable
178 scf = ((zgeop(i, k)/zgeop(i, k - 1))**(1./3.) - 1.)**3 &
179 / (zmgeom(i)/RG)**3 / (zgeop(i, k - 1)/RG)
180 scf = SQRT(- ri(i) * scf)
181 scfm = 1.0 / (1.0 + 3.0 * cb * cc * alm2 * scf)
182 zscfh = 1.0 / (1.0 + 3.0 * cb * cc * zalh2 * scf)
183 coefm(i, k) = cdn * alm2 * (1. - 2. * cb * ri(i) * scfm)
184 coefh(i, k) = cdn * zalh2 * (1. - 3.0 * cb * ri(i) * zscfh)
185 ELSE
186 ! situation stable
187 scf = SQRT(1. + cd * ri(i))
188 coefm(i, k) = cdn * alm2 / (1. + 2. * cb * ri(i) / scf)
189 coefh(i, k) = cdn * zalh2/(1. + 3.0 * cb * ri(i) * scf)
190 ENDIF
191 ELSE
192 l2(i) = (mixlen * MAX(0.0, (paprs(i, k) - paprs(i, itop(i) + 1)) &
193 /(paprs(i, 2) - paprs(i, itop(i) + 1)) ))**2
194 coefm(i, k) = sqrt(max(cdn**2 * (ric - ri(i)) / ric, kstable))
195 coefm(i, k) = l2(i) * coefm(i, k)
196 coefh(i, k) = coefm(i, k) / prandtl ! h et m different
197 ENDIF
198 ENDDO loop_horiz
199 ENDDO loop_vertical
200
201 ! Au-delà du sommet, pas de diffusion turbulente :
202 forall (i = 1: knon)
203 coefh(i, itop(i) + 1:) = 0.
204 coefm(i, itop(i) + 1:) = 0.
205 END forall
206
207 END SUBROUTINE coefkz
208
209 end module coefkz_m

  ViewVC Help
Powered by ViewVC 1.1.21