/[lmdze]/trunk/Sources/dyn3d/bilan_dyn.f
ViewVC logotype

Diff of /trunk/Sources/dyn3d/bilan_dyn.f

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

trunk/libf/dyn3d/bilan_dyn.f revision 30 by guez, Thu Apr 1 09:07:28 2010 UTC trunk/libf/dyn3d/bilan_dyn.f90 revision 55 by guez, Mon Dec 12 13:25:01 2011 UTC
# Line 1  Line 1 
1  !  module bilan_dyn_m
 ! $Header: /home/cvsroot/LMDZ4/libf/dyn3d/bilan_dyn.F,v 1.5 2005/03/16 10:12:17 fairhead Exp $  
 !  
       SUBROUTINE bilan_dyn (ntrac,dt_app,dt_cum,  
      s  ps,masse,pk,flux_u,flux_v,teta,phi,ucov,vcov,trac)  
   
 c   AFAIRE  
 c   Prevoir en champ nq+1 le diagnostique de l'energie  
 c   en faisant Qzon=Cv T + L * ...  
 c             vQ..A=Cp T + L * ...  
   
       USE histcom  
       use calendar  
       use histwrite_m  
       use dimens_m  
       use paramet_m  
       use comconst  
       use comvert  
       use comgeom, only: constang_2d, cu_2d, cv_2d, rlatv  
       use temps  
       use iniprint  
       use inigrads_m, only: inigrads  
   
       IMPLICIT NONE  
   
   
 c====================================================================  
 c  
 c   Sous-programme consacre à des diagnostics dynamiques de base  
 c  
 c  
 c   De facon generale, les moyennes des scalaires Q sont ponderees par  
 c   la masse.  
 c  
 c   Les flux de masse sont eux simplement moyennes.  
 c  
 c====================================================================  
   
 c   Arguments :  
 c   ===========  
   
       integer ntrac  
       real dt_app,dt_cum  
       real ps(iip1,jjp1)  
       real masse(iip1,jjp1,llm),pk(iip1,jjp1,llm)  
       real flux_u(iip1,jjp1,llm)  
       real flux_v(iip1,jjm,llm)  
       real teta(iip1,jjp1,llm)  
       real phi(iip1,jjp1,llm)  
       real ucov(iip1,jjp1,llm)  
       real vcov(iip1,jjm,llm)  
       real trac(iip1,jjp1,llm,ntrac)  
   
 c   Local :  
 c   =======  
   
       integer icum,ncum  
       logical first  
       real zz,zqy,zfactv(jjm,llm)  
   
       integer nQ  
       parameter (nQ=7)  
   
   
 cym      character*6 nom(nQ)  
 cym      character*6 unites(nQ)  
       character*6,save :: nom(nQ)  
       character*6,save :: unites(nQ)  
   
       character*10 file  
       integer ifile  
       parameter (ifile=4)  
   
       integer itemp,igeop,iecin,iang,iu,iovap,iun  
       integer i_sortie  
   
       save first,icum,ncum  
       save itemp,igeop,iecin,iang,iu,iovap,iun  
       save i_sortie  
   
       real time  
       integer itau  
       save time,itau  
       data time,itau/0.,0/  
   
       data first/.true./  
       data itemp,igeop,iecin,iang,iu,iovap,iun/1,2,3,4,5,6,7/  
       data i_sortie/1/  
   
       real ww  
   
 c   variables dynamiques intermédiaires  
       REAL vcont(iip1,jjm,llm),ucont(iip1,jjp1,llm)  
       REAL ang(iip1,jjp1,llm),unat(iip1,jjp1,llm)  
       REAL massebx(iip1,jjp1,llm),masseby(iip1,jjm,llm)  
       REAL vorpot(iip1,jjm,llm)  
       REAL w(iip1,jjp1,llm),ecin(iip1,jjp1,llm),convm(iip1,jjp1,llm)  
       REAL bern(iip1,jjp1,llm)  
   
 c   champ contenant les scalaires advectés.  
       real Q(iip1,jjp1,llm,nQ)  
       
 c   champs cumulés  
       real ps_cum(iip1,jjp1)  
       real masse_cum(iip1,jjp1,llm)  
       real flux_u_cum(iip1,jjp1,llm)  
       real flux_v_cum(iip1,jjm,llm)  
       real Q_cum(iip1,jjp1,llm,nQ)  
       real flux_uQ_cum(iip1,jjp1,llm,nQ)  
       real flux_vQ_cum(iip1,jjm,llm,nQ)  
       real flux_wQ_cum(iip1,jjp1,llm,nQ)  
       real dQ(iip1,jjp1,llm,nQ)  
   
       save ps_cum,masse_cum,flux_u_cum,flux_v_cum  
       save Q_cum,flux_uQ_cum,flux_vQ_cum  
   
 c   champs de tansport en moyenne zonale  
       integer ntr,itr  
       parameter (ntr=5)  
   
 cym      character*10 znom(ntr,nQ)  
 cym      character*20 znoml(ntr,nQ)  
 cym      character*10 zunites(ntr,nQ)  
       character*10,save :: znom(ntr,nQ)  
       character*20,save :: znoml(ntr,nQ)  
       character*10,save :: zunites(ntr,nQ)  
   
       integer iave,itot,immc,itrs,istn  
       data iave,itot,immc,itrs,istn/1,2,3,4,5/  
       character*3 ctrs(ntr)  
       data ctrs/'  ','TOT','MMC','TRS','STN'/  
   
       real zvQ(jjm,llm,ntr,nQ),zvQtmp(jjm,llm)  
       real zavQ(jjm,ntr,nQ),psiQ(jjm,llm+1,nQ)  
       real zmasse(jjm,llm),zamasse(jjm)  
   
       real zv(jjm,llm),psi(jjm,llm+1)  
   
       integer i,j,l,iQ  
   
   
 c   Initialisation du fichier contenant les moyennes zonales.  
 c   ---------------------------------------------------------  
   
       integer fileid  
       integer thoriid, zvertiid  
       save fileid  
   
       integer ndex3d(jjm*llm)  
   
 C   Variables locales  
 C  
       real zjulian  
       character*3 str  
       character*10 ctrac  
       integer ii,jj  
       integer zan, dayref  
 C  
       real rlong(jjm),rlatg(jjm)  
   
       !!print *, "Call sequence information: bilan_dyn"  
   
 c=====================================================================  
 c   Initialisation  
 c=====================================================================  
   
       time=time+dt_app  
       itau=itau+1  
   
       if (first) then  
   
   
         icum=0  
 c       initialisation des fichiers  
         first=.false.  
 c   ncum est la frequence de stokage en pas de temps  
         ncum=dt_cum/dt_app  
         if (abs(ncum*dt_app-dt_cum).gt.1.e-5*dt_app) then  
            print *,  
      .            'Pb : le pas de cumule doit etre multiple du pas'  
            print *,'dt_app=',dt_app  
            print *,'dt_cum=',dt_cum  
            stop  
         endif  
   
         if (i_sortie.eq.1) then  
          file='dynzon'  
          call inigrads(ifile ,(/0./),180./pi,0.,0.,rlatv,-90.,90.,  
      $        180./pi ,presnivs,1. ,dt_cum,file,'dyn_zon ')  
         endif  
   
         nom(itemp)='T'  
         nom(igeop)='gz'  
         nom(iecin)='K'  
         nom(iang)='ang'  
         nom(iu)='u'  
         nom(iovap)='ovap'  
         nom(iun)='un'  
   
         unites(itemp)='K'  
         unites(igeop)='m2/s2'  
         unites(iecin)='m2/s2'  
         unites(iang)='ang'  
         unites(iu)='m/s'  
         unites(iovap)='kg/kg'  
         unites(iun)='un'  
   
   
 c   Initialisation du fichier contenant les moyennes zonales.  
 c   ---------------------------------------------------------  
   
       zan = annee_ref  
       dayref = day_ref  
       CALL ymds2ju(zan, 1, dayref, 0.0, zjulian)  
         
       rlong=0.  
       rlatg=rlatv*180./pi  
         
       call histbeg_totreg('dynzon', rlong(:1), rlatg,  
      .             1, 1, 1, jjm,  
      .             itau_dyn, zjulian, dt_cum, thoriid, fileid)  
   
 C  
 C  Appel a histvert pour la grille verticale  
 C  
       call histvert(fileid, 'presnivs', 'Niveaux sigma','mb',  
      .              llm, presnivs, zvertiid)  
 C  
 C  Appels a histdef pour la definition des variables a sauvegarder  
       do iQ=1,nQ  
          do itr=1,ntr  
             if(itr.eq.1) then  
                znom(itr,iQ)=nom(iQ)  
                znoml(itr,iQ)=nom(iQ)  
                zunites(itr,iQ)=unites(iQ)  
             else  
                znom(itr,iQ)=ctrs(itr)//'v'//nom(iQ)  
                znoml(itr,iQ)='transport : v * '//nom(iQ)//' '//ctrs(itr)  
                zunites(itr,iQ)='m/s * '//unites(iQ)  
             endif  
          enddo  
       enddo  
   
 c   Declarations des champs avec dimension verticale  
 c      print*,'1HISTDEF'  
       do iQ=1,nQ  
          do itr=1,ntr  
       IF (prt_level > 5)  
      . print *,'var ',itr,iQ  
      .      ,znom(itr,iQ),znoml(itr,iQ),zunites(itr,iQ)  
             call histdef(fileid,znom(itr,iQ),znoml(itr,iQ),  
      .        zunites(itr,iQ),1,jjm,thoriid,llm,1,llm,zvertiid,  
      .        'ave(X)',dt_cum,dt_cum)  
          enddo  
 c   Declarations pour les fonctions de courant  
 c      print*,'2HISTDEF'  
           call histdef(fileid,'psi'//nom(iQ)  
      .      ,'stream fn. '//znoml(itot,iQ),  
      .      zunites(itot,iQ),1,jjm,thoriid,llm,1,llm,zvertiid,  
      .      'ave(X)',dt_cum,dt_cum)  
       enddo  
   
   
 c   Declarations pour les champs de transport d'air  
 c      print*,'3HISTDEF'  
       call histdef(fileid, 'masse', 'masse',  
      .             'kg', 1, jjm, thoriid, llm, 1, llm, zvertiid,  
      .             'ave(X)', dt_cum, dt_cum)  
       call histdef(fileid, 'v', 'v',  
      .             'm/s', 1, jjm, thoriid, llm, 1, llm, zvertiid,  
      .             'ave(X)', dt_cum, dt_cum)  
 c   Declarations pour les fonctions de courant  
 c      print*,'4HISTDEF'  
           call histdef(fileid,'psi','stream fn. MMC ','mega t/s',  
      .      1,jjm,thoriid,llm,1,llm,zvertiid,  
      .      'ave(X)',dt_cum,dt_cum)  
   
   
 c   Declaration des champs 1D de transport en latitude  
 c      print*,'5HISTDEF'  
       do iQ=1,nQ  
          do itr=2,ntr  
             call histdef(fileid,'a'//znom(itr,iQ),znoml(itr,iQ),  
      .        zunites(itr,iQ),1,jjm,thoriid,1,1,1,-99,  
      .        'ave(X)',dt_cum,dt_cum)  
          enddo  
       enddo  
   
   
 c      print*,'8HISTDEF'  
                CALL histend(fileid)  
   
   
       endif  
   
   
 c=====================================================================  
 c   Calcul des champs dynamiques  
 c   ----------------------------  
   
 c   énergie cinétique  
       ucont(:,:,:)=0  
       CALL covcont(llm,ucov,vcov,ucont,vcont)  
       CALL enercin(vcov,ucov,vcont,ucont,ecin)  
   
 c   moment cinétique  
       do l=1,llm  
          ang(:,:,l)=ucov(:,:,l)+constang_2d(:,:)  
          unat(:,:,l)=ucont(:,:,l)*cu_2d(:,:)  
       enddo  
   
       Q(:,:,:,itemp)=teta(:,:,:)*pk(:,:,:)/cpp  
       Q(:,:,:,igeop)=phi(:,:,:)  
       Q(:,:,:,iecin)=ecin(:,:,:)  
       Q(:,:,:,iang)=ang(:,:,:)  
       Q(:,:,:,iu)=unat(:,:,:)  
       Q(:,:,:,iovap)=trac(:,:,:,1)  
       Q(:,:,:,iun)=1.  
   
   
 c=====================================================================  
 c   Cumul  
 c=====================================================================  
 c  
       if(icum.EQ.0) then  
          ps_cum=0.  
          masse_cum=0.  
          flux_u_cum=0.  
          flux_v_cum=0.  
          Q_cum=0.  
          flux_vQ_cum=0.  
          flux_uQ_cum=0.  
       endif  
   
       IF (prt_level > 5)  
      . print *,'dans bilan_dyn ',icum,'->',icum+1  
       icum=icum+1  
   
 c   accumulation des flux de masse horizontaux  
       ps_cum=ps_cum+ps  
       masse_cum=masse_cum+masse  
       flux_u_cum=flux_u_cum+flux_u  
       flux_v_cum=flux_v_cum+flux_v  
       do iQ=1,nQ  
       Q_cum(:,:,:,iQ)=Q_cum(:,:,:,iQ)+Q(:,:,:,iQ)*masse(:,:,:)  
       enddo  
   
 c=====================================================================  
 c  FLUX ET TENDANCES  
 c=====================================================================  
   
 c   Flux longitudinal  
 c   -----------------  
       do iQ=1,nQ  
          do l=1,llm  
             do j=1,jjp1  
                do i=1,iim  
                   flux_uQ_cum(i,j,l,iQ)=flux_uQ_cum(i,j,l,iQ)  
      s            +flux_u(i,j,l)*0.5*(Q(i,j,l,iQ)+Q(i+1,j,l,iQ))  
                enddo  
                flux_uQ_cum(iip1,j,l,iQ)=flux_uQ_cum(1,j,l,iQ)  
             enddo  
          enddo  
       enddo  
   
 c    flux méridien  
 c    -------------  
       do iQ=1,nQ  
          do l=1,llm  
             do j=1,jjm  
                do i=1,iip1  
                   flux_vQ_cum(i,j,l,iQ)=flux_vQ_cum(i,j,l,iQ)  
      s            +flux_v(i,j,l)*0.5*(Q(i,j,l,iQ)+Q(i,j+1,l,iQ))  
                enddo  
             enddo  
          enddo  
       enddo  
   
   
 c    tendances  
 c    ---------  
   
 c   convergence horizontale  
       call  convflu(flux_uQ_cum,flux_vQ_cum,llm*nQ,dQ)  
   
 c   calcul de la vitesse verticale  
       call convmas(flux_u_cum,flux_v_cum,convm)  
       CALL vitvert(convm,w)  
   
       do iQ=1,nQ  
          do l=1,llm-1  
             do j=1,jjp1  
                do i=1,iip1  
                   ww=-0.5*w(i,j,l+1)*(Q(i,j,l,iQ)+Q(i,j,l+1,iQ))  
                   dQ(i,j,l  ,iQ)=dQ(i,j,l  ,iQ)-ww  
                   dQ(i,j,l+1,iQ)=dQ(i,j,l+1,iQ)+ww  
                enddo  
             enddo  
          enddo  
       enddo  
       IF (prt_level > 5)  
      . print *,'Apres les calculs fait a chaque pas'  
 c=====================================================================  
 c   PAS DE TEMPS D'ECRITURE  
 c=====================================================================  
       if (icum.eq.ncum) then  
 c=====================================================================  
   
       IF (prt_level > 5)  
      . print *,'Pas d ecriture'  
   
 c   Normalisation  
       do iQ=1,nQ  
          Q_cum(:,:,:,iQ)=Q_cum(:,:,:,iQ)/masse_cum(:,:,:)  
       enddo  
       zz=1./float(ncum)  
       ps_cum=ps_cum*zz  
       masse_cum=masse_cum*zz  
       flux_u_cum=flux_u_cum*zz  
       flux_v_cum=flux_v_cum*zz  
       flux_uQ_cum=flux_uQ_cum*zz  
       flux_vQ_cum=flux_vQ_cum*zz  
       dQ=dQ*zz  
   
   
 c   A retravailler eventuellement  
 c   division de dQ par la masse pour revenir aux bonnes grandeurs  
       do iQ=1,nQ  
          dQ(:,:,:,iQ)=dQ(:,:,:,iQ)/masse_cum(:,:,:)  
       enddo  
   
 c=====================================================================  
 c   Transport méridien  
 c=====================================================================  
   
 c   cumul zonal des masses des mailles  
 c   ----------------------------------  
       zv=0.  
       zmasse=0.  
       call massbar(masse_cum,massebx,masseby)  
       do l=1,llm  
          do j=1,jjm  
             do i=1,iim  
                zmasse(j,l)=zmasse(j,l)+masseby(i,j,l)  
                zv(j,l)=zv(j,l)+flux_v_cum(i,j,l)  
             enddo  
             zfactv(j,l)=cv_2d(1,j)/zmasse(j,l)  
          enddo  
       enddo  
   
 c     print*,'3OK'  
 c   --------------------------------------------------------------  
 c   calcul de la moyenne zonale du transport :  
 c   ------------------------------------------  
 c  
 c                                     --  
 c TOT : la circulation totale       [ vq ]  
 c  
 c                                      -     -  
 c MMC : mean meridional circulation [ v ] [ q ]  
 c  
 c                                     ----      --       - -  
 c TRS : transitoires                [ v'q'] = [ vq ] - [ v q ]  
 c  
 c                                     - * - *       - -       -     -  
 c STT : stationaires                [ v   q   ] = [ v q ] - [ v ] [ q ]  
 c  
 c                                              - -  
 c    on utilise aussi l'intermediaire TMP :  [ v q ]  
 c  
 c    la variable zfactv transforme un transport meridien cumule  
 c    en kg/s * unte-du-champ-transporte en m/s * unite-du-champ-transporte  
 c  
 c   --------------------------------------------------------------  
   
   
 c   ----------------------------------------  
 c   Transport dans le plan latitude-altitude  
 c   ----------------------------------------  
   
       zvQ=0.  
       psiQ=0.  
       do iQ=1,nQ  
          zvQtmp=0.  
          do l=1,llm  
             do j=1,jjm  
 c              print*,'j,l,iQ=',j,l,iQ  
 c   Calcul des moyennes zonales du transort total et de zvQtmp  
                do i=1,iim  
                   zvQ(j,l,itot,iQ)=zvQ(j,l,itot,iQ)  
      s                            +flux_vQ_cum(i,j,l,iQ)  
                   zqy=      0.5*(Q_cum(i,j,l,iQ)*masse_cum(i,j,l)+  
      s                           Q_cum(i,j+1,l,iQ)*masse_cum(i,j+1,l))  
                   zvQtmp(j,l)=zvQtmp(j,l)+flux_v_cum(i,j,l)*zqy  
      s             /(0.5*(masse_cum(i,j,l)+masse_cum(i,j+1,l)))  
                   zvQ(j,l,iave,iQ)=zvQ(j,l,iave,iQ)+zqy  
                enddo  
 c              print*,'aOK'  
 c   Decomposition  
                zvQ(j,l,iave,iQ)=zvQ(j,l,iave,iQ)/zmasse(j,l)  
                zvQ(j,l,itot,iQ)=zvQ(j,l,itot,iQ)*zfactv(j,l)  
                zvQtmp(j,l)=zvQtmp(j,l)*zfactv(j,l)  
                zvQ(j,l,immc,iQ)=zv(j,l)*zvQ(j,l,iave,iQ)*zfactv(j,l)  
                zvQ(j,l,itrs,iQ)=zvQ(j,l,itot,iQ)-zvQtmp(j,l)  
                zvQ(j,l,istn,iQ)=zvQtmp(j,l)-zvQ(j,l,immc,iQ)  
             enddo  
          enddo  
 c   fonction de courant meridienne pour la quantite Q  
          do l=llm,1,-1  
             do j=1,jjm  
                psiQ(j,l,iQ)=psiQ(j,l+1,iQ)+zvQ(j,l,itot,iQ)  
             enddo  
          enddo  
       enddo  
   
 c   fonction de courant pour la circulation meridienne moyenne  
       psi=0.  
       do l=llm,1,-1  
          do j=1,jjm  
             psi(j,l)=psi(j,l+1)+zv(j,l)  
             zv(j,l)=zv(j,l)*zfactv(j,l)  
          enddo  
       enddo  
   
 c     print*,'4OK'  
 c   sorties proprement dites  
       if (i_sortie.eq.1) then  
       do iQ=1,nQ  
          do itr=1,ntr  
             call histwrite(fileid,znom(itr,iQ),itau,zvQ(:,:,itr,iQ))  
          enddo  
          call histwrite(fileid,'psi'//nom(iQ),itau,psiQ(:,1:llm,iQ))  
       enddo  
   
       call histwrite(fileid,'masse',itau,zmasse)  
       call histwrite(fileid,'v',itau,zv)  
       psi=psi*1.e-9  
       call histwrite(fileid,'psi',itau,psi(:,1:llm))  
   
       endif  
   
   
 c   -----------------  
 c   Moyenne verticale  
 c   -----------------  
   
       zamasse=0.  
       do l=1,llm  
          zamasse(:)=zamasse(:)+zmasse(:,l)  
       enddo  
       zavQ=0.  
       do iQ=1,nQ  
          do itr=2,ntr  
             do l=1,llm  
                zavQ(:,itr,iQ)=zavQ(:,itr,iQ)+zvQ(:,l,itr,iQ)*zmasse(:,l)  
             enddo  
             zavQ(:,itr,iQ)=zavQ(:,itr,iQ)/zamasse(:)  
             call histwrite(fileid,'a'//znom(itr,iQ),itau,zavQ(:,itr,iQ))  
          enddo  
       enddo  
   
 c     on doit pouvoir tracer systematiquement la fonction de courant.  
   
 c=====================================================================  
 c/////////////////////////////////////////////////////////////////////  
       icum=0                  !///////////////////////////////////////  
       endif ! icum.eq.ncum    !///////////////////////////////////////  
 c/////////////////////////////////////////////////////////////////////  
 c=====================================================================  
2    
3        return    IMPLICIT NONE
4        end  
5    contains
6    
7      SUBROUTINE bilan_dyn(ps, masse, pk, flux_u, flux_v, teta, phi, ucov, vcov, &
8           trac, dt_app, dt_cum)
9    
10        ! From LMDZ4/libf/dyn3d/bilan_dyn.F, version 1.5 2005/03/16
11        ! 10:12:17 fairhead
12    
13        ! Sous-programme consacré à des diagnostics dynamiques de base.
14        ! De façon générale, les moyennes des scalaires Q sont pondérées
15        ! par la masse. Les flux de masse sont, eux, simplement moyennés.
16    
17        USE histcom, ONLY: histbeg_totreg, histdef, histend, histvert
18        USE calendar, ONLY: ymds2ju
19        USE histwrite_m, ONLY: histwrite
20        USE dimens_m, ONLY: iim, jjm, llm
21        USE paramet_m, ONLY: iip1, jjp1
22        USE comconst, ONLY: cpp
23        USE comvert, ONLY: presnivs
24        USE comgeom, ONLY: constang_2d, cu_2d, cv_2d, rlatv
25        USE temps, ONLY: annee_ref, day_ref, itau_dyn
26        USE inigrads_m, ONLY: inigrads
27        USE nr_util, ONLY: pi
28    
29        ! Arguments:
30    
31        real, intent(in):: dt_app, dt_cum
32        real ps(iip1, jjp1)
33        real masse(iip1, jjp1, llm), pk(iip1, jjp1, llm)
34        real flux_u(iip1, jjp1, llm)
35        real flux_v(iip1, jjm, llm)
36        real, intent(in):: teta(iip1, jjp1, llm)
37        real phi(iip1, jjp1, llm)
38        real ucov(iip1, jjp1, llm)
39        real vcov(iip1, jjm, llm)
40        real, intent(in):: trac(:, :, :) ! (iim + 1, jjm + 1, llm)
41    
42        ! Local:
43    
44        integer:: icum  = 0
45        integer, save:: ncum
46        logical:: first = .true.
47        real zz, zqy, zfactv(jjm, llm)
48    
49        integer, parameter:: nQ = 7
50        character(len=4), parameter:: nom(nQ) = (/'T   ', 'gz  ', 'K   ', 'ang ', &
51             'u   ', 'ovap', 'un  '/)
52        character(len=5), parameter:: unites(nQ) = (/'K    ', 'm2/s2', 'm2/s2', &
53             'ang  ', 'm/s  ', 'kg/kg', 'un   '/)
54    
55        real:: time = 0.
56        integer:: itau = 0
57        real ww
58    
59        ! Variables dynamiques intermédiaires
60        REAL vcont(iip1, jjm, llm), ucont(iip1, jjp1, llm)
61        REAL ang(iip1, jjp1, llm), unat(iip1, jjp1, llm)
62        REAL massebx(iip1, jjp1, llm), masseby(iip1, jjm, llm)
63        REAL w(iip1, jjp1, llm), ecin(iip1, jjp1, llm), convm(iip1, jjp1, llm)
64    
65        ! Champ contenant les scalaires advectés
66        real Q(iip1, jjp1, llm, nQ)
67    
68        ! Champs cumulés
69        real, save:: ps_cum(iip1, jjp1)
70        real, save:: masse_cum(iip1, jjp1, llm)
71        real, save:: flux_u_cum(iip1, jjp1, llm)
72        real, save:: flux_v_cum(iip1, jjm, llm)
73        real, save:: Q_cum(iip1, jjp1, llm, nQ)
74        real, save:: flux_uQ_cum(iip1, jjp1, llm, nQ)
75        real, save:: flux_vQ_cum(iip1, jjm, llm, nQ)
76        real dQ(iip1, jjp1, llm, nQ)
77    
78        ! champs de tansport en moyenne zonale
79        integer itr
80        integer, parameter:: ntr = 5
81    
82        character(len=10), save:: znom(ntr, nQ)
83        character(len=26), save:: znoml(ntr, nQ)
84        character(len=12), save:: zunites(ntr, nQ)
85    
86        integer, parameter:: iave = 1, itot = 2, immc = 3, itrs = 4, istn = 5
87        character(len=3), parameter:: ctrs(ntr) = (/'   ', 'TOT', 'MMC', 'TRS', &
88             'STN'/)
89    
90        real zvQ(jjm, llm, ntr, nQ), zvQtmp(jjm, llm)
91        real zavQ(jjm, 2: ntr, nQ), psiQ(jjm, llm + 1, nQ)
92        real zmasse(jjm, llm)
93    
94        real zv(jjm, llm), psi(jjm, llm + 1)
95    
96        integer i, j, l, iQ
97    
98        ! Initialisation du fichier contenant les moyennes zonales.
99    
100        integer, save:: fileid
101        integer thoriid, zvertiid
102    
103        real zjulian
104        integer zan, dayref
105    
106        real rlong(jjm), rlatg(jjm)
107    
108        !-----------------------------------------------------------------
109    
110        !!print *, "Call sequence information: bilan_dyn"
111    
112        ! Initialisation
113    
114        time = time + dt_app
115        itau = itau + 1
116    
117        first_call: if (first) then
118           ! initialisation des fichiers
119           first = .false.
120           ! ncum est la frequence de stokage en pas de temps
121           ncum = dt_cum / dt_app
122           if (abs(ncum * dt_app - dt_cum) > 1e-5 * dt_app) then
123              print *, 'Problème : le pas de cumul doit être multiple du pas'
124              print *, 'dt_app = ', dt_app
125              print *, 'dt_cum = ', dt_cum
126              stop 1
127           endif
128    
129           call inigrads(i_f=4, x=(/0./), fx=180./pi, xmin=0., xmax=0., y=rlatv, &
130                ymin=-90., ymax=90., fy=180./pi, z=presnivs, fz=1., dt=dt_cum, &
131                file='dynzon', titlel='dyn_zon ')
132    
133           ! Initialisation du fichier contenant les moyennes zonales
134    
135           zan = annee_ref
136           dayref = day_ref
137           CALL ymds2ju(zan, 1, dayref, 0.0, zjulian)
138    
139           rlong = 0.
140           rlatg = rlatv*180./pi
141    
142           call histbeg_totreg('dynzon', rlong(:1), rlatg, 1, 1, 1, jjm, itau_dyn, &
143                zjulian, dt_cum, thoriid, fileid)
144    
145           ! Appel à histvert pour la grille verticale
146    
147           call histvert(fileid, 'presnivs', 'Niveaux sigma', 'mb', llm, presnivs, &
148                zvertiid)
149    
150           ! Appels à histdef pour la définition des variables à sauvegarder
151           do iQ = 1, nQ
152              do itr = 1, ntr
153                 if (itr == 1) then
154                    znom(itr, iQ) = nom(iQ)
155                    znoml(itr, iQ) = nom(iQ)
156                    zunites(itr, iQ) = unites(iQ)
157                 else
158                    znom(itr, iQ) = ctrs(itr)//'v'//nom(iQ)
159                    znoml(itr, iQ) = 'transport : v * '//nom(iQ)//' '//ctrs(itr)
160                    zunites(itr, iQ) = 'm/s * '//unites(iQ)
161                 endif
162              enddo
163           enddo
164    
165           ! Déclarations des champs avec dimension verticale
166           do iQ = 1, nQ
167              do itr = 1, ntr
168                 call histdef(fileid, znom(itr, iQ), znoml(itr, iQ), &
169                      zunites(itr, iQ), 1, jjm, thoriid, llm, 1, llm, zvertiid, &
170                      'ave(X)', dt_cum, dt_cum)
171              enddo
172              ! Declarations pour les fonctions de courant
173              call histdef(fileid, 'psi'//nom(iQ), 'stream fn. '//znoml(itot, iQ), &
174                   zunites(itot, iQ), 1, jjm, thoriid, llm, 1, llm, zvertiid, &
175                   'ave(X)', dt_cum, dt_cum)
176           enddo
177    
178           ! Declarations pour les champs de transport d'air
179           call histdef(fileid, 'masse', 'masse', &
180                'kg', 1, jjm, thoriid, llm, 1, llm, zvertiid, &
181                'ave(X)', dt_cum, dt_cum)
182           call histdef(fileid, 'v', 'v', &
183                'm/s', 1, jjm, thoriid, llm, 1, llm, zvertiid, &
184                'ave(X)', dt_cum, dt_cum)
185           ! Declarations pour les fonctions de courant
186           call histdef(fileid, 'psi', 'stream fn. MMC ', 'mega t/s', &
187                1, jjm, thoriid, llm, 1, llm, zvertiid, &
188                'ave(X)', dt_cum, dt_cum)
189    
190           ! Declaration des champs 1D de transport en latitude
191           do iQ = 1, nQ
192              do itr = 2, ntr
193                 call histdef(fileid, 'a'//znom(itr, iQ), znoml(itr, iQ), &
194                      zunites(itr, iQ), 1, jjm, thoriid, 1, 1, 1, -99, &
195                      'ave(X)', dt_cum, dt_cum)
196              enddo
197           enddo
198    
199           CALL histend(fileid)
200        endif first_call
201    
202        ! Calcul des champs dynamiques
203    
204        ! Énergie cinétique
205        ucont = 0
206        CALL covcont(llm, ucov, vcov, ucont, vcont)
207        CALL enercin(vcov, ucov, vcont, ucont, ecin)
208    
209        ! moment cinétique
210        do l = 1, llm
211           ang(:, :, l) = ucov(:, :, l) + constang_2d
212           unat(:, :, l) = ucont(:, :, l)*cu_2d
213        enddo
214    
215        Q(:, :, :, 1) = teta * pk / cpp
216        Q(:, :, :, 2) = phi
217        Q(:, :, :, 3) = ecin
218        Q(:, :, :, 4) = ang
219        Q(:, :, :, 5) = unat
220        Q(:, :, :, 6) = trac
221        Q(:, :, :, 7) = 1.
222    
223        ! Cumul
224    
225        if (icum == 0) then
226           ps_cum = 0.
227           masse_cum = 0.
228           flux_u_cum = 0.
229           flux_v_cum = 0.
230           Q_cum = 0.
231           flux_vQ_cum = 0.
232           flux_uQ_cum = 0.
233        endif
234    
235        icum = icum + 1
236    
237        ! Accumulation des flux de masse horizontaux
238        ps_cum = ps_cum + ps
239        masse_cum = masse_cum + masse
240        flux_u_cum = flux_u_cum + flux_u
241        flux_v_cum = flux_v_cum + flux_v
242        do iQ = 1, nQ
243           Q_cum(:, :, :, iQ) = Q_cum(:, :, :, iQ) + Q(:, :, :, iQ)*masse
244        enddo
245    
246        ! FLUX ET TENDANCES
247    
248        ! Flux longitudinal
249        forall (iQ = 1: nQ, i = 1: iim) flux_uQ_cum(i, :, :, iQ) &
250             = flux_uQ_cum(i, :, :, iQ) &
251             + flux_u(i, :, :) * 0.5 * (Q(i, :, :, iQ) + Q(i + 1, :, :, iQ))
252        flux_uQ_cum(iip1, :, :, :) = flux_uQ_cum(1, :, :, :)
253    
254        ! Flux méridien
255        forall (iQ = 1: nQ, j = 1: jjm) flux_vQ_cum(:, j, :, iQ) &
256             = flux_vQ_cum(:, j, :, iQ) &
257             + flux_v(:, j, :) * 0.5 * (Q(:, j, :, iQ) + Q(:, j + 1, :, iQ))
258    
259        ! tendances
260    
261        ! convergence horizontale
262        call convflu(flux_uQ_cum, flux_vQ_cum, llm*nQ, dQ)
263    
264        ! calcul de la vitesse verticale
265        call convmas(flux_u_cum, flux_v_cum, convm)
266        CALL vitvert(convm, w)
267    
268        do iQ = 1, nQ
269           do l = 1, llm-1
270              do j = 1, jjp1
271                 do i = 1, iip1
272                    ww = -0.5*w(i, j, l + 1)*(Q(i, j, l, iQ) + Q(i, j, l + 1, iQ))
273                    dQ(i, j, l, iQ) = dQ(i, j, l, iQ)-ww
274                    dQ(i, j, l + 1, iQ) = dQ(i, j, l + 1, iQ) + ww
275                 enddo
276              enddo
277           enddo
278        enddo
279    
280        ! PAS DE TEMPS D'ECRITURE
281    
282        writing_step: if (icum == ncum) then
283           ! Normalisation
284           do iQ = 1, nQ
285              Q_cum(:, :, :, iQ) = Q_cum(:, :, :, iQ)/masse_cum
286           enddo
287           zz = 1. / real(ncum)
288           ps_cum = ps_cum*zz
289           masse_cum = masse_cum*zz
290           flux_u_cum = flux_u_cum*zz
291           flux_v_cum = flux_v_cum*zz
292           flux_uQ_cum = flux_uQ_cum*zz
293           flux_vQ_cum = flux_vQ_cum*zz
294           dQ = dQ*zz
295    
296           ! A retravailler eventuellement
297           ! division de dQ par la masse pour revenir aux bonnes grandeurs
298           do iQ = 1, nQ
299              dQ(:, :, :, iQ) = dQ(:, :, :, iQ)/masse_cum
300           enddo
301    
302           ! Transport méridien
303    
304           ! cumul zonal des masses des mailles
305    
306           zv = 0.
307           zmasse = 0.
308           call massbar(masse_cum, massebx, masseby)
309           do l = 1, llm
310              do j = 1, jjm
311                 do i = 1, iim
312                    zmasse(j, l) = zmasse(j, l) + masseby(i, j, l)
313                    zv(j, l) = zv(j, l) + flux_v_cum(i, j, l)
314                 enddo
315                 zfactv(j, l) = cv_2d(1, j)/zmasse(j, l)
316              enddo
317           enddo
318    
319           ! Transport dans le plan latitude-altitude
320    
321           zvQ = 0.
322           psiQ = 0.
323           do iQ = 1, nQ
324              zvQtmp = 0.
325              do l = 1, llm
326                 do j = 1, jjm
327                    ! Calcul des moyennes zonales du transort total et de zvQtmp
328                    do i = 1, iim
329                       zvQ(j, l, itot, iQ) = zvQ(j, l, itot, iQ) &
330                            + flux_vQ_cum(i, j, l, iQ)
331                       zqy =  0.5 * (Q_cum(i, j, l, iQ) * masse_cum(i, j, l) &
332                            + Q_cum(i, j + 1, l, iQ) * masse_cum(i, j + 1, l))
333                       zvQtmp(j, l) = zvQtmp(j, l) + flux_v_cum(i, j, l) * zqy &
334                            / (0.5 * (masse_cum(i, j, l) + masse_cum(i, j + 1, l)))
335                       zvQ(j, l, iave, iQ) = zvQ(j, l, iave, iQ) + zqy
336                    enddo
337                    ! Decomposition
338                    zvQ(j, l, iave, iQ) = zvQ(j, l, iave, iQ)/zmasse(j, l)
339                    zvQ(j, l, itot, iQ) = zvQ(j, l, itot, iQ)*zfactv(j, l)
340                    zvQtmp(j, l) = zvQtmp(j, l)*zfactv(j, l)
341                    zvQ(j, l, immc, iQ) = zv(j, l)*zvQ(j, l, iave, iQ)*zfactv(j, l)
342                    zvQ(j, l, itrs, iQ) = zvQ(j, l, itot, iQ)-zvQtmp(j, l)
343                    zvQ(j, l, istn, iQ) = zvQtmp(j, l)-zvQ(j, l, immc, iQ)
344                 enddo
345              enddo
346              ! fonction de courant meridienne pour la quantite Q
347              do l = llm, 1, -1
348                 do j = 1, jjm
349                    psiQ(j, l, iQ) = psiQ(j, l + 1, iQ) + zvQ(j, l, itot, iQ)
350                 enddo
351              enddo
352           enddo
353    
354           ! fonction de courant pour la circulation meridienne moyenne
355           psi = 0.
356           do l = llm, 1, -1
357              do j = 1, jjm
358                 psi(j, l) = psi(j, l + 1) + zv(j, l)
359                 zv(j, l) = zv(j, l)*zfactv(j, l)
360              enddo
361           enddo
362    
363           ! sorties proprement dites
364           do iQ = 1, nQ
365              do itr = 1, ntr
366                 call histwrite(fileid, znom(itr, iQ), itau, zvQ(:, :, itr, iQ))
367              enddo
368              call histwrite(fileid, 'psi'//nom(iQ), itau, psiQ(:, :llm, iQ))
369           enddo
370    
371           call histwrite(fileid, 'masse', itau, zmasse)
372           call histwrite(fileid, 'v', itau, zv)
373           psi = psi*1.e-9
374           call histwrite(fileid, 'psi', itau, psi(:, :llm))
375    
376           ! Intégrale verticale
377    
378           forall (iQ = 1: nQ, itr = 2: ntr) zavQ(:, itr, iQ) &
379                = sum(zvQ(:, :, itr, iQ) * zmasse, dim=2) / cv_2d(1, :)
380    
381           do iQ = 1, nQ
382              do itr = 2, ntr
383                 call histwrite(fileid, 'a'//znom(itr, iQ), itau, zavQ(:, itr, iQ))
384              enddo
385           enddo
386    
387           ! On doit pouvoir tracer systematiquement la fonction de courant.
388           icum = 0
389        endif writing_step
390    
391      end SUBROUTINE bilan_dyn
392    
393    end module bilan_dyn_m

Legend:
Removed from v.30  
changed lines
  Added in v.55

  ViewVC Help
Powered by ViewVC 1.1.21