source: LMDZ6/trunk/libf/dyn3d/advtrac.f90 @ 5748

Last change on this file since 5748 was 5748, checked in by dcugnet, 2 days ago
  • Use REAL(KIND=REAL32) and REAL(KIND=REAL64) Iinstead of REAL and DOUBLE PRECISION

to avoid ambiguity problems in generic procedure when reals are promoted to doubles.

  • generic "num2str" replaces "str2int", "str2real", "str2dble" and "str2bool" functions.
  • 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: 13.8 KB
Line 
1! $Id: advtrac.f90 5748 2025-07-02 10:00:08Z dcugnet $
2
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   !
11   USE iniprint_mod_h
12   USE comgeom2_mod_h
13   USE comdissip_mod_h
14   USE infotrac,     ONLY: nqtot, tracers, isoCheck
15   USE control_mod,  ONLY: iapp_tracvl, day_step
16   USE comconst_mod, ONLY: dtvr
17   USE dimensions_mod, ONLY: iim, jjm, llm, ndm
18   USE paramet_mod_h
19IMPLICIT NONE
20   !
21
22
23   !---------------------------------------------------------------------------
24   !     Arguments
25   !---------------------------------------------------------------------------
26   INTEGER, INTENT(OUT) :: iapptrac
27   REAL, INTENT(IN) :: pbaru(ip1jmp1,llm)
28   REAL, INTENT(IN) :: pbarv(ip1jm,  llm)
29   REAL, INTENT(INOUT) ::  q(ip1jmp1,llm,nqtot)
30   REAL, INTENT(IN) :: masse(ip1jmp1,llm)
31   REAL, INTENT(IN) ::     p(ip1jmp1,llmp1 )
32   REAL, INTENT(IN) ::  teta(ip1jmp1,llm)
33   REAL, INTENT(IN) ::    pk(ip1jmp1,llm)
34   REAL, INTENT(OUT) :: flxw(ip1jmp1,llm)
35   !---------------------------------------------------------------------------
36   !     Ajout PPM
37   !---------------------------------------------------------------------------
38   REAL :: massebx(ip1jmp1,llm), masseby(ip1jm,llm)
39   !---------------------------------------------------------------------------
40   !     Variables locales
41   !---------------------------------------------------------------------------
42   INTEGER :: ij, l, iq, iadv
43!   REAL(KIND=KIND(1.d0)) :: t_initial, t_final, tps_cpu
44   REAL :: zdp(ip1jmp1), zdpmin, zdpmax
45   INTEGER, SAVE :: iadvtr=0
46   REAL, DIMENSION(ip1jmp1,llm) :: pbaruc, pbarug, massem, wg
47   REAL, DIMENSION(ip1jm,  llm) :: pbarvc, pbarvg
48   EXTERNAL  minmax
49   SAVE massem, pbaruc, pbarvc
50   !---------------------------------------------------------------------------
51   !     Rajouts pour PPM
52   !---------------------------------------------------------------------------
53   INTEGER indice, n
54   REAL :: dtbon                       ! Pas de temps adaptatif pour que CFL<1
55   REAL :: CFLmaxz, aaa, bbb           ! CFL maximum
56   REAL, DIMENSION(iim,jjp1,llm) :: unatppm, vnatppm, fluxwppm
57   REAL ::    qppm(iim*jjp1,llm,nqtot)
58   REAL ::   psppm(iim,jjp1)           ! pression  au sol
59   REAL, DIMENSION(llmp1) :: apppm, bpppm
60   LOGICAL, SAVE :: dum=.TRUE., fill=.TRUE.
61
62   INTEGER, SAVE :: countcfl=0
63   REAL, DIMENSION(ip1jmp1,llm) :: cflx, cflz
64   REAL, DIMENSION(ip1jm  ,llm) :: cfly
65   REAL, DIMENSION(llm), SAVE :: cflxmax, cflymax, cflzmax
66
67   IF(iadvtr == 0) THEN
68      pbaruc(:,:)=0
69      pbarvc(:,:)=0
70   END IF
71
72   !--- Accumulation des flux de masse horizontaux
73   DO l=1,llm
74      DO ij = 1,ip1jmp1
75         pbaruc(ij,l) = pbaruc(ij,l) + pbaru(ij,l)
76      END DO
77      DO ij = 1,ip1jm
78         pbarvc(ij,l) = pbarvc(ij,l) + pbarv(ij,l)
79      END DO
80   END DO
81
82   !--- Selection de la masse instantannee des mailles avant le transport.
83   IF(iadvtr == 0) THEN
84     CALL SCOPY(ip1jmp1*llm,masse,1,massem,1)
85   ! CALL filtreg ( massem ,jjp1, llm,-2, 2, .TRUE., 1 )
86   END IF
87
88   iadvtr   = iadvtr+1
89   iapptrac = iadvtr
90
91   !--- Test pour savoir si on advecte a ce pas de temps
92   IF(iadvtr /= iapp_tracvl) RETURN
93
94   !   ..  Modif P.Le Van  ( 20/12/97 )  ....
95   !
96   !   traitement des flux de masse avant advection.
97   !       1. calcul de w
98   !       2. groupement des mailles pres du pole.
99
100   CALL groupe(massem, pbaruc, pbarvc, pbarug, pbarvg, wg)
101
102   !--- Flux de masse diaganostiques traceurs
103   flxw = wg / REAL(iapp_tracvl)
104
105   !--- Test sur l'eventuelle creation de valeurs negatives de la masse
106   DO l=1,llm-1
107      DO ij = iip2+1,ip1jm
108         zdp(ij) = pbarug(ij-1,l)    - pbarug(ij,l) &
109                 - pbarvg(ij-iip1,l) + pbarvg(ij,l) &
110                 +     wg(ij,l+1)    -     wg(ij,l)
111      END DO
112! ym  ---> pourquoi jjm-1 et non jjm ? a cause du pole ?
113      CALL SCOPY( jjm -1 ,zdp(iip1+iip1),iip1,zdp(iip2),iip1 )
114      DO ij = iip2,ip1jm
115         zdp(ij)= zdp(ij)*dtvr/ massem(ij,l)
116      END DO
117
118      CALL minmax ( ip1jm-iip1, zdp(iip2), zdpmin,zdpmax )
119
120      IF(MAX(ABS(zdpmin),ABS(zdpmax)) > 0.5) &
121         WRITE(*,*)'WARNING DP/P l=',l,'  MIN:',zdpmin,' MAX:', zdpmax
122
123   END DO
124
125   !-------------------------------------------------------------------------
126   ! Calcul des criteres CFL en X, Y et Z
127   !-------------------------------------------------------------------------
128   IF(countcfl == 0. ) then
129      cflxmax(:)=0.
130      cflymax(:)=0.
131      cflzmax(:)=0.
132   END IF
133
134   countcfl=countcfl+iapp_tracvl
135   cflx(:,:)=0.
136   cfly(:,:)=0.
137   cflz(:,:)=0.
138   DO l=1,llm
139      DO ij=iip2,ip1jm-1
140         IF(pbarug(ij,l)>=0.) then
141            cflx(ij,l)=pbarug(ij,l)*dtvr/masse(ij,l)
142         ELSE
143            cflx(ij,l)=-pbarug(ij,l)*dtvr/masse(ij+1,l)
144         END IF
145      END DO
146   END DO
147
148   DO l=1,llm
149      DO ij=iip2,ip1jm-1,iip1
150         cflx(ij+iip1,l)=cflx(ij,l)
151      END DO
152   END DO
153
154   DO l=1,llm
155      DO ij=1,ip1jm
156         IF(pbarvg(ij,l)>=0.) then
157            cfly(ij,l)=pbarvg(ij,l)*dtvr/masse(ij,l)
158         ELSE
159            cfly(ij,l)=-pbarvg(ij,l)*dtvr/masse(ij+iip1,l)
160         END IF
161      END DO
162   END DO
163
164   DO l=2,llm
165      DO ij=1,ip1jm
166         IF(wg(ij,l) >= 0.) THEN
167            cflz(ij,l)=wg(ij,l)*dtvr/masse(ij,l)
168         ELSE
169            cflz(ij,l)=-wg(ij,l)*dtvr/masse(ij,l-1)
170         END IF
171      END DO
172   END DO
173
174   DO l=1,llm
175      cflxmax(l)=max(cflxmax(l),maxval(cflx(:,l)))
176      cflymax(l)=max(cflymax(l),maxval(cfly(:,l)))
177      cflzmax(l)=max(cflzmax(l),maxval(cflz(:,l)))
178   END DO
179
180   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
181   ! Par defaut, on sort le diagnostic des CFL tous les jours.
182   ! Si on veut le sortir a chaque pas d'advection en cas de plantage
183   !       IF(countcfl==iapp_tracvl) then
184   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
185   IF(countcfl==day_step) then
186      DO l=1,llm
187         WRITE(lunout,*) 'L, CFL[xyz]max:', l, cflxmax(l), cflymax(l), cflzmax(l)
188      END DO
189      countcfl=0
190   END IF
191
192   !---------------------------------------------------------------------------
193   !   Advection proprement dite (Modification Le Croller (07/2001)
194   !---------------------------------------------------------------------------
195
196   !---------------------------------------------------------------------------
197   !   Calcul des moyennes basees sur la masse
198   !---------------------------------------------------------------------------
199   CALL massbar(massem,massebx,masseby)
200
201   IF(isoCheck) WRITE(*,*) 'advtrac 227'
202   CALL check_isotopes_seq(q,ip1jmp1,'advtrac 162')
203
204   !-------------------------------------------------------------------------
205   !       Appel des sous programmes d'advection
206   !-------------------------------------------------------------------------
207   DO iq = 1, nqtot
208!     CALL clock(t_initial)
209      IF(tracers(iq)%parent /= 'air') CYCLE
210      iadv = tracers(iq)%iadv
211      !-----------------------------------------------------------------------
212      SELECT CASE(iadv)
213      !-----------------------------------------------------------------------
214         CASE(0); CYCLE
215         !--------------------------------------------------------------------
216         CASE(10)  !--- Schema de Van Leer I MUSCL
217         !--------------------------------------------------------------------
218!           WRITE(*,*) 'advtrac 239: iq,q(1721,19,:)=',iq,q(1721,19,:)     
219            CALL vlsplt(q,2.,massem,wg,pbarug,pbarvg,dtvr,iq)
220
221         !--------------------------------------------------------------------
222         CASE(14)  !--- Schema "pseuDO amont" + test sur humidite specifique
223                   !--- pour la vapeur d'eau. F. Codron
224         !--------------------------------------------------------------------
225!           WRITE(*,*) 'advtrac 248: iq,q(1721,19,:)=',iq,q(1721,19,:)
226            CALL vlspltqs(q,2.,massem,wg,pbarug,pbarvg,dtvr,p,pk,teta,iq)
227
228         !--------------------------------------------------------------------
229         CASE(12)  !--- Schema de Frederic Hourdin
230         !--------------------------------------------------------------------
231            CALL adaptdt(iadv,dtbon,n,pbarug,massem)   ! pas de temps adaptatif
232            IF(n > 1) WRITE(*,*) 'WARNING horizontal dt=',dtbon,'dtvr=',dtvr,'n=',n
233            DO indice=1,n
234              CALL advn(q(1,1,iq),massem,wg,pbarug,pbarvg,dtbon,1)
235            END DO
236
237         !--------------------------------------------------------------------
238         CASE(13)  !--- Pas de temps adaptatif
239         !--------------------------------------------------------------------
240            CALL adaptdt(iadv,dtbon,n,pbarug,massem)
241            IF(n > 1) WRITE(*,*) 'WARNING horizontal dt=',dtbon,'dtvr=',dtvr,'n=',n
242            DO indice=1,n
243               CALL advn(q(1,1,iq),massem,wg,pbarug,pbarvg,dtbon,2)
244            END DO
245
246         !--------------------------------------------------------------------
247         CASE(20)  !--- Schema de pente SLOPES
248         !--------------------------------------------------------------------
249            CALL pentes_ini (q(1,1,iq),wg,massem,pbarug,pbarvg,0)
250
251         !--------------------------------------------------------------------
252         CASE(30)  !--- Schema de Prather
253         !--------------------------------------------------------------------
254            ! Pas de temps adaptatif
255            CALL adaptdt(iadv,dtbon,n,pbarug,massem)
256            IF(n > 1) WRITE(*,*) 'WARNING horizontal dt=',dtbon,'dtvr=',dtvr,'n=',n
257            CALL prather(q(1,1,iq),wg,massem,pbarug,pbarvg,n,dtbon)
258
259         !--------------------------------------------------------------------
260         CASE(11,16,17,18)   !--- Schemas PPM Lin et Rood
261         !--------------------------------------------------------------------
262            ! Test sur le flux horizontal
263            CALL adaptdt(iadv,dtbon,n,pbarug,massem)   ! pas de temps adaptatif
264            IF(n > 1) WRITE(*,*) 'WARNING horizontal dt=',dtbon,'dtvr=',dtvr,'n=',n
265            ! Test sur le flux vertical
266            CFLmaxz=0.
267            DO l=2,llm
268               DO ij=iip2,ip1jm
269                  aaa=wg(ij,l)*dtvr/massem(ij,l)
270                  CFLmaxz=max(CFLmaxz,aaa)
271                  bbb=-wg(ij,l)*dtvr/massem(ij,l-1)
272                  CFLmaxz=max(CFLmaxz,bbb)
273               END DO
274            END DO
275            IF(CFLmaxz.GE.1) WRITE(*,*) 'WARNING vertical','CFLmaxz=', CFLmaxz
276            !----------------------------------------------------------------
277            !     Ss-prg interface LMDZ.4->PPM3d (ss-prg de Lin)
278            !----------------------------------------------------------------
279            CALL interpre(q(1,1,iq),qppm(1,1,iq),wg,fluxwppm,massem, &
280                 apppm,bpppm,massebx,masseby,pbarug,pbarvg, &
281                 unatppm,vnatppm,psppm)
282
283            !----------------------------------------------------------------
284            DO indice=1,n     !--- VL (version PPM) horiz. et PPM vert.
285            !----------------------------------------------------------------
286               SELECT CASE(iadv)
287                  !----------------------------------------------------------
288                  CASE(11)
289                  !----------------------------------------------------------
290                     CALL ppm3d(1,qppm(1,1,iq),psppm,psppm,unatppm,vnatppm,fluxwppm,dtbon, &
291                                2,2,2,1,iim,jjp1,2,llm,apppm,bpppm,0.01,6400000,fill,dum,220.)
292                  !----------------------------------------------------------
293                  CASE(16) !--- Monotonic PPM
294                  !----------------------------------------------------------
295                     CALL ppm3d(1,qppm(1,1,iq),psppm,psppm,unatppm,vnatppm,fluxwppm,dtbon, &
296                                3,3,3,1,iim,jjp1,2,llm,apppm,bpppm,0.01,6400000,fill,dum,220.)
297                  !----------------------------------------------------------
298                  CASE(17) !--- Semi monotonic PPM
299                  !----------------------------------------------------------
300                     CALL ppm3d(1,qppm(1,1,iq),psppm,psppm,unatppm,vnatppm,fluxwppm,dtbon, &
301                                4,4,4,1,iim,jjp1,2,llm,apppm,bpppm,0.01,6400000, fill,dum,220.)
302                  !----------------------------------------------------------
303                  CASE(18) !--- Positive Definite PPM
304                  !----------------------------------------------------------
305                     CALL ppm3d(1,qppm(1,1,iq),psppm,psppm,unatppm,vnatppm,fluxwppm,dtbon, &
306                                5,5,5,1,iim,jjp1,2,llm,apppm,bpppm,0.01,6400000,fill,dum,220.)
307               END SELECT
308            !----------------------------------------------------------------
309            END DO
310            !----------------------------------------------------------------
311            !     Ss-prg interface PPM3d-LMDZ.4
312            !----------------------------------------------------------------
313            CALL interpost(q(1,1,iq),qppm(1,1,iq))
314      !----------------------------------------------------------------------
315      END SELECT
316      !----------------------------------------------------------------------
317
318      !----------------------------------------------------------------------
319      ! On impose une seule valeur du traceur au pole Sud j=jjm+1=jjp1 et Nord j=1
320      !----------------------------------------------------------------------
321      !  CALL traceurpole(q(1,1,iq),massem)
322
323      !--- Calcul du temps cpu pour un schema donne
324      !  CALL clock(t_final)
325      !ym  tps_cpu=t_final-t_initial
326      !ym  cpuadv(iq)=cpuadv(iq)+tps_cpu
327
328   END DO
329
330   IF(isoCheck) WRITE(*,*) 'advtrac 402'
331   CALL check_isotopes_seq(q,ip1jmp1,'advtrac 397')
332
333   !-------------------------------------------------------------------------
334   !   on reinitialise a zero les flux de masse cumules
335   !-------------------------------------------------------------------------
336   iadvtr=0
337
338END SUBROUTINE advtrac
Note: See TracBrowser for help on using the repository browser.