source: trunk/LMDZ.MARS/libf/phymars/surflayer_interpol.F @ 339

Last change on this file since 339 was 339, checked in by acolaitis, 13 years ago

Minor commit: interpolation can be called with or without thermals, with or without convadj.

File size: 11.6 KB
RevLine 
[267]1      SUBROUTINE surflayer_interpol(ngrid,nlay,pz0,
[319]2     & pg,pz,pu,pv,wmax,pts,ph,z_out,Teta_out,u_out,ustar,tstar,L_mo)
[267]3      IMPLICIT NONE
4!=======================================================================
5!
6!   Subject: interpolation of temperature and velocity norm in the surface layer
[268]7!   by recomputation of surface layer quantities (Richardson, Prandtl, Reynolds, u*, teta*)
[267]8!   ------- 
9!
10!   Author: Arnaud Colaitis 05/08/11
11!   -------
12!
13!   Arguments:
14!   ----------
15!
16!   inputs:
17!   ------
18!     ngrid            size of the horizontal grid
19!     pg               gravity (m s -2)
20!     pz(ngrid,nlay)   height of layers
21!     pu(ngrid,nlay)   u component of the wind
22!     pv(ngrid,nlay)   v component of the wind
23!     pts(ngrid)       surface temperature
24!     ph(ngrid)        potential temperature T*(p/ps)^kappa
25!
26!
27!=======================================================================
28!
29!-----------------------------------------------------------------------
30!   Declarations:
31!   -------------
32
33#include "comcstfi.h"
[339]34#include "callkeys.h"
[267]35
36!   Arguments:
37!   ----------
38
39      INTEGER, INTENT(IN) :: ngrid,nlay
40      REAL, INTENT(IN) :: pz0(ngrid)
41      REAL, INTENT(IN) :: pg,pz(ngrid,nlay)
42      REAL, INTENT(IN) :: pu(ngrid,nlay),pv(ngrid,nlay)
43      REAL, INTENT(IN) :: wmax(ngrid)
44      REAL, INTENT(IN) :: pts(ngrid),ph(ngrid,nlay)
[272]45      REAL, INTENT(IN) :: z_out                  ! output height (in m above surface)
[268]46      REAL, INTENT(OUT) :: Teta_out(ngrid),u_out(ngrid)! interpolated fields at z_out : potential temperature and norm(uv)
[267]47      REAL, INTENT(OUT) :: ustar(ngrid), tstar(ngrid) ! u* and teta*
[319]48      REAL, INTENT(OUT) :: L_mo(ngrid)                ! Monin-Obukhov length
[267]49
50!   Local:
51!   ------
52
53      INTEGER ig
54
55      REAL karman,nu
56      DATA karman,nu/.41,0.001/
57      SAVE karman,nu
58
59!    Local(2):
60!    ---------
[272]61      REAL zout
[267]62
63      REAL rib(ngrid)  ! Bulk Richardson number
64      REAL fm(ngrid) ! stability function for momentum
65      REAL fh(ngrid) ! stability function for heat
66      REAL z1z0,z1z0t ! ratios z1/z0 and z1/z0T
67
68! phim = 1+betam*zeta   or   (1-bm*zeta)**am
69! phih = alphah + betah*zeta    or   alphah(1.-bh*zeta)**ah
70      REAL betam, betah, alphah, bm, bh, lambda
71! ah and am are assumed to be -0.25 and -0.5 respectively
72
73      REAL cdn(ngrid),chn(ngrid)  ! neutral momentum and heat drag coefficient
74      REAL pz0t        ! initial thermal roughness length. (local)
75      REAL ric         ! critical richardson number
76      REAL reynolds(ngrid)    ! reynolds number for UBL
77      REAL prandtl(ngrid)     ! prandtl number for UBL
78      REAL pz0tcomp(ngrid)     ! computed z0t
79      REAL ite
[339]80      REAL residual,zcd0,z1
[267]81      REAL pcdv(ngrid),pcdh(ngrid)
82! For output :
83
[268]84      REAL zu2(ngrid)                  ! Large-scale wind at first layer
[267]85!-----------------------------------------------------------------------
86!   couche de surface:
87!   ------------------
[339]88
89c Init :
90
91      L_mo(:)=0.
92      ustar(:)=0.
[267]93      tstar(:)=0.
[339]94      zout=z_out
95
[267]96      reynolds(:)=0.
97
98! New formulation (AC) :
99
100! phim = 1+betam*zeta   or   (1-bm*zeta)**am
101! phih = alphah + betah*zeta    or   alphah(1.-bh*zeta)**ah
102! am=-0.25, ah=-0.5
103
104      pz0t = 0.     ! for the sake of simplicity
105      pz0tcomp(:) = 0.1*pz0(:)
106      rib(:)=0.
107      pcdv(:)=0.
108      pcdh(:)=0.
109
110! this formulation assumes alphah=1., implying betah=betam
111! We use Dyer et al. parameters, as they cover a broad range of Richardson numbers :
112      bm=16.            !UBL
113      bh=16.            !UBL
114      alphah=1.
115      betam=5.         !SBL
116      betah=5.         !SBL
117      lambda=(sqrt(bh/bm))/alphah
118      ric=betah/(betam**2)
119
120      DO ig=1,ngrid
121
122         ite=0.
123         residual=abs(pz0tcomp(ig)-pz0t)
124
125         do while((residual .gt. 0.01*pz0(ig)) .and.  (ite .lt. 10.))
126
127         pz0t=pz0tcomp(ig)
128
129         if ((pu(ig,1) .ne. 0.) .or. (pv(ig,1) .ne. 0.)) then
130
131! Classical Richardson number formulation
132
133!         rib(ig) = (pg/ph(ig,1))*pz(ig,1)*(ph(ig,1)-pts(ig))
134!     &           /(pu(ig,1)*pu(ig,1) + pv(ig,1)*pv(ig,1))
135
136! Richardson number formulation proposed by D.E. England et al. (1995)
137
[268]138!        IF((pu(ig,1)*pu(ig,1) + pv(ig,1)*pv(ig,1) .lt. 1.)
139!     &            .and. (wmax(ig) .gt. 0.)) THEN
140          zu2(ig)=
141!     &  (MAX(pu(ig,1)*pu(ig,1) + pv(ig,1)*pv(ig,1),wmax(ig)**2))
[292]142     &  ( pu(ig,1)*pu(ig,1) + pv(ig,1)*pv(ig,1))
[268]143!     &  pu(ig,1)*pu(ig,1) + pv(ig,1)*pv(ig,1)
144!        ELSE
145!        zu2(ig)=pu(ig,1)*pu(ig,1) + pv(ig,1)*pv(ig,1)
146!        ENDIF
147
[339]148      if(.not.callrichsl) then
149         rib(ig) = (pg/ph(ig,1))
150     &      *sqrt(pz(ig,1)*pz0(ig))
151     &      *(((log(pz(ig,1)/pz0(ig)))**2)/(log(pz(ig,1)/pz0t)))
152     &      *(ph(ig,1)-pts(ig))/(zu2(ig)+6.)
153      else
[267]154          rib(ig) = (pg/ph(ig,1))
[268]155!     &      *pz(ig,1)*pz0(ig)/sqrt(pz(ig,1)*pz0t)
156     &      *sqrt(pz(ig,1)*pz0(ig))
[267]157     &      *(((log(pz(ig,1)/pz0(ig)))**2)/(log(pz(ig,1)/pz0t)))
[292]158     &      *(ph(ig,1)-pts(ig))/(zu2(ig) + (0.5*wmax(ig))**2)
[267]159
[268]160!     &  /(MAX(pu(ig,1)*pu(ig,1) + pv(ig,1)*pv(ig,1),wmax(ig)**2))
161!     &  /( pu(ig,1)*pu(ig,1) + pv(ig,1)*pv(ig,1) + wmax(ig)**2)
162
[339]163      endif
164
[267]165         else
166         print*,'warning, infinite Richardson at surface'
167         print*,pu(ig,1),pv(ig,1)
168         rib(ig) = ric          ! traiter ce cas !
169         endif
170
171         z1z0=pz(ig,1)/pz0(ig)
172         z1z0t=pz(ig,1)/pz0t
173
174         cdn(ig)=karman/log(z1z0)
175         cdn(ig)=cdn(ig)*cdn(ig)
176         chn(ig)=cdn(ig)*log(z1z0)/log(z1z0t)
177
178! Stable case :
179      if (rib(ig) .gt. 0.) then
180! From D.E. England et al. (95)
181      prandtl(ig)=1.
182         if(rib(ig) .lt. ric) then
183! Assuming alphah=1. and bh=bm for stable conditions :
184            fm(ig)=((ric-rib(ig))/ric)**2
185            fh(ig)=((ric-rib(ig))/ric)**2
186         else
187! For Ri>Ric, we consider Ri->Infinity => no turbulent mixing at surface
188            fm(ig)=0.
189            fh(ig)=0.
190         endif
191! Unstable case :
192      else
193! From D.E. England et al. (95)
194         fm(ig)=sqrt(1.-lambda*bm*rib(ig))
195         fh(ig)=(1./alphah)*((1.-lambda*bh*rib(ig))**0.5)*
196     &                     (1.-lambda*bm*rib(ig))**0.25
197         prandtl(ig)=alphah*((1.-lambda*bm*rib(ig))**0.25)/
198     &             ((1.-lambda*bh*rib(ig))**0.5)
199      endif
200
[272]201       reynolds(ig)=karman*sqrt(fm(ig))
[292]202     &              *sqrt(zu2(ig)+(0.5*wmax(ig))**2)
[272]203!    &               *sqrt(pu(ig,1)**2 + pv(ig,1)**2)
[267]204     &              *pz0(ig)/(log(z1z0)*nu)
205       pz0tcomp(ig)=pz0(ig)*exp(-karman*7.3*
206     &              (reynolds(ig)**0.25)*(prandtl(ig)**0.5))
207
208         
209      residual = abs(pz0t-pz0tcomp(ig))
210      ite = ite+1
211!      if(ite .eq. 10) then
212!        print*, 'iteration max reached'
213!      endif
214!      print*, "iteration nnumber, residual",ite,residual
215
216      enddo  ! of while
217
218          pz0t=0.
219
220! Drag computation :
221
222         pcdv(ig)=cdn(ig)*fm(ig)
223         pcdh(ig)=chn(ig)*fh(ig)
224       
225      ENDDO
226
[339]227!      endif !of if callrichsl
228
[268]229! Large-scale wind at first layer (without gustiness) and
[267]230! u* theta* computation
231      DO ig=1,ngrid
232
[339]233         if (rib(ig) .ge. ric) then
[267]234           ustar(ig)=0.
235           tstar(ig)=0.
236         else
[268]237
238!           ustar(ig)=karman*sqrt(fm(ig)*zu2(ig))/(log(pz(ig,1)/pz0(ig)))
239!           tstar(ig)=karman*fh(ig)*(ph(ig,1)-pts(ig))
240!     &                   /(log(pz(ig,1)/pz0tcomp(ig))*sqrt(fm(ig)))
241
242!simpler definition of u* and teta*, equivalent to the formula above :
243
[292]244            ustar(ig)=sqrt(pcdv(ig))*sqrt(zu2(ig))
245            tstar(ig)=-pcdh(ig)*(pts(ig)-ph(ig,1))
246     &     /sqrt(pcdv(ig))
[268]247
[339]248           if ((tstar(ig) .lt. -50) .and. callrichsl) then
[268]249             print*, fh(ig),rib(ig),(ph(ig,1)-pts(ig))
250     &               ,log(pz(ig,1)/pz0tcomp(ig)),sqrt(fm(ig))
251           endif
[267]252         endif
253      ENDDO
254
255! Monin Obukhov length :
256
257      DO ig=1,ngrid
258         if (rib(ig) .gt. ric) then
259            L_mo(ig)=0.
260         else
261            L_mo(ig)=pts(ig)*(ustar(ig)**2)/(pg*karman*tstar(ig))  !as defined here, L is positive for SBL, negative for UBL
262         endif
263      ENDDO
264
[268]265      DO ig=1,ngrid
[272]266      IF(zout .ge. pz(ig,1)) THEN
267           zout=1.
[267]268           print*, 'Warning, z_out should be less than the first
[272]269     & vertical grid-point'
[267]270           print*, 'z1 =',pz(ig,1)
271           print*, 'z_out=',z_out
272           print*, 'z_out has been changed to 1m
[272]273     & and computation is resumed'
[267]274      ENDIF
275
[272]276      IF(zout .lt. pz0tcomp(ig)) THEN
277           zout=pz0tcomp(ig)
278           print*, 'Warning, z_out should be more than the thermal
279     & roughness length'
280           print*, 'z0 =',pz0tcomp(ig)
[267]281           print*, 'z_out=',z_out
[272]282           print*, 'z_out has been changed to z0t
283     & and computation is resumed'
[267]284      ENDIF
[268]285      ENDDO
[267]286
[272]287      print*, 'interpolation of u and teta at z_out=',zout
[267]288
289      DO ig=1,ngrid
290        IF (L_mo(ig) .gt. 0.) THEN
[272]291           u_out(ig)=(ustar(ig)/karman)*log(zout/pz0(ig)) +
292     &            5.*(ustar(ig)/(karman*L_mo(ig)))*(zout-pz0(ig))
[267]293           Teta_out(ig)=pts(ig)+(tstar(ig)/(prandtl(ig)*karman))
[272]294     &                            *log(zout/pz0tcomp(ig)) +
[267]295     &            5.*(tstar(ig)/(prandtl(ig)*karman*L_mo(ig)))
[272]296     &                            *(zout-pz0tcomp(ig))
[267]297        ELSEIF (L_mo(ig) .lt. 0.) THEN
[268]298
299          IF(L_mo(ig) .gt. -1000.) THEN
300           
301           u_out(ig)=(ustar(ig)/karman)*(
[272]302     &  2.*atan((1.-16.*zout/L_mo(ig))**0.25)
[268]303     & -2.*atan((1.-16.*pz0(ig)/L_mo(ig))**0.25)
[272]304     & -2.*log(1.+(1.-16.*zout/L_mo(ig))**0.25)
[268]305     & +2.*log(1.+(1.-16.*pz0(ig)/L_mo(ig))**0.25)
[272]306     & -   log(1.+sqrt(1.-16.*zout/L_mo(ig)))
[268]307     & +   log(1.+sqrt(1.-16.*pz0(ig)/L_mo(ig)))
[272]308     & +   log(zout/pz0(ig))
[267]309     &                                  )
[268]310
311           Teta_out(ig)=pts(ig)+(tstar(ig)/(prandtl(ig)*karman))*(
312     &  2.*log(1.+sqrt(1.-16.*pz0tcomp(ig)/L_mo(ig)))
[272]313     & -2.*log(1.+sqrt(1.-16.*zout/L_mo(ig)))
314     & +   log(zout/pz0tcomp(ig))
[267]315     &                                                        )
[268]316
317          ELSE
318
319! We have to treat the case where L is very large and negative,
320! corresponding to a very nearly stable atmosphere (but not quite !)
321! i.e. teta* <0 and almost zero. We choose the cutoff
322! corresponding to L_mo < -1000 and use a 3rd order taylor expansion. The difference
323! between the two expression for z/L = -1/1000 is -1.54324*10^-9
324! (we do that to avoid using r*4 precision, otherwise, we get -inf values)         
325
326           u_out(ig)=(ustar(ig)/karman)*(
[272]327     &     (4./L_mo(ig))*(zout-pz0(ig))
328     &   + (20./(L_mo(ig))**2)*(zout**2-pz0(ig)**2)
329     &   + (160./(L_mo(ig))**3)*(zout**3-pz0(ig)**3)
330     &   + log(zout/pz0(ig))
[268]331     &                                   )
332
333           Teta_out(ig)=pts(ig)+(tstar(ig)/(prandtl(ig)*karman))*(
[272]334     &     (8./L_mo(ig))*(zout-pz0tcomp(ig))
335     &   + (48./(L_mo(ig))**2)*(zout**2-pz0tcomp(ig)**2)
336     &   + (1280./(3.*(L_mo(ig))**3))*(zout**3-pz0tcomp(ig)**3)
337     &   + log(zout/pz0tcomp(ig))
[268]338     &                                                           )
339
340          ENDIF
[267]341        ELSE
342           u_out(ig)=0.
[268]343           Teta_out(ig)=pts(ig)
[267]344        ENDIF
345      ENDDO
346
[339]347! when using convective adjustment without thermals, a vertical potential temperature
348! profile is assumed up to the thermal roughness length. Hence, theoretically, theta
349! interpolated at any height in the surface layer is theta at the first level.
350
351      IF ((.not.calltherm).and.(calladj)) THEN
352           Teta_out(:)=ph(:,1)
353      ENDIF
354
[268]355! Usefull diagnostics for the interpolation routine :
356
[339]357!
358!         call WRITEDIAGFI(ngrid,'Ri',
359!     &              'Richardson','m',
360!     &                         2,rib)
361!
[272]362!         call WRITEDIAGFI(ngrid,'z0T',
363!     &              'thermal roughness length','m',
364!     &                         2,pz0tcomp)
365!         call WRITEDIAGFI(ngrid,'z0',
366!     &              'roughness length','m',
367!     &                         2,pz0)
[267]368
369
370      RETURN
371      END
Note: See TracBrowser for help on using the repository browser.