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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 233 - (show annotations)
Tue Nov 7 10:52:46 2017 UTC (6 years, 6 months ago) by guez
File size: 8099 byte(s)
Use separate variables for eddy diffusion coefficient and drag
coefficient in procedure coefkz (following LMDZ). coefkzmin only
computes eddy diffusion coefficient, not drag coefficient.

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

  ViewVC Help
Powered by ViewVC 1.1.21