--- trunk/libf/phylmd/coefkzmin.f 2011/01/06 17:52:19 38 +++ trunk/libf/phylmd/coefkzmin.f90 2011/07/01 15:00:48 47 @@ -1,144 +1,104 @@ -! -! $Header: /home/cvsroot/LMDZ4/libf/phylmd/coefkzmin.F,v 1.1.1.1 2004/05/19 12:53:08 lmdzadmin Exp $ -! - SUBROUTINE coefkzmin(ngrid,ypaprs,ypplay,yu,yv,yt,yq,ycoefm - . ,km,kn) -c SUBROUTINE coefkzmin(ngrid,zlev,teta,ustar,km,kn) - use dimens_m - use dimphy - use SUPHEC_M - IMPLICIT NONE - - -c....................................................................... -c Entrees modifies en attendant une version ou les zlev, et zlay soient -c disponibles. - - REAL ycoefm(klon,klev) - - REAL yu(klon,klev), yv(klon,klev) - REAL yt(klon,klev), yq(klon,klev) - REAL ypaprs(klon,klev+1), ypplay(klon,klev) - REAL yustar(klon) - real yzlay(klon,klev),yzlev(klon,klev+1),yteta(klon,klev) - - integer i - -c....................................................................... -c -c En entree : -c ----------- -c -c zlev : altitude a chaque niveau (interface inferieure de la couche -c de meme indice) -c ustar : u* -c -c teta : temperature potentielle au centre de chaque couche -c (en entree : la valeur au debut du pas de temps) -c -c en sortier : -c ------------ -c -c km : diffusivite turbulente de quantite de mouvement (au bas de chaque -c couche) -c (en sortie : la valeur a la fin du pas de temps) -c kn : diffusivite turbulente des scalaires (au bas de chaque couche) -c (en sortie : la valeur a la fin du pas de temps) -c -c....................................................................... - - real ustar(klon) - real kmin,qmin,pblhmin(klon),coriol(klon) - REAL zlev(klon,klev+1) - REAL teta(klon,klev) - - REAL km(klon,klev+1) - REAL kn(klon,klev+1) - integer l_mix,ngrid - - - integer nlay,nlev - PARAMETER (nlay=klev) - PARAMETER (nlev=klev+1) - - integer ig,k - - real kap - save kap - data kap/0.4/ - - real frif,falpha,fsm - real fl,zzz,zl0,zq2,zn2 - - -c....................................................................... -c en attendant une version ou les zlev, et zlay soient -c disponibles. -c Debut de la partie qui doit etre unclue a terme dans clmain. -c - do i=1,ngrid - yzlay(i,1)=RD*yt(i,1)/(0.5*(ypaprs(i,1)+ypplay(i,1))) - . *(ypaprs(i,1)-ypplay(i,1))/RG - enddo - do k=2,klev - do i=1,ngrid - yzlay(i,k)=yzlay(i,k-1)+RD*0.5*(yt(i,k-1)+yt(i,k)) - s /ypaprs(i,k)*(ypplay(i,k-1)-ypplay(i,k))/RG - enddo - enddo - do k=1,klev - do i=1,ngrid -cATTENTION:on passe la temperature potentielle virt. pour le calcul de K - yteta(i,k)=yt(i,k)*(ypaprs(i,1)/ypplay(i,k))**rkappa - s *(1.+0.61*yq(i,k)) - enddo - enddo - do i=1,ngrid - yzlev(i,1)=0. - yzlev(i,klev+1)=2.*yzlay(i,klev)-yzlay(i,klev-1) - enddo - do k=2,klev - do i=1,ngrid - yzlev(i,k)=0.5*(yzlay(i,k)+yzlay(i,k-1)) - enddo - enddo - - -cIM cf FH yustar(:) =SQRT(ycoefm(:,1)*(yu(:,1)*yu(:,1)+yv(:,1)*yv(:,1))) - yustar(1:ngrid) =SQRT(ycoefm(1:ngrid,1)* - $ (yu(1:ngrid,1)*yu(1:ngrid,1)+yv(1:ngrid,1)*yv(1:ngrid,1))) - -c Fin de la partie qui doit etre unclue a terme dans clmain. - -Cette routine est ecrite pour avoir en entree ustar, teta et zlev -c Ici, on a inclut le calcul de ces trois variables dans la routine -c coefkzmin en attendant une nouvelle version de la couche limite -c ou ces variables seront disponibles. - -c Debut de la routine coefkzmin proprement dite. - - ustar=yustar - teta=yteta - zlev=yzlev - - do ig=1,ngrid - coriol(ig)=1.e-4 - pblhmin(ig)=0.07*ustar(ig)/max(abs(coriol(ig)),2.546e-5) - enddo - - do k=2,klev - do ig=1,ngrid - if (teta(ig,2).gt.teta(ig,1)) then - qmin=ustar(ig)*(max(1.-zlev(ig,k)/pblhmin(ig),0.))**2 - kmin=kap*zlev(ig,k)*qmin - else - kmin=0. ! kmin n'est utilise que pour les SL stables. - endif - kn(ig,k)=kmin - km(ig,k)=kmin - enddo - enddo +module coefkzmin_m + IMPLICIT NONE - return - end +contains + + SUBROUTINE coefkzmin(ngrid, ypaprs, ypplay, yu, yv, yt, yq, ycoefm, km, kn) + + ! From LMDZ4/libf/phylmd/coefkzmin.F, version 1.1.1.1 2004/05/19 12:53:08 + + ! Entrées modifiées en attendant une version où les zlev et zlay + ! soient disponibles. + + USE dimphy, ONLY: klev, klon + USE suphec_m, ONLY: rd, rg, rkappa + + integer, intent(in):: ngrid + REAL, intent(in):: ypaprs(klon, klev+1), ypplay(klon, klev) + REAL, intent(in):: yu(klon, klev), yv(klon, klev) ! wind, in m s-1 + REAL, intent(in):: yt(klon, klev) ! temperature, in K + REAL, intent(in):: yq(klon, klev) + + REAL, intent(in):: ycoefm(klon) ! drag coefficient + + REAL, intent(inout):: km(klon, klev) + ! coefficient de diffusion turbulente de quantité de mouvement (au + ! bas de chaque couche) (en sortie : la valeur à la fin du pas de + ! temps), m2 s-1 + + REAL, intent(inout):: kn(klon, klev) + ! coefficient de diffusion turbulente des scalaires (au bas de + ! chaque couche) (en sortie : la valeur à la fin du pas de temps), m2 s-1 + + ! Local: + + real ustar(ngrid) ! u* + real zlay(ngrid, klev) ! in m + integer i, k + real pblhmin(ngrid) + real, parameter:: coriol = 1e-4 + + REAL zlev(ngrid, 2: klev) + ! altitude at level (interface between layer with same index), in m + + REAL teta(ngrid, klev) + ! température potentielle au centre de chaque couche (la valeur au + ! debut du pas de temps) + + real, PARAMETER:: kap = 0.4 + + !--------------------------------------------------------------------- + + ! Debut de la partie qui doit etre incluse a terme dans clmain. + + do i = 1, ngrid + zlay(i, 1) = RD * yt(i, 1) * 2 / (ypaprs(i, 1) + ypplay(i, 1)) & + * (ypaprs(i, 1) - ypplay(i, 1)) / RG + enddo + + do k = 2, klev + do i = 1, ngrid + zlay(i, k) = zlay(i, k-1) + RD * 0.5 * (yt(i, k - 1) + yt(i, k)) & + / ypaprs(i, k) * (ypplay(i, k - 1) - ypplay(i, k)) / RG + enddo + enddo + + do k=1, klev + do i = 1, ngrid + ! Attention : on passe la temperature potentielle virtuelle + ! pour le calcul de K. + teta(i, k) = yt(i, k) * (ypaprs(i, 1) / ypplay(i, k))**rkappa & + * (1. + 0.61 * yq(i, k)) + enddo + enddo + + forall (k = 2: klev) zlev(:, k) = 0.5 * (zlay(:, k) + zlay(:, k-1)) + ustar = SQRT(ycoefm(:ngrid) * (yu(:ngrid, 1)**2 + yv(:ngrid, 1)**2)) + + ! Fin de la partie qui doit être incluse à terme dans clmain + + ! Cette routine est ecrite pour avoir en entree ustar, teta et zlev + ! Ici, on a inclus le calcul de ces trois variables dans la routine + ! coefkzmin en attendant une nouvelle version de la couche limite + ! ou ces variables seront disponibles. + + ! Debut de la routine coefkzmin proprement dite + + pblhmin = 0.07 * ustar / coriol + + do k = 2, klev + do i = 1, ngrid + if (teta(i, 2) > teta(i, 1)) then + kn(i, k) = kap * zlev(i, k) * ustar(i) & + * (max(1. - zlev(i, k) / pblhmin(i), 0.))**2 + else + kn(i, k) = 0. ! min n'est utilisé que pour les SL stables + endif + km(i, k) = kn(i, k) + enddo + enddo + + end SUBROUTINE coefkzmin + +end module coefkzmin_m