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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 47 - (hide annotations)
Fri Jul 1 15:00:48 2011 UTC (12 years, 10 months ago) by guez
File size: 8804 byte(s)
Split "thermcell.f" and "cv3_routines.f".
Removed copies of files that are now in "L_util".
Moved "mva9" and "diagetpq" to their own files.
Unified variable names across procedures.

1 guez 47 module coefkz_m
2 guez 3
3 guez 40 IMPLICIT none
4 guez 3
5 guez 47 contains
6 guez 3
7 guez 47 SUBROUTINE coefkz(nsrf, knon, paprs, pplay, ksta, ksta_ter, ts, rugos, u, v, &
8     t, q, qsurf, pcfm, pcfh)
9 guez 40
10 guez 47 ! 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 guez 40
15 guez 47 USE indicesol, ONLY : is_oce
16     USE dimphy, ONLY : klev, klon, max
17     USE iniprint, 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 guez 40
23 guez 47 ! Arguments:
24 guez 40
25 guez 47 integer, intent(in):: nsrf ! indicateur de la nature du sol
26     INTEGER, intent(in):: knon ! nombre de points a traiter
27 guez 40
28 guez 47 REAL, intent(in):: paprs(klon, klev+1)
29     ! pression a chaque intercouche (en Pa)
30 guez 40
31 guez 47 real, intent(in):: pplay(klon, klev)
32     ! pression au milieu de chaque couche (en Pa)
33 guez 40
34 guez 47 REAL, intent(in):: ksta, ksta_ter
35     REAL, intent(in):: ts(klon) ! temperature du sol (en Kelvin)
36     REAL, intent(in):: rugos(klon) ! longeur de rugosite (en m)
37     REAL, intent(in):: u(klon, klev), v(klon, klev) ! wind
38     REAL, intent(in):: t(klon, klev) ! temperature (K)
39     real, intent(in):: q(klon, klev) ! vapeur d'eau (kg/kg)
40     real, intent(in):: qsurf(klon)
41     REAL, intent(inout):: pcfm(klon, klev) ! coefficient, vitesse
42     real, intent(inout):: pcfh(klon, klev) ! coefficient, chaleur et humidité
43 guez 40
44 guez 47 ! Local:
45 guez 40
46 guez 47 INTEGER itop(klon) ! numero de couche du sommet de la couche limite
47 guez 40
48 guez 47 ! Quelques constantes et options:
49 guez 40
50 guez 47 REAL, PARAMETER:: cepdu2 =0.1**2
51     REAL, PARAMETER:: CKAP = 0.4
52     REAL, PARAMETER:: cb = 5.
53     REAL, PARAMETER:: cc = 5.
54     REAL, PARAMETER:: cd = 5.
55     REAL, PARAMETER:: clam = 160.
56     REAL, PARAMETER:: ratqs = 0.05 ! ! largeur de distribution de vapeur d'eau
57     LOGICAL, PARAMETER:: richum = .TRUE. ! utilise le nombre de Richardson humide
58     REAL, PARAMETER:: ric = 0.4 ! nombre de Richardson critique
59     REAL, PARAMETER:: prandtl = 0.4
60 guez 40
61 guez 47 REAL kstable ! diffusion minimale (situation stable)
62     REAL, PARAMETER:: mixlen = 35. ! constante controlant longueur de melange
63     INTEGER, PARAMETER:: isommet = klev ! le sommet de la couche limite
64 guez 40
65 guez 47 LOGICAL, PARAMETER:: tvirtu = .TRUE.
66     ! calculer Ri d'une maniere plus performante
67 guez 40
68 guez 47 LOGICAL, PARAMETER:: opt_ec = .FALSE.
69     ! formule du Centre Europeen dans l'atmosphere
70 guez 40
71 guez 47 INTEGER i, k, kk
72     REAL zgeop(klon, klev)
73     REAL zmgeom(klon)
74     REAL zri(klon)
75     REAL zl2(klon)
76 guez 40
77 guez 47 REAL u1(klon), v1(klon), t1(klon), q1(klon), z1(klon)
78     REAL pcfm1(klon), pcfh1(klon)
79 guez 40
80 guez 47 REAL zdphi, zdu2, ztvd, ztvu, zcdn
81     REAL zscf
82     REAL zt, zq, zdelta, zcvm5, zcor, zqs, zfr, zdqs
83     REAL z2geomf, zalh2, zalm2, zscfh, zscfm
84     REAL, PARAMETER:: t_coup = 273.15
85     REAL gamt(2:klev) ! contre-gradient pour la chaleur sensible: Kelvin/metre
86 guez 40
87 guez 47 !--------------------------------------------------------------------
88 guez 40
89 guez 47 ! Initialiser les sorties
90     DO k = 1, klev
91     DO i = 1, knon
92     pcfm(i, k) = 0.
93     pcfh(i, k) = 0.
94     ENDDO
95     ENDDO
96     DO i = 1, knon
97     itop(i) = 0
98     ENDDO
99 guez 40
100 guez 47 ! Prescrire la valeur de contre-gradient
101     if (iflag_pbl.eq.1) then
102     DO k = 3, klev
103     gamt(k) = -1.0E-03
104     ENDDO
105     gamt(2) = -2.5E-03
106     else
107     DO k = 2, klev
108     gamt(k) = 0.0
109     ENDDO
110     ENDIF
111 guez 40
112 guez 47 IF ( nsrf .NE. is_oce ) THEN
113     kstable = ksta_ter
114     ELSE
115     kstable = ksta
116     ENDIF
117 guez 40
118 guez 47 ! Calculer les géopotentiels de chaque couche
119     DO i = 1, knon
120     zgeop(i, 1) = RD * t(i, 1) / (0.5 * (paprs(i, 1) + pplay(i, 1))) &
121     * (paprs(i, 1) - pplay(i, 1))
122     ENDDO
123     DO k = 2, klev
124     DO i = 1, knon
125     zgeop(i, k) = zgeop(i, k-1) &
126     + RD * 0.5*(t(i, k-1)+t(i, k)) / paprs(i, k) &
127     * (pplay(i, k-1)-pplay(i, k))
128     ENDDO
129     ENDDO
130 guez 40
131 guez 47 ! Calculer le frottement au sol (Cdrag)
132 guez 40
133 guez 47 DO i = 1, knon
134     u1(i) = u(i, 1)
135     v1(i) = v(i, 1)
136     t1(i) = t(i, 1)
137     q1(i) = q(i, 1)
138     z1(i) = zgeop(i, 1)
139     ENDDO
140 guez 40
141 guez 47 CALL clcdrag(klon, knon, nsrf, .false., u1, v1, t1, q1, z1, ts, qsurf, &
142     rugos, pcfm1, pcfh1)
143 guez 40
144 guez 47 DO i = 1, knon
145     pcfm(i, 1) = pcfm1(i)
146     pcfh(i, 1) = pcfh1(i)
147     ENDDO
148 guez 40
149 guez 47 ! Calculer les coefficients turbulents dans l'atmosphere
150 guez 40
151 guez 47 DO i = 1, knon
152     itop(i) = isommet
153     ENDDO
154 guez 40
155 guez 47 loop_vertical: DO k = 2, isommet
156     loop_horiz: DO i = 1, knon
157     zdu2 = MAX(cepdu2, (u(i, k)-u(i, k-1))**2 &
158     +(v(i, k)-v(i, k-1))**2)
159     zmgeom(i) = zgeop(i, k)-zgeop(i, k-1)
160     zdphi =zmgeom(i) / 2.0
161     zt = (t(i, k)+t(i, k-1)) * 0.5
162     zq = (q(i, k)+q(i, k-1)) * 0.5
163 guez 40
164 guez 47 ! calculer Qs et dQs/dT:
165 guez 40
166 guez 47 IF (thermcep) THEN
167     zdelta = MAX(0., SIGN(1., RTT-zt))
168     zcvm5 = R5LES*RLVTT/RCPD/(1.0+RVTMP2*zq)*(1.-zdelta) &
169     + R5IES*RLSTT/RCPD/(1.0+RVTMP2*zq)*zdelta
170     zqs = R2ES * FOEEW(zt, zdelta) / pplay(i, k)
171     zqs = MIN(0.5, zqs)
172     zcor = 1./(1.-RETV*zqs)
173     zqs = zqs*zcor
174     zdqs = FOEDE(zt, zdelta, zcvm5, zqs, zcor)
175     ELSE
176     IF (zt .LT. t_coup) THEN
177     zqs = qsats(zt) / pplay(i, k)
178     zdqs = dqsats(zt, zqs)
179     ELSE
180     zqs = qsatl(zt) / pplay(i, k)
181     zdqs = dqsatl(zt, zqs)
182     ENDIF
183     ENDIF
184 guez 40
185 guez 47 ! calculer la fraction nuageuse (processus humide):
186 guez 40
187 guez 47 zfr = (zq+ratqs*zq-zqs) / (2.0*ratqs*zq)
188     zfr = MAX(0.0, MIN(1.0, zfr))
189     IF (.NOT.richum) zfr = 0.0
190 guez 40
191 guez 47 ! calculer le nombre de Richardson:
192 guez 40
193 guez 47 IF (tvirtu) THEN
194     ztvd =( t(i, k) &
195     + zdphi/RCPD/(1.+RVTMP2*zq) &
196     *( (1.-zfr) + zfr*(1.+RLVTT*zqs/RD/zt)/(1.+zdqs) ) &
197     )*(1.+RETV*q(i, k))
198     ztvu =( t(i, k-1) &
199     - zdphi/RCPD/(1.+RVTMP2*zq) &
200     *( (1.-zfr) + zfr*(1.+RLVTT*zqs/RD/zt)/(1.+zdqs) ) &
201     )*(1.+RETV*q(i, k-1))
202     zri(i) =zmgeom(i)*(ztvd-ztvu)/(zdu2*0.5*(ztvd+ztvu))
203     zri(i) = zri(i) &
204     + zmgeom(i)*zmgeom(i)/RG*gamt(k) &
205     *(paprs(i, k)/101325.0)**RKAPPA &
206     /(zdu2*0.5*(ztvd+ztvu))
207     ELSE
208     ! calcul de Ridchardson compatible LMD5
209     zri(i) =(RCPD*(t(i, k)-t(i, k-1)) &
210     -RD*0.5*(t(i, k)+t(i, k-1))/paprs(i, k) &
211     *(pplay(i, k)-pplay(i, k-1)) &
212     )*zmgeom(i)/(zdu2*0.5*RCPD*(t(i, k-1)+t(i, k)))
213     zri(i) = zri(i) + &
214     zmgeom(i)*zmgeom(i)*gamt(k)/RG &
215     *(paprs(i, k)/101325.0)**RKAPPA &
216     /(zdu2*0.5*(t(i, k-1)+t(i, k)))
217     ENDIF
218 guez 40
219 guez 47 ! finalement, les coefficients d'echange sont obtenus:
220 guez 40
221 guez 47 zcdn = SQRT(zdu2) / zmgeom(i) * RG
222 guez 40
223 guez 47 IF (opt_ec) THEN
224     z2geomf = zgeop(i, k-1)+zgeop(i, k)
225     zalm2 = (0.5*ckap/RG*z2geomf &
226     /(1.+0.5*ckap/rg/clam*z2geomf))**2
227     zalh2 = (0.5*ckap/rg*z2geomf &
228     /(1.+0.5*ckap/RG/(clam*SQRT(1.5*cd))*z2geomf))**2
229     IF (zri(i).LT.0.0) THEN
230     ! situation instable
231     zscf = ((zgeop(i, k)/zgeop(i, k-1))**(1./3.)-1.)**3 &
232     / (zmgeom(i)/RG)**3 / (zgeop(i, k-1)/RG)
233     zscf = SQRT(-zri(i)*zscf)
234     zscfm = 1.0 / (1.0+3.0*cb*cc*zalm2*zscf)
235     zscfh = 1.0 / (1.0+3.0*cb*cc*zalh2*zscf)
236     pcfm(i, k) = zcdn*zalm2*(1.-2.0*cb*zri(i)*zscfm)
237     pcfh(i, k) = zcdn*zalh2*(1.-3.0*cb*zri(i)*zscfh)
238     ELSE
239     ! situation stable
240     zscf = SQRT(1.+cd*zri(i))
241     pcfm(i, k) = zcdn*zalm2/(1.+2.0*cb*zri(i)/zscf)
242     pcfh(i, k) = zcdn*zalh2/(1.+3.0*cb*zri(i)*zscf)
243     ENDIF
244     ELSE
245     zl2(i) = (mixlen*MAX(0.0, (paprs(i, k)-paprs(i, itop(i)+1)) &
246     /(paprs(i, 2)-paprs(i, itop(i)+1)) ))**2
247     pcfm(i, k) = sqrt(max(zcdn*zcdn*(ric-zri(i))/ric, kstable))
248     pcfm(i, k)= zl2(i)* pcfm(i, k)
249     pcfh(i, k) = pcfm(i, k) /prandtl ! h et m different
250     ENDIF
251     ENDDO loop_horiz
252     ENDDO loop_vertical
253 guez 40
254 guez 47 ! Au-dela du sommet, pas de diffusion turbulente:
255 guez 40
256 guez 47 DO i = 1, knon
257     IF (itop(i)+1 .LE. klev) THEN
258     DO k = itop(i)+1, klev
259     pcfh(i, k) = 0.
260     pcfm(i, k) = 0.
261     ENDDO
262     ENDIF
263     ENDDO
264 guez 40
265 guez 47 END SUBROUTINE coefkz
266 guez 40
267 guez 47 end module coefkz_m

  ViewVC Help
Powered by ViewVC 1.1.21