source: LMDZ6/branches/LMDZ-tracers/libf/dyn3d/advtrac.F90 @ 3999

Last change on this file since 3999 was 3852, checked in by dcugnet, 4 years ago

Extension of the tracers management.

The tracers files can be:

1) "traceur.def": old format, with:

  • the number of tracers on the first line
  • one line for each tracer: <tracer name> <hadv> <vadv> [<parent name>]

2) "tracer.def": new format with one section each model component.
3) "tracer_<name>.def": new format with a single section.

The formats 2 and 3 reading is driven by the "type_trac" key, which can be a

coma-separated list of components.

  • Format 2: read the sections from the "tracer.def" file.
  • format 3: read one section each "tracer_<section name>.def" file.
  • the first line of a section is "&<section name>
  • the other lines start with a tracer name followed by <key>=<val> pairs.
  • the "default" tracer name is reserved ; the other tracers of the section inherit its <key>=<val>, except for the keys that are redefined locally.

This format helps keeping the tracers files compact, thanks to the "default"
special tracer and the three levels of factorization:

  • on the tracers names: a tracer name can be a coma-separated list of tracers => all the tracers of the list have the same <key>=<val> properties
  • on the parents names: the value of the "parent" property can be a coma-separated list of tracers => only possible for geographic tagging tracers
  • on the phases: the property "phases" is [g](l][s] (gas/liquid/solid)

Read information is stored in the vector "tracers(:)", of derived type "tra".

"isotopes_params.def" is a similar file, with one section each isotopes family.
It contains a database of isotopes properties ; if there are second generation
tracers (isotopes), the corresponding sections are read.

Read information is stored in the vector "isotopes(:)", of derived type "iso".

