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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 134 - (hide annotations)
Wed Apr 29 15:47:56 2015 UTC (9 years ago) by guez
File size: 8406 byte(s)
Sources inside, compilation outside.
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 guez 62 t, q, qsurf, coefm, coefh)
9 guez 40
10 guez 62 ! Authors: F. Hourdin, M. Forichon, Z. X. Li (LMD/CNRS)
11 guez 47 ! 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 62 USE indicesol, ONLY: is_oce
16 guez 71 USE dimphy, ONLY: klev, klon
17 guez 62 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 guez 40
24 guez 47 ! Arguments:
25 guez 40
26 guez 47 integer, intent(in):: nsrf ! indicateur de la nature du sol
27     INTEGER, intent(in):: knon ! nombre de points a traiter
28 guez 40
29 guez 47 REAL, intent(in):: paprs(klon, klev+1)
30     ! pression a chaque intercouche (en Pa)
31 guez 40
32 guez 47 real, intent(in):: pplay(klon, klev)
33     ! pression au milieu de chaque couche (en Pa)
34 guez 40
35 guez 47 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 guez 62 REAL, intent(out):: coefm(:, :) ! (knon, klev) coefficient, vitesse
43 guez 40
44 guez 62 real, intent(out):: coefh(:, :) ! (knon, klev)
45     ! coefficient, chaleur et humidité
46    
47 guez 47 ! Local:
48 guez 40
49 guez 62 INTEGER itop(knon) ! numero de couche du sommet de la couche limite
50 guez 40
51 guez 47 ! Quelques constantes et options:
52 guez 40
53 guez 47 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 guez 62 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 guez 47 REAL, PARAMETER:: ric = 0.4 ! nombre de Richardson critique
65     REAL, PARAMETER:: prandtl = 0.4
66 guez 40
67 guez 47 REAL kstable ! diffusion minimale (situation stable)
68 guez 62 REAL, PARAMETER:: mixlen = 35. ! constante contrôlant longueur de mélange
69     INTEGER, PARAMETER:: isommet = klev ! sommet de la couche limite
70 guez 40
71 guez 47 LOGICAL, PARAMETER:: tvirtu = .TRUE.
72     ! calculer Ri d'une maniere plus performante
73 guez 40
74 guez 47 LOGICAL, PARAMETER:: opt_ec = .FALSE.
75     ! formule du Centre Europeen dans l'atmosphere
76 guez 40
77 guez 105 INTEGER i, k
78 guez 47 REAL zgeop(klon, klev)
79     REAL zmgeom(klon)
80 guez 62 REAL ri(klon)
81     REAL l2(klon)
82 guez 40
83 guez 47 REAL u1(klon), v1(klon), t1(klon), q1(klon), z1(klon)
84 guez 40
85 guez 62 REAL zdphi, zdu2, ztvd, ztvu, cdn
86     REAL scf
87 guez 103 REAL zt, zq, zcvm5, zcor, zqs, zfr, zdqs
88     logical zdelta
89 guez 62 REAL z2geomf, zalh2, alm2, zscfh, scfm
90 guez 47 REAL, PARAMETER:: t_coup = 273.15
91     REAL gamt(2:klev) ! contre-gradient pour la chaleur sensible: Kelvin/metre
92 guez 40
93 guez 47 !--------------------------------------------------------------------
94 guez 40
95 guez 47 ! Prescrire la valeur de contre-gradient
96     if (iflag_pbl.eq.1) then
97     DO k = 3, klev
98     gamt(k) = -1.0E-03
99     ENDDO
100     gamt(2) = -2.5E-03
101     else
102     DO k = 2, klev
103     gamt(k) = 0.0
104     ENDDO
105     ENDIF
106 guez 40
107 guez 47 IF ( nsrf .NE. is_oce ) THEN
108     kstable = ksta_ter
109     ELSE
110     kstable = ksta
111     ENDIF
112 guez 40
113 guez 47 ! Calculer les géopotentiels de chaque couche
114     DO i = 1, knon
115     zgeop(i, 1) = RD * t(i, 1) / (0.5 * (paprs(i, 1) + pplay(i, 1))) &
116     * (paprs(i, 1) - pplay(i, 1))
117     ENDDO
118     DO k = 2, klev
119     DO i = 1, knon
120     zgeop(i, k) = zgeop(i, k-1) &
121     + RD * 0.5*(t(i, k-1)+t(i, k)) / paprs(i, k) &
122     * (pplay(i, k-1)-pplay(i, k))
123     ENDDO
124     ENDDO
125 guez 40
126 guez 47 ! Calculer le frottement au sol (Cdrag)
127 guez 40
128 guez 47 DO i = 1, knon
129     u1(i) = u(i, 1)
130     v1(i) = v(i, 1)
131     t1(i) = t(i, 1)
132     q1(i) = q(i, 1)
133     z1(i) = zgeop(i, 1)
134     ENDDO
135 guez 40
136 guez 47 CALL clcdrag(klon, knon, nsrf, .false., u1, v1, t1, q1, z1, ts, qsurf, &
137 guez 62 rugos, coefm(:, 1), coefh(:, 1))
138 guez 40
139 guez 47 ! Calculer les coefficients turbulents dans l'atmosphere
140 guez 40
141 guez 62 itop = isommet
142 guez 40
143 guez 47 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 guez 40
152 guez 47 ! calculer Qs et dQs/dT:
153 guez 40
154 guez 47 IF (thermcep) THEN
155 guez 103 zdelta = RTT >=zt
156     zcvm5 = merge(R5IES * RLSTT, R5LES * RLVTT, zdelta) / RCPD &
157     / (1. + RVTMP2*zq)
158 guez 47 zqs = R2ES * FOEEW(zt, zdelta) / pplay(i, k)
159     zqs = MIN(0.5, zqs)
160     zcor = 1./(1.-RETV*zqs)
161     zqs = zqs*zcor
162     zdqs = FOEDE(zt, zdelta, zcvm5, zqs, zcor)
163     ELSE
164 guez 62 IF (zt < t_coup) THEN
165 guez 47 zqs = qsats(zt) / pplay(i, k)
166     zdqs = dqsats(zt, zqs)
167     ELSE
168     zqs = qsatl(zt) / pplay(i, k)
169     zdqs = dqsatl(zt, zqs)
170     ENDIF
171     ENDIF
172 guez 40
173 guez 47 ! calculer la fraction nuageuse (processus humide):
174 guez 40
175 guez 47 zfr = (zq+ratqs*zq-zqs) / (2.0*ratqs*zq)
176     zfr = MAX(0.0, MIN(1.0, zfr))
177     IF (.NOT.richum) zfr = 0.0
178 guez 40
179 guez 47 ! calculer le nombre de Richardson:
180 guez 40
181 guez 47 IF (tvirtu) THEN
182     ztvd =( t(i, k) &
183     + zdphi/RCPD/(1.+RVTMP2*zq) &
184     *( (1.-zfr) + zfr*(1.+RLVTT*zqs/RD/zt)/(1.+zdqs) ) &
185     )*(1.+RETV*q(i, k))
186     ztvu =( t(i, k-1) &
187     - zdphi/RCPD/(1.+RVTMP2*zq) &
188     *( (1.-zfr) + zfr*(1.+RLVTT*zqs/RD/zt)/(1.+zdqs) ) &
189     )*(1.+RETV*q(i, k-1))
190 guez 62 ri(i) =zmgeom(i)*(ztvd-ztvu)/(zdu2*0.5*(ztvd+ztvu))
191     ri(i) = ri(i) &
192 guez 47 + zmgeom(i)*zmgeom(i)/RG*gamt(k) &
193     *(paprs(i, k)/101325.0)**RKAPPA &
194     /(zdu2*0.5*(ztvd+ztvu))
195     ELSE
196     ! calcul de Ridchardson compatible LMD5
197 guez 62 ri(i) =(RCPD*(t(i, k)-t(i, k-1)) &
198 guez 47 -RD*0.5*(t(i, k)+t(i, k-1))/paprs(i, k) &
199     *(pplay(i, k)-pplay(i, k-1)) &
200     )*zmgeom(i)/(zdu2*0.5*RCPD*(t(i, k-1)+t(i, k)))
201 guez 62 ri(i) = ri(i) + &
202 guez 47 zmgeom(i)*zmgeom(i)*gamt(k)/RG &
203     *(paprs(i, k)/101325.0)**RKAPPA &
204     /(zdu2*0.5*(t(i, k-1)+t(i, k)))
205     ENDIF
206 guez 40
207 guez 47 ! finalement, les coefficients d'echange sont obtenus:
208 guez 40
209 guez 62 cdn = SQRT(zdu2) / zmgeom(i) * RG
210 guez 40
211 guez 47 IF (opt_ec) THEN
212     z2geomf = zgeop(i, k-1)+zgeop(i, k)
213 guez 62 alm2 = (0.5*ckap/RG*z2geomf &
214 guez 47 /(1.+0.5*ckap/rg/clam*z2geomf))**2
215     zalh2 = (0.5*ckap/rg*z2geomf &
216     /(1.+0.5*ckap/RG/(clam*SQRT(1.5*cd))*z2geomf))**2
217 guez 62 IF (ri(i) < 0.) THEN
218 guez 47 ! situation instable
219 guez 62 scf = ((zgeop(i, k)/zgeop(i, k-1))**(1./3.)-1.)**3 &
220 guez 47 / (zmgeom(i)/RG)**3 / (zgeop(i, k-1)/RG)
221 guez 62 scf = SQRT(-ri(i)*scf)
222     scfm = 1.0 / (1.0+3.0*cb*cc*alm2*scf)
223     zscfh = 1.0 / (1.0+3.0*cb*cc*zalh2*scf)
224     coefm(i, k) = cdn * alm2 * (1. - 2. * cb * ri(i) * scfm)
225     coefh(i, k) = cdn*zalh2*(1.-3.0*cb*ri(i)*zscfh)
226 guez 47 ELSE
227     ! situation stable
228 guez 62 scf = SQRT(1.+cd*ri(i))
229     coefm(i, k) = cdn * alm2 / (1. + 2. * cb * ri(i) / scf)
230     coefh(i, k) = cdn*zalh2/(1.+3.0*cb*ri(i)*scf)
231 guez 47 ENDIF
232     ELSE
233 guez 62 l2(i) = (mixlen*MAX(0.0, (paprs(i, k)-paprs(i, itop(i)+1)) &
234 guez 47 /(paprs(i, 2)-paprs(i, itop(i)+1)) ))**2
235 guez 62 coefm(i, k) = sqrt(max(cdn**2 * (ric - ri(i)) / ric, kstable))
236     coefm(i, k)= l2(i) * coefm(i, k)
237     coefh(i, k) = coefm(i, k) / prandtl ! h et m different
238 guez 47 ENDIF
239     ENDDO loop_horiz
240     ENDDO loop_vertical
241 guez 40
242 guez 62 ! Au-delà du sommet, pas de diffusion turbulente :
243     forall (i = 1: knon)
244     coefh(i, itop(i) + 1:) = 0.
245     coefm(i, itop(i) + 1:) = 0.
246     END forall
247 guez 40
248 guez 47 END SUBROUTINE coefkz
249 guez 40
250 guez 47 end module coefkz_m

  ViewVC Help
Powered by ViewVC 1.1.21