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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 229 - (show annotations)
Mon Nov 6 17:20:45 2017 UTC (6 years, 6 months ago) by guez
File size: 8037 byte(s)
Use iflag_pbl from module conf_phys in yamada4 instead of getting it
as argument.

In clvent, simplifications using the fact that zx_alf2 = 0 and zx_alf1
= 1 (discarding the possibility to change this).

In physiq, no need for temporary variables z[uv]strph: compute actual
arguments of aaam_bud directly.

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)
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(:, :) ! (knon, klev) coefficient, vitesse
39
40 real, intent(out):: coefh(:, :) ! (knon, klev)
41 ! coefficient, chaleur et humidité
42
43 ! Local:
44
45 INTEGER knon ! nombre de points a traiter
46 INTEGER itop(size(coefm, 1)) ! (knon) numero de couche du sommet
47 ! de la couche limite
48
49 ! Quelques constantes et options:
50
51 REAL, PARAMETER:: cepdu2 =0.1**2
52 REAL, PARAMETER:: CKAP = 0.4
53 REAL, PARAMETER:: cb = 5.
54 REAL, PARAMETER:: cc = 5.
55 REAL, PARAMETER:: cd = 5.
56 REAL, PARAMETER:: clam = 160.
57 REAL, PARAMETER:: ratqs = 0.05 ! largeur de distribution de vapeur d'eau
58
59 LOGICAL, PARAMETER:: richum = .TRUE.
60 ! utilise le nombre de Richardson humide
61
62 REAL, PARAMETER:: ric = 0.4 ! nombre de Richardson critique
63 REAL, PARAMETER:: prandtl = 0.4
64
65 REAL kstable ! diffusion minimale (situation stable)
66 REAL, PARAMETER:: mixlen = 35. ! constante contrôlant longueur de mélange
67 INTEGER, PARAMETER:: isommet = klev ! sommet de la couche limite
68
69 LOGICAL, PARAMETER:: tvirtu = .TRUE.
70 ! calculer Ri d'une maniere plus performante
71
72 LOGICAL, PARAMETER:: opt_ec = .FALSE.
73 ! formule du Centre Europeen dans l'atmosphere
74
75 INTEGER i, k
76 REAL zgeop(klon, klev)
77 REAL zmgeom(klon)
78 REAL ri(klon)
79 REAL l2(klon)
80
81 REAL u1(klon), v1(klon), t1(klon), q1(klon), z1(klon)
82
83 REAL zdphi, zdu2, ztvd, ztvu, cdn
84 REAL scf
85 REAL zt, zq, zcvm5, zcor, zqs, zfr, zdqs
86 logical zdelta
87 REAL z2geomf, zalh2, alm2, zscfh, scfm
88 REAL gamt(2:klev) ! contre-gradient pour la chaleur sensible: Kelvin/metre
89
90 !--------------------------------------------------------------------
91
92 knon = size(coefm, 1)
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(nsrf, u1, v1, t1, q1, z1, ts, qsurf, rugos, coefm(:, 1), &
136 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 zdelta = RTT >=zt
154 zcvm5 = merge(R5IES * RLSTT, R5LES * RLVTT, zdelta) / RCPD &
155 / (1. + RVTMP2*zq)
156 zqs = R2ES * FOEEW(zt, zdelta) / pplay(i, k)
157 zqs = MIN(0.5, zqs)
158 zcor = 1./(1.-RETV*zqs)
159 zqs = zqs*zcor
160 zdqs = FOEDE(zt, zdelta, zcvm5, zqs, zcor)
161
162 ! calculer la fraction nuageuse (processus humide):
163
164 zfr = (zq+ratqs*zq-zqs) / (2.0*ratqs*zq)
165 zfr = MAX(0.0, MIN(1.0, zfr))
166 IF (.NOT.richum) zfr = 0.0
167
168 ! calculer le nombre de Richardson:
169
170 IF (tvirtu) THEN
171 ztvd =( t(i, k) &
172 + zdphi/RCPD/(1.+RVTMP2*zq) &
173 *( (1.-zfr) + zfr*(1.+RLVTT*zqs/RD/zt)/(1.+zdqs) ) &
174 )*(1.+RETV*q(i, k))
175 ztvu =( t(i, k-1) &
176 - zdphi/RCPD/(1.+RVTMP2*zq) &
177 *( (1.-zfr) + zfr*(1.+RLVTT*zqs/RD/zt)/(1.+zdqs) ) &
178 )*(1.+RETV*q(i, k-1))
179 ri(i) =zmgeom(i)*(ztvd-ztvu)/(zdu2*0.5*(ztvd+ztvu))
180 ri(i) = ri(i) &
181 + zmgeom(i)*zmgeom(i)/RG*gamt(k) &
182 *(paprs(i, k)/101325.0)**RKAPPA &
183 /(zdu2*0.5*(ztvd+ztvu))
184 ELSE
185 ! calcul de Ridchardson compatible LMD5
186 ri(i) =(RCPD*(t(i, k)-t(i, k-1)) &
187 -RD*0.5*(t(i, k)+t(i, k-1))/paprs(i, k) &
188 *(pplay(i, k)-pplay(i, k-1)) &
189 )*zmgeom(i)/(zdu2*0.5*RCPD*(t(i, k-1)+t(i, k)))
190 ri(i) = ri(i) + &
191 zmgeom(i)*zmgeom(i)*gamt(k)/RG &
192 *(paprs(i, k)/101325.0)**RKAPPA &
193 /(zdu2*0.5*(t(i, k-1)+t(i, k)))
194 ENDIF
195
196 ! finalement, les coefficients d'echange sont obtenus:
197
198 cdn = SQRT(zdu2) / zmgeom(i) * RG
199
200 IF (opt_ec) THEN
201 z2geomf = zgeop(i, k-1)+zgeop(i, k)
202 alm2 = (0.5*ckap/RG*z2geomf &
203 /(1.+0.5*ckap/rg/clam*z2geomf))**2
204 zalh2 = (0.5*ckap/rg*z2geomf &
205 /(1.+0.5*ckap/RG/(clam*SQRT(1.5*cd))*z2geomf))**2
206 IF (ri(i) < 0.) THEN
207 ! situation instable
208 scf = ((zgeop(i, k)/zgeop(i, k-1))**(1./3.)-1.)**3 &
209 / (zmgeom(i)/RG)**3 / (zgeop(i, k-1)/RG)
210 scf = SQRT(-ri(i)*scf)
211 scfm = 1.0 / (1.0+3.0*cb*cc*alm2*scf)
212 zscfh = 1.0 / (1.0+3.0*cb*cc*zalh2*scf)
213 coefm(i, k) = cdn * alm2 * (1. - 2. * cb * ri(i) * scfm)
214 coefh(i, k) = cdn*zalh2*(1.-3.0*cb*ri(i)*zscfh)
215 ELSE
216 ! situation stable
217 scf = SQRT(1.+cd*ri(i))
218 coefm(i, k) = cdn * alm2 / (1. + 2. * cb * ri(i) / scf)
219 coefh(i, k) = cdn*zalh2/(1.+3.0*cb*ri(i)*scf)
220 ENDIF
221 ELSE
222 l2(i) = (mixlen*MAX(0.0, (paprs(i, k)-paprs(i, itop(i)+1)) &
223 /(paprs(i, 2)-paprs(i, itop(i)+1)) ))**2
224 coefm(i, k) = sqrt(max(cdn**2 * (ric - ri(i)) / ric, kstable))
225 coefm(i, k)= l2(i) * coefm(i, k)
226 coefh(i, k) = coefm(i, k) / prandtl ! h et m different
227 ENDIF
228 ENDDO loop_horiz
229 ENDDO loop_vertical
230
231 ! Au-delà du sommet, pas de diffusion turbulente :
232 forall (i = 1: knon)
233 coefh(i, itop(i) + 1:) = 0.
234 coefm(i, itop(i) + 1:) = 0.
235 END forall
236
237 END SUBROUTINE coefkz
238
239 end module coefkz_m

  ViewVC Help
Powered by ViewVC 1.1.21