The "getKey" function helps to get the values of the parameters stored in
"tracers" or "isotopes".

  • Property copyright set to
    Name of program: LMDZ
    Creation date: 1984
    Version: LMDZ5
    License: CeCILL version 2
    Holder: Laboratoire de m\'et\'eorologie dynamique, CNRS, UMR 8539
    See the license file in the root directory
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 14.6 KB
RevLine 
[1279]1! $Id: advtrac.F90 3852 2021-02-22 16:28:31Z evignon $
[1146]2
[1549]3SUBROUTINE advtrac(pbaru,pbarv , p,  masse,q,iapptrac,teta, flxw, pk)
4  !     Auteur :  F. Hourdin
5  !
6  !     Modif. P. Le Van     (20/12/97)
7  !            F. Codron     (10/99)
8  !            D. Le Croller (07/2001)
9  !            M.A Filiberti (04/2002)
10  !
[3852]11  USE infotrac, ONLY: nqtot, tracers
[1987]12  USE control_mod, ONLY: iapp_tracvl, day_step
[2597]13  USE comconst_mod, ONLY: dtvr
[524]14
[1549]15  IMPLICIT NONE
16  !
17  include "dimensions.h"
18  include "paramet.h"
19  include "comdissip.h"
20  include "comgeom2.h"
21  include "description.h"
22  include "iniprint.h"
[524]23
[1549]24  !-------------------------------------------------------------------
25  !     Arguments
26  !-------------------------------------------------------------------
[1987]27  INTEGER,INTENT(OUT) :: iapptrac
28  REAL,INTENT(IN) :: pbaru(ip1jmp1,llm)
29  REAL,INTENT(IN) :: pbarv(ip1jm,llm)
30  REAL,INTENT(INOUT) :: q(ip1jmp1,llm,nqtot)
31  REAL,INTENT(IN) :: masse(ip1jmp1,llm)
32  REAL,INTENT(IN) :: p( ip1jmp1,llmp1 )
33  REAL,INTENT(IN) :: teta(ip1jmp1,llm)
34  REAL,INTENT(IN) :: pk(ip1jmp1,llm)
35  REAL,INTENT(OUT) :: flxw(ip1jmp1,llm)
36  !-------------------------------------------------------------------
[1549]37  !     Ajout PPM
38  !--------------------------------------------------------
39  REAL massebx(ip1jmp1,llm),masseby(ip1jm,llm)
40  !-------------------------------------------------------------
41  !     Variables locales
42  !-------------------------------------------------------------
[524]43
[1549]44  REAL pbaruc(ip1jmp1,llm),pbarvc(ip1jm,llm)
45  REAL massem(ip1jmp1,llm),zdp(ip1jmp1)
46  REAL pbarug(ip1jmp1,llm),pbarvg(ip1jm,llm),wg(ip1jmp1,llm)
47  REAL (kind=kind(1.d0)) :: t_initial, t_final, tps_cpu
48  INTEGER iadvtr
49  INTEGER ij,l,iq,iiq
[3852]50  INTEGER, POINTER :: iadv(:)
[1549]51  REAL zdpmin, zdpmax
52  EXTERNAL  minmax
53  SAVE iadvtr, massem, pbaruc, pbarvc
54  DATA iadvtr/0/
55  !----------------------------------------------------------
56  !     Rajouts pour PPM
57  !----------------------------------------------------------
58  INTEGER indice,n
59  REAL dtbon ! Pas de temps adaptatif pour que CFL<1
60  REAL CFLmaxz,aaa,bbb ! CFL maximum
61  REAL psppm(iim,jjp1) ! pression  au sol
62  REAL unatppm(iim,jjp1,llm),vnatppm(iim,jjp1,llm)
63  REAL qppm(iim*jjp1,llm,nqtot)
64  REAL fluxwppm(iim,jjp1,llm)
65  REAL apppm(llmp1), bpppm(llmp1)
66  LOGICAL dum,fill
67  DATA fill/.true./
68  DATA dum/.true./
[524]69
[1549]70  integer,save :: countcfl=0
71  real cflx(ip1jmp1,llm)
72  real cfly(ip1jm,llm)
73  real cflz(ip1jmp1,llm)
74  real, save :: cflxmax(llm),cflymax(llm),cflzmax(llm)
[524]75
[3852]76  iadv => tracers(:)%iadv
77
[1549]78  IF(iadvtr.EQ.0) THEN
[2239]79     pbaruc(:,:)=0
80     pbarvc(:,:)=0
[1549]81  ENDIF
[524]82
[1549]83  !   accumulation des flux de masse horizontaux
84  DO l=1,llm
85     DO ij = 1,ip1jmp1
86        pbaruc(ij,l) = pbaruc(ij,l) + pbaru(ij,l)
87     ENDDO
88     DO ij = 1,ip1jm
89        pbarvc(ij,l) = pbarvc(ij,l) + pbarv(ij,l)
90     ENDDO
91  ENDDO
[524]92
[1549]93  !   selection de la masse instantannee des mailles avant le transport.
94  IF(iadvtr.EQ.0) THEN
[524]95
[1549]96     CALL SCOPY(ip1jmp1*llm,masse,1,massem,1)
97     !cc         CALL filtreg ( massem ,jjp1, llm,-2, 2, .TRUE., 1 )
98     !
99  ENDIF
[524]100
[1549]101  iadvtr   = iadvtr+1
102  iapptrac = iadvtr
[524]103
104
[1549]105  !   Test pour savoir si on advecte a ce pas de temps
106  IF ( iadvtr.EQ.iapp_tracvl ) THEN
[524]107
[1549]108     !c   ..  Modif P.Le Van  ( 20/12/97 )  ....
109     !c
[524]110
[1549]111     !   traitement des flux de masse avant advection.
112     !     1. calcul de w
113     !     2. groupement des mailles pres du pole.
[524]114
[1549]115     CALL groupe( massem, pbaruc,pbarvc, pbarug,pbarvg,wg )
[524]116
[1549]117     ! ... Flux de masse diaganostiques traceurs
118     flxw = wg / REAL(iapp_tracvl)
[524]119
[1549]120     !  test sur l'eventuelle creation de valeurs negatives de la masse
121     DO l=1,llm-1
122        DO ij = iip2+1,ip1jm
123           zdp(ij) =    pbarug(ij-1,l)   - pbarug(ij,l) &
124                - pbarvg(ij-iip1,l) + pbarvg(ij,l) &
125                +       wg(ij,l+1)  - wg(ij,l)
126        ENDDO
127        CALL SCOPY( jjm -1 ,zdp(iip1+iip1),iip1,zdp(iip2),iip1 )
128        DO ij = iip2,ip1jm
129           zdp(ij)= zdp(ij)*dtvr/ massem(ij,l)
130        ENDDO
[524]131
132
[1549]133        CALL minmax ( ip1jm-iip1, zdp(iip2), zdpmin,zdpmax )
[524]134
[1549]135        IF(MAX(ABS(zdpmin),ABS(zdpmax)).GT.0.5) THEN
136           PRINT*,'WARNING DP/P l=',l,'  MIN:',zdpmin, &
137                '   MAX:', zdpmax
138        ENDIF
[1279]139
[1549]140     ENDDO
[1279]141
142
[1549]143     !-------------------------------------------------------------------
144     ! Calcul des criteres CFL en X, Y et Z
145     !-------------------------------------------------------------------
[1279]146
[1549]147     if (countcfl == 0. ) then
148        cflxmax(:)=0.
149        cflymax(:)=0.
150        cflzmax(:)=0.
151     endif
[1279]152
[1549]153     countcfl=countcfl+iapp_tracvl
154     cflx(:,:)=0.
155     cfly(:,:)=0.
156     cflz(:,:)=0.
157     do l=1,llm
158        do ij=iip2,ip1jm-1
159           if (pbarug(ij,l)>=0.) then
160              cflx(ij,l)=pbarug(ij,l)*dtvr/masse(ij,l)
161           else
162              cflx(ij,l)=-pbarug(ij,l)*dtvr/masse(ij+1,l)
163           endif
164        enddo
165     enddo
166     do l=1,llm
167        do ij=iip2,ip1jm-1,iip1
168           cflx(ij+iip1,l)=cflx(ij,l)
169        enddo
170     enddo
[1279]171
[1549]172     do l=1,llm
173        do ij=1,ip1jm
174           if (pbarvg(ij,l)>=0.) then
175              cfly(ij,l)=pbarvg(ij,l)*dtvr/masse(ij,l)
176           else
177              cfly(ij,l)=-pbarvg(ij,l)*dtvr/masse(ij+iip1,l)
178           endif
179        enddo
180     enddo
[1279]181
[1549]182     do l=2,llm
183        do ij=1,ip1jm
184           if (wg(ij,l)>=0.) then
185              cflz(ij,l)=wg(ij,l)*dtvr/masse(ij,l)
186           else
187              cflz(ij,l)=-wg(ij,l)*dtvr/masse(ij,l-1)
188           endif
189        enddo
190     enddo
191
192     do l=1,llm
193        cflxmax(l)=max(cflxmax(l),maxval(cflx(:,l)))
194        cflymax(l)=max(cflymax(l),maxval(cfly(:,l)))
195        cflzmax(l)=max(cflzmax(l),maxval(cflz(:,l)))
196     enddo
197
[1279]198!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
[1549]199     ! Par defaut, on sort le diagnostic des CFL tous les jours.
200     ! Si on veut le sortir a chaque pas d'advection en cas de plantage
201     !     if (countcfl==iapp_tracvl) then
[1279]202!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
[1549]203     if (countcfl==day_step) then
204        do l=1,llm
[1817]205           write(lunout,*) 'L, CFL[xyz]max:', l, cflxmax(l), cflymax(l), &
206                cflzmax(l)
[1549]207        enddo
208        countcfl=0
209     endif
[524]210
[1549]211     !-------------------------------------------------------------------
212     !   Advection proprement dite (Modification Le Croller (07/2001)
213     !-------------------------------------------------------------------
[524]214
[1549]215     !----------------------------------------------------
216     !        Calcul des moyennes basées sur la masse
217     !----------------------------------------------------
218     call massbar(massem,massebx,masseby)         
219
220     !-----------------------------------------------------------
221     !     Appel des sous programmes d'advection
222     !-----------------------------------------------------------
[2270]223
[3852]224     call check_isotopes_seq(q,ip1jmp1,'advtrac 162')
[2270]225
[3852]226     do iq=1,nqtot
[1549]227        !        call clock(t_initial)
[3852]228        if(iadv(iq) == 0 .OR. tracers(iq)%igen /= 1) cycle
[1549]229        !   ----------------------------------------------------------------
230        !   Schema de Van Leer I MUSCL
231        !   ----------------------------------------------------------------
[524]232        if(iadv(iq).eq.10) THEN
[2270]233           ! CRisi: on fait passer tout q pour avoir acces aux fils
234           
[2286]235           !write(*,*) 'advtrac 239: iq,q(1721,19,:)=',iq,q(1721,19,:)     
[2270]236           call vlsplt(q,2.,massem,wg,pbarug,pbarvg,dtvr,iq)
237           
[1549]238           !   ----------------------------------------------------------------
239           !   Schema "pseudo amont" + test sur humidite specifique
240           !    pour la vapeur d'eau. F. Codron
241           !   ----------------------------------------------------------------
[524]242        else if(iadv(iq).eq.14) then
[1549]243           !
[2286]244           !write(*,*) 'advtrac 248: iq,q(1721,19,:)=',iq,q(1721,19,:)
[2270]245           CALL vlspltqs( q, 2., massem, wg , &
246                pbarug,pbarvg,dtvr,p,pk,teta,iq)
247           
[1549]248           !   ----------------------------------------------------------------
249           !   Schema de Frederic Hourdin
250           !   ----------------------------------------------------------------
[524]251        else if(iadv(iq).eq.12) then
[1549]252           !            Pas de temps adaptatif
[524]253           call adaptdt(iadv(iq),dtbon,n,pbarug,massem)
254           if (n.GT.1) then
[1549]255              write(*,*) 'WARNING horizontal dt=',dtbon,'dtvr=', &
256                   dtvr,'n=',n
[524]257           endif
258           do indice=1,n
[1549]259              call advn(q(1,1,iq),massem,wg,pbarug,pbarvg,dtbon,1)
[524]260           end do
261        else if(iadv(iq).eq.13) then
[1549]262           !            Pas de temps adaptatif
[524]263           call adaptdt(iadv(iq),dtbon,n,pbarug,massem)
264           if (n.GT.1) then
[1549]265              write(*,*) 'WARNING horizontal dt=',dtbon,'dtvr=', &
266                   dtvr,'n=',n
[524]267           endif
[1549]268           do indice=1,n
269              call advn(q(1,1,iq),massem,wg,pbarug,pbarvg,dtbon,2)
270           end do
271           !   ----------------------------------------------------------------
272           !   Schema de pente SLOPES
273           !   ----------------------------------------------------------------
[524]274        else if (iadv(iq).eq.20) then
[1549]275           call pentes_ini (q(1,1,iq),wg,massem,pbarug,pbarvg,0)
[524]276
[1549]277           !   ----------------------------------------------------------------
278           !   Schema de Prather
279           !   ----------------------------------------------------------------
[524]280        else if (iadv(iq).eq.30) then
[1549]281           !            Pas de temps adaptatif
[524]282           call adaptdt(iadv(iq),dtbon,n,pbarug,massem)
283           if (n.GT.1) then
[1549]284              write(*,*) 'WARNING horizontal dt=',dtbon,'dtvr=', &
285                   dtvr,'n=',n
[524]286           endif
[1549]287           call  prather(q(1,1,iq),wg,massem,pbarug,pbarvg, &
288                n,dtbon)
[960]289
[1549]290           !   ----------------------------------------------------------------
291           !   Schemas PPM Lin et Rood
292           !   ----------------------------------------------------------------
293        else if (iadv(iq).eq.11.OR.(iadv(iq).GE.16.AND. &
294             iadv(iq).LE.18)) then
[524]295
[1549]296           !        Test sur le flux horizontal
297           !        Pas de temps adaptatif
298           call adaptdt(iadv(iq),dtbon,n,pbarug,massem)
299           if (n.GT.1) then
300              write(*,*) 'WARNING horizontal dt=',dtbon,'dtvr=', &
301                   dtvr,'n=',n
302           endif
303           !        Test sur le flux vertical
304           CFLmaxz=0.
305           do l=2,llm
306              do ij=iip2,ip1jm
307                 aaa=wg(ij,l)*dtvr/massem(ij,l)
308                 CFLmaxz=max(CFLmaxz,aaa)
309                 bbb=-wg(ij,l)*dtvr/massem(ij,l-1)
310                 CFLmaxz=max(CFLmaxz,bbb)
311              enddo
[524]312           enddo
[1549]313           if (CFLmaxz.GE.1) then
314              write(*,*) 'WARNING vertical','CFLmaxz=', CFLmaxz
315           endif
[524]316
[1549]317           !-----------------------------------------------------------
318           !        Ss-prg interface LMDZ.4->PPM3d
319           !-----------------------------------------------------------
[524]320
[1549]321           call interpre(q(1,1,iq),qppm(1,1,iq),wg,fluxwppm,massem, &
322                apppm,bpppm,massebx,masseby,pbarug,pbarvg, &
323                unatppm,vnatppm,psppm)
[524]324
[1549]325           do indice=1,n
326              !----------------------------------------------------------------
327              !                         VL (version PPM) horiz. et PPM vert.
328              !----------------------------------------------------------------
329              if (iadv(iq).eq.11) then
330                 !                  Ss-prg PPM3d de Lin
331                 call ppm3d(1,qppm(1,1,iq), &
332                      psppm,psppm, &
333                      unatppm,vnatppm,fluxwppm,dtbon,2,2,2,1, &
334                      iim,jjp1,2,llm,apppm,bpppm,0.01,6400000, &
335                      fill,dum,220.)
[524]336
[1549]337                 !-------------------------------------------------------------
338                 !                           Monotonic PPM
339                 !-------------------------------------------------------------
340              else if (iadv(iq).eq.16) then
341                 !                  Ss-prg PPM3d de Lin
342                 call ppm3d(1,qppm(1,1,iq), &
343                      psppm,psppm, &
344                      unatppm,vnatppm,fluxwppm,dtbon,3,3,3,1, &
345                      iim,jjp1,2,llm,apppm,bpppm,0.01,6400000, &
346                      fill,dum,220.)
347                 !-------------------------------------------------------------
[524]348
[1549]349                 !-------------------------------------------------------------
350                 !                           Semi Monotonic PPM
351                 !-------------------------------------------------------------
352              else if (iadv(iq).eq.17) then
353                 !                  Ss-prg PPM3d de Lin
354                 call ppm3d(1,qppm(1,1,iq), &
355                      psppm,psppm, &
356                      unatppm,vnatppm,fluxwppm,dtbon,4,4,4,1, &
357                      iim,jjp1,2,llm,apppm,bpppm,0.01,6400000, &
358                      fill,dum,220.)
359                 !-------------------------------------------------------------
[524]360
[1549]361                 !-------------------------------------------------------------
362                 !                         Positive Definite PPM
363                 !-------------------------------------------------------------
364              else if (iadv(iq).eq.18) then
365                 !                  Ss-prg PPM3d de Lin
366                 call ppm3d(1,qppm(1,1,iq), &
367                      psppm,psppm, &
368                      unatppm,vnatppm,fluxwppm,dtbon,5,5,5,1, &
369                      iim,jjp1,2,llm,apppm,bpppm,0.01,6400000, &
370                      fill,dum,220.)
371                 !-------------------------------------------------------------
372              endif
373           enddo
374           !-----------------------------------------------------------------
375           !               Ss-prg interface PPM3d-LMDZ.4
376           !-----------------------------------------------------------------
377           call interpost(q(1,1,iq),qppm(1,1,iq))
378        endif
379        !----------------------------------------------------------------------
[524]380
[1549]381        !-----------------------------------------------------------------
382        ! On impose une seule valeur du traceur au pôle Sud j=jjm+1=jjp1
383        ! et Nord j=1
384        !-----------------------------------------------------------------
[524]385
[1549]386        !                  call traceurpole(q(1,1,iq),massem)
[524]387
[1549]388        ! calcul du temps cpu pour un schema donne
[524]389
[1549]390        !                  call clock(t_final)
391        !ym                  tps_cpu=t_final-t_initial
392        !ym                  cpuadv(iq)=cpuadv(iq)+tps_cpu
[524]393
[1549]394     end DO
[524]395
[3852]396     call check_isotopes_seq(q,ip1jmp1,'advtrac 397')
[524]397
[1549]398     !------------------------------------------------------------------
399     !   on reinitialise a zero les flux de masse cumules
400     !---------------------------------------------------
401     iadvtr=0
[524]402
[1549]403  ENDIF ! if iadvtr.EQ.iapp_tracvl
[524]404
[1549]405END SUBROUTINE advtrac
Note: See TracBrowser for help on using the repository browser.