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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 207 - (show annotations)
Thu Sep 1 10:30:53 2016 UTC (7 years, 8 months ago) by guez
File size: 7990 byte(s)
New philosophy on compiler options.

Removed source code for thermcep = f. (Not used in LMDZ either.)

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

  ViewVC Help
Powered by ViewVC 1.1.21