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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 207 - (hide 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 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 suphec_m, ONLY: rcpd, rd, retv, rg, rkappa, rlstt, rlvtt, rtt
18     USE yoethf_m, ONLY: r2es, r5ies, r5les, rvtmp2
19 guez 207 USE fcttre, ONLY: dqsatl, dqsats, foede, foeew, qsatl, qsats
20 guez 62 USE conf_phys_m, ONLY: iflag_pbl
21     use clcdrag_m, only: clcdrag
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 guez 62 REAL, intent(out):: coefm(:, :) ! (knon, klev) coefficient, vitesse
42 guez 40
43 guez 62 real, intent(out):: coefh(:, :) ! (knon, klev)
44     ! coefficient, chaleur et humidité
45    
46 guez 47 ! Local:
47 guez 40
48 guez 62 INTEGER itop(knon) ! numero de couche du sommet de la couche limite
49 guez 40
50 guez 47 ! Quelques constantes et options:
51 guez 40
52 guez 47 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 guez 62 REAL, PARAMETER:: ratqs = 0.05 ! largeur de distribution de vapeur d'eau
59 guez 207
60 guez 62 LOGICAL, PARAMETER:: richum = .TRUE.
61     ! utilise le nombre de Richardson humide
62    
63 guez 47 REAL, PARAMETER:: ric = 0.4 ! nombre de Richardson critique
64     REAL, PARAMETER:: prandtl = 0.4
65 guez 40
66 guez 47 REAL kstable ! diffusion minimale (situation stable)
67 guez 62 REAL, PARAMETER:: mixlen = 35. ! constante contrôlant longueur de mélange
68     INTEGER, PARAMETER:: isommet = klev ! sommet de la couche limite
69 guez 40
70 guez 47 LOGICAL, PARAMETER:: tvirtu = .TRUE.
71     ! calculer Ri d'une maniere plus performante
72 guez 40
73 guez 47 LOGICAL, PARAMETER:: opt_ec = .FALSE.
74     ! formule du Centre Europeen dans l'atmosphere
75 guez 40
76 guez 105 INTEGER i, k
77 guez 47 REAL zgeop(klon, klev)
78     REAL zmgeom(klon)
79 guez 62 REAL ri(klon)
80     REAL l2(klon)
81 guez 40
82 guez 47 REAL u1(klon), v1(klon), t1(klon), q1(klon), z1(klon)
83 guez 40
84 guez 62 REAL zdphi, zdu2, ztvd, ztvu, cdn
85     REAL scf
86 guez 103 REAL zt, zq, zcvm5, zcor, zqs, zfr, zdqs
87     logical zdelta
88 guez 62 REAL z2geomf, zalh2, alm2, zscfh, scfm
89 guez 47 REAL gamt(2:klev) ! contre-gradient pour la chaleur sensible: Kelvin/metre
90 guez 40
91 guez 47 !--------------------------------------------------------------------
92 guez 40
93 guez 47 ! 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 guez 40
105 guez 47 IF ( nsrf .NE. is_oce ) THEN
106     kstable = ksta_ter
107     ELSE
108     kstable = ksta
109     ENDIF
110 guez 40
111 guez 47 ! 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 guez 40
124 guez 47 ! Calculer le frottement au sol (Cdrag)
125 guez 40
126 guez 47 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 guez 40
134 guez 47 CALL clcdrag(klon, knon, nsrf, .false., u1, v1, t1, q1, z1, ts, qsurf, &
135 guez 62 rugos, coefm(:, 1), coefh(:, 1))
136 guez 40
137 guez 47 ! Calculer les coefficients turbulents dans l'atmosphere
138 guez 40
139 guez 62 itop = isommet
140 guez 40
141 guez 47 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 guez 40
150 guez 47 ! calculer Qs et dQs/dT:
151 guez 40
152 guez 207 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 guez 40
161 guez 47 ! calculer la fraction nuageuse (processus humide):
162 guez 40
163 guez 47 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 guez 40
167 guez 47 ! calculer le nombre de Richardson:
168 guez 40
169 guez 47 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 guez 62 ri(i) =zmgeom(i)*(ztvd-ztvu)/(zdu2*0.5*(ztvd+ztvu))
179     ri(i) = ri(i) &
180 guez 47 + 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 guez 62 ri(i) =(RCPD*(t(i, k)-t(i, k-1)) &
186 guez 47 -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 guez 62 ri(i) = ri(i) + &
190 guez 47 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 guez 40
195 guez 47 ! finalement, les coefficients d'echange sont obtenus:
196 guez 40
197 guez 62 cdn = SQRT(zdu2) / zmgeom(i) * RG
198 guez 40
199 guez 47 IF (opt_ec) THEN
200     z2geomf = zgeop(i, k-1)+zgeop(i, k)
201 guez 62 alm2 = (0.5*ckap/RG*z2geomf &
202 guez 47 /(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 guez 62 IF (ri(i) < 0.) THEN
206 guez 47 ! situation instable
207 guez 62 scf = ((zgeop(i, k)/zgeop(i, k-1))**(1./3.)-1.)**3 &
208 guez 47 / (zmgeom(i)/RG)**3 / (zgeop(i, k-1)/RG)
209 guez 62 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 guez 47 ELSE
215     ! situation stable
216 guez 62 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 guez 47 ENDIF
220     ELSE
221 guez 62 l2(i) = (mixlen*MAX(0.0, (paprs(i, k)-paprs(i, itop(i)+1)) &
222 guez 47 /(paprs(i, 2)-paprs(i, itop(i)+1)) ))**2
223 guez 62 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 guez 47 ENDIF
227     ENDDO loop_horiz
228     ENDDO loop_vertical
229 guez 40
230 guez 62 ! 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 guez 40
236 guez 47 END SUBROUTINE coefkz
237 guez 40
238 guez 47 end module coefkz_m

  ViewVC Help
Powered by ViewVC 1.1.21