/[lmdze]/trunk/libf/phylmd/coefkz.f90
ViewVC logotype

Contents of /trunk/libf/phylmd/coefkz.f90

Parent Directory Parent Directory | Revision Log Revision Log


Revision 71 - (show annotations)
Mon Jul 8 18:12:18 2013 UTC (10 years, 9 months ago) by guez
File size: 8434 byte(s)
No reason to call inidissip in ce0l.

In inidissip, set random seed to 1 beacuse PGI compiler does not
accept all zeros.

dq was computed needlessly in caladvtrac. Arguments masse and dq of
calfis not used.

Replaced real*8 by double precision.

Pass arrays with inverted order of vertical levels to conflx instead
of creating local variables for this inside conflx.

1 module coefkz_m
2
3 IMPLICIT none
4
5 contains
6
7 SUBROUTINE coefkz(nsrf, knon, paprs, pplay, ksta, ksta_ter, ts, rugos, u, v, &
8 t, q, qsurf, coefm, coefh)
9
10 ! Authors: F. Hourdin, M. Forichon, Z. X. Li (LMD/CNRS)
11 ! date: 1993/09/22
12 ! Objet : calculer le coefficient de frottement du sol ("Cdrag") et les
13 ! coefficients d'échange turbulent dans l'atmosphère.
14
15 USE indicesol, ONLY: is_oce
16 USE dimphy, ONLY: klev, klon
17 USE conf_gcm_m, ONLY: prt_level
18 USE suphec_m, ONLY: rcpd, rd, retv, rg, rkappa, rlstt, rlvtt, rtt
19 USE yoethf_m, ONLY: r2es, r5ies, r5les, rvtmp2
20 USE fcttre, ONLY: dqsatl, dqsats, foede, foeew, qsatl, qsats, thermcep
21 USE conf_phys_m, ONLY: iflag_pbl
22 use clcdrag_m, only: clcdrag
23
24 ! Arguments:
25
26 integer, intent(in):: nsrf ! indicateur de la nature du sol
27 INTEGER, intent(in):: knon ! nombre de points a traiter
28
29 REAL, intent(in):: paprs(klon, klev+1)
30 ! pression a chaque intercouche (en Pa)
31
32 real, intent(in):: pplay(klon, klev)
33 ! pression au milieu de chaque couche (en Pa)
34
35 REAL, intent(in):: ksta, ksta_ter
36 REAL, intent(in):: ts(klon) ! temperature du sol (en Kelvin)
37 REAL, intent(in):: rugos(klon) ! longeur de rugosite (en m)
38 REAL, intent(in):: u(klon, klev), v(klon, klev) ! wind
39 REAL, intent(in):: t(klon, klev) ! temperature (K)
40 real, intent(in):: q(klon, klev) ! vapeur d'eau (kg/kg)
41 real, intent(in):: qsurf(klon)
42 REAL, intent(out):: coefm(:, :) ! (knon, klev) coefficient, vitesse
43
44 real, intent(out):: coefh(:, :) ! (knon, klev)
45 ! coefficient, chaleur et humidité
46
47 ! Local:
48
49 INTEGER itop(knon) ! numero de couche du sommet 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, kk
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, zdelta, zcvm5, zcor, zqs, zfr, zdqs
88 REAL z2geomf, zalh2, alm2, zscfh, scfm
89 REAL, PARAMETER:: t_coup = 273.15
90 REAL gamt(2:klev) ! contre-gradient pour la chaleur sensible: Kelvin/metre
91
92 !--------------------------------------------------------------------
93
94 ! Prescrire la valeur de contre-gradient
95 if (iflag_pbl.eq.1) then
96 DO k = 3, klev
97 gamt(k) = -1.0E-03
98 ENDDO
99 gamt(2) = -2.5E-03
100 else
101 DO k = 2, klev
102 gamt(k) = 0.0
103 ENDDO
104 ENDIF
105
106 IF ( nsrf .NE. is_oce ) THEN
107 kstable = ksta_ter
108 ELSE
109 kstable = ksta
110 ENDIF
111
112 ! Calculer les géopotentiels de chaque couche
113 DO i = 1, knon
114 zgeop(i, 1) = RD * t(i, 1) / (0.5 * (paprs(i, 1) + pplay(i, 1))) &
115 * (paprs(i, 1) - pplay(i, 1))
116 ENDDO
117 DO k = 2, klev
118 DO i = 1, knon
119 zgeop(i, k) = zgeop(i, k-1) &
120 + RD * 0.5*(t(i, k-1)+t(i, k)) / paprs(i, k) &
121 * (pplay(i, k-1)-pplay(i, k))
122 ENDDO
123 ENDDO
124
125 ! Calculer le frottement au sol (Cdrag)
126
127 DO i = 1, knon
128 u1(i) = u(i, 1)
129 v1(i) = v(i, 1)
130 t1(i) = t(i, 1)
131 q1(i) = q(i, 1)
132 z1(i) = zgeop(i, 1)
133 ENDDO
134
135 CALL clcdrag(klon, knon, nsrf, .false., u1, v1, t1, q1, z1, ts, qsurf, &
136 rugos, coefm(:, 1), coefh(:, 1))
137
138 ! Calculer les coefficients turbulents dans l'atmosphere
139
140 itop = isommet
141
142 loop_vertical: DO k = 2, isommet
143 loop_horiz: DO i = 1, knon
144 zdu2 = MAX(cepdu2, (u(i, k)-u(i, k-1))**2 &
145 +(v(i, k)-v(i, k-1))**2)
146 zmgeom(i) = zgeop(i, k)-zgeop(i, k-1)
147 zdphi =zmgeom(i) / 2.0
148 zt = (t(i, k)+t(i, k-1)) * 0.5
149 zq = (q(i, k)+q(i, k-1)) * 0.5
150
151 ! calculer Qs et dQs/dT:
152
153 IF (thermcep) THEN
154 zdelta = MAX(0., SIGN(1., RTT-zt))
155 zcvm5 = R5LES*RLVTT/RCPD/(1.0+RVTMP2*zq)*(1.-zdelta) &
156 + R5IES*RLSTT/RCPD/(1.0+RVTMP2*zq)*zdelta
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 ELSE
163 IF (zt < t_coup) THEN
164 zqs = qsats(zt) / pplay(i, k)
165 zdqs = dqsats(zt, zqs)
166 ELSE
167 zqs = qsatl(zt) / pplay(i, k)
168 zdqs = dqsatl(zt, zqs)
169 ENDIF
170 ENDIF
171
172 ! calculer la fraction nuageuse (processus humide):
173
174 zfr = (zq+ratqs*zq-zqs) / (2.0*ratqs*zq)
175 zfr = MAX(0.0, MIN(1.0, zfr))
176 IF (.NOT.richum) zfr = 0.0
177
178 ! calculer le nombre de Richardson:
179
180 IF (tvirtu) THEN
181 ztvd =( t(i, k) &
182 + zdphi/RCPD/(1.+RVTMP2*zq) &
183 *( (1.-zfr) + zfr*(1.+RLVTT*zqs/RD/zt)/(1.+zdqs) ) &
184 )*(1.+RETV*q(i, k))
185 ztvu =( t(i, k-1) &
186 - zdphi/RCPD/(1.+RVTMP2*zq) &
187 *( (1.-zfr) + zfr*(1.+RLVTT*zqs/RD/zt)/(1.+zdqs) ) &
188 )*(1.+RETV*q(i, k-1))
189 ri(i) =zmgeom(i)*(ztvd-ztvu)/(zdu2*0.5*(ztvd+ztvu))
190 ri(i) = ri(i) &
191 + zmgeom(i)*zmgeom(i)/RG*gamt(k) &
192 *(paprs(i, k)/101325.0)**RKAPPA &
193 /(zdu2*0.5*(ztvd+ztvu))
194 ELSE
195 ! calcul de Ridchardson compatible LMD5
196 ri(i) =(RCPD*(t(i, k)-t(i, k-1)) &
197 -RD*0.5*(t(i, k)+t(i, k-1))/paprs(i, k) &
198 *(pplay(i, k)-pplay(i, k-1)) &
199 )*zmgeom(i)/(zdu2*0.5*RCPD*(t(i, k-1)+t(i, k)))
200 ri(i) = ri(i) + &
201 zmgeom(i)*zmgeom(i)*gamt(k)/RG &
202 *(paprs(i, k)/101325.0)**RKAPPA &
203 /(zdu2*0.5*(t(i, k-1)+t(i, k)))
204 ENDIF
205
206 ! finalement, les coefficients d'echange sont obtenus:
207
208 cdn = SQRT(zdu2) / zmgeom(i) * RG
209
210 IF (opt_ec) THEN
211 z2geomf = zgeop(i, k-1)+zgeop(i, k)
212 alm2 = (0.5*ckap/RG*z2geomf &
213 /(1.+0.5*ckap/rg/clam*z2geomf))**2
214 zalh2 = (0.5*ckap/rg*z2geomf &
215 /(1.+0.5*ckap/RG/(clam*SQRT(1.5*cd))*z2geomf))**2
216 IF (ri(i) < 0.) THEN
217 ! situation instable
218 scf = ((zgeop(i, k)/zgeop(i, k-1))**(1./3.)-1.)**3 &
219 / (zmgeom(i)/RG)**3 / (zgeop(i, k-1)/RG)
220 scf = SQRT(-ri(i)*scf)
221 scfm = 1.0 / (1.0+3.0*cb*cc*alm2*scf)
222 zscfh = 1.0 / (1.0+3.0*cb*cc*zalh2*scf)
223 coefm(i, k) = cdn * alm2 * (1. - 2. * cb * ri(i) * scfm)
224 coefh(i, k) = cdn*zalh2*(1.-3.0*cb*ri(i)*zscfh)
225 ELSE
226 ! situation stable
227 scf = SQRT(1.+cd*ri(i))
228 coefm(i, k) = cdn * alm2 / (1. + 2. * cb * ri(i) / scf)
229 coefh(i, k) = cdn*zalh2/(1.+3.0*cb*ri(i)*scf)
230 ENDIF
231 ELSE
232 l2(i) = (mixlen*MAX(0.0, (paprs(i, k)-paprs(i, itop(i)+1)) &
233 /(paprs(i, 2)-paprs(i, itop(i)+1)) ))**2
234 coefm(i, k) = sqrt(max(cdn**2 * (ric - ri(i)) / ric, kstable))
235 coefm(i, k)= l2(i) * coefm(i, k)
236 coefh(i, k) = coefm(i, k) / prandtl ! h et m different
237 ENDIF
238 ENDDO loop_horiz
239 ENDDO loop_vertical
240
241 ! Au-delà du sommet, pas de diffusion turbulente :
242 forall (i = 1: knon)
243 coefh(i, itop(i) + 1:) = 0.
244 coefm(i, itop(i) + 1:) = 0.
245 END forall
246
247 END SUBROUTINE coefkz
248
249 end module coefkz_m

  ViewVC Help
Powered by ViewVC 1.1.21